Loose monad condition on test methods
This commit is contained in:
parent
c60dd98fc5
commit
1a788a6261
@ -7,6 +7,8 @@ and this project adheres to
|
|||||||
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
[Haskell Package Versioning Policy](https://pvp.haskell.org/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.9.0.0] - 2020-07-24
|
||||||
## Fixed
|
## Fixed
|
||||||
- Location of a parse error is returned in a singleton array with key
|
- Location of a parse error is returned in a singleton array with key
|
||||||
`locations`.
|
`locations`.
|
||||||
@ -21,7 +23,7 @@ and this project adheres to
|
|||||||
- `Error.Error` is an error representation with a message and source location.
|
- `Error.Error` is an error representation with a message and source location.
|
||||||
- `Error.Response` represents a result of running a GraphQL query.
|
- `Error.Response` represents a result of running a GraphQL query.
|
||||||
- `Type.Schema` exports `Type` which lists all types possible in the schema.
|
- `Type.Schema` exports `Type` which lists all types possible in the schema.
|
||||||
- Parsing subscriptions (the execution always fails yet).
|
- Parsing subscriptions.
|
||||||
- `Error.ResponseEventStream`, `Type.Out.Resolve`, `Type.Out.Subscribe` and
|
- `Error.ResponseEventStream`, `Type.Out.Resolve`, `Type.Out.Subscribe` and
|
||||||
`Type.Out.SourceEventStream` define subscription resolvers.
|
`Type.Out.SourceEventStream` define subscription resolvers.
|
||||||
- `Error.ResolverException` is an exception that can be thrown by (field value
|
- `Error.ResolverException` is an exception that can be thrown by (field value
|
||||||
@ -57,8 +59,6 @@ and this project adheres to
|
|||||||
## Removed
|
## Removed
|
||||||
- `Trans.ActionT` is an unneeded layer of complexity. `Type.Out.Resolver`
|
- `Trans.ActionT` is an unneeded layer of complexity. `Type.Out.Resolver`
|
||||||
represents possible resolver configurations.
|
represents possible resolver configurations.
|
||||||
- `Type.Out.Resolver`: It . Resolvers are a
|
|
||||||
part of the fields and are called `Trans.ResolverT`.
|
|
||||||
- `Execute.executeWithName`. `Execute.execute` takes the operation name and
|
- `Execute.executeWithName`. `Execute.execute` takes the operation name and
|
||||||
completely replaces `executeWithName`.
|
completely replaces `executeWithName`.
|
||||||
|
|
||||||
@ -323,7 +323,8 @@ and this project adheres to
|
|||||||
### Added
|
### Added
|
||||||
- Data types for the GraphQL language.
|
- Data types for the GraphQL language.
|
||||||
|
|
||||||
[Unreleased]: https://github.com/caraus-ecms/graphql/compare/v0.8.0.0...HEAD
|
[Unreleased]: https://github.com/caraus-ecms/graphql/compare/v0.9.0.0...HEAD
|
||||||
|
[0.9.0.0]: https://github.com/caraus-ecms/graphql/compare/v0.8.0.0...v0.9.0.0
|
||||||
[0.8.0.0]: https://github.com/caraus-ecms/graphql/compare/v0.7.0.0...v0.8.0.0
|
[0.8.0.0]: https://github.com/caraus-ecms/graphql/compare/v0.7.0.0...v0.8.0.0
|
||||||
[0.7.0.0]: https://github.com/caraus-ecms/graphql/compare/v0.6.1.0...v0.7.0.0
|
[0.7.0.0]: https://github.com/caraus-ecms/graphql/compare/v0.6.1.0...v0.7.0.0
|
||||||
[0.6.1.0]: https://github.com/caraus-ecms/graphql/compare/v0.6.0.0...v0.6.1.0
|
[0.6.1.0]: https://github.com/caraus-ecms/graphql/compare/v0.6.0.0...v0.6.1.0
|
||||||
|
94
README.md
94
README.md
@ -29,6 +29,100 @@ API documentation is available through
|
|||||||
You'll also find a small tutorial with some examples under
|
You'll also find a small tutorial with some examples under
|
||||||
[docs/tutorial](https://github.com/caraus-ecms/graphql/tree/master/docs/tutorial).
|
[docs/tutorial](https://github.com/caraus-ecms/graphql/tree/master/docs/tutorial).
|
||||||
|
|
||||||
|
### Getting started
|
||||||
|
|
||||||
|
We start with a simple GraphQL API that provides us with some famous and less
|
||||||
|
famous cites.
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
"""
|
||||||
|
Root Query type.
|
||||||
|
"""
|
||||||
|
type Query {
|
||||||
|
"""
|
||||||
|
Provides a cite.
|
||||||
|
"""
|
||||||
|
cite: String!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is called a GraphQL schema, it defines all queries supported by the API.
|
||||||
|
`Query` is the root query type. Every GraphQL API should define a query type.
|
||||||
|
|
||||||
|
`Query` has a single field `cite` that returns a `String`. The `!` after the
|
||||||
|
type denotes that the returned value cannot be `Null`. GraphQL fields are
|
||||||
|
nullable by default.
|
||||||
|
|
||||||
|
To be able to work with this schema, we are going to implement it in Haskell.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
import Control.Exception (SomeException)
|
||||||
|
import qualified Data.Aeson as Aeson
|
||||||
|
import qualified Data.ByteString.Lazy.Char8 as ByteString.Lazy.Char8
|
||||||
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
|
import Language.GraphQL
|
||||||
|
import Language.GraphQL.Type
|
||||||
|
import qualified Language.GraphQL.Type.Out as Out
|
||||||
|
|
||||||
|
-- GraphQL supports 3 kinds of operations: queries, mutations and subscriptions.
|
||||||
|
-- Our first schema supports only queries.
|
||||||
|
schema :: Schema IO
|
||||||
|
schema = Schema
|
||||||
|
{ query = queryType, mutation = Nothing, subscription = Nothing }
|
||||||
|
|
||||||
|
-- GraphQL distinguishes between input and output types. Input types are field
|
||||||
|
-- argument types and they are defined in Language.GraphQL.Type.In. Output types
|
||||||
|
-- are result types, they are defined in Language.GraphQL.Type.Out. Root types
|
||||||
|
-- are always object types.
|
||||||
|
--
|
||||||
|
-- Here we define a type "Query". The second argument is an optional
|
||||||
|
-- description, the third one is the list of interfaces implemented by the
|
||||||
|
-- object type. The last argument is a field map. Keys are field names, values
|
||||||
|
-- are field definitions and resolvers. Resolvers are the functions, where the
|
||||||
|
-- actual logic lives, they return values for the respective fields.
|
||||||
|
queryType :: Out.ObjectType IO
|
||||||
|
queryType = Out.ObjectType "Query" (Just "Root Query type.") []
|
||||||
|
$ HashMap.singleton "cite" citeResolver
|
||||||
|
where
|
||||||
|
-- 'ValueResolver' is a 'Resolver' data constructor, it combines a field
|
||||||
|
-- definition with its resolver function. This function resolves a value for
|
||||||
|
-- a field (as opposed to the 'EventStreamResolver' used by subscriptions).
|
||||||
|
-- Our resolver just returns a constant value.
|
||||||
|
citeResolver = ValueResolver citeField
|
||||||
|
$ pure "Piscis primum a capite foetat"
|
||||||
|
-- The first argument is an optional field description. The second one is
|
||||||
|
-- the field type and the third one is for arguments (we have none in this
|
||||||
|
-- example).
|
||||||
|
--
|
||||||
|
-- GraphQL has named and wrapping types. String is a scalar, named type.
|
||||||
|
-- Named types are nullable by default. To make our "cite" field
|
||||||
|
-- non-nullable, we wrap it in the wrapping type, Non-Null.
|
||||||
|
citeField = Out.Field
|
||||||
|
(Just "Provides a cite.") (Out.NonNullScalarType string) HashMap.empty
|
||||||
|
|
||||||
|
-- Now we can execute a query. Since our schema defines only one field,
|
||||||
|
-- everything we can do is to ask to resolve it and give back the result.
|
||||||
|
-- Since subscriptions don't return plain values, the 'graphql' function returns
|
||||||
|
-- an 'Either'. 'Left' is for subscriptions, 'Right' is for queries and
|
||||||
|
-- mutations.
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
Right result <- graphql schema "{ cite }"
|
||||||
|
ByteString.Lazy.Char8.putStrLn $ Aeson.encode result
|
||||||
|
```
|
||||||
|
|
||||||
|
Executing this query produces the following JSON:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"cite": "Piscis primum a capite foetat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Further information
|
## Further information
|
||||||
|
|
||||||
- [Contributing guidelines](CONTRIBUTING.md).
|
- [Contributing guidelines](CONTRIBUTING.md).
|
||||||
|
@ -11,6 +11,7 @@ module Test.Hspec.GraphQL
|
|||||||
, shouldResolveTo
|
, shouldResolveTo
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.Catch (MonadCatch)
|
||||||
import qualified Data.Aeson as Aeson
|
import qualified Data.Aeson as Aeson
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
@ -18,8 +19,8 @@ import Language.GraphQL.Error
|
|||||||
import Test.Hspec.Expectations (Expectation, expectationFailure, shouldBe, shouldNotSatisfy)
|
import Test.Hspec.Expectations (Expectation, expectationFailure, shouldBe, shouldNotSatisfy)
|
||||||
|
|
||||||
-- | Asserts that a query resolves to some value.
|
-- | Asserts that a query resolves to some value.
|
||||||
shouldResolveTo
|
shouldResolveTo :: MonadCatch m
|
||||||
:: Either (ResponseEventStream IO Aeson.Value) Aeson.Object
|
=> Either (ResponseEventStream m Aeson.Value) Aeson.Object
|
||||||
-> Aeson.Object
|
-> Aeson.Object
|
||||||
-> Expectation
|
-> Expectation
|
||||||
shouldResolveTo (Right actual) expected = actual `shouldBe` expected
|
shouldResolveTo (Right actual) expected = actual `shouldBe` expected
|
||||||
@ -27,8 +28,8 @@ shouldResolveTo _ _ = expectationFailure
|
|||||||
"the query is expected to resolve to a value, but it resolved to an event stream"
|
"the query is expected to resolve to a value, but it resolved to an event stream"
|
||||||
|
|
||||||
-- | Asserts that the response doesn't contain any errors.
|
-- | Asserts that the response doesn't contain any errors.
|
||||||
shouldResolve
|
shouldResolve :: MonadCatch m
|
||||||
:: (Text -> IO (Either (ResponseEventStream IO Aeson.Value) Aeson.Object))
|
=> (Text -> IO (Either (ResponseEventStream m Aeson.Value) Aeson.Object))
|
||||||
-> Text
|
-> Text
|
||||||
-> Expectation
|
-> Expectation
|
||||||
shouldResolve executor query = do
|
shouldResolve executor query = do
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
resolver: lts-16.6
|
resolver: lts-16.10
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- .
|
- .
|
||||||
|
Loading…
Reference in New Issue
Block a user