mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-08-16 14:10:30 +03:00
Use Dataset Clones for all SQLite tests
[GDC-718]: https://hasurahq.atlassian.net/browse/GDC-718?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7743 GitOrigin-RevId: 6c3577c1d4ffd2212a72b6e1a24e0e384f2db046
This commit is contained in:
parent
1fe7fe43b8
commit
b012f2ebc7
@ -25,12 +25,13 @@ services:
|
||||
ports:
|
||||
- "65007:8100"
|
||||
volumes:
|
||||
- "./sqlite/test/db.chinook.sqlite:/db.chinook.sqlite"
|
||||
- "./sqlite/test/db.sqlite:/db.sqlite"
|
||||
- "./sqlite/dataset_templates:/app/sqlite/dataset_templates"
|
||||
environment:
|
||||
METRICS: y
|
||||
PRETTY_PRINT_LOGS: y
|
||||
LOG_LEVEL: debug
|
||||
DATASETS: y
|
||||
DATASET_DELETE: y
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
|
@ -69,7 +69,7 @@ services:
|
||||
depends_on:
|
||||
- reference-agent
|
||||
image: "hasura/dc-agent-tests:${HASURA_VERSION}"
|
||||
command: ["tests-dc-api", 'test', '-u', 'http://reference-agent:8100', '-s', '{}']
|
||||
command: ["tests-dc-api", 'test', '--agent-base-url', 'http://reference-agent:8100']
|
||||
restart: on-failure
|
||||
|
||||
swagger-ui:
|
||||
|
2
dc-agents/sqlite/.gitignore
vendored
2
dc-agents/sqlite/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
node_modules
|
||||
dist
|
||||
./*.sqlite
|
||||
./dataset_clones/
|
||||
dataset_clones/
|
||||
|
Binary file not shown.
Binary file not shown.
@ -66,7 +66,7 @@ function mkTemplatePath(name: string): string {
|
||||
if(name != safeName) {
|
||||
throw(Error(`Template name ${name} is not valid.`));
|
||||
}
|
||||
return path.join(DATASET_TEMPLATES, safeName);
|
||||
return path.join(DATASET_TEMPLATES, safeName + ".sqlite");
|
||||
}
|
||||
|
||||
function mkClonePath(name: string): string {
|
||||
@ -75,5 +75,5 @@ function mkClonePath(name: string): string {
|
||||
if(name != safeName) {
|
||||
throw(Error(`Template name ${name} is not valid.`));
|
||||
}
|
||||
return path.join(DATASET_CLONES, safeName);
|
||||
return path.join(DATASET_CLONES, safeName + ".sqlite");
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ addSource =
|
||||
name: myfoobar
|
||||
replace_configuration: false
|
||||
configuration:
|
||||
db: /db.chinook.sqlite
|
||||
value: {}
|
||||
|]
|
||||
|
||||
listSourceKinds :: Value
|
||||
|
@ -13,13 +13,11 @@ import Data.Aeson qualified as Aeson
|
||||
import Data.Aeson.Lens (key, _Array)
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Data.Vector qualified as Vector
|
||||
import Harness.Backend.DataConnector.Chinook qualified as Chinook
|
||||
import Harness.Backend.DataConnector.Chinook.Reference qualified as Reference
|
||||
import Harness.Backend.DataConnector.Chinook.Sqlite qualified as Sqlite
|
||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||
import Harness.Quoter.Graphql (graphql)
|
||||
import Harness.Quoter.Yaml (yaml)
|
||||
import Harness.Test.BackendType (BackendTypeConfig)
|
||||
import Harness.Test.Fixture qualified as Fixture
|
||||
import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment)
|
||||
import Harness.TestEnvironment qualified as TE
|
||||
@ -33,67 +31,14 @@ spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.runWithLocalTestEnvironment
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Reference.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Chinook.setupAction (sourceMetadata Reference.backendTypeMetadata Reference.sourceConfiguration) Reference.agentConfig testEnvironment
|
||||
]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Sqlite.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnvironment, _) ->
|
||||
[ Chinook.setupAction (sourceMetadata Sqlite.backendTypeMetadata Sqlite.sourceConfiguration) Sqlite.agentConfig testEnvironment
|
||||
]
|
||||
}
|
||||
[ Reference.chinookFixture,
|
||||
Sqlite.chinookFixture
|
||||
]
|
||||
)
|
||||
tests
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
sourceMetadata :: BackendTypeConfig -> Aeson.Value -> Aeson.Value
|
||||
sourceMetadata backendTypeMetadata config =
|
||||
let source = Fixture.backendSourceName backendTypeMetadata
|
||||
backendTypeString = Fixture.backendTypeString backendTypeMetadata
|
||||
in [yaml|
|
||||
name : *source
|
||||
kind: *backendTypeString
|
||||
tables:
|
||||
- table: [Album]
|
||||
object_relationships:
|
||||
- name: Artist
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [Artist]
|
||||
column_mapping:
|
||||
ArtistId: ArtistId
|
||||
- table: [Artist]
|
||||
array_relationships:
|
||||
- name: Albums
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [Album]
|
||||
column_mapping:
|
||||
ArtistId: ArtistId
|
||||
- table: [Invoice]
|
||||
array_relationships:
|
||||
- name: InvoiceLines
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [InvoiceLine]
|
||||
column_mapping:
|
||||
InvoiceId: InvoiceId
|
||||
- table: [InvoiceLine]
|
||||
object_relationships:
|
||||
- name: Invoice
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [Invoice]
|
||||
column_mapping:
|
||||
InvoiceId: InvoiceId
|
||||
configuration: *config
|
||||
|]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
tests :: Fixture.Options -> SpecWith (TestEnvironment, a)
|
||||
tests opts = describe "Aggregate Query Tests" $ do
|
||||
nodeTests opts
|
||||
|
@ -22,7 +22,7 @@ import Data.Aeson.KeyMap qualified as KM
|
||||
import Data.Aeson.Lens
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Data.Vector qualified as Vector
|
||||
import Harness.Backend.DataConnector.Chinook (ChinookTestEnv)
|
||||
import Harness.Backend.DataConnector.Chinook (ChinookTestEnv, NameFormatting (..))
|
||||
import Harness.Backend.DataConnector.Chinook qualified as Chinook
|
||||
import Harness.Backend.DataConnector.Chinook.Reference qualified as Reference
|
||||
import Harness.Backend.DataConnector.Chinook.Sqlite qualified as Sqlite
|
||||
@ -47,15 +47,15 @@ spec = do
|
||||
Fixture.runWithLocalTestEnvironmentSingleSetup
|
||||
( NE.fromList
|
||||
[ Fixture
|
||||
{ name = Fixture.Backend Reference.backendTypeMetadata,
|
||||
mkLocalTestEnvironment = \_ -> pure $ Chinook.ChinookTestEnv Reference.sourceConfiguration id id id,
|
||||
{ name = Fixture.Backend Reference.backendTypeConfig,
|
||||
mkLocalTestEnvironment = Reference.mkChinookStaticTestEnvironment,
|
||||
setupTeardown = \(testEnv, _localEnv) ->
|
||||
[emptySetupAction testEnv],
|
||||
customOptions = Nothing
|
||||
},
|
||||
Fixture
|
||||
{ name = Fixture.Backend Sqlite.backendTypeMetadata,
|
||||
mkLocalTestEnvironment = \_ -> pure $ Chinook.ChinookTestEnv Sqlite.sourceConfiguration id id Sqlite.formatForeignKeyName,
|
||||
{ name = Fixture.Backend Sqlite.backendTypeConfig,
|
||||
mkLocalTestEnvironment = Sqlite.mkChinookCloneTestEnvironment,
|
||||
setupTeardown = \(testEnv, _localEnv) ->
|
||||
[emptySetupAction testEnv],
|
||||
customOptions = Nothing
|
||||
@ -66,20 +66,8 @@ spec = do
|
||||
|
||||
Fixture.runWithLocalTestEnvironmentSingleSetup
|
||||
( NE.fromList
|
||||
[ Fixture
|
||||
{ name = Fixture.Backend Reference.backendTypeMetadata,
|
||||
mkLocalTestEnvironment = \_ -> pure $ Chinook.ChinookTestEnv Reference.sourceConfiguration id id id,
|
||||
setupTeardown = \(testEnv, _localEnv) ->
|
||||
[Chinook.setupAction Chinook.referenceSourceConfig Reference.agentConfig testEnv],
|
||||
customOptions = Nothing
|
||||
},
|
||||
Fixture
|
||||
{ name = Fixture.Backend Sqlite.backendTypeMetadata,
|
||||
mkLocalTestEnvironment = \_ -> pure $ Chinook.ChinookTestEnv Sqlite.sourceConfiguration id id Sqlite.formatForeignKeyName,
|
||||
setupTeardown = \(testEnv, _localEnv) ->
|
||||
[Chinook.setupAction Chinook.sqliteSourceConfig Sqlite.agentConfig testEnv],
|
||||
customOptions = Nothing
|
||||
}
|
||||
[ Reference.chinookFixture,
|
||||
Sqlite.chinookFixture
|
||||
]
|
||||
)
|
||||
schemaInspectionTests
|
||||
@ -89,7 +77,7 @@ spec = do
|
||||
schemaInspectionTests :: Fixture.Options -> SpecWith (TestEnvironment, ChinookTestEnv)
|
||||
schemaInspectionTests opts = describe "Schema and Source Inspection" $ do
|
||||
describe "get_source_tables" $ do
|
||||
it "success" $ \(testEnvironment, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
let sortYamlArray :: J.Value -> IO J.Value
|
||||
sortYamlArray (J.Array a) = pure $ J.Array (Vector.fromList (sort (Vector.toList a)))
|
||||
sortYamlArray _ = fail "Should return Array"
|
||||
@ -97,17 +85,17 @@ schemaInspectionTests opts = describe "Schema and Source Inspection" $ do
|
||||
case BackendType.backendSourceName <$> getBackendTypeConfig testEnvironment of
|
||||
Nothing -> pendingWith "Backend not found for testEnvironment"
|
||||
Just sourceString -> do
|
||||
let album = formatTableName ["Album"]
|
||||
artist = formatTableName ["Artist"]
|
||||
customer = formatTableName ["Customer"]
|
||||
employee = formatTableName ["Employee"]
|
||||
genre = formatTableName ["Genre"]
|
||||
invoice = formatTableName ["Invoice"]
|
||||
invoiceLine = formatTableName ["InvoiceLine"]
|
||||
mediaType = formatTableName ["MediaType"]
|
||||
playlist = formatTableName ["Playlist"]
|
||||
playlistTrack = formatTableName ["PlaylistTrack"]
|
||||
track = formatTableName ["Track"]
|
||||
let album = _nfFormatTableName ["Album"]
|
||||
artist = _nfFormatTableName ["Artist"]
|
||||
customer = _nfFormatTableName ["Customer"]
|
||||
employee = _nfFormatTableName ["Employee"]
|
||||
genre = _nfFormatTableName ["Genre"]
|
||||
invoice = _nfFormatTableName ["Invoice"]
|
||||
invoiceLine = _nfFormatTableName ["InvoiceLine"]
|
||||
mediaType = _nfFormatTableName ["MediaType"]
|
||||
playlist = _nfFormatTableName ["Playlist"]
|
||||
playlistTrack = _nfFormatTableName ["PlaylistTrack"]
|
||||
track = _nfFormatTableName ["Track"]
|
||||
shouldReturnYamlF
|
||||
sortYamlArray
|
||||
opts
|
||||
@ -134,7 +122,7 @@ schemaInspectionTests opts = describe "Schema and Source Inspection" $ do
|
||||
|]
|
||||
|
||||
describe "get_table_info" $ do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
let removeDescriptions (J.Object o) = J.Object (KM.delete "description" (removeDescriptions <$> o))
|
||||
removeDescriptions (J.Array a) = J.Array (removeDescriptions <$> a)
|
||||
removeDescriptions x = x
|
||||
@ -153,12 +141,12 @@ schemaInspectionTests opts = describe "Schema and Source Inspection" $ do
|
||||
case BackendType.backendSourceName <$> getBackendTypeConfig testEnvironment of
|
||||
Nothing -> pendingWith "Backend not found for testEnvironment"
|
||||
Just sourceString -> do
|
||||
let album = formatTableName ["Album"]
|
||||
artist = formatTableName ["Artist"]
|
||||
albumId = formatColumnName "AlbumId"
|
||||
artistId = formatColumnName "ArtistId"
|
||||
title = formatColumnName "Title"
|
||||
artistForeignKeys = formatForeignKeyName "Artist"
|
||||
let album = _nfFormatTableName ["Album"]
|
||||
artist = _nfFormatTableName ["Artist"]
|
||||
albumId = _nfFormatColumnName "AlbumId"
|
||||
artistId = _nfFormatColumnName "ArtistId"
|
||||
title = _nfFormatColumnName "Title"
|
||||
artistForeignKeys = _nfFormatForeignKeyName "Artist"
|
||||
shouldReturnYamlF
|
||||
(pure . removeDescriptions)
|
||||
opts
|
||||
@ -341,12 +329,12 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
|]
|
||||
|
||||
describe "<kind>_track_table" $ do
|
||||
it "success" $ \(testEnvironment, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
case (backendTypeString &&& backendSourceName) <$> TestEnvironment.getBackendTypeConfig testEnvironment of
|
||||
Nothing -> pendingWith "Backend Type not found in testEnvironment"
|
||||
Just (backendType, sourceName) -> do
|
||||
let actionType = backendType <> "_track_table"
|
||||
album = formatTableName ["Album"]
|
||||
album = _nfFormatTableName ["Album"]
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postMetadata
|
||||
@ -363,15 +351,15 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
|]
|
||||
|
||||
describe "<kind>_create_object_relationship" $ do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
let foreignKeySupport = (getBackendTypeConfig testEnvironment >>= BackendType.parseCapabilities) <&> API._dscSupportsForeignKeys . API._cDataSchema
|
||||
case (backendTypeString &&& backendSourceName) <$> getBackendTypeConfig testEnvironment of
|
||||
Nothing -> pendingWith "Backend Type not found in testEnvironment"
|
||||
Just (backendType, sourceName) -> do
|
||||
let actionType = backendType <> "_track_table"
|
||||
artistTable = formatTableName ["Artist"]
|
||||
albumTable = formatTableName ["Album"]
|
||||
artistId = formatColumnName "ArtistId"
|
||||
artistTable = _nfFormatTableName ["Artist"]
|
||||
albumTable = _nfFormatTableName ["Album"]
|
||||
artistId = _nfFormatColumnName "ArtistId"
|
||||
GraphqlEngine.postMetadata_
|
||||
testEnvironment
|
||||
[yaml|
|
||||
@ -406,7 +394,7 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
|]
|
||||
|
||||
describe "<kind>_create_array_relationship" $ do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
let foreignKeySupport = (getBackendTypeConfig testEnvironment >>= BackendType.parseCapabilities) <&> API._dscSupportsForeignKeys . API._cDataSchema
|
||||
when
|
||||
(foreignKeySupport == Just False)
|
||||
@ -415,9 +403,9 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
Nothing -> pendingWith "Backend Type not found in testEnvironment"
|
||||
Just (backendType, sourceName) -> do
|
||||
let actionType = backendType <> "_create_array_relationship"
|
||||
albumTable = formatTableName ["Album"]
|
||||
artistTable = formatTableName ["Artist"]
|
||||
artistId = formatColumnName "ArtistId"
|
||||
albumTable = _nfFormatTableName ["Album"]
|
||||
artistTable = _nfFormatTableName ["Artist"]
|
||||
artistId = _nfFormatColumnName "ArtistId"
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postMetadata
|
||||
@ -440,14 +428,14 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
|]
|
||||
|
||||
describe "export_metadata" $ do
|
||||
it "produces the expected metadata structure" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "produces the expected metadata structure" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}, ..}) -> do
|
||||
case ((fold . backendServerUrl) &&& backendTypeString &&& backendSourceName) <$> TestEnvironment.getBackendTypeConfig testEnvironment of
|
||||
Nothing -> pendingWith "Backend Type not found in testEnvironment"
|
||||
Just (agentUrl, (backendType, sourceName)) -> do
|
||||
let foreignKeySupport = (getBackendTypeConfig testEnvironment >>= BackendType.parseCapabilities) <&> API._dscSupportsForeignKeys . API._cDataSchema
|
||||
albumTable = formatTableName ["Album"]
|
||||
artistTable = formatTableName ["Artist"]
|
||||
artistId = formatColumnName "ArtistId"
|
||||
albumTable = _nfFormatTableName ["Album"]
|
||||
artistTable = _nfFormatTableName ["Artist"]
|
||||
artistId = _nfFormatColumnName "ArtistId"
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postMetadata
|
||||
@ -500,7 +488,7 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
|]
|
||||
|
||||
describe "<kind>_drop_relationship" $ do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
let foreignKeySupport = (getBackendTypeConfig testEnvironment >>= BackendType.parseCapabilities) <&> API._dscSupportsForeignKeys . API._cDataSchema
|
||||
when
|
||||
(foreignKeySupport == Just False)
|
||||
@ -509,7 +497,7 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
Nothing -> pendingWith "Backend Type not found in testEnvironment"
|
||||
Just (backendType, sourceName) -> do
|
||||
let actionType = backendType <> "_drop_relationship"
|
||||
artistTable = formatTableName ["Artist"]
|
||||
artistTable = _nfFormatTableName ["Artist"]
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postMetadata
|
||||
@ -527,7 +515,7 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
|]
|
||||
|
||||
describe "<kind>_untrack_table" $ do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {..}) -> do
|
||||
it "success" $ \(testEnvironment@TestEnvironment {}, Chinook.ChinookTestEnv {nameFormatting = NameFormatting {..}}) -> do
|
||||
let foreignKeySupport = (getBackendTypeConfig testEnvironment >>= BackendType.parseCapabilities) <&> API._dscSupportsForeignKeys . API._cDataSchema
|
||||
when
|
||||
(foreignKeySupport == Just False)
|
||||
@ -536,7 +524,7 @@ schemaCrudTests opts = describe "A series of actions to setup and teardown a sou
|
||||
Nothing -> pendingWith "Backend Type not found in testEnvironment"
|
||||
Just (backendType, sourceName) -> do
|
||||
let actionType = backendType <> "_untrack_table"
|
||||
artistTable = formatTableName ["Artist"]
|
||||
artistTable = _nfFormatTableName ["Artist"]
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postMetadata
|
||||
|
@ -25,7 +25,6 @@ where
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Harness.Backend.DataConnector.Chinook qualified as Chinook
|
||||
import Harness.Backend.DataConnector.Chinook.Reference qualified as Reference
|
||||
import Harness.Backend.DataConnector.Chinook.Sqlite qualified as Sqlite
|
||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||
@ -46,14 +45,8 @@ spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.runWithLocalTestEnvironment
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Reference.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnv, _) ->
|
||||
[Chinook.setupAction Chinook.referenceSourceConfig Reference.agentConfig testEnv]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Sqlite.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnv, _) ->
|
||||
[Chinook.setupAction Chinook.sqliteSourceConfig Sqlite.agentConfig testEnv]
|
||||
}
|
||||
[ Reference.chinookFixture,
|
||||
Sqlite.chinookFixture
|
||||
]
|
||||
)
|
||||
tests
|
||||
@ -169,7 +162,7 @@ paginationTests :: Fixture.Options -> SpecWith (TestEnvironment, a)
|
||||
paginationTests opts =
|
||||
describe "Pagination" $ do
|
||||
it "works with pagination" $ \(testEnvironment, _) -> do
|
||||
-- NOTE: We order by in this pagination test to ensure that the rows are ordered correctly (which they are not in db.chinook.sqlite)
|
||||
-- NOTE: We order by in this pagination test to ensure that the rows are ordered correctly (which they are not in Sqlite Chinook)
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postGraphql
|
||||
|
@ -24,14 +24,8 @@ spec :: SpecWith GlobalTestEnvironment
|
||||
spec =
|
||||
Fixture.runWithLocalTestEnvironment
|
||||
( NE.fromList
|
||||
[ (Fixture.fixture $ Fixture.Backend Reference.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnv, _) ->
|
||||
[Chinook.setupAction Chinook.referenceSourceConfig Reference.agentConfig testEnv]
|
||||
},
|
||||
(Fixture.fixture $ Fixture.Backend Sqlite.backendTypeMetadata)
|
||||
{ Fixture.setupTeardown = \(testEnv, _) ->
|
||||
[Chinook.setupAction Chinook.sqliteSourceConfig Sqlite.agentConfig testEnv]
|
||||
}
|
||||
[ Reference.chinookFixture,
|
||||
Sqlite.chinookFixture
|
||||
]
|
||||
)
|
||||
tests
|
||||
|
@ -10,6 +10,7 @@ module Command
|
||||
SandwichArguments (..),
|
||||
TestConfig (..),
|
||||
AgentOptions (..),
|
||||
AgentConfig (..),
|
||||
NameCasing (..),
|
||||
ExportDataConfig (..),
|
||||
ExportFormat (..),
|
||||
@ -55,9 +56,13 @@ data SensitiveOutputHandling
|
||||
|
||||
data AgentOptions = AgentOptions
|
||||
{ _aoAgentBaseUrl :: BaseUrl,
|
||||
_aoAgentConfig :: Maybe API.Config
|
||||
_aoAgentConfig :: AgentConfig
|
||||
}
|
||||
|
||||
data AgentConfig
|
||||
= ManualConfig API.Config
|
||||
| DatasetConfig (Maybe API.Config)
|
||||
|
||||
data NameCasing
|
||||
= PascalCase
|
||||
| Lowercase
|
||||
@ -181,15 +186,23 @@ agentOptionsParser =
|
||||
<> metavar "URL"
|
||||
<> help "The base URL of the Data Connector agent to be tested"
|
||||
)
|
||||
<*> optional
|
||||
( option
|
||||
configValue
|
||||
( long "agent-config"
|
||||
<> short 's'
|
||||
<> metavar "JSON"
|
||||
<> help "The configuration JSON to be sent to the agent via the X-Hasura-DataConnector-Config header. If omitted, datasets will be used to load test data and provide this configuration dynamically"
|
||||
)
|
||||
)
|
||||
<*> ( ManualConfig
|
||||
<$> option
|
||||
configValue
|
||||
( long "agent-config"
|
||||
<> metavar "JSON"
|
||||
<> help "The configuration JSON to be sent to the agent via the X-Hasura-DataConnector-Config header. If omitted, datasets will be used to load test data and provide this configuration dynamically"
|
||||
)
|
||||
<|> DatasetConfig
|
||||
<$> optional
|
||||
( option
|
||||
configValue
|
||||
( long "merge-agent-config"
|
||||
<> metavar "JSON"
|
||||
<> help "Datasets will be used to load test data and provide configuration JSON to be sent to the agent via the X-Hasura-DataConnector-Config header. This config will be merged with the dataset-provided config before being sent to the agent."
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
exportDataConfigParser :: Parser ExportDataConfig
|
||||
exportDataConfigParser =
|
||||
|
@ -2,7 +2,7 @@ module Main (main) where
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Command (AgentOptions (..), Command (..), SandwichArguments (..), TestOptions (..), parseCommandLine)
|
||||
import Command (AgentConfig (..), AgentOptions (..), Command (..), SandwichArguments (..), TestOptions (..), parseCommandLine)
|
||||
import Control.Exception (bracket)
|
||||
import Data.Aeson.Text (encodeToLazyText)
|
||||
import Data.Foldable (for_)
|
||||
@ -12,7 +12,7 @@ import Hasura.Backends.DataConnector.API (openApiSchema)
|
||||
import Hasura.Backends.DataConnector.API qualified as API
|
||||
import Servant.Client ((//))
|
||||
import System.Environment (withArgs)
|
||||
import Test.AgentAPI (guardCapabilitiesResponse, guardSchemaResponse)
|
||||
import Test.AgentAPI (guardCapabilitiesResponse, guardSchemaResponse, mergeAgentConfig)
|
||||
import Test.AgentClient (AgentIOClient (..), introduceAgentClient, mkAgentClientConfig, mkAgentIOClient)
|
||||
import Test.AgentDatasets (DatasetCloneInfo (..), chinookTemplate, createClone, deleteClone, usesDataset)
|
||||
import Test.AgentTestContext (AgentTestContext (..), introduceAgentTestContext)
|
||||
@ -46,18 +46,18 @@ tests testData capabilitiesResponse@API.CapabilitiesResponse {..} = do
|
||||
for_ (API._cMetrics _crCapabilities) \m -> Test.Specs.MetricsSpec.spec m
|
||||
for_ (API._cExplain _crCapabilities) \_ -> Test.Specs.ExplainSpec.spec testData _crCapabilities
|
||||
|
||||
getChinookSchema :: API.Capabilities -> Maybe API.Config -> AgentIOClient -> IO API.SchemaResponse
|
||||
getChinookSchema :: API.Capabilities -> AgentConfig -> AgentIOClient -> IO API.SchemaResponse
|
||||
getChinookSchema API.Capabilities {..} manuallyProvidedConfig (AgentIOClient agentClient) = do
|
||||
case manuallyProvidedConfig of
|
||||
Just config -> (agentClient // API._schema) testSourceName config >>= guardSchemaResponse
|
||||
Nothing ->
|
||||
ManualConfig config -> (agentClient // API._schema) testSourceName config >>= guardSchemaResponse
|
||||
DatasetConfig mergeConfig ->
|
||||
if isJust _cDatasets
|
||||
then
|
||||
bracket
|
||||
(createClone agentClient chinookTemplate)
|
||||
(deleteClone agentClient)
|
||||
( \DatasetCloneInfo {..} ->
|
||||
(agentClient // API._schema) testSourceName _dciAgentConfig >>= guardSchemaResponse
|
||||
(agentClient // API._schema) testSourceName (mergeAgentConfig _dciAgentConfig mergeConfig) >>= guardSchemaResponse
|
||||
)
|
||||
else fail $ "The agent does not support datasets, therefore an agent configuration must be provided on the command line (--agent-config)"
|
||||
|
||||
|
@ -9,20 +9,22 @@ The executable also has the ability to export the OpenAPI spec of the Data Conne
|
||||
### Running Tests
|
||||
First, start your Data Connector agent and ensure it is populated with the [Chinook data set](https://github.com/lerocha/chinook-database/). For example, you could start the Reference Agent by following the instructions in [its README](../../dc-agents/reference/README.md).
|
||||
|
||||
To run the tests against the agent (for example), you must specify the agent's URL on the command line (`-u`), as well as the agent's configuration JSON (`-s`, sent in the `X-Hasura-DataConnector-Config` header):
|
||||
To run the tests against the agent (for example), you must specify the agent's URL on the command line (`--agent-base-url`), as well as the agent's configuration JSON (`--agent-config`, sent in the `X-Hasura-DataConnector-Config` header):
|
||||
|
||||
```
|
||||
cabal run test:tests-dc-api -- test -u "http://localhost:8100" -s '{}'
|
||||
cabal run test:tests-dc-api -- test --agent-base-url "http://localhost:8100" --agent-config '{}'
|
||||
```
|
||||
|
||||
The test suite will discover what capabilities the agent has by querying it. It will then tailor the tests that it will run to match only those capabilities that the agent has said it supports.
|
||||
|
||||
If your agent supports the datasets capability, you can omit the `--agent-config` argument and the test suite will clone the Chinook dataset template on the agent to run its test against. If you need to specify some additional configuration to be added to the cloned dataset's configuration, you can specify it using `--merge-agent-config`.
|
||||
|
||||
The test suite is implemented using the [Sandwich](https://codedownio.github.io/sandwich/) test framework. The standard Sandwich command line arguments can be passed by suffixing your command line with `sandwich` and then all following args will be passed to Sandwich.
|
||||
|
||||
For example, to run the Terminal UI mode of Sandwich, you could run:
|
||||
|
||||
```
|
||||
cabal run test:tests-dc-api -- test -u "http://localhost:8100" -s '{}' sandwich --tui
|
||||
cabal run test:tests-dc-api -- test --agent-base-url "http://localhost:8100" --agent-config '{}' sandwich --tui
|
||||
```
|
||||
|
||||
By default Sandwich will write test results into a `test_runs` folder. Every test has a folder that will contain debug information, for example:
|
||||
|
@ -21,12 +21,15 @@ module Test.AgentAPI
|
||||
explain,
|
||||
getMetrics,
|
||||
getSourceNameAndConfig,
|
||||
mergeAgentConfig,
|
||||
)
|
||||
where
|
||||
|
||||
import Command (AgentConfig (..))
|
||||
import Control.Monad.Catch (MonadThrow)
|
||||
import Control.Monad.IO.Class (MonadIO)
|
||||
import Control.Monad.Reader (MonadReader)
|
||||
import Data.Aeson.KeyMap qualified as KeyMap
|
||||
import Data.Maybe (isJust)
|
||||
import Data.Text (Text)
|
||||
import Hasura.Backends.DataConnector.API qualified as API
|
||||
@ -108,13 +111,20 @@ supportsDatasets = isJust . API._cDatasets . API._crCapabilities
|
||||
getSourceNameAndConfig :: (HasAgentTestContext context, HasDatasetContext context, MonadReader context m, MonadThrow m) => m (API.SourceName, API.Config)
|
||||
getSourceNameAndConfig = do
|
||||
AgentTestContext {..} <- getAgentTestContext
|
||||
case _atcManualConfig of
|
||||
Just config -> pure (_atcSourceName, config)
|
||||
Nothing ->
|
||||
case _atcAgentConfig of
|
||||
ManualConfig config -> pure (_atcSourceName, config)
|
||||
DatasetConfig mergeConfig ->
|
||||
if supportsDatasets _atcCapabilitiesResponse
|
||||
then do
|
||||
cloneInfo <- _dcClone <$> getDatasetContext
|
||||
case cloneInfo of
|
||||
Just DatasetCloneInfo {..} -> pure (_atcSourceName, _dciAgentConfig)
|
||||
Just DatasetCloneInfo {..} ->
|
||||
let mergedConfig = mergeAgentConfig _dciAgentConfig mergeConfig
|
||||
in pure (_atcSourceName, mergedConfig)
|
||||
Nothing -> expectationFailure "Expected a dataset clone to have been created, because the agent supports datasets, but one wasn't"
|
||||
else expectationFailure "An agent configuration is required to be provided if the agent does not support datasets"
|
||||
|
||||
mergeAgentConfig :: API.Config -> Maybe API.Config -> API.Config
|
||||
mergeAgentConfig (API.Config configA) mergeConfig =
|
||||
let configB = maybe mempty API.unConfig mergeConfig
|
||||
in API.Config $ KeyMap.union configA configB
|
||||
|
@ -8,6 +8,7 @@ module Test.AgentTestContext
|
||||
)
|
||||
where
|
||||
|
||||
import Command (AgentConfig)
|
||||
import Control.Monad.Reader.Class (MonadReader)
|
||||
import GHC.Stack (HasCallStack)
|
||||
import Hasura.Backends.DataConnector.API qualified as API
|
||||
@ -20,7 +21,7 @@ data AgentTestContext = AgentTestContext
|
||||
_atcCapabilitiesResponse :: API.CapabilitiesResponse,
|
||||
-- | This is the configuration passed by the user on the command line which will
|
||||
-- be used in preference to any dataset clone's config if it is specified
|
||||
_atcManualConfig :: Maybe API.Config
|
||||
_atcAgentConfig :: AgentConfig
|
||||
}
|
||||
|
||||
introduceAgentTestContext :: forall context m. (Monad m) => AgentTestContext -> SpecFree (LabelValue "agent-test-context" AgentTestContext :> context) m () -> SpecFree context m ()
|
||||
|
@ -3,24 +3,27 @@
|
||||
-- | Chinook Based Agent Fixtures used in DataConnector specific
|
||||
-- Specs.
|
||||
module Harness.Backend.DataConnector.Chinook
|
||||
( setupAction,
|
||||
referenceSourceConfig,
|
||||
sqliteSourceConfig,
|
||||
( ChinookTestEnv (..),
|
||||
NameFormatting (..),
|
||||
mkChinookCloneTestEnvironment,
|
||||
mkChinookStaticTestEnvironment,
|
||||
setupChinookSourceAction,
|
||||
setupCustomSourceAction,
|
||||
testRoleName,
|
||||
ChinookTestEnv (..),
|
||||
)
|
||||
where
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Control.Monad.Managed (Managed)
|
||||
import Data.Aeson qualified as Aeson
|
||||
import Data.ByteString (ByteString)
|
||||
import Harness.Backend.DataConnector.Chinook.Reference qualified as Reference
|
||||
import Harness.Backend.DataConnector.Chinook.Sqlite qualified as Sqlite
|
||||
import Harness.DataConnectorAgent (createManagedClone)
|
||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||
import Harness.Quoter.Yaml (yaml)
|
||||
import Harness.Test.Fixture qualified as Fixture
|
||||
import Harness.TestEnvironment (TestEnvironment)
|
||||
import Harness.TestEnvironment (TestEnvironment, getBackendTypeConfig)
|
||||
import Hasura.Backends.DataConnector.API qualified as API
|
||||
import Hasura.Prelude
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -28,26 +31,78 @@ import Hasura.Prelude
|
||||
data ChinookTestEnv = ChinookTestEnv
|
||||
{ -- | Default configuration JSON for the backend source.
|
||||
backendSourceConfig :: Aeson.Value,
|
||||
-- | Can be used to apply custom formatting to table names. Eg.,
|
||||
-- adjusting the casing.
|
||||
formatTableName :: [Text] -> [Text],
|
||||
-- | Can be used to apply custom formatting to column names. Eg.,
|
||||
-- adjusting the casing.
|
||||
formatColumnName :: Text -> Text,
|
||||
formatForeignKeyName :: Text -> Text
|
||||
-- | Default configuration for the backend config that sets the agent configuration
|
||||
backendAgentConfig :: Aeson.Value,
|
||||
-- | Name formatting functions to correct for backend-specific naming rules
|
||||
nameFormatting :: NameFormatting
|
||||
}
|
||||
|
||||
setupAction :: Aeson.Value -> Aeson.Value -> TestEnvironment -> Fixture.SetupAction
|
||||
setupAction sourceMetadata backendConfig' testEnv =
|
||||
data NameFormatting = NameFormatting
|
||||
{ -- | Can be used to apply custom formatting to table names. Eg.,
|
||||
-- adjusting the casing.
|
||||
_nfFormatTableName :: [Text] -> [Text],
|
||||
-- | Can be used to apply custom formatting to column names. Eg.,
|
||||
-- adjusting the casing.
|
||||
_nfFormatColumnName :: Text -> Text,
|
||||
_nfFormatForeignKeyName :: Text -> Text
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- | Create a test environment that uses agent dataset cloning to clone a copy of the Chinook
|
||||
-- DB for the test and use that as the source config configured in HGE.
|
||||
-- This should be used with agents that support datasets.
|
||||
mkChinookCloneTestEnvironment :: NameFormatting -> TestEnvironment -> Managed ChinookTestEnv
|
||||
mkChinookCloneTestEnvironment nameFormatting testEnv = do
|
||||
backendTypeConfig <- getBackendTypeConfig testEnv `onNothing` fail "Unable to find backend type config in this test environment"
|
||||
agentUrl <- Fixture.backendServerUrl backendTypeConfig `onNothing` fail ("Backend " <> show (Fixture.backendType backendTypeConfig) <> " does not have a server url")
|
||||
cloneConfig <- API._dccrConfig <$> createManagedClone agentUrl testEnv (API.DatasetTemplateName "Chinook")
|
||||
let agentBackendConfig = mkAgentBackendConfig backendTypeConfig
|
||||
let cloneConfigValue = Aeson.Object $ API.unConfig cloneConfig
|
||||
let sourceConfig =
|
||||
[yaml|
|
||||
value: *cloneConfigValue
|
||||
template:
|
||||
timeout:
|
||||
|]
|
||||
pure $ ChinookTestEnv sourceConfig agentBackendConfig nameFormatting
|
||||
|
||||
-- | Create a test environment that uses the source config specified to connect to a specific DB on the agent
|
||||
-- that contains the Chinook dataset.
|
||||
-- This should be used with agents that do not support datasets.
|
||||
mkChinookStaticTestEnvironment :: NameFormatting -> Aeson.Value -> TestEnvironment -> Managed ChinookTestEnv
|
||||
mkChinookStaticTestEnvironment nameFormatting sourceConfig testEnv = do
|
||||
backendTypeConfig <- getBackendTypeConfig testEnv `onNothing` fail "Unable to find backend type config in this test environment"
|
||||
let agentBackendConfig = mkAgentBackendConfig backendTypeConfig
|
||||
pure $ ChinookTestEnv sourceConfig agentBackendConfig nameFormatting
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- | Sets up a source in HGE using the source returned by 'mkSourceMetadata'
|
||||
setupCustomSourceAction ::
|
||||
-- | Function that makes a source metadata, taking the 'BackendTypeConfig' and source's configuration as its input parameters
|
||||
(Fixture.BackendTypeConfig -> Aeson.Value -> Aeson.Value) ->
|
||||
(TestEnvironment, ChinookTestEnv) ->
|
||||
Fixture.SetupAction
|
||||
(setup sourceMetadata backendConfig' testEnv)
|
||||
setupCustomSourceAction mkSourceMetadata testEnvs@(testEnv, _chinookTestEnv) =
|
||||
Fixture.SetupAction
|
||||
(setupCustomSource mkSourceMetadata testEnvs)
|
||||
(const $ teardown testEnv)
|
||||
|
||||
-- | Setup the schema given source metadata and backend config.
|
||||
setup :: Aeson.Value -> Aeson.Value -> TestEnvironment -> IO ()
|
||||
setup sourceMetadata backendConfig' testEnvironment = do
|
||||
-- | Sets up a source in HGE that contains tracked Chinook tables (see 'mkChinookSourceMetadata')
|
||||
setupChinookSourceAction :: (TestEnvironment, ChinookTestEnv) -> Fixture.SetupAction
|
||||
setupChinookSourceAction = setupCustomSourceAction mkChinookSourceMetadata
|
||||
|
||||
setupCustomSource ::
|
||||
-- | Function that makes a source metadata, taking the 'BackendTypeConfig' and source's configuration as its input parameters
|
||||
(Fixture.BackendTypeConfig -> Aeson.Value -> Aeson.Value) ->
|
||||
(TestEnvironment, ChinookTestEnv) ->
|
||||
IO ()
|
||||
setupCustomSource mkSourceMetadata (testEnv, ChinookTestEnv {..}) = do
|
||||
backendTypeConfig <- getBackendTypeConfig testEnv `onNothing` fail "Unable to find backend type config in this test environment"
|
||||
let sourceMetadata = mkSourceMetadata backendTypeConfig backendSourceConfig
|
||||
-- Clear and reconfigure the metadata
|
||||
GraphqlEngine.setSource testEnvironment sourceMetadata (Just backendConfig')
|
||||
GraphqlEngine.setSource testEnv sourceMetadata (Just backendAgentConfig)
|
||||
|
||||
-- | Teardown the schema and tracking in the most expected way.
|
||||
teardown :: TestEnvironment -> IO ()
|
||||
@ -56,15 +111,21 @@ teardown testEnvironment = do
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
referenceSourceConfig :: Aeson.Value
|
||||
referenceSourceConfig = mkChinookSourceConfig Reference.backendTypeMetadata Reference.sourceConfiguration
|
||||
mkAgentBackendConfig :: Fixture.BackendTypeConfig -> Aeson.Value
|
||||
mkAgentBackendConfig backendTypeConfig =
|
||||
let backendType = Fixture.backendTypeString backendTypeConfig
|
||||
uri = Fixture.backendServerUrl backendTypeConfig
|
||||
in [yaml|
|
||||
dataconnector:
|
||||
*backendType:
|
||||
uri: *uri
|
||||
|]
|
||||
|
||||
sqliteSourceConfig :: Aeson.Value
|
||||
sqliteSourceConfig = mkChinookSourceConfig Sqlite.backendTypeMetadata Sqlite.sourceConfiguration
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- | Build a standard Chinook Source given an Agent specific @configuration@ field.
|
||||
mkChinookSourceConfig :: Fixture.BackendTypeConfig -> Aeson.Value -> Aeson.Value
|
||||
mkChinookSourceConfig backendTypeMetadata config =
|
||||
mkChinookSourceMetadata :: Fixture.BackendTypeConfig -> Aeson.Value -> Aeson.Value
|
||||
mkChinookSourceMetadata backendTypeMetadata config =
|
||||
let source = Fixture.backendSourceName backendTypeMetadata
|
||||
backendTypeString = Fixture.backendTypeString backendTypeMetadata
|
||||
in [yaml|
|
||||
@ -126,7 +187,7 @@ tables:
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [Customer]
|
||||
column_mapping:
|
||||
column_mapping:
|
||||
EmployeeId: SupportRepId
|
||||
select_permissions:
|
||||
- role: test-role
|
||||
@ -161,7 +222,22 @@ tables:
|
||||
SupportRep:
|
||||
Country:
|
||||
_ceq: [ "$", "Country" ]
|
||||
|
||||
- table: [Invoice]
|
||||
array_relationships:
|
||||
- name: InvoiceLines
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [InvoiceLine]
|
||||
column_mapping:
|
||||
InvoiceId: InvoiceId
|
||||
- table: [InvoiceLine]
|
||||
object_relationships:
|
||||
- name: Invoice
|
||||
using:
|
||||
manual_configuration:
|
||||
remote_table: [Invoice]
|
||||
column_mapping:
|
||||
InvoiceId: InvoiceId
|
||||
|
||||
configuration:
|
||||
*config
|
||||
|
@ -4,23 +4,28 @@
|
||||
--
|
||||
-- NOTE: This module is intended to be imported qualified.
|
||||
module Harness.Backend.DataConnector.Chinook.Reference
|
||||
( agentConfig,
|
||||
sourceConfiguration,
|
||||
backendTypeMetadata,
|
||||
( backendTypeConfig,
|
||||
mkChinookStaticTestEnvironment,
|
||||
chinookFixture,
|
||||
)
|
||||
where
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Control.Monad.Managed (Managed)
|
||||
import Data.Aeson qualified as Aeson
|
||||
import Harness.Backend.DataConnector.Chinook (ChinookTestEnv, NameFormatting (..))
|
||||
import Harness.Backend.DataConnector.Chinook qualified as Chinook
|
||||
import Harness.Quoter.Yaml (yaml)
|
||||
import Harness.Test.BackendType qualified as BackendType
|
||||
import Harness.Test.Fixture (Fixture (..), FixtureName (..))
|
||||
import Harness.TestEnvironment (TestEnvironment)
|
||||
import Hasura.Prelude
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
backendTypeMetadata :: BackendType.BackendTypeConfig
|
||||
backendTypeMetadata =
|
||||
backendTypeConfig :: BackendType.BackendTypeConfig
|
||||
backendTypeConfig =
|
||||
BackendType.BackendTypeConfig
|
||||
{ backendType = BackendType.DataConnectorReference,
|
||||
backendSourceName = "chinook_reference",
|
||||
@ -75,21 +80,27 @@ backendTypeMetadata =
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- | Reference Agent @backend_configs@ field.
|
||||
agentConfig :: Aeson.Value
|
||||
agentConfig =
|
||||
let backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
in [yaml|
|
||||
dataconnector:
|
||||
*backendType:
|
||||
uri: "http://127.0.0.1:65005/"
|
||||
|]
|
||||
mkChinookStaticTestEnvironment :: TestEnvironment -> Managed ChinookTestEnv
|
||||
mkChinookStaticTestEnvironment = Chinook.mkChinookStaticTestEnvironment nameFormatting sourceConfiguration
|
||||
|
||||
nameFormatting :: NameFormatting
|
||||
nameFormatting = NameFormatting id id id
|
||||
|
||||
-- | Reference Agent specific @sources@ entry @configuration@ field.
|
||||
sourceConfiguration :: Aeson.Value
|
||||
sourceConfiguration =
|
||||
[yaml|
|
||||
value: {}
|
||||
template:
|
||||
timeout:
|
||||
|]
|
||||
value: {}
|
||||
template:
|
||||
timeout:
|
||||
|]
|
||||
|
||||
chinookFixture :: Fixture ChinookTestEnv
|
||||
chinookFixture =
|
||||
Fixture
|
||||
{ name = Backend backendTypeConfig,
|
||||
mkLocalTestEnvironment = mkChinookStaticTestEnvironment,
|
||||
setupTeardown = \testEnvs ->
|
||||
[Chinook.setupChinookSourceAction testEnvs],
|
||||
customOptions = Nothing
|
||||
}
|
||||
|
@ -4,24 +4,27 @@
|
||||
--
|
||||
-- NOTE: This module is intended to be imported qualified.
|
||||
module Harness.Backend.DataConnector.Chinook.Sqlite
|
||||
( agentConfig,
|
||||
sourceConfiguration,
|
||||
backendTypeMetadata,
|
||||
formatForeignKeyName,
|
||||
( backendTypeConfig,
|
||||
mkChinookCloneTestEnvironment,
|
||||
chinookFixture,
|
||||
)
|
||||
where
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Data.Aeson qualified as Aeson
|
||||
import Control.Monad.Managed (Managed)
|
||||
import Harness.Backend.DataConnector.Chinook (ChinookTestEnv, NameFormatting (..))
|
||||
import Harness.Backend.DataConnector.Chinook qualified as Chinook
|
||||
import Harness.Quoter.Yaml (yaml)
|
||||
import Harness.Test.BackendType qualified as BackendType
|
||||
import Harness.Test.Fixture (Fixture (..), FixtureName (..))
|
||||
import Harness.TestEnvironment
|
||||
import Hasura.Prelude
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
backendTypeMetadata :: BackendType.BackendTypeConfig
|
||||
backendTypeMetadata =
|
||||
backendTypeConfig :: BackendType.BackendTypeConfig
|
||||
backendTypeConfig =
|
||||
BackendType.BackendTypeConfig
|
||||
{ backendType = BackendType.DataConnectorSqlite,
|
||||
backendSourceName = "chinook_sqlite",
|
||||
@ -94,28 +97,24 @@ backendTypeMetadata =
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- | Reference Agent @backend_configs@ field.
|
||||
agentConfig :: Aeson.Value
|
||||
agentConfig =
|
||||
let backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
in [yaml|
|
||||
dataconnector:
|
||||
*backendType:
|
||||
uri: "http://127.0.0.1:65007/"
|
||||
|]
|
||||
mkChinookCloneTestEnvironment :: TestEnvironment -> Managed ChinookTestEnv
|
||||
mkChinookCloneTestEnvironment = Chinook.mkChinookCloneTestEnvironment nameFormatting
|
||||
|
||||
-- | Sqlite Agent specific @sources@ entry @configuration@ field.
|
||||
sourceConfiguration :: Aeson.Value
|
||||
sourceConfiguration =
|
||||
[yaml|
|
||||
value:
|
||||
db: "/db.chinook.sqlite"
|
||||
template:
|
||||
timeout:
|
||||
|]
|
||||
nameFormatting :: NameFormatting
|
||||
nameFormatting = NameFormatting id id formatForeignKeyName
|
||||
|
||||
-- | Construct foreign key relationship names.
|
||||
formatForeignKeyName :: Text -> Text
|
||||
formatForeignKeyName = \case
|
||||
"Artist" -> "ArtistId->Artist.ArtistId"
|
||||
x -> x
|
||||
|
||||
chinookFixture :: Fixture ChinookTestEnv
|
||||
chinookFixture =
|
||||
Fixture
|
||||
{ name = Backend backendTypeConfig,
|
||||
mkLocalTestEnvironment = mkChinookCloneTestEnvironment,
|
||||
setupTeardown = \testEnvs ->
|
||||
[Chinook.setupChinookSourceAction testEnvs],
|
||||
customOptions = Nothing
|
||||
}
|
||||
|
@ -14,9 +14,11 @@ where
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Data.Aeson qualified as Aeson
|
||||
import Data.Aeson.KeyMap qualified as KeyMap
|
||||
import Data.Text qualified as Text
|
||||
import Data.Text.Extended qualified as Text (commaSeparated)
|
||||
import Data.Time qualified as Time
|
||||
import Harness.DataConnectorAgent (createClone, deleteClone)
|
||||
import Harness.Exceptions
|
||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||
import Harness.Quoter.Yaml (yaml)
|
||||
@ -25,7 +27,8 @@ import Harness.Test.Fixture qualified as Fixture
|
||||
import Harness.Test.Permissions qualified as Permissions
|
||||
import Harness.Test.Schema (SchemaName)
|
||||
import Harness.Test.Schema qualified as Schema
|
||||
import Harness.TestEnvironment (TestEnvironment)
|
||||
import Harness.TestEnvironment (TestEnvironment (..))
|
||||
import Hasura.Backends.DataConnector.API qualified as API
|
||||
import Hasura.Prelude
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
@ -83,18 +86,18 @@ setupTablesAction ts env =
|
||||
(const $ teardown ts (env, ()))
|
||||
|
||||
-- | Metadata source information for the default Sqlite instance.
|
||||
sourceMetadata :: Aeson.Value
|
||||
sourceMetadata =
|
||||
sourceMetadata :: API.Config -> Aeson.Value
|
||||
sourceMetadata (API.Config config) =
|
||||
let source = Fixture.backendSourceName backendTypeMetadata
|
||||
backendType = BackendType.backendTypeString backendTypeMetadata
|
||||
explicitMainConfig = KeyMap.insert "explicit_main_schema" (Aeson.Bool True) config
|
||||
in [yaml|
|
||||
name: *source
|
||||
kind: *backendType
|
||||
tables: []
|
||||
configuration:
|
||||
db: "/db.sqlite"
|
||||
explicit_main_schema: true
|
||||
|]
|
||||
name: *source
|
||||
kind: *backendType
|
||||
tables: []
|
||||
configuration:
|
||||
value: *explicitMainConfig
|
||||
|]
|
||||
|
||||
backendConfig :: Aeson.Value
|
||||
backendConfig =
|
||||
@ -102,15 +105,20 @@ backendConfig =
|
||||
in [yaml|
|
||||
dataconnector:
|
||||
*backendType:
|
||||
uri: "http://127.0.0.1:65007/"
|
||||
uri: *sqliteAgentUri
|
||||
|]
|
||||
|
||||
sqliteAgentUri :: String
|
||||
sqliteAgentUri = "http://127.0.0.1:65007/"
|
||||
|
||||
-- | 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 tables (testEnvironment, _) = do
|
||||
-- Create the database clone
|
||||
cloneConfig <- API._dccrConfig <$> createClone sqliteAgentUri testEnvironment (API.DatasetTemplateName "Empty")
|
||||
-- Clear and reconfigure the metadata
|
||||
GraphqlEngine.setSource testEnvironment sourceMetadata (Just backendConfig)
|
||||
GraphqlEngine.setSource testEnvironment (sourceMetadata cloneConfig) (Just backendConfig)
|
||||
-- Setup and track tables
|
||||
for_ tables $ \table -> do
|
||||
createTable testEnvironment table
|
||||
@ -164,11 +172,15 @@ teardown (reverse -> tables) (testEnvironment, _) = do
|
||||
( forFinally_ tables $ \table ->
|
||||
Schema.untrackRelationships table testEnvironment
|
||||
)
|
||||
-- Then teardown tables
|
||||
( forFinally_ tables $ \table ->
|
||||
finally
|
||||
(untrackTable testEnvironment table)
|
||||
(dropTable testEnvironment table)
|
||||
( finally
|
||||
-- Then teardown tables
|
||||
( forFinally_ tables $ \table ->
|
||||
finally
|
||||
(untrackTable testEnvironment table)
|
||||
(dropTable testEnvironment table)
|
||||
)
|
||||
-- Then delete the db clone
|
||||
(deleteClone sqliteAgentUri testEnvironment)
|
||||
)
|
||||
|
||||
-- | Call the Metadata API and pass in a Raw SQL statement to the
|
||||
|
43
server/lib/test-harness/src/Harness/DataConnectorAgent.hs
Normal file
43
server/lib/test-harness/src/Harness/DataConnectorAgent.hs
Normal file
@ -0,0 +1,43 @@
|
||||
module Harness.DataConnectorAgent
|
||||
( createClone,
|
||||
deleteClone,
|
||||
createManagedClone,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Exception.Lifted (finally, throwIO)
|
||||
import Control.Monad.Managed (MonadManaged, managed)
|
||||
import Harness.TestEnvironment (TestEnvironment (..))
|
||||
import Hasura.Backends.DataConnector.API qualified as API
|
||||
import Hasura.Prelude
|
||||
import Network.HTTP.Client qualified as Http
|
||||
import Servant (NamedRoutes, Proxy (..))
|
||||
import Servant.Client (Client, ClientM, client, mkClientEnv, parseBaseUrl, runClientM, (//))
|
||||
|
||||
runDataConnectorAgentRequests :: String -> (Client ClientM (NamedRoutes API.Routes) -> ClientM a) -> IO a
|
||||
runDataConnectorAgentRequests agentUri runWithClient = do
|
||||
clientEnv <- mkClientEnv <$> Http.newManager Http.defaultManagerSettings <*> parseBaseUrl agentUri
|
||||
results <- flip runClientM clientEnv $ do
|
||||
runWithClient $ client (Proxy @(NamedRoutes API.Routes))
|
||||
results `onLeft` throwIO
|
||||
|
||||
createClone :: String -> TestEnvironment -> API.DatasetTemplateName -> IO API.DatasetCreateCloneResponse
|
||||
createClone agentUri TestEnvironment {..} templateName = runDataConnectorAgentRequests agentUri $ \dcClient -> do
|
||||
let cloneName = API.DatasetCloneName (tshow uniqueTestId)
|
||||
(dcClient // API._datasets // API._createClone) cloneName (API.DatasetCreateCloneRequest templateName)
|
||||
|
||||
deleteClone :: String -> TestEnvironment -> IO API.DatasetDeleteCloneResponse
|
||||
deleteClone agentUri TestEnvironment {..} = runDataConnectorAgentRequests agentUri $ \dcClient -> do
|
||||
let cloneName = API.DatasetCloneName (tshow uniqueTestId)
|
||||
(dcClient // API._datasets // API._deleteClone) cloneName
|
||||
|
||||
withClone :: String -> TestEnvironment -> API.DatasetTemplateName -> (API.DatasetCreateCloneResponse -> IO a) -> IO a
|
||||
withClone agentUri TestEnvironment {..} templateName useClone = runDataConnectorAgentRequests agentUri $ \dcClient -> do
|
||||
let cloneName = API.DatasetCloneName (tshow uniqueTestId)
|
||||
response <- (dcClient // API._datasets // API._createClone) cloneName (API.DatasetCreateCloneRequest templateName)
|
||||
finally
|
||||
(liftIO $ useClone response)
|
||||
((dcClient // API._datasets // API._deleteClone) cloneName)
|
||||
|
||||
createManagedClone :: MonadManaged m => String -> TestEnvironment -> API.DatasetTemplateName -> m API.DatasetCreateCloneResponse
|
||||
createManagedClone agentUri testEnvironment templateName = managed (withClone agentUri testEnvironment templateName)
|
@ -290,7 +290,7 @@ startServerThread = do
|
||||
dataconnector:
|
||||
foobar:
|
||||
display_name: FOOBARDB
|
||||
uri: "http://localhost:65007" |]
|
||||
uri: "http://localhost:65005" |]
|
||||
thread <-
|
||||
Async.async
|
||||
( runApp
|
||||
|
@ -26,12 +26,14 @@ library
|
||||
, hedgehog
|
||||
, hspec
|
||||
, hspec-core
|
||||
, http-client
|
||||
, http-conduit
|
||||
, http-types
|
||||
, insert-ordered-containers
|
||||
, lens
|
||||
, lens-aeson
|
||||
, libyaml
|
||||
, lifted-base
|
||||
, managed
|
||||
, morpheus-graphql
|
||||
, mtl
|
||||
@ -51,6 +53,7 @@ library
|
||||
, safe
|
||||
, safe-exceptions
|
||||
, servant-server
|
||||
, servant-client
|
||||
, sop-core
|
||||
, stm
|
||||
, string-interpolate
|
||||
@ -125,6 +128,7 @@ library
|
||||
Harness.Backend.Postgres
|
||||
Harness.Backend.Sqlserver
|
||||
Harness.Constants
|
||||
Harness.DataConnectorAgent
|
||||
Harness.Env
|
||||
Harness.Exceptions
|
||||
Harness.GraphqlEngine
|
||||
|
Loading…
Reference in New Issue
Block a user