Add a test for Distinct queries

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6426
Co-authored-by: Gil Mizrahi <8547573+soupi@users.noreply.github.com>
GitOrigin-RevId: 65387489ab0cabe0cb520799821380732ecef3e7
This commit is contained in:
Tom Harding 2022-11-01 19:56:50 +00:00 committed by hasura-bot
parent 600aaf9358
commit fbcf90d56f
3 changed files with 182 additions and 8 deletions

View File

@ -117,6 +117,7 @@ executable api-tests
Test.Queries.Directives.IncludeSpec
Test.Queries.Directives.SkipSpec
Test.Queries.DirectivesSpec
Test.Queries.DistinctSpec
Test.Queries.ExplainSpec
Test.Queries.FilterSearchSpec
Test.Queries.FragmentsSpec

View File

@ -0,0 +1,167 @@
{-# LANGUAGE QuasiQuotes #-}
-- |
-- Tests for @distinct@ queries.
--
-- https://hasura.io/docs/latest/queries/postgres/distinct-queries/
module Test.Queries.DistinctSpec where
import Data.Aeson (Value)
import Data.List.NonEmpty qualified as NE
import Harness.Backend.BigQuery qualified as BigQuery
import Harness.Backend.Citus qualified as Citus
import Harness.Backend.Postgres qualified as Postgres
import Harness.GraphqlEngine (postGraphql)
import Harness.Quoter.Graphql (graphql)
import Harness.Quoter.Yaml (interpolateYaml)
import Harness.Test.Fixture qualified as Fixture
import Harness.Test.Schema (Table (..), table)
import Harness.Test.Schema qualified as Schema
import Harness.TestEnvironment (TestEnvironment)
import Harness.Yaml (shouldReturnYaml)
import Hasura.Prelude
import Test.Hspec (SpecWith, it)
spec :: SpecWith TestEnvironment
spec = do
Fixture.run
( NE.fromList
[ (Fixture.fixture $ Fixture.Backend Fixture.Postgres)
{ Fixture.setupTeardown = \(testEnv, _) ->
[ Postgres.setupTablesAction schema testEnv
]
},
(Fixture.fixture $ Fixture.Backend Fixture.Citus)
{ Fixture.setupTeardown = \(testEnv, _) ->
[ Citus.setupTablesAction schema testEnv
]
},
(Fixture.fixture $ Fixture.Backend Fixture.BigQuery)
{ Fixture.setupTeardown = \(testEnv, _) ->
[ BigQuery.setupTablesAction schema testEnv
],
Fixture.customOptions =
Just $
Fixture.defaultOptions
{ Fixture.stringifyNumbers = True
}
}
]
)
tests
--------------------------------------------------------------------------------
-- Schema
schema :: [Schema.Table]
schema =
[ (table "author")
{ tableColumns =
[ Schema.column "id" Schema.TInt,
Schema.column "name" Schema.TStr,
Schema.columnNull "genre" Schema.TStr,
Schema.column "age" Schema.TInt
],
tablePrimaryKey = ["id"],
tableData =
[ [Schema.VInt 1, Schema.VStr "Alice", Schema.VStr "Action", Schema.VInt 25],
[Schema.VInt 2, Schema.VStr "Bob", Schema.VStr "Biography", Schema.VInt 40],
[Schema.VInt 3, Schema.VStr "Carol", Schema.VStr "Crime", Schema.VInt 35],
[Schema.VInt 4, Schema.VStr "Dave", Schema.VStr "Action", Schema.VInt 30],
[Schema.VInt 5, Schema.VStr "Eve", Schema.VStr "Crime", Schema.VInt 25],
[Schema.VInt 6, Schema.VStr "Bart", Schema.VNull, Schema.VInt 25]
]
}
]
--------------------------------------------------------------------------------
-- Tests
-- We specify the nulls ordering because the behaviour is not consistent between
-- postgres and cockroach.
--
-- For postgres and citus:
-- - @asc_nulls_last@ is the behaviour of @asc@
-- - @desc_nulls_first@ is the behaviour of @desc@
--
-- For cockroach, it's the opposite:
-- - @asc_nulls_first@ is the behaviour of @asc@
-- - @desc_nulls_last@ is the behaviour of @desc@
tests :: Fixture.Options -> SpecWith TestEnvironment
tests opts = do
let shouldBe :: IO Value -> Value -> IO ()
shouldBe = shouldReturnYaml opts
it "Find the oldest writer of each genre - nulls last" \testEnvironment -> do
let schemaName :: Schema.SchemaName
schemaName = Schema.getSchemaName testEnvironment
actual :: IO Value
actual =
postGraphql
testEnvironment
[graphql|
query {
#{schemaName}_author (
distinct_on: [genre],
order_by: [ { genre: asc_nulls_last }, { age: desc }, { id: asc } ]
) {
id
name
}
}
|]
expected :: Value
expected =
[interpolateYaml|
data:
#{schemaName}_author:
- id: 4
name: Dave
- id: 2
name: Bob
- id: 3
name: Carol
- id: 6
name: Bart
|]
actual `shouldBe` expected
it "Find the oldest writer of each genre - nulls first" \testEnvironment -> do
let schemaName :: Schema.SchemaName
schemaName = Schema.getSchemaName testEnvironment
actual :: IO Value
actual =
postGraphql
testEnvironment
[graphql|
query {
#{schemaName}_author (
distinct_on: [genre],
order_by: [ { genre: asc_nulls_first }, { age: desc }, { id: asc } ]
) {
id
name
}
}
|]
expected :: Value
expected =
[interpolateYaml|
data:
#{schemaName}_author:
- id: 6
name: Bart
- id: 4
name: Dave
- id: 2
name: Bob
- id: 3
name: Carol
|]
actual `shouldBe` expected

