content: {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE DerivingStrategies #-}
  {-# LANGUAGE DuplicateRecordFields #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuasiQuotes #-}
  {-# LANGUAGE TemplateHaskell #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE TypeOperators #-}
  {-# LANGUAGE NoImplicitPrelude #-}
  
  module Case.ResponseTypes.Test
    ( test,
    )
  where
  
  import Data.Aeson (FromJSON)
  import Data.Morpheus.Client
    ( EncodeScalar (..),
      Fetch (..),
      FetchError (..),
      ScalarValue (..),
      declareLocalTypesInline,
      raw,
    )
  import Data.Morpheus.Types.Internal.AST
    ( Position (..),
      PropName (PropIndex),
      at,
      custom,
      withPath,
    )
  import Relude
  import Spec.Utils
    ( assertFetch,
      path,
    )
  import Test.Tasty
    ( TestTree,
      testGroup,
    )
  
  newtype GitTimestamp = GitTimestamp
    { unGitTimestamp :: Text
    }
    deriving (Eq, Show)
  
  instance EncodeScalar GitTimestamp where
    encodeScalar (GitTimestamp x) = String x
  
  type Res a = Either (FetchError a) a
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw| 
      query SimpleQuery 
        { queryTypeName 
        }
    |]
  
  simpleQuery :: Res SimpleQuery
  simpleQuery =
    Right
      SimpleQuery
        { queryTypeName = Just "TestQuery"
        }
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw|
      query PartialResponse
        { queryTypeName
        }
    |]
  
  partialResponse :: Res PartialResponse
  partialResponse =
    Left
      ( FetchErrorParseFailure
          "Error in $.data.queryTypeName: parsing Text failed, expected String, but encountered Number"
      )
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw|
      query NoResponseOrError
        {
          queryTypeName
        }
    |]
  
  noResponseOrError :: Res NoResponseOrError
  noResponseOrError = Left FetchErrorNoResult
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw|
      mutation SimpleMutation
        {
          mutationTypeName
        }
    |]
  
  simpleMutation :: Either a SimpleMutation
  simpleMutation =
    Right
      ( SimpleMutation
          { mutationTypeName = Just "TestMutation"
          }
      )
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw|
      subscription SimpleSubscription
        {
          subscriptionTypeName
        }
    |]
  
  simpleSubscription :: Res SimpleSubscription
  simpleSubscription =
    Right
      ( SimpleSubscription
          { subscriptionTypeName =
              Just "TestSubscription"
          }
      )
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw|
      query ErrorsWithType
        {
          queryTypeName
        }
    |]
  
  errorsWithType :: Res ErrorsWithType
  errorsWithType =
    Left
      ( FetchErrorProducedErrors
          ( ("Failure" `at` Position {line = 3, column = 7})
              `withPath` ["queryTypeName"]
              `custom` "QUERY_BAD"
              :| []
          )
          (Just ErrorsWithType {queryTypeName = Just "TestQuery"})
      )
  
  declareLocalTypesInline
    (path "ResponseTypes/schema.json")
    [raw|
      query TestErrorsQuery
        {
          queryTypeName
        }
    |]
  
  testErrorsQuery :: Res TestErrorsQuery
  testErrorsQuery =
    Left
      ( FetchErrorProducedErrors
          ( ("Failure" `at` Position {line = 3, column = 7})
              `withPath` [ "queryTypeName",
                           PropIndex 0
                         ]
              :| []
          )
          ( Just
              TestErrorsQuery
                { queryTypeName = Just "TestQuery"
                }
          )
      )
  
  check ::
    ( Args a ~ (),
      Fetch a,
      FromJSON a,
      Eq a,
      Show a
    ) =>
    FilePath ->
    Res a ->
    TestTree
  check name =
    assertFetch
      "ResponseTypes"
      (Just name)
      ()
  
  test :: TestTree
  test =
    testGroup
      "Response Types"
      [ check "query" simpleQuery,
        check "partialResponse" partialResponse,
        check "noResponseOrError" noResponseOrError,
        check "mutation" simpleMutation,
        check "subscription" simpleSubscription,
        check "errorsWithType" errorsWithType,
        check "errors" testErrorsQuery
      ]
  