From d7583df6fb8ebc67bc92a2a24e5f49620607ccda Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Sun, 15 Sep 2024 23:31:59 -0700 Subject: [PATCH 01/17] chore(graphql-default-value-transformer): tidy tests --- ...grapphql-default-value-transformer.test.ts | 185 ++---------------- 1 file changed, 20 insertions(+), 165 deletions(-) diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts index 344b350d5f..c4eb7274c5 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts @@ -41,180 +41,35 @@ describe('DefaultValueModelTransformer:', () => { ).toThrow('The @default directive may only be added to scalar or enum field types.'); }); - it('throws if @default is used with a null value', () => { + it.each([ + { + type: 'String', + value: undefined, + expectedError: 'Directive "@default" argument "value" of type "String!" is required, but it was not provided.', + }, + { type: 'Int', value: '"text"', expectedError: 'Default value "text" is not a valid Int.' }, + { type: 'Boolean', value: '"text"', expectedError: 'Default value "text" is not a valid Boolean.' }, + { type: 'AWSJSON', value: '"text"', expectedError: 'Default value "text" is not a valid AWSJSON.' }, + { type: 'AWSDate', value: '"text"', expectedError: 'Default value "text" is not a valid AWSDate.' }, + { type: 'AWSDateTime', value: '"text"', expectedError: 'Default value "text" is not a valid AWSDateTime.' }, + { type: 'AWSTime', value: '"text"', expectedError: 'Default value "text" is not a valid AWSTime.' }, + { type: 'AWSTimestamp', value: '"text"', expectedError: 'Default value "text" is not a valid AWSTimestamp.' }, + { type: 'AWSURL', value: '"text"', expectedError: 'Default value "text" is not a valid AWSURL.' }, + { type: 'AWSPhone', value: '"text"', expectedError: 'Default value "text" is not a valid AWSPhone.' }, + { type: 'AWSIPAddress', value: '"text"', expectedError: 'Default value "text" is not a valid AWSIPAddress.' }, + ])(`throws if @default is used with invalid type. %type check.`, ({ type, value, expectedError }) => { const schema = ` type Test @model { - id: ID! - name: String @default - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Directive "@default" argument "value" of type "String!" is required, but it was not provided.'); - }); - - it('throws if @default is used with invalid type. Int check.', () => { - const schema = ` - type Test @model { - id: ID! - value: Int @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid Int.'); - }); - - it('throws if @default is used with invalid type. Boolean check.', () => { - const schema = ` - type Test @model { - id: ID! - value: Boolean @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid Boolean.'); - }); - - it('throws if @default is used with invalid type. AWSJSON check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSJSON @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSJSON.'); - }); - - it('throws if @default is used with invalid type. AWSDate check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSDate @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSDate.'); - }); - - it('throws if @default is used with invalid type. AWSDateTime check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSDateTime @default(value: "text") + id: ID! + value: ${type} ${value !== undefined ? `@default(value: ${value})` : '@default'} } `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSDateTime.'); - }); - - it('throws if @default is used with invalid type. AWSTime check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSTime @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSTime.'); - }); - - it('throws if @default is used with invalid type. AWSTimestamp check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSTimestamp @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSTimestamp.'); - }); - - it('throws if @default is used with invalid type. AWSURL check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSURL @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSURL.'); - }); - - it('throws if @default is used with invalid type. AWSPhone check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSPhone @default(value: "text") - } - `; - - expect(() => - testTransform({ - schema, - transformers: [new ModelTransformer(), new DefaultValueTransformer()], - }), - ).toThrow('Default value "text" is not a valid AWSPhone.'); - }); - - it('throws if @default is used with invalid type. AWSIPAddress check.', () => { - const schema = ` - type Test @model { - id: ID! - value: AWSIPAddress @default(value: "text") - } - `; - expect(() => testTransform({ schema, transformers: [new ModelTransformer(), new DefaultValueTransformer()], }), - ).toThrow('Default value "text" is not a valid AWSIPAddress.'); + ).toThrow(expectedError); }); it('should validate enum values', async () => { From 3a1487646a3999371dfaa8e47980c8a4eeb02168 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Mon, 16 Sep 2024 13:03:08 -0700 Subject: [PATCH 02/17] test(graphql-default-value-transformer): add unit tests for auto increment support --- ...hql-default-value-transformer.test.ts.snap | 216 ++++++++++++++++++ ...grapphql-default-value-transformer.test.ts | 75 +++++- 2 files changed, 289 insertions(+), 2 deletions(-) diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap index 320a27b4e9..ee5dfc9faf 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap @@ -231,6 +231,222 @@ $util.qr($context.args.input.put(\\"stringValue\\", $util.defaultIfNull($ctx.arg {}" `; +exports[`DefaultValueModelTransformer: should successfully transform a schema that implies auto-increment 1`] = ` +"type TestAutoIncrement { + id: ID! + value: Int +} + +input ModelStringInput { + ne: String + eq: String + le: String + lt: String + ge: String + gt: String + contains: String + notContains: String + between: [String] + beginsWith: String + attributeExists: Boolean + attributeType: ModelAttributeTypes + size: ModelSizeInput +} + +input ModelIntInput { + ne: Int + eq: Int + le: Int + lt: Int + ge: Int + gt: Int + between: [Int] + attributeExists: Boolean + attributeType: ModelAttributeTypes +} + +input ModelFloatInput { + ne: Float + eq: Float + le: Float + lt: Float + ge: Float + gt: Float + between: [Float] + attributeExists: Boolean + attributeType: ModelAttributeTypes +} + +input ModelBooleanInput { + ne: Boolean + eq: Boolean + attributeExists: Boolean + attributeType: ModelAttributeTypes +} + +input ModelIDInput { + ne: ID + eq: ID + le: ID + lt: ID + ge: ID + gt: ID + contains: ID + notContains: ID + between: [ID] + beginsWith: ID + attributeExists: Boolean + attributeType: ModelAttributeTypes + size: ModelSizeInput +} + +input ModelSubscriptionStringInput { + ne: String + eq: String + le: String + lt: String + ge: String + gt: String + contains: String + notContains: String + between: [String] + beginsWith: String + in: [String] + notIn: [String] +} + +input ModelSubscriptionIntInput { + ne: Int + eq: Int + le: Int + lt: Int + ge: Int + gt: Int + between: [Int] + in: [Int] + notIn: [Int] +} + +input ModelSubscriptionFloatInput { + ne: Float + eq: Float + le: Float + lt: Float + ge: Float + gt: Float + between: [Float] + in: [Float] + notIn: [Float] +} + +input ModelSubscriptionBooleanInput { + ne: Boolean + eq: Boolean +} + +input ModelSubscriptionIDInput { + ne: ID + eq: ID + le: ID + lt: ID + ge: ID + gt: ID + contains: ID + notContains: ID + between: [ID] + beginsWith: ID + in: [ID] + notIn: [ID] +} + +enum ModelAttributeTypes { + binary + binarySet + bool + list + map + number + numberSet + string + stringSet + _null +} + +input ModelSizeInput { + ne: Int + eq: Int + le: Int + lt: Int + ge: Int + gt: Int + between: [Int] +} + +enum ModelSortDirection { + ASC + DESC +} + +type ModelTestAutoIncrementConnection { + items: [TestAutoIncrement]! + nextToken: String +} + +input ModelTestAutoIncrementFilterInput { + id: ModelIDInput + value: ModelIntInput + and: [ModelTestAutoIncrementFilterInput] + or: [ModelTestAutoIncrementFilterInput] + not: ModelTestAutoIncrementFilterInput +} + +type Query { + getTestAutoIncrement(id: ID!): TestAutoIncrement + listTestAutoIncrements(id: ID, filter: ModelTestAutoIncrementFilterInput, limit: Int, nextToken: String, sortDirection: ModelSortDirection): ModelTestAutoIncrementConnection +} + +input ModelTestAutoIncrementConditionInput { + value: ModelIntInput + and: [ModelTestAutoIncrementConditionInput] + or: [ModelTestAutoIncrementConditionInput] + not: ModelTestAutoIncrementConditionInput +} + +input CreateTestAutoIncrementInput { + id: ID + value: Int +} + +input UpdateTestAutoIncrementInput { + id: ID! + value: Int +} + +input DeleteTestAutoIncrementInput { + id: ID! +} + +type Mutation { + createTestAutoIncrement(input: CreateTestAutoIncrementInput!, condition: ModelTestAutoIncrementConditionInput): TestAutoIncrement + updateTestAutoIncrement(input: UpdateTestAutoIncrementInput!, condition: ModelTestAutoIncrementConditionInput): TestAutoIncrement + deleteTestAutoIncrement(input: DeleteTestAutoIncrementInput!, condition: ModelTestAutoIncrementConditionInput): TestAutoIncrement +} + +input ModelSubscriptionTestAutoIncrementFilterInput { + id: ModelSubscriptionIDInput + value: ModelSubscriptionIntInput + and: [ModelSubscriptionTestAutoIncrementFilterInput] + or: [ModelSubscriptionTestAutoIncrementFilterInput] +} + +type Subscription { + onCreateTestAutoIncrement(filter: ModelSubscriptionTestAutoIncrementFilterInput): TestAutoIncrement @aws_subscribe(mutations: [\\"createTestAutoIncrement\\"]) + onUpdateTestAutoIncrement(filter: ModelSubscriptionTestAutoIncrementFilterInput): TestAutoIncrement @aws_subscribe(mutations: [\\"updateTestAutoIncrement\\"]) + onDeleteTestAutoIncrement(filter: ModelSubscriptionTestAutoIncrementFilterInput): TestAutoIncrement @aws_subscribe(mutations: [\\"deleteTestAutoIncrement\\"]) +} +" +`; + exports[`DefaultValueModelTransformer: should successfully transform simple valid schema 1`] = ` "type Post { id: ID! diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts index c4eb7274c5..477b848d54 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts @@ -1,5 +1,10 @@ import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; -import { constructDataSourceStrategies, getResourceNamesForStrategy, validateModelSchema } from '@aws-amplify/graphql-transformer-core'; +import { + constructDataSourceStrategies, + getResourceNamesForStrategy, + POSTGRES_DB_TYPE, + validateModelSchema, +} from '@aws-amplify/graphql-transformer-core'; import { parse } from 'graphql'; import { mockSqlDataSourceStrategy, testTransform } from '@aws-amplify/graphql-transformer-test-utils'; import { PrimaryKeyTransformer } from '@aws-amplify/graphql-index-transformer'; @@ -45,7 +50,7 @@ describe('DefaultValueModelTransformer:', () => { { type: 'String', value: undefined, - expectedError: 'Directive "@default" argument "value" of type "String!" is required, but it was not provided.', + expectedError: 'The @default directive requires a value property on non Postgres datasources.', }, { type: 'Int', value: '"text"', expectedError: 'Default value "text" is not a valid Int.' }, { type: 'Boolean', value: '"text"', expectedError: 'Default value "text" is not a valid Boolean.' }, @@ -193,4 +198,70 @@ describe('DefaultValueModelTransformer:', () => { expect(out.resolvers['Mutation.createNote.init.1.req.vtl']).toBeDefined(); expect(out.resolvers['Mutation.createNote.init.2.req.vtl']).toBeUndefined(); }); + + it.each([{ strategy: mockSqlDataSourceStrategy() }])( + 'throws if auto-increment is implied on a non-Postgres datasource', + ({ strategy }) => { + const schema = ` + type CoffeeQueue @model { + id: ID! @primaryKey + orderNumber: Int! @default + name: String + }`; + expect(() => { + testTransform({ + schema: schema, + transformers: [new ModelTransformer(), new DefaultValueTransformer(), new PrimaryKeyTransformer()], + dataSourceStrategies: constructDataSourceStrategies(schema, strategy), + }); + }).toThrow('The @default directive requires a value property on non Postgres datasources.'); + }, + ); + + it.each([ + { typeStr: 'Boolean' }, + { typeStr: 'AWSJSON' }, + { typeStr: 'AWSDate' }, + { typeStr: 'AWSDateTime' }, + { typeStr: 'AWSTime' }, + { typeStr: 'AWSTime' }, + { typeStr: 'AWSURL' }, + { typeStr: 'AWSPhone' }, + { typeStr: 'AWSIPAddress' }, + ])('throws if auto-increment is implied on non-int types', ({ typeStr }) => { + const strategy = mockSqlDataSourceStrategy({ dbType: POSTGRES_DB_TYPE }); + + expect(() => { + const schema = ` + type Test @model { + id: ID! @primaryKey + value: ${typeStr} @default + } + `; + testTransform({ + schema, + transformers: [new ModelTransformer(), new DefaultValueTransformer(), new PrimaryKeyTransformer()], + dataSourceStrategies: constructDataSourceStrategies(schema, strategy), + }); + }).toThrow('The empty @default (auto-increment) may only be applied to integer fields.'); + }); + + it('should successfully transform a schema that implies auto-increment', async () => { + const schema = ` + type TestAutoIncrement @model { + id: ID! @primaryKey + value: Int @default + } + `; + const strategy = mockSqlDataSourceStrategy({ dbType: POSTGRES_DB_TYPE }); + const out = testTransform({ + schema, + transformers: [new ModelTransformer(), new DefaultValueTransformer(), new PrimaryKeyTransformer()], + dataSourceStrategies: constructDataSourceStrategies(schema, strategy), + }); + expect(out).toBeDefined(); + expect(out.schema).toMatchSnapshot(); + const parsedSchema = parse(out.schema); + validateModelSchema(parsedSchema); + }); }); From 5c05668f6f9018faa1fa60d7305ca73742ab1305 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Mon, 16 Sep 2024 13:06:52 -0700 Subject: [PATCH 03/17] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20utils=20to=20detec?= =?UTF-8?q?t=20Postgres=20datasource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../amplify-graphql-transformer-core/API.md | 6 ++++++ .../src/index.ts | 2 ++ .../utils/model-datasource-strategy-utils.ts | 21 +++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/packages/amplify-graphql-transformer-core/API.md b/packages/amplify-graphql-transformer-core/API.md index ad5de175f2..fcc972b318 100644 --- a/packages/amplify-graphql-transformer-core/API.md +++ b/packages/amplify-graphql-transformer-core/API.md @@ -487,6 +487,12 @@ export const isMutationNode: (obj: DefinitionNode) => obj is ObjectTypeDefinitio // @public (undocumented) export const isObjectTypeDefinitionNode: (obj: DefinitionNode) => obj is ObjectTypeDefinitionNode; +// @public (undocumented) +export const isPostgresDbType: (dbType: ModelDataSourceStrategyDbType) => dbType is ModelDataSourceStrategySqlDbType; + +// @public (undocumented) +export const isPostgresModel: (ctx: DataSourceStrategiesProvider, typename: string) => boolean; + // @public (undocumented) export const isQueryNode: (obj: DefinitionNode) => obj is ObjectTypeDefinitionNode | (InterfaceTypeDefinitionNode & { name: { diff --git a/packages/amplify-graphql-transformer-core/src/index.ts b/packages/amplify-graphql-transformer-core/src/index.ts index 999869500d..ffb107f89b 100644 --- a/packages/amplify-graphql-transformer-core/src/index.ts +++ b/packages/amplify-graphql-transformer-core/src/index.ts @@ -61,6 +61,8 @@ export { isDefaultDynamoDbModelDataSourceStrategy, isDynamoDbModel, isDynamoDbType, + isPostgresModel, + isPostgresDbType, isModelType, isMutationNode, isObjectTypeDefinitionNode, diff --git a/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts b/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts index 5e460a0b7d..5c39bbfb39 100644 --- a/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts +++ b/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts @@ -141,6 +141,27 @@ export const isSqlModel = (ctx: DataSourceStrategiesProvider, typename: string): return isSqlDbType(modelDataSourceType.dbType); }; +/** + * Checks if the given model is a PostgreSQL model + * @param ctx Transformer Context + * @param typename Model name + * @returns boolean + */ +export const isPostgresModel = (ctx: DataSourceStrategiesProvider, typename: string): boolean => { + if (isBuiltInGraphqlType(typename)) { + return false; + } + const modelDataSourceType = getModelDataSourceStrategy(ctx, typename); + return isPostgresDbType(modelDataSourceType.dbType); +}; + +/** + * Type predicate that returns true if `dbType` is a PostgreSQL database type + */ +export const isPostgresDbType = (dbType: ModelDataSourceStrategyDbType): dbType is ModelDataSourceStrategySqlDbType => { + return dbType === POSTGRES_DB_TYPE; +}; + /** * Type predicate that returns true if `obj` is a SQLLambdaModelDataSourceStrategy */ From e25b75f42cbd8d565280d5617551a6743d4f59fb Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Mon, 16 Sep 2024 13:15:03 -0700 Subject: [PATCH 04/17] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20support=20auto=20i?= =?UTF-8?q?ncrement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements support for auto increment (serial) fields from Postgres datasources. Such fields are denoted by an empty `@default` applied to an `Int` field. --- .../src/graphql-default-value-transformer.ts | 26 ++++++++++++++----- .../__snapshots__/index.test.ts.snap | 2 +- .../src/directives/default.ts | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts index 7178eaad41..9972f638b5 100644 --- a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts +++ b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts @@ -4,6 +4,7 @@ import { InputObjectDefinitionWrapper, InvalidDirectiveError, isDynamoDbModel, + isPostgresModel, MappingTemplate, TransformerPluginBase, } from '@aws-amplify/graphql-transformer-core'; @@ -22,7 +23,6 @@ import { Kind, ObjectTypeDefinitionNode, StringValueNode, - TypeNode, } from 'graphql'; import { methodCall, printBlock, qref, raw, ref, str } from 'graphql-mapping-template'; import { getBaseType, isEnum, isListType, isScalarOrEnum, ModelResourceIDs, toCamelCase } from 'graphql-transformer-common'; @@ -31,16 +31,24 @@ import { TypeValidators } from './validators'; const nonStringTypes = ['Int', 'Float', 'Boolean', 'AWSTimestamp', 'AWSJSON']; -const validateFieldType = (ctx: TransformerSchemaVisitStepContextProvider, type: TypeNode): void => { +const validateFieldType = (ctx: TransformerSchemaVisitStepContextProvider, config: DefaultValueDirectiveConfiguration): void => { + const type = config.field.type; + const argc = config.directive.arguments!.length; const enums = ctx.output.getTypeDefinitionsOfKind(Kind.ENUM_TYPE_DEFINITION) as EnumTypeDefinitionNode[]; if (isListType(type) || !isScalarOrEnum(type, enums)) { throw new InvalidDirectiveError('The @default directive may only be added to scalar or enum field types.'); } + if (isPostgresModel(ctx, config.object.name.value) && argc === 0 && getBaseType(type) !== 'Int') { + throw new InvalidDirectiveError('The empty @default (auto-increment) may only be applied to integer fields.'); + } }; -const validateDirectiveArguments = (directive: DirectiveNode): void => { - if (directive.arguments!.length === 0) throw new InvalidDirectiveError('The @default directive must have a value property'); - if (directive.arguments!.length > 1) throw new InvalidDirectiveError('The @default directive only takes a value property'); +const validateDirectiveArguments = (ctx: TransformerSchemaVisitStepContextProvider, config: DefaultValueDirectiveConfiguration): void => { + const argc = config.directive.arguments!.length; + const isPostgres = isPostgresModel(ctx, config.object.name.value); + if (!isPostgres && argc === 0) + throw new InvalidDirectiveError('The @default directive requires a value property on non Postgres datasources.'); + if (argc > 1) throw new InvalidDirectiveError('The @default directive only takes a value property'); }; const validateModelDirective = (config: DefaultValueDirectiveConfiguration): void => { @@ -74,8 +82,8 @@ const validateDefaultValueType = (ctx: TransformerSchemaVisitStepContextProvider const validate = (ctx: TransformerSchemaVisitStepContextProvider, config: DefaultValueDirectiveConfiguration): void => { validateModelDirective(config); - validateFieldType(ctx, config.field.type); - validateDirectiveArguments(config.directive); + validateFieldType(ctx, config); + validateDirectiveArguments(ctx, config); // Validate the default values only for the DynamoDB datasource. // For SQL, the database determines and sets the default value. We will not validate the value in transformers. @@ -123,6 +131,10 @@ export class DefaultValueTransformer extends TransformerPluginBase { const input = InputObjectDefinitionWrapper.fromObject(name, config.object, ctx.inputDocument); const fieldWrapper = input.fields.find((f) => f.name === config.field.name.value); fieldWrapper?.makeNullable(); + + if (isPostgresModel(ctx, typeName)) { + ctx.output.updateInput(input.serialize()); + } } } }; diff --git a/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap b/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap index 8e5b36eecb..c0a20f5bdf 100644 --- a/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/amplify-graphql-directives/src/__tests__/__snapshots__/index.test.ts.snap @@ -255,7 +255,7 @@ exports[`Directive Definitions DefaultDirective 1`] = ` Object { "defaults": Object {}, "definition": " - directive @default(value: String!) on FIELD_DEFINITION + directive @default(value: String) on FIELD_DEFINITION ", "name": "default", } diff --git a/packages/amplify-graphql-directives/src/directives/default.ts b/packages/amplify-graphql-directives/src/directives/default.ts index 4aa8c33020..c378c08073 100644 --- a/packages/amplify-graphql-directives/src/directives/default.ts +++ b/packages/amplify-graphql-directives/src/directives/default.ts @@ -2,7 +2,7 @@ import { Directive } from './directive'; const name = 'default'; const definition = /* GraphQL */ ` - directive @${name}(value: String!) on FIELD_DEFINITION + directive @${name}(value: String) on FIELD_DEFINITION `; const defaults = {}; From f2e350b38bda77d6afc8a0477150b30a1085877d Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 10:15:10 -0700 Subject: [PATCH 05/17] test(graphql-default-value-transformer): pk can be auto increment --- ...hql-default-value-transformer.test.ts.snap | 222 ++++++++++++++++++ ...grapphql-default-value-transformer.test.ts | 20 ++ 2 files changed, 242 insertions(+) diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap index ee5dfc9faf..9786544d0d 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap @@ -1,5 +1,227 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`DefaultValueModelTransformer: should allow auto-increment primary key 1`] = ` +"type CoffeeQueue { + orderNumber: Int! + customer: String! + order: String +} + +input ModelStringInput { + ne: String + eq: String + le: String + lt: String + ge: String + gt: String + contains: String + notContains: String + between: [String] + beginsWith: String + attributeExists: Boolean + attributeType: ModelAttributeTypes + size: ModelSizeInput +} + +input ModelIntInput { + ne: Int + eq: Int + le: Int + lt: Int + ge: Int + gt: Int + between: [Int] + attributeExists: Boolean + attributeType: ModelAttributeTypes +} + +input ModelFloatInput { + ne: Float + eq: Float + le: Float + lt: Float + ge: Float + gt: Float + between: [Float] + attributeExists: Boolean + attributeType: ModelAttributeTypes +} + +input ModelBooleanInput { + ne: Boolean + eq: Boolean + attributeExists: Boolean + attributeType: ModelAttributeTypes +} + +input ModelIDInput { + ne: ID + eq: ID + le: ID + lt: ID + ge: ID + gt: ID + contains: ID + notContains: ID + between: [ID] + beginsWith: ID + attributeExists: Boolean + attributeType: ModelAttributeTypes + size: ModelSizeInput +} + +input ModelSubscriptionStringInput { + ne: String + eq: String + le: String + lt: String + ge: String + gt: String + contains: String + notContains: String + between: [String] + beginsWith: String + in: [String] + notIn: [String] +} + +input ModelSubscriptionIntInput { + ne: Int + eq: Int + le: Int + lt: Int + ge: Int + gt: Int + between: [Int] + in: [Int] + notIn: [Int] +} + +input ModelSubscriptionFloatInput { + ne: Float + eq: Float + le: Float + lt: Float + ge: Float + gt: Float + between: [Float] + in: [Float] + notIn: [Float] +} + +input ModelSubscriptionBooleanInput { + ne: Boolean + eq: Boolean +} + +input ModelSubscriptionIDInput { + ne: ID + eq: ID + le: ID + lt: ID + ge: ID + gt: ID + contains: ID + notContains: ID + between: [ID] + beginsWith: ID + in: [ID] + notIn: [ID] +} + +enum ModelAttributeTypes { + binary + binarySet + bool + list + map + number + numberSet + string + stringSet + _null +} + +input ModelSizeInput { + ne: Int + eq: Int + le: Int + lt: Int + ge: Int + gt: Int + between: [Int] +} + +enum ModelSortDirection { + ASC + DESC +} + +type ModelCoffeeQueueConnection { + items: [CoffeeQueue]! + nextToken: String +} + +input ModelCoffeeQueueFilterInput { + orderNumber: ModelIntInput + customer: ModelStringInput + order: ModelStringInput + and: [ModelCoffeeQueueFilterInput] + or: [ModelCoffeeQueueFilterInput] + not: ModelCoffeeQueueFilterInput +} + +type Query { + getCoffeeQueue(orderNumber: Int!): CoffeeQueue + listCoffeeQueues(orderNumber: Int, filter: ModelCoffeeQueueFilterInput, limit: Int, nextToken: String, sortDirection: ModelSortDirection): ModelCoffeeQueueConnection +} + +input ModelCoffeeQueueConditionInput { + customer: ModelStringInput + order: ModelStringInput + and: [ModelCoffeeQueueConditionInput] + or: [ModelCoffeeQueueConditionInput] + not: ModelCoffeeQueueConditionInput +} + +input CreateCoffeeQueueInput { + orderNumber: Int + customer: String! + order: String +} + +input UpdateCoffeeQueueInput { + orderNumber: Int! + customer: String + order: String +} + +input DeleteCoffeeQueueInput { + orderNumber: Int! +} + +type Mutation { + createCoffeeQueue(input: CreateCoffeeQueueInput!, condition: ModelCoffeeQueueConditionInput): CoffeeQueue + updateCoffeeQueue(input: UpdateCoffeeQueueInput!, condition: ModelCoffeeQueueConditionInput): CoffeeQueue + deleteCoffeeQueue(input: DeleteCoffeeQueueInput!, condition: ModelCoffeeQueueConditionInput): CoffeeQueue +} + +input ModelSubscriptionCoffeeQueueFilterInput { + orderNumber: ModelSubscriptionIntInput + customer: ModelSubscriptionStringInput + order: ModelSubscriptionStringInput + and: [ModelSubscriptionCoffeeQueueFilterInput] + or: [ModelSubscriptionCoffeeQueueFilterInput] +} + +type Subscription { + onCreateCoffeeQueue(filter: ModelSubscriptionCoffeeQueueFilterInput): CoffeeQueue @aws_subscribe(mutations: [\\"createCoffeeQueue\\"]) + onUpdateCoffeeQueue(filter: ModelSubscriptionCoffeeQueueFilterInput): CoffeeQueue @aws_subscribe(mutations: [\\"updateCoffeeQueue\\"]) + onDeleteCoffeeQueue(filter: ModelSubscriptionCoffeeQueueFilterInput): CoffeeQueue @aws_subscribe(mutations: [\\"deleteCoffeeQueue\\"]) +} +" +`; + exports[`DefaultValueModelTransformer: should be supported on a required field. 1`] = ` "type Test { id: ID! diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts index 477b848d54..41fe31e6b0 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts @@ -264,4 +264,24 @@ describe('DefaultValueModelTransformer:', () => { const parsedSchema = parse(out.schema); validateModelSchema(parsedSchema); }); + + it('should allow auto-increment primary key', async () => { + const schema = ` + type CoffeeQueue @model { + orderNumber: Int! @primaryKey @default + order: String! + customer: String + } + `; + const strategy = mockSqlDataSourceStrategy({ dbType: POSTGRES_DB_TYPE }); + const out = testTransform({ + schema, + transformers: [new ModelTransformer(), new DefaultValueTransformer(), new PrimaryKeyTransformer()], + dataSourceStrategies: constructDataSourceStrategies(schema, strategy), + }); + expect(out).toBeDefined(); + expect(out.schema).toMatchSnapshot(); + const parsedSchema = parse(out.schema); + validateModelSchema(parsedSchema); + }); }); From 978079aa2272842323fb7034fe6d024382a813fa Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 11:07:37 -0700 Subject: [PATCH 06/17] test(graphql-default-value-transformer): auto-increment crud e2e --- codebuild_specs/e2e_workflow.yml | 134 +++++++------ .../__tests__/sql-pg-auto-increment.test.ts | 61 ++++++ .../sql-models-auto-increment.ts | 187 ++++++++++++++++++ ...hql-default-value-transformer.test.ts.snap | 16 +- 4 files changed, 328 insertions(+), 70 deletions(-) create mode 100644 packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.test.ts create mode 100644 packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts diff --git a/codebuild_specs/e2e_workflow.yml b/codebuild_specs/e2e_workflow.yml index 7b1c947886..2ee18c1c4e 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_auto_increment + 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-auto-increment.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-auto-increment.test.ts b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.test.ts new file mode 100644 index 0000000000..c406df63fc --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.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 { testGraphQLAPIAutoIncrement } from '../sql-tests-common/sql-models-auto-increment'; + +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()}coffee_queue" ("orderNumber" SERIAL PRIMARY KEY, "order" VARCHAR(256) NOT NULL, "customer" VARCHAR(256))`, + ], + { + 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, + }); + + testGraphQLAPIAutoIncrement( + constructTestOptions('ssm'), + 'creates a GraphQL API from SQL-based models with SSM Credential Store', + ImportedRDSType.POSTGRESQL, + ); + + testGraphQLAPIAutoIncrement( + constructTestOptions('connectionUri'), + 'creates a GraphQL API from SQL-based models using Connection String SSM parameter', + ImportedRDSType.POSTGRESQL, + ); +}); diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts new file mode 100644 index 0000000000..17fa2212e5 --- /dev/null +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -0,0 +1,187 @@ +import * as path from 'path'; +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 { initCDKProject, cdkDeploy, cdkDestroy } from '../commands'; +import { SqlDatatabaseController } from '../sql-datatabase-controller'; +import { CRUDLHelper } from '../utils/sql-crudl-helper'; +import { ONE_MINUTE } from '../utils/duration-constants'; + +export const testGraphQLAPIAutoIncrement = ( + options: { + projFolderName: string; + region: string; + connectionConfigName: string; + dbController: SqlDatatabaseController; + resourceNames: { sqlLambdaAliasName: string }; + }, + testBlockDescription: string, + engine: ImportedRDSType, +): void => { + describe(`${testBlockDescription} - ${engine}`, () => { + const amplifyGraphqlSchema = ` + type CoffeeQueue @model @refersTo(name: "${getRDSTableNamePrefix()}coffee_queue") { + orderNumber: Int! @primaryKey @default + order: String! + customer: String + } + `; + + const { projFolderName, region, connectionConfigName, dbController, resourceNames } = options; + const templatePath = path.resolve(path.join(__dirname, '..', '__tests__', 'backends', 'sql-models')); + + let projRoot: string; + let name: string; + let outputs: Promise; + let coffeeQueueTableCRUDLHelper: CRUDLHelper; + + beforeAll(async () => { + projRoot = await createNewProjectDir(projFolderName); + name = await initCDKProject(projRoot, templatePath); + dbController.writeDbDetails(projRoot, connectionConfigName, amplifyGraphqlSchema); + outputs = await cdkDeploy(projRoot, '--all', { postDeployWaitMs: ONE_MINUTE }); + const { awsAppsyncApiEndpoint: apiEndpoint, awsAppsyncApiKey: apiKey } = outputs[name]; + + const appSyncClient = new AWSAppSyncClient({ + url: apiEndpoint, + region, + disableOffline: true, + auth: { + type: AUTH_TYPE.API_KEY, + apiKey, + }, + }); + + coffeeQueueTableCRUDLHelper = new CRUDLHelper(appSyncClient, 'CoffeeQueue', 'CoffeeQueues', ['orderNumber', 'order', 'customer']); + }); + + 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 coffee queue table with auto increment primary key - ${engine}`, async () => { + // Order Coffee Mutation + const createCoffeeOrder1 = await coffeeQueueTableCRUDLHelper.create({ customer: 'petesv', order: 'cold brew' }); + + expect(createCoffeeOrder1).toBeDefined(); + expect(createCoffeeOrder1.orderNumber).toBeDefined(); + expect(createCoffeeOrder1.customer).toEqual('petesv'); + expect(createCoffeeOrder1.order).toEqual('cold brew'); + + // Get Todo Query + const getCoffeeOrder1 = await coffeeQueueTableCRUDLHelper.get({ orderNumber: createCoffeeOrder1.orderNumber }); + + expect(getCoffeeOrder1.orderNumber).toEqual(createCoffeeOrder1.orderNumber); + expect(getCoffeeOrder1.customer).toEqual(createCoffeeOrder1.customer); + + // Update Todo Mutation + const updateCoffeeOrder1 = await coffeeQueueTableCRUDLHelper.update({ + orderNumber: createCoffeeOrder1.orderNumber, + customer: 'petesv', + order: 'hot brew', + }); + + expect(updateCoffeeOrder1.orderNumber).toEqual(createCoffeeOrder1.orderNumber); + expect(updateCoffeeOrder1.order).toEqual('hot brew'); + + // Get Todo Query after update + const getUpdatedCoffeeOrder1 = await coffeeQueueTableCRUDLHelper.get({ orderNumber: createCoffeeOrder1.orderNumber }); + + expect(getUpdatedCoffeeOrder1.orderNumber).toEqual(createCoffeeOrder1.orderNumber); + expect(getUpdatedCoffeeOrder1.order).toEqual('hot brew'); + + // List Todo Query + const createCofffeeOrder2 = await coffeeQueueTableCRUDLHelper.create({ order: 'latte' }); + const listTodo = await coffeeQueueTableCRUDLHelper.list(); + + expect(listTodo.items.length).toEqual(2); + expect(listTodo.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + orderNumber: getUpdatedCoffeeOrder1.orderNumber, + order: 'hot brew', + }), + expect.objectContaining({ + orderNumber: createCofffeeOrder2.orderNumber, + order: 'latte', + }), + ]), + ); + + // Delete Todo Mutation + const deleteCoffeeOrder1 = await coffeeQueueTableCRUDLHelper.delete({ orderNumber: createCoffeeOrder1.orderNumber }); + + expect(deleteCoffeeOrder1.orderNumber).toEqual(createCoffeeOrder1.orderNumber); + expect(deleteCoffeeOrder1.order).toEqual('hot brew'); + + const getDeletedCoffeeOrder1 = await coffeeQueueTableCRUDLHelper.get({ orderNumber: createCoffeeOrder1.orderNumber }); + + expect(getDeletedCoffeeOrder1).toBeNull(); + + // List Todo Query after delete + const listCoffeeOrdersAfterDelete = await coffeeQueueTableCRUDLHelper.list(); + + expect(listCoffeeOrdersAfterDelete.items.length).toEqual(1); + expect(listCoffeeOrdersAfterDelete.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + orderNumber: createCofffeeOrder2.orderNumber, + order: 'latte', + }), + ]), + ); + + // Check invalid CRUD operation returns generic error message + const createTodo6 = await coffeeQueueTableCRUDLHelper.create({ order: 'mocha' }); + + try { + await coffeeQueueTableCRUDLHelper.create({ orderNumber: createTodo6.orderNumber, order: 'americano' }); + } catch (error) { + console.log('throw in create'); + coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); + } + + const invalidOrderNumber = 99999999; + + try { + await coffeeQueueTableCRUDLHelper.get({ orderNumber: invalidOrderNumber }); + } catch (error) { + console.log('throw in get'); + coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); + } + + try { + await coffeeQueueTableCRUDLHelper.update({ orderNumber: invalidOrderNumber, order: 'cortado' }); + } catch (error) { + console.log('throw in update'); + coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); + } + + try { + await coffeeQueueTableCRUDLHelper.delete({ orderNumber: invalidOrderNumber }); + } catch (error) { + console.log('throw in delete'); + coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); + } + }); + + 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, + }); + const response = await client.send(command); + expect(response.RequestedProvisionedConcurrentExecutions).toEqual(2); + }); + }); +}; diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap index 9786544d0d..85be8a4600 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap @@ -3,8 +3,8 @@ exports[`DefaultValueModelTransformer: should allow auto-increment primary key 1`] = ` "type CoffeeQueue { orderNumber: Int! - customer: String! - order: String + order: String! + customer: String } input ModelStringInput { @@ -164,8 +164,8 @@ type ModelCoffeeQueueConnection { input ModelCoffeeQueueFilterInput { orderNumber: ModelIntInput - customer: ModelStringInput order: ModelStringInput + customer: ModelStringInput and: [ModelCoffeeQueueFilterInput] or: [ModelCoffeeQueueFilterInput] not: ModelCoffeeQueueFilterInput @@ -177,8 +177,8 @@ type Query { } input ModelCoffeeQueueConditionInput { - customer: ModelStringInput order: ModelStringInput + customer: ModelStringInput and: [ModelCoffeeQueueConditionInput] or: [ModelCoffeeQueueConditionInput] not: ModelCoffeeQueueConditionInput @@ -186,14 +186,14 @@ input ModelCoffeeQueueConditionInput { input CreateCoffeeQueueInput { orderNumber: Int - customer: String! - order: String + order: String! + customer: String } input UpdateCoffeeQueueInput { orderNumber: Int! - customer: String order: String + customer: String } input DeleteCoffeeQueueInput { @@ -208,8 +208,8 @@ type Mutation { input ModelSubscriptionCoffeeQueueFilterInput { orderNumber: ModelSubscriptionIntInput - customer: ModelSubscriptionStringInput order: ModelSubscriptionStringInput + customer: ModelSubscriptionStringInput and: [ModelSubscriptionCoffeeQueueFilterInput] or: [ModelSubscriptionCoffeeQueueFilterInput] } From 89f3fd387c8cfad8db1f3a07753cd7d685029366 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 13:31:55 -0700 Subject: [PATCH 07/17] chore: describe test purpose --- .../src/sql-tests-common/sql-models-auto-increment.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts index 17fa2212e5..8ef74eb116 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -20,6 +20,10 @@ export const testGraphQLAPIAutoIncrement = ( engine: ImportedRDSType, ): void => { describe(`${testBlockDescription} - ${engine}`, () => { + // In particular, we want to verify that the new CREATE operation + // is allowed to omit the primary key field, and that the primary key + // we get back is the correct, db generated value. + // NOTE: Expects underlying orderNumber column to be a serial primary key in Postgres table const amplifyGraphqlSchema = ` type CoffeeQueue @model @refersTo(name: "${getRDSTableNamePrefix()}coffee_queue") { orderNumber: Int! @primaryKey @default From 2e5eebd25ac59e5d548cf13548446ac74ad3059d Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 13:32:31 -0700 Subject: [PATCH 08/17] chore: removing logging --- .../src/sql-tests-common/sql-models-auto-increment.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts index 8ef74eb116..cca6d1b400 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -149,7 +149,6 @@ export const testGraphQLAPIAutoIncrement = ( try { await coffeeQueueTableCRUDLHelper.create({ orderNumber: createTodo6.orderNumber, order: 'americano' }); } catch (error) { - console.log('throw in create'); coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } @@ -158,21 +157,18 @@ export const testGraphQLAPIAutoIncrement = ( try { await coffeeQueueTableCRUDLHelper.get({ orderNumber: invalidOrderNumber }); } catch (error) { - console.log('throw in get'); coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } try { await coffeeQueueTableCRUDLHelper.update({ orderNumber: invalidOrderNumber, order: 'cortado' }); } catch (error) { - console.log('throw in update'); coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } try { await coffeeQueueTableCRUDLHelper.delete({ orderNumber: invalidOrderNumber }); } catch (error) { - console.log('throw in delete'); coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } }); From 50db9e8271256cbc341fe3f26a37077fca136c97 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 13:39:38 -0700 Subject: [PATCH 09/17] chore: describe why invalid cases are invalid --- .../src/sql-tests-common/sql-models-auto-increment.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts index cca6d1b400..24f629bf40 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -147,27 +147,28 @@ export const testGraphQLAPIAutoIncrement = ( const createTodo6 = await coffeeQueueTableCRUDLHelper.create({ order: 'mocha' }); try { + // Invalid because the pk (orderNumber) already exists await coffeeQueueTableCRUDLHelper.create({ orderNumber: createTodo6.orderNumber, order: 'americano' }); } catch (error) { coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } - const invalidOrderNumber = 99999999; + const biggerThanAnyExistingOrderNumber = 99999999; try { - await coffeeQueueTableCRUDLHelper.get({ orderNumber: invalidOrderNumber }); + await coffeeQueueTableCRUDLHelper.get({ orderNumber: biggerThanAnyExistingOrderNumber }); } catch (error) { coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } try { - await coffeeQueueTableCRUDLHelper.update({ orderNumber: invalidOrderNumber, order: 'cortado' }); + await coffeeQueueTableCRUDLHelper.update({ orderNumber: biggerThanAnyExistingOrderNumber, order: 'cortado' }); } catch (error) { coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } try { - await coffeeQueueTableCRUDLHelper.delete({ orderNumber: invalidOrderNumber }); + await coffeeQueueTableCRUDLHelper.delete({ orderNumber: biggerThanAnyExistingOrderNumber }); } catch (error) { coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } From 12d5f285a0995b5f1772538c4dafdd603e793a0f Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 13:43:38 -0700 Subject: [PATCH 10/17] chore: remove unecessary e2e test case --- .../src/sql-tests-common/sql-models-auto-increment.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts index 24f629bf40..1ac361494b 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -173,16 +173,5 @@ export const testGraphQLAPIAutoIncrement = ( coffeeQueueTableCRUDLHelper.checkGenericError(error?.message); } }); - - 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, - }); - const response = await client.send(command); - expect(response.RequestedProvisionedConcurrentExecutions).toEqual(2); - }); }); }; From 1824129dd10c46db04f1f39cd18429730674c2f8 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 14:04:38 -0700 Subject: [PATCH 11/17] chore: test messaging clarity --- .../sql-tests-common/sql-models-auto-increment.ts | 3 +-- ...rapphql-default-value-transformer.test.ts.snap | 2 +- ...ify-grapphql-default-value-transformer.test.ts | 15 ++++++++------- .../src/graphql-default-value-transformer.ts | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts index 1ac361494b..c6874683ed 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -1,5 +1,4 @@ import * as path from 'path'; -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'; @@ -32,7 +31,7 @@ export const testGraphQLAPIAutoIncrement = ( } `; - const { projFolderName, region, connectionConfigName, dbController, resourceNames } = options; + const { projFolderName, region, connectionConfigName, dbController } = options; const templatePath = path.resolve(path.join(__dirname, '..', '__tests__', 'backends', 'sql-models')); let projRoot: string; diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap index 85be8a4600..e37213cd0a 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/__snapshots__/amplify-grapphql-default-value-transformer.test.ts.snap @@ -453,7 +453,7 @@ $util.qr($context.args.input.put(\\"stringValue\\", $util.defaultIfNull($ctx.arg {}" `; -exports[`DefaultValueModelTransformer: should successfully transform a schema that implies auto-increment 1`] = ` +exports[`DefaultValueModelTransformer: should successfully transform a simple schema with @default 1`] = ` "type TestAutoIncrement { id: ID! value: Int diff --git a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts index 41fe31e6b0..fc5911c731 100644 --- a/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts +++ b/packages/amplify-graphql-default-value-transformer/src/__tests__/amplify-grapphql-default-value-transformer.test.ts @@ -2,6 +2,7 @@ import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { constructDataSourceStrategies, getResourceNamesForStrategy, + MYSQL_DB_TYPE, POSTGRES_DB_TYPE, validateModelSchema, } from '@aws-amplify/graphql-transformer-core'; @@ -50,7 +51,7 @@ describe('DefaultValueModelTransformer:', () => { { type: 'String', value: undefined, - expectedError: 'The @default directive requires a value property on non Postgres datasources.', + expectedError: 'The @default directive requires a value property on non-Postgres datasources.', }, { type: 'Int', value: '"text"', expectedError: 'Default value "text" is not a valid Int.' }, { type: 'Boolean', value: '"text"', expectedError: 'Default value "text" is not a valid Boolean.' }, @@ -199,8 +200,8 @@ describe('DefaultValueModelTransformer:', () => { expect(out.resolvers['Mutation.createNote.init.2.req.vtl']).toBeUndefined(); }); - it.each([{ strategy: mockSqlDataSourceStrategy() }])( - 'throws if auto-increment is implied on a non-Postgres datasource', + it.each([{ strategy: mockSqlDataSourceStrategy({ dbType: MYSQL_DB_TYPE }), datasourceName: 'mysql' }])( + 'throws if @default (no args) is used non-Postgres datasource (%datasourceName)', ({ strategy }) => { const schema = ` type CoffeeQueue @model { @@ -214,7 +215,7 @@ describe('DefaultValueModelTransformer:', () => { transformers: [new ModelTransformer(), new DefaultValueTransformer(), new PrimaryKeyTransformer()], dataSourceStrategies: constructDataSourceStrategies(schema, strategy), }); - }).toThrow('The @default directive requires a value property on non Postgres datasources.'); + }).toThrow('The @default directive requires a value property on non-Postgres datasources.'); }, ); @@ -228,7 +229,7 @@ describe('DefaultValueModelTransformer:', () => { { typeStr: 'AWSURL' }, { typeStr: 'AWSPhone' }, { typeStr: 'AWSIPAddress' }, - ])('throws if auto-increment is implied on non-int types', ({ typeStr }) => { + ])('throws if @default (no args) is used on non-int types (case: $typeStr)', ({ typeStr }) => { const strategy = mockSqlDataSourceStrategy({ dbType: POSTGRES_DB_TYPE }); expect(() => { @@ -243,10 +244,10 @@ describe('DefaultValueModelTransformer:', () => { transformers: [new ModelTransformer(), new DefaultValueTransformer(), new PrimaryKeyTransformer()], dataSourceStrategies: constructDataSourceStrategies(schema, strategy), }); - }).toThrow('The empty @default (auto-increment) may only be applied to integer fields.'); + }).toThrow('The @default directive requires a value property on non-Int types.'); }); - it('should successfully transform a schema that implies auto-increment', async () => { + it('should successfully transform a simple schema with @default', async () => { const schema = ` type TestAutoIncrement @model { id: ID! @primaryKey diff --git a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts index 9972f638b5..b86ee47805 100644 --- a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts +++ b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts @@ -39,7 +39,7 @@ const validateFieldType = (ctx: TransformerSchemaVisitStepContextProvider, confi throw new InvalidDirectiveError('The @default directive may only be added to scalar or enum field types.'); } if (isPostgresModel(ctx, config.object.name.value) && argc === 0 && getBaseType(type) !== 'Int') { - throw new InvalidDirectiveError('The empty @default (auto-increment) may only be applied to integer fields.'); + throw new InvalidDirectiveError('The @default directive requires a value property on non-Int types.'); } }; @@ -47,7 +47,7 @@ const validateDirectiveArguments = (ctx: TransformerSchemaVisitStepContextProvid const argc = config.directive.arguments!.length; const isPostgres = isPostgresModel(ctx, config.object.name.value); if (!isPostgres && argc === 0) - throw new InvalidDirectiveError('The @default directive requires a value property on non Postgres datasources.'); + throw new InvalidDirectiveError('The @default directive requires a value property on non-Postgres datasources.'); if (argc > 1) throw new InvalidDirectiveError('The @default directive only takes a value property'); }; From ba881542aed8b0bf11adcf6caf139e5714ed6d85 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 14:08:16 -0700 Subject: [PATCH 12/17] chore: type safety --- .../src/graphql-default-value-transformer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts index b86ee47805..2ed188d645 100644 --- a/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts +++ b/packages/amplify-graphql-default-value-transformer/src/graphql-default-value-transformer.ts @@ -33,7 +33,7 @@ const nonStringTypes = ['Int', 'Float', 'Boolean', 'AWSTimestamp', 'AWSJSON']; const validateFieldType = (ctx: TransformerSchemaVisitStepContextProvider, config: DefaultValueDirectiveConfiguration): void => { const type = config.field.type; - const argc = config.directive.arguments!.length; + const argc = config.directive.arguments?.length ?? 0; const enums = ctx.output.getTypeDefinitionsOfKind(Kind.ENUM_TYPE_DEFINITION) as EnumTypeDefinitionNode[]; if (isListType(type) || !isScalarOrEnum(type, enums)) { throw new InvalidDirectiveError('The @default directive may only be added to scalar or enum field types.'); @@ -44,7 +44,7 @@ const validateFieldType = (ctx: TransformerSchemaVisitStepContextProvider, confi }; const validateDirectiveArguments = (ctx: TransformerSchemaVisitStepContextProvider, config: DefaultValueDirectiveConfiguration): void => { - const argc = config.directive.arguments!.length; + const argc = config.directive.arguments?.length ?? 0; const isPostgres = isPostgresModel(ctx, config.object.name.value); if (!isPostgres && argc === 0) throw new InvalidDirectiveError('The @default directive requires a value property on non-Postgres datasources.'); From f6f18b96d505ac2744398ddf2cedf987a1f7dee1 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 14:13:37 -0700 Subject: [PATCH 13/17] chore: alphabetize list --- packages/amplify-graphql-transformer-core/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/amplify-graphql-transformer-core/src/index.ts b/packages/amplify-graphql-transformer-core/src/index.ts index ffb107f89b..ac8f8f796b 100644 --- a/packages/amplify-graphql-transformer-core/src/index.ts +++ b/packages/amplify-graphql-transformer-core/src/index.ts @@ -61,11 +61,11 @@ export { isDefaultDynamoDbModelDataSourceStrategy, isDynamoDbModel, isDynamoDbType, - isPostgresModel, - isPostgresDbType, isModelType, isMutationNode, isObjectTypeDefinitionNode, + isPostgresDbType, + isPostgresModel, isQueryNode, isQueryType, isSqlDbType, From 47caabffef34a2e0942b8c648ab9894df13c0772 Mon Sep 17 00:00:00 2001 From: "Peter V." <98245483+p5quared@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:16:58 -0700 Subject: [PATCH 14/17] chore: type of return value asserts against string Co-authored-by: Tim Schmelter --- .../src/utils/model-datasource-strategy-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts b/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts index 5c39bbfb39..863877e78a 100644 --- a/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts +++ b/packages/amplify-graphql-transformer-core/src/utils/model-datasource-strategy-utils.ts @@ -158,7 +158,7 @@ export const isPostgresModel = (ctx: DataSourceStrategiesProvider, typename: str /** * Type predicate that returns true if `dbType` is a PostgreSQL database type */ -export const isPostgresDbType = (dbType: ModelDataSourceStrategyDbType): dbType is ModelDataSourceStrategySqlDbType => { +export const isPostgresDbType = (dbType: ModelDataSourceStrategyDbType): dbType is 'POSTGRES' => { return dbType === POSTGRES_DB_TYPE; }; From b929519b1eccc06c12930ba2b2ed8417755a6109 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 14:34:23 -0700 Subject: [PATCH 15/17] chore: test ensures customers can insert to serial fields with custom values --- .../src/sql-tests-common/sql-models-auto-increment.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts index c6874683ed..daa635660e 100644 --- a/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts +++ b/packages/amplify-graphql-api-construct-tests/src/sql-tests-common/sql-models-auto-increment.ts @@ -101,10 +101,12 @@ export const testGraphQLAPIAutoIncrement = ( expect(getUpdatedCoffeeOrder1.orderNumber).toEqual(createCoffeeOrder1.orderNumber); expect(getUpdatedCoffeeOrder1.order).toEqual('hot brew'); - // List Todo Query - const createCofffeeOrder2 = await coffeeQueueTableCRUDLHelper.create({ order: 'latte' }); - const listTodo = await coffeeQueueTableCRUDLHelper.list(); + // List Todo Query & Create with custom SERIAL field value + const customOrderNumber = 42; + const createCofffeeOrder2 = await coffeeQueueTableCRUDLHelper.create({ orderNumber: customOrderNumber, order: 'latte' }); + expect(createCofffeeOrder2.orderNumber).toEqual(customOrderNumber); + const listTodo = await coffeeQueueTableCRUDLHelper.list(); expect(listTodo.items.length).toEqual(2); expect(listTodo.items).toEqual( expect.arrayContaining([ From 37c7198c7ff092f2f6982a44fd7a2d2bc7602395 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 15:04:30 -0700 Subject: [PATCH 16/17] chore: verify that @default(value) works on mysql --- .../src/sql-tests-common/sql-models.ts | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) 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..ad4a46ad4f 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 @@ -20,10 +20,11 @@ export const testGraphQLAPI = ( engine: ImportedRDSType, ): void => { describe(`${testBlockDescription} - ${engine}`, () => { + const defaultTodoDescription = 'Lorem Ipsum yadda yadda'; const amplifyGraphqlSchema = ` type Todo @model @refersTo(name: "${getRDSTableNamePrefix()}todos") { id: ID! @primaryKey - description: String! + description: String! @default("${defaultTodoDescription}") } type Student @model @refersTo(name: "${getRDSTableNamePrefix()}students") { studentId: Int! @primaryKey(sortKeyFields: ["classId"]) @@ -72,6 +73,32 @@ export const testGraphQLAPI = ( deleteProjectDir(projRoot); }); + test(`check default value on todo table - ${engine}`, async () => { + // Create Todo Mutation + const createTodo1 = await toDoTableCRUDLHelper.create({}); + + expect(createTodo1).toBeDefined(); + expect(createTodo1.id).toBeDefined(); + expect(createTodo1.description).toEqual(defaultTodoDescription); + + // Get Todo Query + const getTodo1 = await toDoTableCRUDLHelper.getById(createTodo1.id); + expect(getTodo1.id).toEqual(createTodo1.id); + expect(getTodo1.description).toEqual(createTodo1.description); + + // Update Todo Mutation + const updateTodo1 = await toDoTableCRUDLHelper.update({ id: createTodo1.id, description: 'Updated Todo #1' }); + + expect(updateTodo1.id).toEqual(createTodo1.id); + expect(updateTodo1.description).toEqual('Updated Todo #1'); + + // Get Todo Query after update + const getUpdatedTodo1 = await toDoTableCRUDLHelper.getById(createTodo1.id); + + expect(getUpdatedTodo1.id).toEqual(createTodo1.id); + expect(getUpdatedTodo1.description).toEqual('Updated Todo #1'); + }); + test(`check CRUDL on todo table with default primary key - ${engine}`, async () => { // Create Todo Mutation const createTodo1 = await toDoTableCRUDLHelper.create({ description: 'Todo #1' }); From f0adbce9fa0fb6e076521f24342d363c9b47bf03 Mon Sep 17 00:00:00 2001 From: Peter Vaiciulis Date: Tue, 1 Oct 2024 15:45:21 -0700 Subject: [PATCH 17/17] chore: remove unecessary ssm test case --- .../src/__tests__/sql-pg-auto-increment.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.test.ts b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.test.ts index c406df63fc..acbdc63398 100644 --- a/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.test.ts +++ b/packages/amplify-graphql-api-construct-tests/src/__tests__/sql-pg-auto-increment.test.ts @@ -47,12 +47,6 @@ describe('CDK GraphQL Transformer deployments with Postgres SQL datasources', () resourceNames, }); - testGraphQLAPIAutoIncrement( - constructTestOptions('ssm'), - 'creates a GraphQL API from SQL-based models with SSM Credential Store', - ImportedRDSType.POSTGRESQL, - ); - testGraphQLAPIAutoIncrement( constructTestOptions('connectionUri'), 'creates a GraphQL API from SQL-based models using Connection String SSM parameter',