View File

@ -61,7 +61,13 @@ run_ :: HasCallStack => String -> IO ()
run_ query = do
void $
runWithRetry
(\conn -> (Execute.executeBigQuery conn Execute.BigQuery {Execute.query = fromString query, Execute.parameters = mempty}))
( \conn -> do
res <-
Execute.executeBigQuery
conn
Execute.BigQuery {Execute.query = fromString query, Execute.parameters = mempty}
onLeft res \x -> liftIO (bigQueryError x query)
)
bigQueryError :: HasCallStack => Execute.ExecuteProblem -> String -> IO a
bigQueryError e query =
@ -85,7 +91,7 @@ removeDataset schemaName =
void $ runWithRetry (\conn -> Execute.deleteDataset conn $ unSchemaName schemaName)
-- | Serialize Table into a SQL statement, as needed, and execute it on the BigQuery backend
createTable :: SchemaName -> Schema.Table -> IO ()
createTable :: HasCallStack => SchemaName -> Schema.Table -> IO ()
createTable schemaName table@Schema.Table {tableName, tableColumns} = do
run_ $
T.unpack $
@ -149,7 +155,7 @@ serialize = \case
VCustomValue bsv -> Schema.formatBackendScalarValueType $ Schema.backendScalarValue bsv bsvBigQuery
-- | Serialize Table into an SQL DROP statement and execute it
dropTable :: SchemaName -> Schema.Table -> IO ()
dropTable :: HasCallStack => SchemaName -> Schema.Table -> IO ()
dropTable schemaName Schema.Table {tableName} = do
run_ $
T.unpack $
@ -193,7 +199,7 @@ untrackTable testEnvironment schemaName Schema.Table {tableName} = do
-- | Setup the schema in the most expected way.
-- NOTE: Certain test modules may warrant having their own local version.
setup :: [Schema.Table] -> (TestEnvironment, ()) -> IO ()
setup :: HasCallStack => [Schema.Table] -> (TestEnvironment, ()) -> IO ()
setup tables' (testEnvironment, _) = do
let source = defaultSource BigQuery
backendType = defaultBackendTypeString BigQuery
@ -249,24 +255,24 @@ teardown (reverse -> tables) (testEnvironment, _) = do
-- remove test dataset
(removeDataset schemaName)
setupTablesAction :: [Schema.Table] -> TestEnvironment -> SetupAction
setupTablesAction :: HasCallStack => [Schema.Table] -> TestEnvironment -> SetupAction
setupTablesAction ts env =
SetupAction
(setup ts (env, ()))
(const $ teardown ts (env, ()))
setupPermissionsAction :: [Permissions.Permission] -> TestEnvironment -> SetupAction
setupPermissionsAction :: HasCallStack => [Permissions.Permission] -> TestEnvironment -> SetupAction
setupPermissionsAction permissions env =
SetupAction
(setupPermissions permissions env)
(const $ teardownPermissions permissions env)
-- | Setup the given permissions to the graphql engine in a TestEnvironment.
setupPermissions :: [Permissions.Permission] -> TestEnvironment -> IO ()
setupPermissions :: HasCallStack => [Permissions.Permission] -> TestEnvironment -> IO ()
setupPermissions permissions env = Permissions.setup BigQuery permissions env
-- | Remove the given permissions from the graphql engine in a TestEnvironment.
teardownPermissions :: [Permissions.Permission] -> TestEnvironment -> IO ()
teardownPermissions :: HasCallStack => [Permissions.Permission] -> TestEnvironment -> IO ()
teardownPermissions permissions env = Permissions.teardown BigQuery permissions env
-- | We get @jobRateLimitExceeded@ errors from BigQuery if we run too many DML operations in short intervals.