mirror of
https://github.com/hasura/graphql-engine.git
synced 2025-01-05 14:27:59 +03:00
chore(server): add tests/support for inserting JSON arrays
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9704 GitOrigin-RevId: 4c2820c302d056bed92bf61e3670419c6da1563e
This commit is contained in:
parent
90048c84bf
commit
cb02a9a034
@ -62,6 +62,11 @@ ghcid-api-tests-run: start-api-tests-backends
|
||||
ghcid-test-harness:
|
||||
$(call run_ghcid,test-harness)
|
||||
|
||||
.PHONY: ghcid-pg-client
|
||||
## ghcid-pg-client: build and watch pg-client in ghcid
|
||||
ghcid-pg-client:
|
||||
$(call run_ghcid,pg-client)
|
||||
|
||||
.PHONY: ghcid-api-tests-pro
|
||||
## ghcid-api-tests-pro: build and watch api-tests in pro
|
||||
ghcid-api-tests-pro:
|
||||
|
@ -9,9 +9,9 @@ import Data.List.NonEmpty qualified as NE
|
||||
import Harness.Backend.Citus qualified as Citus
|
||||
import Harness.Backend.Cockroach qualified as Cockroach
|
||||
import Harness.Backend.Postgres qualified as Postgres
|
||||
import Harness.GraphqlEngine (postGraphql)
|
||||
import Harness.GraphqlEngine (postGraphql, postGraphqlWithVariables)
|
||||
import Harness.Quoter.Graphql (graphql)
|
||||
import Harness.Quoter.Yaml (interpolateYaml)
|
||||
import Harness.Quoter.Yaml (interpolateYaml, yaml)
|
||||
import Harness.Schema qualified as Schema
|
||||
import Harness.Test.Fixture qualified as Fixture
|
||||
import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment)
|
||||
@ -60,6 +60,23 @@ spec = do
|
||||
)
|
||||
nestedArrayTests
|
||||
|
||||
-- CockroachDB does not support json arrays
|
||||
Fixture.run
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Postgres.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnv, _) ->
|
||||
[ Postgres.setupTablesAction schema testEnv
|
||||
]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Citus.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnv, _) ->
|
||||
[ Citus.setupTablesAction schema testEnv
|
||||
]
|
||||
}
|
||||
]
|
||||
)
|
||||
jsonArrayTests
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Schema
|
||||
|
||||
@ -72,13 +89,22 @@ textArrayType =
|
||||
Schema.bstCockroach = Just "text[]"
|
||||
}
|
||||
|
||||
nestedTextArrayType :: Schema.ScalarType
|
||||
nestedTextArrayType =
|
||||
nestedIntArrayType :: Schema.ScalarType
|
||||
nestedIntArrayType =
|
||||
Schema.TCustomType
|
||||
$ Schema.defaultBackendScalarType
|
||||
{ Schema.bstPostgres = Just "text[][]",
|
||||
Schema.bstCitus = Just "text[][]",
|
||||
Schema.bstCockroach = Just "text[]" -- nested arrays aren't supported in Cockroach, so we'll skip this test anyway
|
||||
{ Schema.bstPostgres = Just "int[][]",
|
||||
Schema.bstCitus = Just "int[][]",
|
||||
Schema.bstCockroach = Just "int[]" -- nested arrays aren't supported in Cockroach, so we'll skip this test anyway
|
||||
}
|
||||
|
||||
jsonArrayType :: Schema.ScalarType
|
||||
jsonArrayType =
|
||||
Schema.TCustomType
|
||||
$ Schema.defaultBackendScalarType
|
||||
{ Schema.bstPostgres = Just "json[]",
|
||||
Schema.bstCitus = Just "json[]",
|
||||
Schema.bstCockroach = Just "json" -- arrays of json aren't supported in Cockroach, so we'll skip this test
|
||||
}
|
||||
|
||||
schema :: [Schema.Table]
|
||||
@ -88,7 +114,8 @@ schema =
|
||||
[ Schema.column "id" Schema.defaultSerialType,
|
||||
Schema.column "name" Schema.TStr,
|
||||
Schema.column "emails" textArrayType,
|
||||
Schema.column "grid" nestedTextArrayType
|
||||
Schema.column "grid" nestedIntArrayType,
|
||||
Schema.column "jsons" jsonArrayType
|
||||
],
|
||||
Schema.tablePrimaryKey = ["id"]
|
||||
}
|
||||
@ -123,7 +150,8 @@ singleArrayTests = do
|
||||
{
|
||||
name: "Ash",
|
||||
emails: "{ash@ash.com, ash123@ash.com}",
|
||||
grid: "{}"
|
||||
grid: "{}",
|
||||
jsons: "{}"
|
||||
}
|
||||
]
|
||||
) {
|
||||
@ -138,7 +166,7 @@ singleArrayTests = do
|
||||
|
||||
shouldReturnYaml testEnvironment actual expected
|
||||
|
||||
it "Using native GraphQL array syntax" \testEnvironment -> do
|
||||
it "Text array using native GraphQL array syntax" \testEnvironment -> do
|
||||
let expected :: Value
|
||||
expected =
|
||||
[interpolateYaml|
|
||||
@ -161,7 +189,8 @@ singleArrayTests = do
|
||||
{
|
||||
name: "Ash",
|
||||
emails: ["ash@ash.com", "ash123@ash.com"],
|
||||
grid: []
|
||||
grid: [],
|
||||
jsons: []
|
||||
}
|
||||
]
|
||||
) {
|
||||
@ -176,6 +205,90 @@ singleArrayTests = do
|
||||
|
||||
shouldReturnYaml testEnvironment actual expected
|
||||
|
||||
jsonArrayTests :: SpecWith TestEnvironment
|
||||
jsonArrayTests = do
|
||||
describe "saves JSON arrays" $ do
|
||||
it "JSON array using native GraphQL array syntax" \testEnvironment -> do
|
||||
let expected :: Value
|
||||
expected =
|
||||
[interpolateYaml|
|
||||
data:
|
||||
insert_hasura_author:
|
||||
affected_rows: 1
|
||||
returning:
|
||||
- name: "Bruce"
|
||||
jsons: [{ name: "Mr Horse", age: 100}, { name: "Mr Dog", age: 1}]
|
||||
|]
|
||||
|
||||
actual :: IO Value
|
||||
actual =
|
||||
postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
mutation {
|
||||
insert_hasura_author (
|
||||
objects: [
|
||||
{
|
||||
name: "Bruce",
|
||||
emails: ["something@something.com"]
|
||||
grid: [],
|
||||
jsons: ["{ \"name\": \"Mr Horse\", \"age\": 100}", "{\"name\":\"Mr Dog\", \"age\": 1}"]
|
||||
}
|
||||
]
|
||||
) {
|
||||
affected_rows
|
||||
returning {
|
||||
name
|
||||
jsons
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
|
||||
shouldReturnYaml testEnvironment actual expected
|
||||
|
||||
it "JSON array using native GraphQL array syntax and variable" \testEnvironment -> do
|
||||
let expected :: Value
|
||||
expected =
|
||||
[interpolateYaml|
|
||||
data:
|
||||
insert_hasura_author:
|
||||
affected_rows: 1
|
||||
returning:
|
||||
- name: "Bruce"
|
||||
jsons: [{ name: "Mr Horse", age: 100}, "horses"]
|
||||
|]
|
||||
|
||||
actual :: IO Value
|
||||
actual =
|
||||
postGraphqlWithVariables
|
||||
testEnvironment
|
||||
[graphql|
|
||||
mutation json_variables_test($jsonArray: [json]) {
|
||||
insert_hasura_author (
|
||||
objects: [
|
||||
{
|
||||
name: "Bruce",
|
||||
emails: ["something2@something2.com"],
|
||||
grid: [],
|
||||
jsons: $jsonArray
|
||||
}
|
||||
]
|
||||
) {
|
||||
affected_rows
|
||||
returning {
|
||||
name
|
||||
jsons
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
[yaml|
|
||||
jsonArray: [{ name: "Mr Horse", age: 100 }, "horses"]
|
||||
|]
|
||||
|
||||
shouldReturnYaml testEnvironment actual expected
|
||||
|
||||
describe "Filters with contains" $ do
|
||||
it "finds values using _contains" \testEnvironment -> do
|
||||
void
|
||||
@ -188,7 +301,8 @@ singleArrayTests = do
|
||||
{
|
||||
name: "contains",
|
||||
emails: ["horse@horse.com", "dog@dog.com"],
|
||||
grid: []
|
||||
grid: [],
|
||||
jsons: []
|
||||
}
|
||||
]
|
||||
) {
|
||||
@ -234,7 +348,8 @@ singleArrayTests = do
|
||||
{
|
||||
name: "contained_in",
|
||||
emails: ["horse@horse2.com", "dog@dog2.com"],
|
||||
grid: []
|
||||
grid: [],
|
||||
jsons: []
|
||||
}
|
||||
]
|
||||
) {
|
||||
@ -285,8 +400,8 @@ nestedArrayTests = do
|
||||
affected_rows: 1
|
||||
returning:
|
||||
- name: "Ash"
|
||||
grid: [["one", "two", "three"],
|
||||
["four", "five", "six"]]
|
||||
grid: [[1,2,3],
|
||||
[4,5,6]]
|
||||
|]
|
||||
|
||||
actual :: IO Value
|
||||
@ -300,7 +415,8 @@ nestedArrayTests = do
|
||||
{
|
||||
name: "Ash",
|
||||
emails: "{}",
|
||||
grid: "{{one,two,three},{four,five,six}}"
|
||||
grid: "{{1,2,3},{4,5,6}}",
|
||||
jsons: "{}"
|
||||
}
|
||||
]
|
||||
) {
|
||||
|
@ -332,7 +332,27 @@ buildArrayLiteral ts =
|
||||
PGValLquery t -> TELit $ escape t
|
||||
PGValLtxtquery t -> TELit $ escape t
|
||||
PGValUnknown t -> TELit $ escape t
|
||||
PGValJSON (PG.JSON j) -> case j of
|
||||
-- this is delicate - we want to encode JSON
|
||||
-- that is provided to HGE as raw JSON literals provided via variables,
|
||||
-- and in stringified form as received when
|
||||
-- inlined in a query. Therefore we need to check whether any string
|
||||
-- receive is a genuine JSON string value, or a stringified rich value.
|
||||
String s -> case decode (txtToLbs s) of
|
||||
Just jv -> fromJson jv -- it was some actual JSON in disguise! encode it like usual
|
||||
Nothing -> TELit $ escape (escape s) -- it's an actual JSON string, so add quotes again
|
||||
_ -> fromJson j
|
||||
PGValJSONB (PG.JSONB j) -> case j of
|
||||
-- we do the same for JSONB as JSON
|
||||
String s -> case decode (txtToLbs s) of
|
||||
Just jv -> fromJsonb jv -- it was some actual JSON in disguise! encode it like usual
|
||||
Nothing -> TELit $ escape (escape s) -- it's an actual JSON string, so add quotes again
|
||||
_ -> fromJsonb j
|
||||
other -> txtEncodedVal other
|
||||
|
||||
fromJson = TELit . escape . bsToTxt . PE.encodingBytes . PE.json_ast
|
||||
fromJsonb = TELit . escape . bsToTxt . PE.encodingBytes . PE.jsonb_ast
|
||||
|
||||
inner = \case
|
||||
TENull -> "null"
|
||||
TELit t -> t
|
||||
|
Loading…
Reference in New Issue
Block a user