graphql-engine/server/tests-hspec/Test/UpdateManySpec.hs
Samir Talwar eab4f75212 An ErrorMessage type, to encapsulate.
This introduces an `ErrorMessage` newtype which wraps `Text` in a manner which is designed to be easy to construct, and difficult to deconstruct.

It provides functionality similar to `Data.Text.Extended`, but designed _only_ for error messages. Error messages are constructed through `fromString`, concatenation, or the `toErrorValue` function, which is designed to be overridden for all meaningful domain types that might show up in an error message. Notably, there are not and should never be instances of `ToErrorValue` for `String`, `Text`, `Int`, etc. This is so that we correctly represent the value in a way that is specific to its type. For example, all `Name` values (from the _graphql-parser-hs_ library) are single-quoted now; no exceptions.

I have mostly had to add `instance ToErrorValue` for various backend types (and also add newtypes where necessary). Some of these are not strictly necessary for this changeset, as I had bigger aspirations when I started. These aspirations have been tempered by trying and failing twice.

As such, in this changeset, I have started by introducing this type to the `parseError` and `parseErrorWith` functions. In the future, I would like to extend this to the `QErr` record and the various `throwError` functions, but this is a much larger task and should probably be done in stages.

For now, `toErrorMessage` and `fromErrorMessage` are provided for conversion to and from `Text`, but the intent is to stop exporting these once all error messages are converted to the new type.

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5018
GitOrigin-RevId: 84b37e238992e4312255a87ca44f41af65e2d89a
2022-07-18 20:27:06 +00:00

240 lines
5.1 KiB
Haskell

{-# LANGUAGE QuasiQuotes #-}
-- | Test multiple updates (update_table_many).
module Test.UpdateManySpec (spec) where
import Harness.Backend.Postgres qualified as Postgres
import Harness.GraphqlEngine qualified as GraphqlEngine
import Harness.Quoter.Graphql (graphql)
import Harness.Quoter.Yaml (shouldReturnYaml, yaml)
import Harness.Test.Context qualified as Context
import Harness.Test.Schema (Table (..), table)
import Harness.Test.Schema qualified as Schema
import Harness.TestEnvironment (TestEnvironment)
import Test.Hspec (SpecWith, describe, it)
import Prelude
--------------------------------------------------------------------------------
-- ** Preamble
spec :: SpecWith TestEnvironment
spec =
describe "UpdateManySpec" $ Context.run [postgresContext] tests
where
postgresContext =
Context.Context
{ name = Context.Backend Context.Postgres,
mkLocalTestEnvironment = Context.noLocalTestEnvironment,
setup = Postgres.setup schema,
teardown = Postgres.teardown schema,
customOptions = Nothing
}
--------------------------------------------------------------------------------
-- ** Schema
schema :: [Schema.Table]
schema =
[ artist,
album
]
artist :: Schema.Table
artist =
(table "artist")
{ tableColumns =
[ Schema.column "id" Schema.defaultSerialType,
Schema.column "name" Schema.TStr
],
tablePrimaryKey = ["id"],
tableData =
[ [Schema.VInt 1, Schema.VStr "first"],
[Schema.VInt 2, Schema.VStr "second"],
[Schema.VInt 3, Schema.VStr "third"]
]
}
album :: Schema.Table
album =
(table "album")
{ tableColumns =
[ Schema.column "id" Schema.defaultSerialType,
Schema.column "albumname" Schema.TStr,
Schema.column "artist_id" Schema.TInt
],
tablePrimaryKey = ["albumname"],
tableReferences = [Schema.Reference "artist_id" "artist" "id"],
tableData =
[ [Schema.VInt 1, Schema.VStr "first album", Schema.VInt 1],
[Schema.VInt 2, Schema.VStr "second album", Schema.VInt 2],
[Schema.VInt 3, Schema.VStr "third album", Schema.VInt 3]
]
}
--------------------------------------------------------------------------------
-- * Tests
tests :: Context.Options -> SpecWith TestEnvironment
tests opts = do
it "Update no records" $ \testEnvironment ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnvironment
[graphql|
mutation {
update_hasura_artist_many(
updates: [
{ where: { id: { _eq: 10 } }
_set: { name: "test" }
}
]
){
affected_rows
}
}
|]
)
[yaml|
data:
update_hasura_artist_many:
- affected_rows: 0
|]
it "Update single record" $ \testEnvironment ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnvironment
[graphql|
mutation {
update_hasura_artist_many(
updates: [
{ where: { id: { _eq: 10 } }
_set: { name: "test" }
}
{ where: { id: { _gt: 2 } }
_set: { name: "test" }
}
]
){
affected_rows
}
}
|]
)
[yaml|
data:
update_hasura_artist_many:
- affected_rows: 0
- affected_rows: 1
|]
it "Update record multiple times" $ \testEnvironment ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnvironment
[graphql|
mutation {
update_hasura_artist_many(
updates: [
{ where: { id: { _gt: 2 } }
_set: { name: "test" }
}
{ where: { name: { _eq: "test" } }
_set: { name: "changed name" }
}
]
){
affected_rows
returning {
name
}
}
}
|]
)
[yaml|
data:
update_hasura_artist_many:
- affected_rows: 1
returning:
- name: "test"
- affected_rows: 1
returning:
- name: "changed name"
|]
it "Update record multiple times with overlapping conditions" $ \testEnvironment ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnvironment
[graphql|
mutation {
update_hasura_artist_many(
updates: [
{ where: { id: { _gt: 2 } }
_set: { name: "test" }
}
{ where: { id: { _eq: 3 } }
_set: { name: "changed name" }
}
]
){
affected_rows
returning {
name
}
}
}
|]
)
[yaml|
data:
update_hasura_artist_many:
- affected_rows: 1
returning:
- name: "test"
- affected_rows: 1
returning:
- name: "changed name"
|]
it "Revert on error" $ \testEnvironment ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
testEnvironment
[graphql|
mutation {
update_hasura_album_many(
updates: [
{ where: { id: { _eq: 1 } }
_set: { albumname: "test" }
}
{ where: { id: { _eq: 1 } }
_set: { artist_id: 4 }
}
]
){
affected_rows
returning {
name
}
}
}
|]
)
[yaml|
errors:
- extensions:
code: validation-failed
path: $.selectionSet.update_hasura_album_many.selectionSet.returning.selectionSet.name
message: 'field ''name'' not found in type: ''hasura_album'''
|]