From bbd311d1974002160149786e15a264283ac83bf1 Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Wed, 25 Sep 2024 11:34:56 -0700 Subject: [PATCH 1/8] chore: graphql prep for test migration Signed-off-by: Kevin Shan --- .../schemas/sql-array-objects/schema.graphql | 19 +++++++++++++++++++ .../schemas/sql-models/schema.graphql | 10 ++++++++++ 2 files changed, 29 insertions(+) create mode 100644 packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql create mode 100644 packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/schema.graphql diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql new file mode 100644 index 0000000000..08643afe1f --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql @@ -0,0 +1,19 @@ +input AMPLIFY { + engine: String = "postgres" + globalAuthRule: AuthRule = { allow: public } +} + +type Contact @refersTo(name: "e2e_test_contact") @model { + id: Int! @primaryKey + firstname: String + lastname: String + tags: [String] + address: ContactAddress +} + +type ContactAddress { + city: String! + state: String! + street: String! + zip: String! +} diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/schema.graphql b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/schema.graphql new file mode 100644 index 0000000000..b99fe7eeb8 --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/schema.graphql @@ -0,0 +1,10 @@ +type Todo @model @refersTo(name: "e2e_test_todos") { + id: ID! @primaryKey + description: String! +} +type Student @model @refersTo(name: "e2e_test_students") { + studentId: Int! @primaryKey(sortKeyFields: ["classId"]) + classId: String! + firstName: String + lastName: String +} From 8439764b7744fda54af8c7291e5b0e7313cd4a2f Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Wed, 25 Sep 2024 15:33:16 -0700 Subject: [PATCH 2/8] refactor: generic graphql field selection string with fieldmap Signed-off-by: Kevin Shan --- .../schemas/sql-array-objects/field-map.ts | 14 +++++ .../schemas/sql-models/field-map.ts | 13 +++++ .../src/sql-tests-common/sql-models.ts | 54 +++++++++---------- .../src/utils/sql-crudl-helper.ts | 45 +++++++++++----- 4 files changed, 85 insertions(+), 41 deletions(-) create mode 100644 packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/field-map.ts create mode 100644 packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/field-map.ts diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/field-map.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/field-map.ts new file mode 100644 index 0000000000..c5b6bd9210 --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/field-map.ts @@ -0,0 +1,14 @@ +import { FieldMap } from '../../../utils/sql-crudl-helper'; + +export const contactFieldMap: FieldMap = { + id: true, + firstname: true, + lastname: true, + tags: true, + address: { + city: true, + state: true, + street: true, + zip: true, + }, +}; diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/field-map.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/field-map.ts new file mode 100644 index 0000000000..c338fad0bd --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-models/field-map.ts @@ -0,0 +1,13 @@ +import { FieldMap } from '../../../utils/sql-crudl-helper'; + +export const toDoFieldMap: FieldMap = { + id: true, + description: true, +}; + +export const studentFieldMap: FieldMap = { + studentId: true, + classId: true, + firstName: true, + lastName: true, +}; diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models.ts index 612ca423e9..0411dd2290 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models.ts @@ -1,11 +1,13 @@ import * as path from 'path'; +import * as fs from 'fs-extra'; import { LambdaClient, GetProvisionedConcurrencyConfigCommand } from '@aws-sdk/client-lambda'; import { ImportedRDSType } from '@aws-amplify/graphql-transformer-core'; import AWSAppSyncClient, { AUTH_TYPE } from 'aws-appsync'; -import { createNewProjectDir, deleteProjectDir, getRDSTableNamePrefix } from 'amplify-category-api-e2e-core'; +import { createNewProjectDir, deleteProjectDir } from 'amplify-category-api-e2e-core'; import { initCDKProject, cdkDeploy, cdkDestroy } from '../commands'; import { SqlDatatabaseController } from '../sql-datatabase-controller'; import { CRUDLHelper } from '../utils/sql-crudl-helper'; +import { toDoFieldMap, studentFieldMap } from './schemas/sql-models/field-map'; import { ONE_MINUTE } from '../utils/duration-constants'; export const testGraphQLAPI = ( @@ -20,32 +22,31 @@ export const testGraphQLAPI = ( engine: ImportedRDSType, ): void => { describe(`${testBlockDescription} - ${engine}`, () => { - const amplifyGraphqlSchema = ` - type Todo @model @refersTo(name: "${getRDSTableNamePrefix()}todos") { - id: ID! @primaryKey - description: String! - } - type Student @model @refersTo(name: "${getRDSTableNamePrefix()}students") { - studentId: Int! @primaryKey(sortKeyFields: ["classId"]) - classId: String! - firstName: String - lastName: String - } - `; - const { projFolderName, region, connectionConfigName, dbController, resourceNames } = options; - const templatePath = path.resolve(path.join(__dirname, '..', '__tests__', 'backends', 'sql-models')); - let projRoot; - let name; - let outputs; - let toDoTableCRUDLHelper, studentTableCRUDLHelper; + let region, lambdaFunctionName, lambdaAliasName; + + let dbController: SqlDatatabaseController; + let toDoTableCRUDLHelper: CRUDLHelper; + let studentTableCRUDLHelper: CRUDLHelper; beforeAll(async () => { + ({ + region, + dbController, + resourceNames: { sqlLambdaAliasName: lambdaAliasName }, + } = options); + const { projFolderName, connectionConfigName } = options; + + const templatePath = path.resolve(path.join(__dirname, '..', '__tests__', 'backends', 'sql-models')); + const schemaPath = path.resolve(path.join(__dirname, '..', 'sql-tests-common', 'schemas', 'sql-models', 'schema.graphql')); + const schemaConfigString = fs.readFileSync(schemaPath).toString(); + projRoot = await createNewProjectDir(projFolderName); - name = await initCDKProject(projRoot, templatePath); - dbController.writeDbDetails(projRoot, connectionConfigName, amplifyGraphqlSchema); - outputs = await cdkDeploy(projRoot, '--all', { postDeployWaitMs: ONE_MINUTE }); + const name = await initCDKProject(projRoot, templatePath); + dbController.writeDbDetails(projRoot, connectionConfigName, schemaConfigString); + const outputs = await cdkDeploy(projRoot, '--all', { postDeployWaitMs: ONE_MINUTE }); const { awsAppsyncApiEndpoint: apiEndpoint, awsAppsyncApiKey: apiKey } = outputs[name]; + lambdaFunctionName = outputs[name].SQLFunctionName; const appSyncClient = new AWSAppSyncClient({ url: apiEndpoint, @@ -57,8 +58,8 @@ export const testGraphQLAPI = ( }, }); - toDoTableCRUDLHelper = new CRUDLHelper(appSyncClient, 'Todo', 'Todos', ['id', 'description']); - studentTableCRUDLHelper = new CRUDLHelper(appSyncClient, 'Student', 'Students', ['studentId', 'classId', 'firstName', 'lastName']); + toDoTableCRUDLHelper = new CRUDLHelper(appSyncClient, 'Todo', 'Todos', toDoFieldMap); + studentTableCRUDLHelper = new CRUDLHelper(appSyncClient, 'Student', 'Students', studentFieldMap); }); afterAll(async () => { @@ -380,10 +381,9 @@ export const testGraphQLAPI = ( test(`check SQL Lambda provisioned concurrency - ${engine}`, async () => { const client = new LambdaClient({ region }); - const functionName = outputs[name].SQLFunctionName; const command = new GetProvisionedConcurrencyConfigCommand({ - FunctionName: functionName, - Qualifier: resourceNames.sqlLambdaAliasName, + FunctionName: lambdaFunctionName, + Qualifier: lambdaAliasName, }); const response = await client.send(command); expect(response.RequestedProvisionedConcurrentExecutions).toEqual(2); diff --git a/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts b/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts index 76c7aecbeb..c26615d82b 100644 --- a/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts +++ b/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts @@ -1,6 +1,16 @@ import AWSAppSyncClient from 'aws-appsync'; import gql from 'graphql-tag'; +/** + * Type that represents the GraphQL field selection string structure + * GraphQL does not diffrentiate between return single object or array of primitives/objects + * If field value is an object or array of objects, define as nested object, otherwise <[key]: true> pair + * Future: handle edge cases e.g. nested arrays and optional fields + */ +export type FieldMap = { + [key: string]: true | FieldMap; +}; + /** * A class that attempts to handle basic/generic CRUDL operations using AppSyncClient API */ @@ -9,14 +19,14 @@ export class CRUDLHelper { private readonly appSyncClient: AWSAppSyncClient, private readonly modelName: string, private readonly modelListName: string, - private readonly fields: Array, + private readonly fieldMap: FieldMap, ) {} public create = async (args: Record): Promise> => { const mutation = ` mutation Create${this.modelName}($input: Create${this.modelName}Input!, $condition: Model${this.modelName}ConditionInput) { create${this.modelName}(input: $input, condition: $condition) { - ${this.getOutputFields()} + ${this.getOutputFields(this.fieldMap)} } } `; @@ -34,7 +44,7 @@ export class CRUDLHelper { const query = ` query Get${this.modelName}(${this.getQueryInputTypes(args)}) { get${this.modelName}(${this.getQueryInputs(args)}) { - ${this.getOutputFields()} + ${this.getOutputFields(this.fieldMap)} } } `; @@ -53,7 +63,7 @@ export class CRUDLHelper { const query = ` query { get${this.modelName}(id: "${id}") { - ${this.getOutputFields()} + ${this.getOutputFields(this.fieldMap)} } } `; @@ -70,7 +80,7 @@ export class CRUDLHelper { const mutation = ` mutation Update${this.modelName}($input: Update${this.modelName}Input!, $condition: Model${this.modelName}ConditionInput) { update${this.modelName}(input: $input, condition: $condition) { - ${this.getOutputFields()} + ${this.getOutputFields(this.fieldMap)} } } `; @@ -88,7 +98,7 @@ export class CRUDLHelper { const mutation = ` mutation Delete${this.modelName}($input: Delete${this.modelName}Input!, $condition: Model${this.modelName}ConditionInput) { delete${this.modelName}(input: $input, condition: $condition) { - ${this.getOutputFields()} + ${this.getOutputFields(this.fieldMap)} } } `; @@ -107,7 +117,7 @@ export class CRUDLHelper { query List${this.modelListName}($limit: Int, $nextToken: String, $filter: Model${this.modelName}FilterInput) { list${this.modelListName}(limit: $limit, nextToken: $nextToken, filter: $filter) { items { - ${this.getOutputFields()} + ${this.getOutputFields(this.fieldMap)} } nextToken } @@ -132,14 +142,21 @@ export class CRUDLHelper { expect(errorMessage).toEqual('GraphQL error: Error processing the request. Check the logs for more details.'); }; - private getMutationInputs = (args: Record): string => { - return Object.entries(args) - .map(([key, value]) => `${key}: "${value}"`) - .join(', '); - }; + private getOutputFields = (fieldMap: FieldMap, indentLevel = 1): string => { + let output = ''; + const indent = ' '.repeat(indentLevel); + + for (const [key, value] of Object.entries(fieldMap)) { + if (value === true) { + output += `${indent}${key}\n`; + } else if (typeof value === 'object') { + output += `${indent}${key} {\n`; + output += this.getOutputFields(value, indentLevel + 1); + output += `${indent}}\n`; + } + } - private getOutputFields = (): string => { - return `${this.fields.join('\n')}\n`; + return output; }; private getQueryInputTypes = (args: Record): string => { From 5d1456e737b3ea7a4dd83bb27cfe7c6566f38904 Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Wed, 25 Sep 2024 16:21:05 -0700 Subject: [PATCH 3/8] feat: add postgres array objects e2e test Signed-off-by: Kevin Shan --- codebuild_specs/e2e_workflow.yml | 134 ++++----- .../__tests__/sql-pg-array-objects.test.ts | 61 +++++ .../src/sql-tests-common/sql-array-objects.ts | 255 ++++++++++++++++++ 3 files changed, 388 insertions(+), 62 deletions(-) create mode 100644 packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts create mode 100644 packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-array-objects.ts diff --git a/codebuild_specs/e2e_workflow.yml b/codebuild_specs/e2e_workflow.yml index 7b1c947886..1f15a19006 100644 --- a/codebuild_specs/e2e_workflow.yml +++ b/codebuild_specs/e2e_workflow.yml @@ -763,7 +763,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=14848' TEST_SUITE: >- src/__tests__/utils.test.ts|src/__tests__/ddb-iam-access.test.ts|src/__tests__/data-construct.test.ts|src/__tests__/custom-logic.test.ts|src/__tests__/amplify-table-5.test.ts - CLI_REGION: eu-north-1 + CLI_REGION: eu-south-1 depend-on: - publish_to_local_registry - identifier: >- @@ -775,7 +775,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=14848' TEST_SUITE: >- src/__tests__/add-resources.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/single-gsi-single-record.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/single-gsi-empty-table.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/single-gsi-1k-records.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/single-gsi-10k-records.test.ts - CLI_REGION: ap-northeast-1 + CLI_REGION: ap-northeast-2 depend-on: - publish_to_local_registry - identifier: >- @@ -787,7 +787,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=14848' TEST_SUITE: >- src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-update-attr-single-record.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-update-attr-empty-table.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-update-attr-1k-records.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-update-attr-10k-records.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-single-record.test.ts - CLI_REGION: ap-northeast-2 + CLI_REGION: ap-south-1 depend-on: - publish_to_local_registry - identifier: >- @@ -799,7 +799,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=14848' TEST_SUITE: >- src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-empty-table.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-1k-records.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/replace-2-gsis-10k-records.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/3-gsis-single-record.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/3-gsis-empty-table.test.ts - CLI_REGION: ap-south-1 + CLI_REGION: ap-southeast-1 depend-on: - publish_to_local_registry - identifier: 3_gsis_1k_records_3_gsis_10k_records @@ -810,7 +810,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=14848' TEST_SUITE: >- src/__tests__/deploy-velocity-temporarily-disabled/3-gsis-1k-records.test.ts|src/__tests__/deploy-velocity-temporarily-disabled/3-gsis-10k-records.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 depend-on: - publish_to_local_registry - identifier: sql_pg_models @@ -834,6 +834,16 @@ batch: USE_PARENT_ACCOUNT: 1 depend-on: - publish_to_local_registry + - identifier: sql_pg_array_objects + buildspec: codebuild_specs/run_cdk_tests.yml + env: + compute-type: BUILD_GENERAL1_MEDIUM + variables: + NODE_OPTIONS: '--max-old-space-size=6656' + TEST_SUITE: src/__tests__/sql-pg-array-objects.test.ts + CLI_REGION: ap-southeast-2 + depend-on: + - publish_to_local_registry - identifier: sql_mysql_canary buildspec: codebuild_specs/run_cdk_tests.yml env: @@ -841,7 +851,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/sql-mysql-canary.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: sql_models_2 @@ -851,7 +861,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/sql-models-2.test.ts - CLI_REGION: ca-central-1 + CLI_REGION: eu-central-1 depend-on: - publish_to_local_registry - identifier: sql_models_1 @@ -861,7 +871,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/sql-models-1.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: eu-north-1 depend-on: - publish_to_local_registry - identifier: sql_iam_access @@ -871,7 +881,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/sql-iam-access.test.ts - CLI_REGION: eu-north-1 + CLI_REGION: eu-west-1 depend-on: - publish_to_local_registry - identifier: default_ddb_canary @@ -881,7 +891,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/default-ddb-canary.test.ts - CLI_REGION: eu-north-1 + CLI_REGION: eu-south-1 depend-on: - publish_to_local_registry - identifier: base_cdk_ap_east_1 @@ -1081,7 +1091,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/amplify-table-4.test.ts - CLI_REGION: eu-west-1 + CLI_REGION: eu-west-2 depend-on: - publish_to_local_registry - identifier: amplify_table_3 @@ -1091,7 +1101,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/amplify-table-3.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-west-3 depend-on: - publish_to_local_registry - identifier: amplify_table_2 @@ -1101,7 +1111,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/amplify-table-2.test.ts - CLI_REGION: eu-west-3 + CLI_REGION: me-south-1 depend-on: - publish_to_local_registry - identifier: amplify_table_1 @@ -1111,7 +1121,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/amplify-table-1.test.ts - CLI_REGION: me-south-1 + CLI_REGION: sa-east-1 depend-on: - publish_to_local_registry - identifier: amplify_ddb_canary @@ -1121,7 +1131,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/amplify-ddb-canary.test.ts - CLI_REGION: sa-east-1 + CLI_REGION: us-east-1 depend-on: - publish_to_local_registry - identifier: all_auth_modes @@ -1131,7 +1141,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/all-auth-modes.test.ts - CLI_REGION: us-east-1 + CLI_REGION: us-east-2 depend-on: - publish_to_local_registry - identifier: admin_role @@ -1141,7 +1151,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/admin-role.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-1 depend-on: - publish_to_local_registry - identifier: sql_custom_ssl @@ -1151,7 +1161,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/sql-custom-ssl/sql-custom-ssl.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: restricted_field_auth_gen2 @@ -1162,7 +1172,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/restricted-field-auth/restricted-field-auth-gen2.test.ts - CLI_REGION: ap-northeast-2 + CLI_REGION: ap-south-1 depend-on: - publish_to_local_registry - identifier: restricted_field_auth_gen1 @@ -1173,7 +1183,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/restricted-field-auth/restricted-field-auth-gen1.test.ts - CLI_REGION: ap-south-1 + CLI_REGION: ap-southeast-1 depend-on: - publish_to_local_registry - identifier: restricted_field_auth_gen2_subscriptions_off @@ -1184,7 +1194,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/restricted-field-auth/subscriptions-off/restricted-field-auth-gen2-subscriptions-off.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 depend-on: - publish_to_local_registry - identifier: restricted_field_auth_gen1_subscriptions_off @@ -1195,7 +1205,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/restricted-field-auth/subscriptions-off/restricted-field-auth-gen1-subscriptions-off.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: references_sqlprimary_sqlrelated @@ -1206,7 +1216,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/references/references-sqlprimary-sqlrelated.test.ts - CLI_REGION: ap-south-1 + CLI_REGION: ap-southeast-1 depend-on: - publish_to_local_registry - identifier: references_sqlprimary_ddbrelated @@ -1217,7 +1227,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/references/references-sqlprimary-ddbrelated.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 depend-on: - publish_to_local_registry - identifier: references_ddbprimary_sqlrelated @@ -1228,7 +1238,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/references/references-ddbprimary-sqlrelated.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: references_ddbprimary_ddbrelated @@ -1239,7 +1249,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/references/references-ddbprimary-ddbrelated.test.ts - CLI_REGION: ca-central-1 + CLI_REGION: eu-central-1 depend-on: - publish_to_local_registry - identifier: recursive_relationships_sql @@ -1250,7 +1260,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/recursive/recursive-relationships-sql.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: eu-north-1 depend-on: - publish_to_local_registry - identifier: recursive_relationships_ddb @@ -1261,7 +1271,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/recursive/recursive-relationships-ddb.test.ts - CLI_REGION: eu-north-1 + CLI_REGION: eu-south-1 depend-on: - publish_to_local_registry - identifier: uuid_pk_sqlprimary_sqlrelated @@ -1272,7 +1282,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/postgres-uuid-pk/uuid-pk-sqlprimary-sqlrelated.test.ts - CLI_REGION: eu-south-1 + CLI_REGION: eu-west-1 depend-on: - publish_to_local_registry - identifier: uuid_pk_sqlprimary_ddbrelated @@ -1283,7 +1293,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/postgres-uuid-pk/uuid-pk-sqlprimary-ddbrelated.test.ts - CLI_REGION: eu-west-1 + CLI_REGION: eu-west-2 depend-on: - publish_to_local_registry - identifier: uuid_pk_ddbprimary_sqlrelated @@ -1294,7 +1304,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/postgres-uuid-pk/uuid-pk-ddbprimary-sqlrelated.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-west-3 depend-on: - publish_to_local_registry - identifier: multi_relationship_sqlprimary_sqlrelated @@ -1305,7 +1315,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/multi-relationship/multi-relationship-sqlprimary-sqlrelated.test.ts - CLI_REGION: eu-west-3 + CLI_REGION: me-south-1 depend-on: - publish_to_local_registry - identifier: multi_relationship_sqlprimary_ddbrelated @@ -1316,7 +1326,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/multi-relationship/multi-relationship-sqlprimary-ddbrelated.test.ts - CLI_REGION: me-south-1 + CLI_REGION: sa-east-1 depend-on: - publish_to_local_registry - identifier: multi_relationship_ddbprimary_sqlrelated @@ -1327,7 +1337,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/multi-relationship/multi-relationship-ddbprimary-sqlrelated.test.ts - CLI_REGION: sa-east-1 + CLI_REGION: us-east-1 depend-on: - publish_to_local_registry - identifier: multi_relationship_ddbprimary_ddbrelated @@ -1338,7 +1348,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/relationships/multi-relationship/multi-relationship-ddbprimary-ddbrelated.test.ts - CLI_REGION: us-east-1 + CLI_REGION: us-east-2 depend-on: - publish_to_local_registry - identifier: relationships_gen1 @@ -1348,7 +1358,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/relationships/gen1/relationships-gen1.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-1 depend-on: - publish_to_local_registry - identifier: assoc_field_subscriptions_off @@ -1359,7 +1369,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/owner-auth/subscriptions-off/assoc-field-subscriptions-off.test.ts - CLI_REGION: ap-northeast-2 + CLI_REGION: ap-south-1 depend-on: - publish_to_local_registry - identifier: bind_sql_ids @@ -1369,7 +1379,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/owner-auth/bind-sql-ids/bind-sql-ids.test.ts - CLI_REGION: ap-south-1 + CLI_REGION: ap-southeast-1 depend-on: - publish_to_local_registry - identifier: assoc_field_sqlprimary_sqlrelated @@ -1380,7 +1390,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/owner-auth/assoc-field/assoc-field-sqlprimary-sqlrelated.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 depend-on: - publish_to_local_registry - identifier: assoc_field_sqlprimary_ddbrelated @@ -1391,7 +1401,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/owner-auth/assoc-field/assoc-field-sqlprimary-ddbrelated.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: assoc_field_ddbprimary_sqlrelated @@ -1402,7 +1412,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/owner-auth/assoc-field/assoc-field-ddbprimary-sqlrelated.test.ts - CLI_REGION: ca-central-1 + CLI_REGION: eu-central-1 depend-on: - publish_to_local_registry - identifier: assoc_field_ddbprimary_ddbrelated @@ -1413,7 +1423,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/owner-auth/assoc-field/assoc-field-ddbprimary-ddbrelated.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: eu-north-1 depend-on: - publish_to_local_registry - identifier: static_group_auth_sqlprimary_sqlrelated_subscriptions_off @@ -1424,7 +1434,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/static-group-auth/static-group-auth-sqlprimary-sqlrelated-subscriptions-off.test.ts - CLI_REGION: eu-north-1 + CLI_REGION: eu-south-1 depend-on: - publish_to_local_registry - identifier: static_group_auth_sqlprimary_ddbrelated_subscriptions_off @@ -1435,7 +1445,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/static-group-auth/static-group-auth-sqlprimary-ddbrelated-subscriptions-off.test.ts - CLI_REGION: eu-south-1 + CLI_REGION: eu-west-1 depend-on: - publish_to_local_registry - identifier: static_group_auth_ddbprimary_sqlrelated_subscriptions_off @@ -1446,7 +1456,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/static-group-auth/static-group-auth-ddbprimary-sqlrelated-subscriptions-off.test.ts - CLI_REGION: eu-west-1 + CLI_REGION: eu-west-2 depend-on: - publish_to_local_registry - identifier: static_group_auth_ddbprimary_ddbrelated_subscriptions_off @@ -1457,7 +1467,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/static-group-auth/static-group-auth-ddbprimary-ddbrelated-subscriptions-off.test.ts - CLI_REGION: eu-west-2 + CLI_REGION: eu-west-3 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_sqlprimary_sqlrelated_subscriptions_off @@ -1468,7 +1478,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/dynamic-group-auth/dynamic-group-auth-sqlprimary-sqlrelated-subscriptions-off.test.ts - CLI_REGION: eu-west-3 + CLI_REGION: me-south-1 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_sqlprimary_ddbrelated_subscriptions_off @@ -1479,7 +1489,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/dynamic-group-auth/dynamic-group-auth-sqlprimary-ddbrelated-subscriptions-off.test.ts - CLI_REGION: me-south-1 + CLI_REGION: sa-east-1 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_ddbprimary_sqlrelated_subscriptions_off @@ -1490,7 +1500,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/dynamic-group-auth/dynamic-group-auth-ddbprimary-sqlrelated-subscriptions-off.test.ts - CLI_REGION: sa-east-1 + CLI_REGION: us-east-1 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_ddbprimary_ddbrelated_subscriptions_off @@ -1501,7 +1511,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/subscriptions-off/dynamic-group-auth/dynamic-group-auth-ddbprimary-ddbrelated-subscriptions-off.test.ts - CLI_REGION: us-east-1 + CLI_REGION: us-east-2 depend-on: - publish_to_local_registry - identifier: static_group_auth_sqlprimary_sqlrelated @@ -1512,7 +1522,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/static-group-auth/static-group-auth-sqlprimary-sqlrelated.test.ts - CLI_REGION: us-east-2 + CLI_REGION: us-west-1 depend-on: - publish_to_local_registry - identifier: static_group_auth_sqlprimary_ddbrelated @@ -1523,7 +1533,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/static-group-auth/static-group-auth-sqlprimary-ddbrelated.test.ts - CLI_REGION: us-west-1 + CLI_REGION: us-west-2 depend-on: - publish_to_local_registry - identifier: static_group_auth_ddbprimary_sqlrelated @@ -1534,7 +1544,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/static-group-auth/static-group-auth-ddbprimary-sqlrelated.test.ts - CLI_REGION: us-west-2 + CLI_REGION: ap-northeast-1 depend-on: - publish_to_local_registry - identifier: static_group_auth_ddbprimary_ddbrelated @@ -1545,7 +1555,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/static-group-auth/static-group-auth-ddbprimary-ddbrelated.test.ts - CLI_REGION: ap-northeast-1 + CLI_REGION: ap-northeast-2 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_sqlprimary_sqlrelated @@ -1556,7 +1566,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/dynamic-group-auth/dynamic-group-auth-sqlprimary-sqlrelated.test.ts - CLI_REGION: ap-northeast-2 + CLI_REGION: ap-south-1 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_sqlprimary_ddbrelated @@ -1567,7 +1577,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/dynamic-group-auth/dynamic-group-auth-sqlprimary-ddbrelated.test.ts - CLI_REGION: ap-south-1 + CLI_REGION: ap-southeast-1 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_ddbprimary_sqlrelated @@ -1578,7 +1588,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/dynamic-group-auth/dynamic-group-auth-ddbprimary-sqlrelated.test.ts - CLI_REGION: ap-southeast-1 + CLI_REGION: ap-southeast-2 depend-on: - publish_to_local_registry - identifier: dynamic_group_auth_ddbprimary_ddbrelated @@ -1589,7 +1599,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/group-auth/dynamic-group-auth/dynamic-group-auth-ddbprimary-ddbrelated.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: generation @@ -1610,7 +1620,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/deploy-velocity/single-gsi-100k-records.test.ts - CLI_REGION: ap-southeast-2 + CLI_REGION: ca-central-1 depend-on: - publish_to_local_registry - identifier: replace_2_gsis_update_attr_100k_records @@ -1621,7 +1631,7 @@ batch: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: >- src/__tests__/deploy-velocity/replace-2-gsis-update-attr-100k-records.test.ts - CLI_REGION: ca-central-1 + CLI_REGION: eu-central-1 depend-on: - publish_to_local_registry - identifier: replace_2_gsis_100k_records @@ -1631,7 +1641,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/deploy-velocity/replace-2-gsis-100k-records.test.ts - CLI_REGION: eu-central-1 + CLI_REGION: eu-north-1 depend-on: - publish_to_local_registry - identifier: 3_gsis_100k_records @@ -1641,7 +1651,7 @@ batch: variables: NODE_OPTIONS: '--max-old-space-size=6656' TEST_SUITE: src/__tests__/deploy-velocity/3-gsis-100k-records.test.ts - CLI_REGION: eu-north-1 + CLI_REGION: eu-south-1 depend-on: - publish_to_local_registry - identifier: conversation diff --git a/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts new file mode 100644 index 0000000000..fac443f81e --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts @@ -0,0 +1,61 @@ +import generator from 'generate-password'; +import { getResourceNamesForStrategyName, ImportedRDSType } from '@aws-amplify/graphql-transformer-core'; +import { getRDSTableNamePrefix } from 'amplify-category-api-e2e-core'; +import { SqlDatatabaseController } from '../sql-datatabase-controller'; +import { DURATION_1_HOUR } from '../utils/duration-constants'; +import { testGraphQLAPIArrayAndObjects } from '../sql-tests-common/sql-array-objects'; + +jest.setTimeout(DURATION_1_HOUR); + +describe('CDK GraphQL Transformer deployments with Postgres SQL datasources', () => { + const projFolderName = 'pgmodels'; + + // sufficient password length that meets the requirements for RDS cluster/instance + const [username, password, identifier] = generator.generateMultiple(3, { length: 11 }); + const region = process.env.CLI_REGION ?? 'us-west-2'; + const engine = 'postgres'; + + const databaseController: SqlDatatabaseController = new SqlDatatabaseController( + [ + `CREATE TABLE "${getRDSTableNamePrefix()}contact" ("id" INT PRIMARY KEY, "firstname" VARCHAR(20), "lastname" VARCHAR(50), "tags" VARCHAR[], "address" JSON)`, + ], + { + identifier, + engine, + username, + password, + region, + }, + ); + + const strategyName = `${engine}DBStrategy`; + const resourceNames = getResourceNamesForStrategyName(strategyName); + + beforeAll(async () => { + await databaseController.setupDatabase(); + }); + + afterAll(async () => { + await databaseController.cleanupDatabase(); + }); + + const constructTestOptions = (connectionConfigName: string) => ({ + projFolderName, + region, + connectionConfigName, + dbController: databaseController, + resourceNames, + }); + + testGraphQLAPIArrayAndObjects( + constructTestOptions('ssm'), + 'RDS Postgres Model Directive with SSM Credential Store', + ImportedRDSType.POSTGRESQL, + ); + + testGraphQLAPIArrayAndObjects( + constructTestOptions('connectionUri'), + 'RDS Postgres Model Directive using Connection String SSM parameter', + ImportedRDSType.POSTGRESQL, + ); +}); diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-array-objects.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-array-objects.ts new file mode 100644 index 0000000000..ba698455f3 --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-array-objects.ts @@ -0,0 +1,255 @@ +import * as path from 'path'; +import * as fs from 'fs-extra'; +import { LambdaClient, GetProvisionedConcurrencyConfigCommand } from '@aws-sdk/client-lambda'; +import { ImportedRDSType } from '@aws-amplify/graphql-transformer-core'; +import AWSAppSyncClient, { AUTH_TYPE } from 'aws-appsync'; +import { createNewProjectDir, deleteProjectDir } from 'amplify-category-api-e2e-core'; +import { initCDKProject, cdkDeploy, cdkDestroy } from '../commands'; +import { SqlDatatabaseController } from '../sql-datatabase-controller'; +import { CRUDLHelper } from '../utils/sql-crudl-helper'; +import { contactFieldMap } from './schemas/sql-array-objects/field-map'; +import { ONE_MINUTE } from '../utils/duration-constants'; + +export const testGraphQLAPIArrayAndObjects = ( + options: { + projFolderName: string; + region: string; + connectionConfigName: string; + dbController: SqlDatatabaseController; + resourceNames: { sqlLambdaAliasName: string }; + }, + testBlockDescription: string, + engine: ImportedRDSType, +): void => { + describe(`${testBlockDescription} - ${engine}`, () => { + let projRoot; + let region, lambdaFunctionName, lambdaAliasName; + + let dbController: SqlDatatabaseController; + let contactTableCRUDLHelper: CRUDLHelper; + + beforeAll(async () => { + ({ + region, + dbController, + resourceNames: { sqlLambdaAliasName: lambdaAliasName }, + } = options); + const { projFolderName, connectionConfigName } = options; + + const templatePath = path.resolve(path.join(__dirname, '..', '__tests__', 'backends', 'sql-models')); + const schemaPath = path.resolve(path.join(__dirname, '..', 'sql-tests-common', 'schemas', 'sql-array-objects', 'schema.graphql')); + const schemaConfigString = fs.readFileSync(schemaPath).toString(); + + projRoot = await createNewProjectDir(projFolderName); + const name = await initCDKProject(projRoot, templatePath); + dbController.writeDbDetails(projRoot, connectionConfigName, schemaConfigString); + const outputs = await cdkDeploy(projRoot, '--all', { postDeployWaitMs: ONE_MINUTE }); + const { awsAppsyncApiEndpoint: apiEndpoint, awsAppsyncApiKey: apiKey } = outputs[name]; + lambdaFunctionName = outputs[name].SQLFunctionName; + + const appSyncClient = new AWSAppSyncClient({ + url: apiEndpoint, + region, + disableOffline: true, + auth: { + type: AUTH_TYPE.API_KEY, + apiKey, + }, + }); + + contactTableCRUDLHelper = new CRUDLHelper(appSyncClient, 'Contact', 'Contacts', contactFieldMap); + }); + + afterAll(async () => { + try { + await cdkDestroy(projRoot, '--all'); + await dbController.clearDatabase(); + } catch (err) { + console.log(`Error invoking 'cdk destroy': ${err}`); + } + + deleteProjectDir(projRoot); + }); + + test(`check CRUDL on contact table with array and objects - ${engine}`, async () => { + // Create Contact Mutation + const contact1 = await contactTableCRUDLHelper.create({ + id: 1, + firstname: 'David', + lastname: 'Smith', + tags: ['tag1', 'tag2'], + address: { + city: 'Seattle', + state: 'WA', + street: '123 Main St', + zip: '98115', + }, + }); + const contact2 = await contactTableCRUDLHelper.create({ + id: 2, + firstname: 'Chris', + lastname: 'Sundersingh', + tags: ['tag3', 'tag4'], + address: { + city: 'Seattle', + state: 'WA', + street: '456 Another St', + zip: '98119', + }, + }); + + expect(contact1).toBeDefined(); + expect(contact1.id).toEqual(1); + expect(contact1.firstname).toEqual('David'); + expect(contact1.lastname).toEqual('Smith'); + expect(contact1.tags).toEqual(expect.arrayContaining(['tag1', 'tag2'])); + expect(contact1.address).toEqual( + expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '123 Main St', + zip: '98115', + }), + ); + + // Get Contact Query + const getContact1 = await contactTableCRUDLHelper.get({ id: contact1.id }); + + expect(getContact1.id).toEqual(contact1.id); + expect(getContact1.firstname).toEqual('David'); + expect(getContact1.lastname).toEqual('Smith'); + expect(getContact1.tags).toEqual(expect.arrayContaining(['tag1', 'tag2'])); + expect(getContact1.address).toEqual( + expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '123 Main St', + zip: '98115', + }), + ); + + // Update Contact Query + const updateContact1 = await contactTableCRUDLHelper.update({ + id: contact1.id, + firstname: 'David', + lastname: 'Jones', + tags: ['tag1', 'tag2', 'tag3'], + address: { + city: 'Seattle', + state: 'WA', + street: '12345 Main St', + zip: '98110', + }, + }); + + expect(updateContact1.id).toEqual(contact1.id); + expect(updateContact1.firstname).toEqual('David'); + expect(updateContact1.lastname).toEqual('Jones'); + expect(updateContact1.tags).toEqual(expect.arrayContaining(['tag1', 'tag2', 'tag3'])); + expect(updateContact1.address).toEqual( + expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '12345 Main St', + zip: '98110', + }), + ); + + // Get Contact Query after update + const getUpdatedContact1 = await contactTableCRUDLHelper.get({ id: contact1.id }); + + expect(getUpdatedContact1.id).toEqual(contact1.id); + expect(getUpdatedContact1.firstname).toEqual('David'); + expect(getUpdatedContact1.lastname).toEqual('Jones'); + expect(getUpdatedContact1.tags).toEqual(expect.arrayContaining(['tag1', 'tag2', 'tag3'])); + expect(getUpdatedContact1.address).toEqual( + expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '12345 Main St', + zip: '98110', + }), + ); + + // List Contact Query + const listContact = await contactTableCRUDLHelper.list(); + + expect(listContact.items.length).toEqual(2); + expect(listContact.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: contact1.id, + firstname: 'David', + lastname: 'Jones', + tags: expect.arrayContaining(['tag1', 'tag2', 'tag3']), + address: expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '12345 Main St', + zip: '98110', + }), + }), + expect.objectContaining({ + id: contact2.id, + firstname: 'Chris', + lastname: 'Sundersingh', + tags: expect.arrayContaining(['tag3', 'tag4']), + address: expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '456 Another St', + zip: '98119', + }), + }), + ]), + ); + + // Delete Contact Mutation + const deleteContact1 = await contactTableCRUDLHelper.delete({ id: contact1.id }); + + expect(deleteContact1.id).toEqual(contact1.id); + expect(deleteContact1.firstname).toEqual('David'); + expect(deleteContact1.lastname).toEqual('Jones'); + expect(deleteContact1.tags).toEqual(expect.arrayContaining(['tag1', 'tag2', 'tag3'])); + expect(deleteContact1.address).toEqual( + expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '12345 Main St', + zip: '98110', + }), + ); + + // List Contact Query after delete + const listContactAfterDelete = await contactTableCRUDLHelper.list(); + + expect(listContactAfterDelete.items.length).toEqual(1); + expect(listContactAfterDelete.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: contact2.id, + firstname: 'Chris', + lastname: 'Sundersingh', + tags: expect.arrayContaining(['tag3', 'tag4']), + address: expect.objectContaining({ + city: 'Seattle', + state: 'WA', + street: '456 Another St', + zip: '98119', + }), + }), + ]), + ); + }); + + test(`check SQL Lambda provisioned concurrency - ${engine}`, async () => { + const client = new LambdaClient({ region }); + const command = new GetProvisionedConcurrencyConfigCommand({ + FunctionName: lambdaFunctionName, + Qualifier: lambdaAliasName, + }); + const response = await client.send(command); + expect(response.RequestedProvisionedConcurrentExecutions).toEqual(2); + }); + }); +}; From 55840d7667a219f415a20dc22ca7cad2f31c1d4d Mon Sep 17 00:00:00 2001 From: Tim Schmelter Date: Fri, 27 Sep 2024 16:32:57 -0700 Subject: [PATCH 4/8] test: remove bootstrap in test code --- .../amplify-graphql-api-construct-tests/src/commands.ts | 3 --- packages/graphql-transformers-e2e-tests/src/cdkUtils.ts | 9 --------- 2 files changed, 12 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/commands.ts b/packages/amplify-graphql-api-construct-tests/src/commands.ts index 10a82b79c6..062cc5b298 100644 --- a/packages/amplify-graphql-api-construct-tests/src/commands.ts +++ b/packages/amplify-graphql-api-construct-tests/src/commands.ts @@ -122,9 +122,6 @@ export const cdkDeploy = async (cwd: string, option: string, props?: CdkDeployPr env: { npm_config_registry: 'https://registry.npmjs.org/' }, noOutputTimeout, }; - // This prevents us from maintaining a separate CDK account bootstrap process as we add support for new accounts, regions. - // Checks and succeeds early (a no-op) if the account-region combination is already bootstrapped. - await spawn(getNpxPath(), ['cdk', 'bootstrap'], commandOptions).runAsync(); await spawn( getNpxPath(), diff --git a/packages/graphql-transformers-e2e-tests/src/cdkUtils.ts b/packages/graphql-transformers-e2e-tests/src/cdkUtils.ts index c54a340cac..eebc720d88 100644 --- a/packages/graphql-transformers-e2e-tests/src/cdkUtils.ts +++ b/packages/graphql-transformers-e2e-tests/src/cdkUtils.ts @@ -26,15 +26,6 @@ export const deployJsonServer = () => { throw new Error(`'yarn' failed with exit code: ${yarnServerResult.exitCode}`); } - const cdkBootstrapResult = execa.sync('npx', ['cdk', 'bootstrap', '--require-approval', 'never'], { - cwd: jsonServerRootDirectory, - stdio: 'inherit', - }); - - if (cdkBootstrapResult.exitCode !== 0) { - throw new Error(`CDK bootstrap failed with exit code: ${cdkBootstrapResult.exitCode}`); - } - const cdkDeployResult = execa.sync('npx', ['cdk', 'deploy', '--outputsFile', outputValuesFile, '--require-approval', 'never'], { cwd: jsonServerRootDirectory, stdio: 'inherit', From a8ecafbec5054b25be1a0575094cba3d8833486f Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Mon, 30 Sep 2024 11:41:03 -0700 Subject: [PATCH 5/8] chore: schema cleanup Signed-off-by: Kevin Shan --- .../schemas/sql-array-objects/schema.graphql | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql index 08643afe1f..9cd38f48fd 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/schemas/sql-array-objects/schema.graphql @@ -1,8 +1,3 @@ -input AMPLIFY { - engine: String = "postgres" - globalAuthRule: AuthRule = { allow: public } -} - type Contact @refersTo(name: "e2e_test_contact") @model { id: Int! @primaryKey firstname: String From 8aeaa6003c76b37f0199279fbac8ca2304f4736f Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Mon, 30 Sep 2024 14:11:52 -0700 Subject: [PATCH 6/8] chore: final cleanup Signed-off-by: Kevin Shan --- .../src/utils/sql-crudl-helper.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts b/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts index c26615d82b..3c65f1aac3 100644 --- a/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts +++ b/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts @@ -159,12 +159,6 @@ export class CRUDLHelper { return output; }; - private getQueryInputTypes = (args: Record): string => { - return Object.entries(args) - .map(([key, value]) => `$${key}: ${this.getGraphQLType(value)}!`) - .join(', '); - }; - private getQueryInputs = (args: Record): string => { return Object.keys(args) .map((key) => `${key}: $${key}`) @@ -181,4 +175,10 @@ export class CRUDLHelper { return 'String'; } }; + + private getQueryInputTypes = (args: Record): string => { + return Object.entries(args) + .map(([key, value]) => `$${key}: ${this.getGraphQLType(value)}!`) + .join(', '); + }; } From 4e3e3df79cfa95c0002d03f3d49cd76faf74eb13 Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Tue, 1 Oct 2024 12:04:04 -0700 Subject: [PATCH 7/8] chore: add explanation on FieldMap ans examples Signed-off-by: Kevin Shan --- .../src/utils/sql-crudl-helper.ts | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts b/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts index 3c65f1aac3..992ee4ed7a 100644 --- a/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts +++ b/packages/amplify-graphql-api-construct-tests/src/utils/sql-crudl-helper.ts @@ -2,10 +2,40 @@ import AWSAppSyncClient from 'aws-appsync'; import gql from 'graphql-tag'; /** - * Type that represents the GraphQL field selection string structure - * GraphQL does not diffrentiate between return single object or array of primitives/objects - * If field value is an object or array of objects, define as nested object, otherwise <[key]: true> pair - * Future: handle edge cases e.g. nested arrays and optional fields + * Type that represents the GraphQL seletion set structure, used for conversion of FieldMap object to selection set string. + * + * Selecting scalar array: + * - Scalar array in GraphQL custom type is same in syntax in selection set as a single scalar field. + * + * Selecting object/array of objects: + * - Syntax for selecting fields is the same regardless of whether a field returns a single object or an array of objects. + * + * Example: + * - selection set in object: + * ```typescript + * { id: number, name: string, tags: string[], address: { street: string, city: string } } + * ``` + * - in FieldMap: + * ```typescript + * { id: true, name: true, tags: true, address: { street: true, city: true } } + * ``` + * - in selection set syntax string: + * ```typescript + * `id + * name + * tags + * address { + * street + * city + * }` + * ``` + * + * Note: + * - If field value is an object or array of objects, define as nested object. + * - Otherwise, use a `<[key]: true>` pair + * + * Future: + * - Handle edge cases e.g. nested arrays and optional fields. */ export type FieldMap = { [key: string]: true | FieldMap; From 869e7b816b0d4626c4c35964bb2bf056dc67fa8e Mon Sep 17 00:00:00 2001 From: Kevin Shan Date: Tue, 1 Oct 2024 14:49:12 -0700 Subject: [PATCH 8/8] chore: remove dup test Signed-off-by: Kevin Shan --- .../src/__tests__/sql-pg-array-objects.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts index fac443f81e..887dc26330 100644 --- a/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts +++ b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-array-objects.test.ts @@ -47,12 +47,6 @@ describe('CDK GraphQL Transformer deployments with Postgres SQL datasources', () resourceNames, }); - testGraphQLAPIArrayAndObjects( - constructTestOptions('ssm'), - 'RDS Postgres Model Directive with SSM Credential Store', - ImportedRDSType.POSTGRESQL, - ); - testGraphQLAPIArrayAndObjects( constructTestOptions('connectionUri'), 'RDS Postgres Model Directive using Connection String SSM parameter',