graphql-engine/server/tests-hspec/Test/ObjectRelationshipsSpec.hs
2022-02-21 17:06:04 +00:00

284 lines
5.8 KiB
Haskell

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
-- | Testing object relationships.
module Test.ObjectRelationshipsSpec (spec) where
import Data.Text (Text)
import Harness.Backend.Mysql qualified as Mysql
import Harness.Backend.Sqlserver qualified as Sqlserver
import Harness.GraphqlEngine qualified as GraphqlEngine
import Harness.Quoter.Graphql
import Harness.Quoter.Sql
import Harness.Quoter.Yaml
import Harness.State (State)
import Harness.Test.Context qualified as Context
import Test.Hspec
import Prelude
--------------------------------------------------------------------------------
-- Preamble
spec :: SpecWith State
spec = do
Context.run
[ Context.Context
{ name = Context.SQLServer,
mkLocalState = Context.noLocalState,
setup = mssqlSetup,
teardown = \_ -> mssqlTeardown,
customOptions = Nothing
}
]
mssqlTests
Context.run
[ Context.Context
{ name = Context.MySQL,
mkLocalState = Context.noLocalState,
setup = mysqlSetup,
teardown = \_ -> mysqlTeardown,
customOptions = Nothing
}
]
mysqlTests
-- Tests
mysqlTests :: Context.Options -> SpecWith State
mysqlTests opts = do
usingWhereClause opts
xdescribe
"Pending: The MySQL backend currently fails with relationship fields that are null.\
\ (https://github.com/hasura/graphql-engine-mono/issues/3650)"
(nullField opts)
mssqlTests :: Context.Options -> SpecWith State
mssqlTests opts = do
usingWhereClause opts
nullField opts
usingWhereClause :: Context.Options -> SpecWith State
usingWhereClause opts = do
it "Author of article where id=1" $ \state ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
state
[graphql|
query {
hasura_article(where: {id: {_eq: 1}}) {
id
author {
id
}
}
}
|]
)
[yaml|
data:
hasura_article:
- id: 1
author:
id: 1
|]
nullField :: Context.Options -> SpecWith State
nullField opts = do
it "Can realise a null relationship field" $ \state ->
shouldReturnYaml
opts
( GraphqlEngine.postGraphql
state
[graphql|
query {
hasura_article(where: {id: {_eq: 4}}) {
id
author {
id
}
}
}
|]
)
[yaml|
data:
hasura_article:
- author: null
id: 4
|]
--------------------------------------------------------------------------------
-- Unified test setup/teardown definitions
trackTableAuthor :: Text -> State -> IO ()
trackTableAuthor backendSource state = do
let requestType = backendSource <> "_track_table"
GraphqlEngine.post_
state
"/v1/metadata"
[yaml|
type: *requestType
args:
source: *backendSource
table:
schema: hasura
name: author
|]
trackTableArticle :: Text -> State -> IO ()
trackTableArticle backendSource state = do
let requestType = backendSource <> "_track_table"
GraphqlEngine.post_
state
"/v1/metadata"
[yaml|
type: *requestType
args:
source: *backendSource
table:
schema: hasura
name: article
|]
trackRelationshipArticleAuthor :: Text -> State -> IO ()
trackRelationshipArticleAuthor backendSource state = do
let requestType = backendSource <> "_create_object_relationship"
GraphqlEngine.post_
state
"/v1/metadata"
[yaml|
type: *requestType
args:
source: *backendSource
table:
name: article
schema: hasura
name: author
using:
foreign_key_constraint_on: author_id
|]
--------------------------------------------------------------------------------
-- MySQL backend
mysqlSetup :: (State, ()) -> IO ()
mysqlSetup (state, _) = do
-- Clear and reconfigure the metadata
GraphqlEngine.setSource state Mysql.defaultSourceMetadata
mysqlCreateTableAuthor
mysqlCreateTableArticle
trackTableAuthor "mysql" state
trackTableArticle "mysql" state
trackRelationshipArticleAuthor "mysql" state
mysqlCreateTableAuthor :: IO ()
mysqlCreateTableAuthor = do
Mysql.run_
[sql|
CREATE TABLE author
(
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(45) UNIQUE KEY
);
|]
Mysql.run_
[sql|
INSERT INTO author
(name)
VALUES
( 'Author 1' ),
( 'Author 2' );
|]
mysqlCreateTableArticle :: IO ()
mysqlCreateTableArticle = do
Mysql.run_
[sql|
CREATE TABLE article (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
author_id INT UNSIGNED,
FOREIGN KEY (author_id) REFERENCES author(id)
);
|]
Mysql.run_
[sql|
INSERT INTO article
(author_id)
VALUES
( 1 ),
( 1 ),
( 2 ),
( null );
|]
mysqlTeardown :: IO ()
mysqlTeardown = do
Mysql.run_ [sql| DROP TABLE article; |]
Mysql.run_ [sql| DROP TABLE author; |]
--------------------------------------------------------------------------------
-- MSSQL backend
mssqlSetup :: (State, ()) -> IO ()
mssqlSetup (state, _) = do
-- Clear and reconfigure the metadata
GraphqlEngine.setSource state Sqlserver.defaultSourceMetadata
mssqlCreateTableAuthor
mssqlCreateTableArticle
trackTableAuthor "mssql" state
trackTableArticle "mssql" state
trackRelationshipArticleAuthor "mssql" state
mssqlCreateTableAuthor :: IO ()
mssqlCreateTableAuthor = do
Sqlserver.run_
[sql|
CREATE TABLE author
(
id INT IDENTITY PRIMARY KEY,
name VARCHAR(45) UNIQUE
);
|]
Sqlserver.run_
[sql|
INSERT INTO author
(name)
VALUES
( 'Author 1' ),
( 'Author 2' );
|]
-- Setup tables
mssqlCreateTableArticle :: IO ()
mssqlCreateTableArticle = do
Sqlserver.run_
[sql|
CREATE TABLE article
(
id INT IDENTITY PRIMARY KEY,
author_id INT ,
FOREIGN KEY (author_id) REFERENCES author(id)
);
|]
Sqlserver.run_
[sql|
INSERT INTO article
(author_id)
VALUES
( 1 ),
( 1 ),
( 2 ),
( null );
|]
mssqlTeardown :: IO ()
mssqlTeardown = do
Sqlserver.run_ [sql| DROP TABLE article; |]
Sqlserver.run_ [sql| DROP TABLE author; |]