diff --git a/packages/amplify_datastore/example/lib/models/CustomTypeWithAppsyncScalarTypes.dart b/packages/amplify_datastore/example/lib/models/CustomTypeWithAppsyncScalarTypes.dart index 8d110d6129..bdf0530756 100644 --- a/packages/amplify_datastore/example/lib/models/CustomTypeWithAppsyncScalarTypes.dart +++ b/packages/amplify_datastore/example/lib/models/CustomTypeWithAppsyncScalarTypes.dart @@ -19,10 +19,11 @@ // ignore_for_file: public_member_api_docs, annotate_overrides, dead_code, dead_codepublic_member_api_docs, depend_on_referenced_packages, file_names, library_private_types_in_public_api, no_leading_underscores_for_library_prefixes, no_leading_underscores_for_local_identifiers, non_constant_identifier_names, null_check_on_nullable_type_parameter, override_on_non_overriding_member, prefer_adjacent_string_concatenation, prefer_const_constructors, prefer_if_null_operators, prefer_interpolation_to_compose_strings, slash_for_doc_comments, sort_child_properties_last, unnecessary_const, unnecessary_constructor_name, unnecessary_late, unnecessary_new, unnecessary_null_aware_assignments, unnecessary_nullable_for_final_variable_declarations, unnecessary_string_interpolations, use_build_context_synchronously -import 'ModelProvider.dart'; import 'package:amplify_core/amplify_core.dart' as amplify_core; import 'package:collection/collection.dart'; +import 'ModelProvider.dart'; + /** This is an auto generated class representing the CustomTypeWithAppsyncScalarTypes type in your schema. */ class CustomTypeWithAppsyncScalarTypes { final String? _stringValue; @@ -738,14 +739,17 @@ class CustomTypeWithAppsyncScalarTypes { .toList() : null, _customTypeValue = json['customTypeValue'] != null - ? SimpleCustomType.fromJson( - new Map.from(json['customTypeValue'])) + ? json['customTypeValue']['serializedData'] != null + ? SimpleCustomType.fromJson(new Map.from( + json['customTypeValue']['serializedData'])) + : SimpleCustomType.fromJson( + new Map.from(json['customTypeValue'])) : null, _listOfCustomTypeValue = json['listOfCustomTypeValue'] is List ? (json['listOfCustomTypeValue'] as List) .where((e) => e != null) - .map((e) => - SimpleCustomType.fromJson(new Map.from(e))) + .map((e) => SimpleCustomType.fromJson( + new Map.from(e['serializedData'] ?? e))) .toList() : null; diff --git a/packages/amplify_datastore/example/lib/models/ModelWithCustomType.dart b/packages/amplify_datastore/example/lib/models/ModelWithCustomType.dart index 4013a30b5d..5cf1c363f7 100644 --- a/packages/amplify_datastore/example/lib/models/ModelWithCustomType.dart +++ b/packages/amplify_datastore/example/lib/models/ModelWithCustomType.dart @@ -19,10 +19,11 @@ // ignore_for_file: public_member_api_docs, annotate_overrides, dead_code, dead_codepublic_member_api_docs, depend_on_referenced_packages, file_names, library_private_types_in_public_api, no_leading_underscores_for_library_prefixes, no_leading_underscores_for_local_identifiers, non_constant_identifier_names, null_check_on_nullable_type_parameter, override_on_non_overriding_member, prefer_adjacent_string_concatenation, prefer_const_constructors, prefer_if_null_operators, prefer_interpolation_to_compose_strings, slash_for_doc_comments, sort_child_properties_last, unnecessary_const, unnecessary_constructor_name, unnecessary_late, unnecessary_new, unnecessary_null_aware_assignments, unnecessary_nullable_for_final_variable_declarations, unnecessary_string_interpolations, use_build_context_synchronously -import 'ModelProvider.dart'; import 'package:amplify_core/amplify_core.dart' as amplify_core; import 'package:collection/collection.dart'; +import 'ModelProvider.dart'; + /** This is an auto generated class representing the ModelWithCustomType type in your schema. */ class ModelWithCustomType extends amplify_core.Model { static const classType = const _ModelWithCustomTypeModelType(); @@ -152,14 +153,18 @@ class ModelWithCustomType extends amplify_core.Model { ModelWithCustomType.fromJson(Map json) : id = json['id'], _customTypeValue = json['customTypeValue'] != null - ? CustomTypeWithAppsyncScalarTypes.fromJson( - new Map.from(json['customTypeValue'])) + ? json['customTypeValue']['serializedData'] != null + ? CustomTypeWithAppsyncScalarTypes.fromJson( + new Map.from( + json['customTypeValue']['serializedData'])) + : CustomTypeWithAppsyncScalarTypes.fromJson( + new Map.from(json['customTypeValue'])) : null, _listOfCustomTypeValue = json['listOfCustomTypeValue'] is List ? (json['listOfCustomTypeValue'] as List) .where((e) => e != null) .map((e) => CustomTypeWithAppsyncScalarTypes.fromJson( - new Map.from(e))) + new Map.from(e['serializedData'] ?? e))) .toList() : null, _createdAt = json['createdAt'] != null diff --git a/packages/api/amplify_api_dart/test/graphql_test.dart b/packages/api/amplify_api_dart/test/graphql_test.dart index 1c14641b0b..bf1e9d0ed9 100644 --- a/packages/api/amplify_api_dart/test/graphql_test.dart +++ b/packages/api/amplify_api_dart/test/graphql_test.dart @@ -14,84 +14,13 @@ import 'package:aws_common/testing.dart'; import 'package:collection/collection.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; import 'test_data/fake_amplify_configuration.dart'; import 'test_models/ModelProvider.dart'; import 'util.dart'; final _deepEquals = const DeepCollectionEquality().equals; -// Success Mocks -const _expectedQuerySuccessResponseBody = { - 'data': { - 'listBlogs': { - 'items': [ - { - 'id': 'TEST_ID', - 'name': 'Test App Blog', - 'createdAt': '2022-06-28T17:36:52.460Z', - } - ], - }, - }, -}; - -final _modelQueryId = uuid(); -final _expectedModelQueryResult = { - 'data': { - 'getBlog': { - 'createdAt': '2021-07-21T22:23:33.707Z', - 'id': _modelQueryId, - 'name': 'Test App Blog', - }, - }, -}; -const _expectedMutateSuccessResponseBody = { - 'data': { - 'createBlog': { - 'id': 'TEST_ID', - 'name': 'Test App Blog', - 'createdAt': '2022-07-06T18:42:26.126Z', - }, - }, -}; - -// Error Mocks -const _errorMessage = 'Unable to parse GraphQL query.'; -const _errorLocations = [ - {'line': 2, 'column': 3}, - {'line': 4, 'column': 5}, -]; -const _errorPath = ['a', 1, 'b']; -const _errorExtensions = { - 'a': 'blah', - 'b': {'c': 'd'}, -}; -const _errorType = 'DynamoDB:ConditionalCheckFailedException'; -const _errorInfo = {'a': 'b'}; -const _expectedErrorResponseBody = { - 'data': null, - 'errors': [ - { - 'message': _errorMessage, - 'locations': _errorLocations, - 'path': _errorPath, - 'extensions': _errorExtensions, - 'errorType': _errorType, - 'errorInfo': _errorInfo, - }, - ], -}; - -const _authErrorMessage = 'Not authorized'; -const _expectedAuthErrorResponseBody = { - 'data': null, - 'errors': [ - { - 'message': _authErrorMessage, - }, - ], -}; - final mockHttpClient = MockAWSHttpClient((request, _) async { if (request.headers[xApiKey] != 'abc123' && request.headers[AWSHeaders.authorization] == testFunctionToken) { @@ -99,7 +28,7 @@ final mockHttpClient = MockAWSHttpClient((request, _) async { // does not work for this query. return AWSHttpResponse( statusCode: 401, - body: utf8.encode(json.encode(_expectedAuthErrorResponseBody)), + body: utf8.encode(json.encode(expectedAuthErrorResponseBody)), ); } if (request.headers[xApiKey] != 'abc123') { @@ -110,25 +39,32 @@ final mockHttpClient = MockAWSHttpClient((request, _) async { if (body.contains('getBlog')) { return AWSHttpResponse( statusCode: 200, - body: utf8.encode(json.encode(_expectedModelQueryResult)), + body: utf8.encode(json.encode(expectedModelQueryResult)), ); } if (body.contains('TestMutate')) { return AWSHttpResponse( statusCode: 400, - body: utf8.encode(json.encode(_expectedMutateSuccessResponseBody)), + body: utf8.encode(json.encode(expectedMutateSuccessResponseBody)), ); } if (body.contains('TestError')) { return AWSHttpResponse( statusCode: 400, - body: utf8.encode(json.encode(_expectedErrorResponseBody)), + body: utf8.encode(json.encode(expectedErrorResponseBody)), + ); + } + if (body.contains('createModelWithCustomType')) { + return AWSHttpResponse( + statusCode: 200, + body: utf8 + .encode(json.encode(expectedModelWithCustomTypeSuccessResponseBody)), ); } return AWSHttpResponse( statusCode: 400, - body: utf8.encode((json.encode(_expectedQuerySuccessResponseBody))), + body: utf8.encode((json.encode(expectedQuerySuccessResponseBody))), ); }); @@ -195,7 +131,7 @@ void main() { final operation = Amplify.API.query(request: req); final res = await operation.response; - final expected = json.encode(_expectedQuerySuccessResponseBody['data']); + final expected = json.encode(expectedQuerySuccessResponseBody['data']); expect(res.data, equals(expected)); expect(res.errors, isEmpty); @@ -219,7 +155,7 @@ void main() { final operation = Amplify.API.query(request: req); final res = await operation.response; - final expected = json.encode(_expectedQuerySuccessResponseBody['data']); + final expected = json.encode(expectedQuerySuccessResponseBody['data']); expect(res.data, equals(expected)); expect(res.errors, isEmpty); @@ -242,7 +178,23 @@ void main() { final operation = Amplify.API.mutate(request: req); final res = await operation.response; - final expected = json.encode(_expectedMutateSuccessResponseBody['data']); + final expected = json.encode(expectedMutateSuccessResponseBody['data']); + + expect(res.data, equals(expected)); + expect(res.errors, isEmpty); + }); + + test('Mutate returns proper response.data for custom types', () async { + final req = GraphQLRequest( + document: modelWithCustomTypeDocument, + variables: modelWithCustomTypeVariables, + ); + + final operation = Amplify.API.mutate(request: req); + final res = await operation.response; + + final expected = + json.encode(expectedModelWithCustomTypeSuccessResponseBody['data']); expect(res.data, equals(expected)); expect(res.errors, isEmpty); @@ -255,7 +207,7 @@ void main() { const expectedDoc = 'query getBlog(\$id: ID!) { getBlog(id: \$id) { $blogSelectionSet } }'; const decodePath = 'getBlog'; - final blog = Blog(id: _modelQueryId, name: 'Lorem ipsum $_modelQueryId'); + final blog = Blog(id: modelQueryId, name: 'Lorem ipsum $modelQueryId'); final req = ModelQueries.get(Blog.classType, blog.modelIdentifier); final operation = Amplify.API.query(request: req); @@ -263,15 +215,49 @@ void main() { // request asserts expect(req.document, expectedDoc); - expect(_deepEquals(req.variables, {'id': _modelQueryId}), isTrue); + expect(_deepEquals(req.variables, {'id': modelQueryId}), isTrue); expect(req.modelType, Blog.classType); expect(req.decodePath, decodePath); // response asserts expect(res.data, isA()); - expect(res.data?.id, _modelQueryId); + expect(res.data?.id, modelQueryId); + expect(res.errors, isEmpty); + }); + + test( + 'Mutation.create returns proper response.data for Models with custom types', + () async { + const expectedDoc = modelWithCustomTypeDocument; + const decodePath = 'createModelWithCustomType'; + final req = ModelMutations.create( + modelWithCustomType, + ); + + final operation = Amplify.API.query(request: req); + final res = await operation.response; + + // request asserts + expect(req.document, expectedDoc); + expect(_deepEquals(req.variables, modelWithCustomTypeVariables), isTrue); + expect(req.modelType, ModelWithCustomType.classType); + expect(req.decodePath, decodePath); + // response asserts + expect(res.data, isA()); + expect(res.data?.id, modelCustomTypeId); + + final data = res.data!; + expect( + data.customTypeValue, + equals(modelWithCustomType.customTypeValue), + ); + expect( + data.listOfCustomTypeValue, + equals(modelWithCustomType.listOfCustomTypeValue), + ); expect(res.errors, isEmpty); }); }); + const graphQLDocument = '''subscription MySubscription { onCreateBlog { id @@ -550,15 +536,15 @@ void main() { final res = await operation.response; const errorExpected = GraphQLResponseError( - message: _errorMessage, + message: errorMessage, locations: [ GraphQLResponseErrorLocation(2, 3), GraphQLResponseErrorLocation(4, 5), ], - path: [..._errorPath], - extensions: {..._errorExtensions}, - errorType: _errorType, - errorInfo: _errorInfo, + path: [...errorPath], + extensions: {...errorExtensions}, + errorType: errorType, + errorInfo: errorInfo, ); expect(res.data, equals(null)); @@ -585,7 +571,7 @@ void main() { final res = await operation.response; const errorExpected = GraphQLResponseError( - message: _authErrorMessage, + message: authErrorMessage, ); expect(res.data, equals(null)); diff --git a/packages/api/amplify_api_dart/test/mocks.dart b/packages/api/amplify_api_dart/test/mocks.dart new file mode 100644 index 0000000000..239ca2ffe9 --- /dev/null +++ b/packages/api/amplify_api_dart/test/mocks.dart @@ -0,0 +1,347 @@ +import 'package:amplify_core/amplify_core.dart'; + +import 'test_models/ModelProvider.dart'; + +// Mock requests +const modelWithCustomTypeDocument = + r'mutation createModelWithCustomType($input: CreateModelWithCustomTypeInput!, $condition: ModelModelWithCustomTypeConditionInput) { createModelWithCustomType(input: $input, condition: $condition) { id customTypeValue { stringValue listOfStringValue intValue listOfIntValue floatValue listOfFloatValue booleanValue listOfBooleanValue awsDateValue listOfAWSDateValue awsDateTimeValue listOfAWSDateTimeValue awsTimeValue listOfAWSTimeValue awsTimestampValue listOfAWSTimestampValue awsEmailValue listOfAWSEmailValue awsJsonValue listOfAWSJsonValue awsPhoneValue listOfAWSPhoneValue awsURLValue listOfAWSURLValue awsIPAddressValue listOfAWSIPAddressValue enumValue listOfEnumValue customTypeValue { foo } listOfCustomTypeValue { foo } } listOfCustomTypeValue { stringValue listOfStringValue intValue listOfIntValue floatValue listOfFloatValue booleanValue listOfBooleanValue awsDateValue listOfAWSDateValue awsDateTimeValue listOfAWSDateTimeValue awsTimeValue listOfAWSTimeValue awsTimestampValue listOfAWSTimestampValue awsEmailValue listOfAWSEmailValue awsJsonValue listOfAWSJsonValue awsPhoneValue listOfAWSPhoneValue awsURLValue listOfAWSURLValue awsIPAddressValue listOfAWSIPAddressValue enumValue listOfEnumValue customTypeValue { foo } listOfCustomTypeValue { foo } } createdAt updatedAt } }'; +final modelCustomTypeId = uuid(); +final modelWithCustomTypeVariables = { + 'input': { + 'id': modelCustomTypeId, + 'customTypeValue': { + 'stringValue': 'foo', + 'listOfStringValue': ['foo', 'bar'], + 'intValue': 42, + 'listOfIntValue': [1, 2, 3], + 'floatValue': 3.14, + 'listOfFloatValue': [3.14, 6.28], + 'booleanValue': true, + 'listOfBooleanValue': [true, false], + 'awsDateValue': '2021-07-07', + 'listOfAWSDateValue': ['2021-07-07', '2021-07-08'], + 'awsDateTimeValue': '2021-07-07T20:20:20.000000000Z', + 'listOfAWSDateTimeValue': [ + '2021-07-07T20:20:20.000000000Z', + '2021-07-08T20:20:20.000000000Z', + ], + 'awsTimeValue': '20:20:20Z', + 'listOfAWSTimeValue': ['20:20:20Z', '21:21:21Z'], + 'awsTimestampValue': 1625660420, + 'listOfAWSTimestampValue': [1625660420, 1625746820], + 'awsEmailValue': 'example@amazon.com', + 'listOfAWSEmailValue': [ + 'example+foo@amazon.com', + 'example+bar@amazon.com', + ], + 'awsJsonValue': '{"a":1,"b":3,"string":234}', + 'listOfAWSJsonValue': [ + '{"a":1,"b":3,"string":234}', + '{"a":2,"b":4,"string":567}', + ], + 'awsPhoneValue': '2234567890', + 'listOfAWSPhoneValue': ['2234567890', '2234567891'], + 'awsURLValue': 'https://aws.amazon.com', + 'listOfAWSURLValue': ['https://aws.amazon.com', 'https://flutter.dev'], + 'awsIPAddressValue': '1.0.0.1', + 'listOfAWSIPAddressValue': ['1.0.0.1', '1.0.0.2'], + 'enumValue': 'yes', + 'listOfEnumValue': ['yes', 'no'], + 'customTypeValue': { + 'foo': 'bar', + }, + 'listOfCustomTypeValue': [ + { + 'foo': 'bar', + }, + { + 'foo': 'baz', + } + ], + }, + 'listOfCustomTypeValue': [ + { + 'stringValue': 'foo', + 'listOfStringValue': ['foo', 'bar'], + 'intValue': 42, + 'listOfIntValue': [1, 2, 3], + 'floatValue': 3.14, + 'listOfFloatValue': [3.14, 6.28], + 'booleanValue': true, + 'listOfBooleanValue': [true, false], + 'awsDateValue': '2021-07-07', + 'listOfAWSDateValue': ['2021-07-07', '2021-07-08'], + 'awsDateTimeValue': '2021-07-07T20:20:20.000000000Z', + 'listOfAWSDateTimeValue': [ + '2021-07-07T20:20:20.000000000Z', + '2021-07-08T20:20:20.000000000Z', + ], + 'awsTimeValue': '20:20:20Z', + 'listOfAWSTimeValue': ['20:20:20Z', '21:21:21Z'], + 'awsTimestampValue': 1625660420, + 'listOfAWSTimestampValue': [1625660420, 1625746820], + 'awsEmailValue': 'example@amazon.com', + 'listOfAWSEmailValue': [ + 'example+foo@amazon.com', + 'example+bar@amazon.com', + ], + 'awsJsonValue': '{"a":1,"b":3,"string":234}', + 'listOfAWSJsonValue': [ + '{"a":1,"b":3,"string":234}', + '{"a":2,"b":4,"string":567}', + ], + 'awsPhoneValue': '2234567890', + 'listOfAWSPhoneValue': ['2234567890', '2234567891'], + 'awsURLValue': 'https://aws.amazon.com', + 'listOfAWSURLValue': ['https://aws.amazon.com', 'https://flutter.dev'], + 'awsIPAddressValue': '1.0.0.1', + 'listOfAWSIPAddressValue': ['1.0.0.1', '1.0.0.2'], + 'enumValue': 'yes', + 'listOfEnumValue': ['yes', 'no'], + 'customTypeValue': { + 'foo': 'bar', + }, + 'listOfCustomTypeValue': [ + { + 'foo': 'bar', + }, + { + 'foo': 'baz', + } + ], + } + ], + }, +}; + +// Success Mocks +const expectedQuerySuccessResponseBody = { + 'data': { + 'listBlogs': { + 'items': [ + { + 'id': 'TEST_ID', + 'name': 'Test App Blog', + 'createdAt': '2022-06-28T17:36:52.460Z', + } + ], + }, + }, +}; + +final modelQueryId = uuid(); +final expectedModelQueryResult = { + 'data': { + 'getBlog': { + 'createdAt': '2021-07-21T22:23:33.707Z', + 'id': modelQueryId, + 'name': 'Test App Blog', + }, + }, +}; +const expectedMutateSuccessResponseBody = { + 'data': { + 'createBlog': { + 'id': 'TEST_ID', + 'name': 'Test App Blog', + 'createdAt': '2022-07-06T18:42:26.126Z', + }, + }, +}; +final expectedModelWithCustomTypeSuccessResponseBody = { + 'data': { + 'createModelWithCustomType': { + 'id': modelCustomTypeId, + 'customTypeValue': { + 'stringValue': 'foo', + 'listOfStringValue': ['foo', 'bar'], + 'intValue': 42, + 'listOfIntValue': [1, 2, 3], + 'floatValue': 3.14, + 'listOfFloatValue': [3.14, 6.28], + 'booleanValue': true, + 'listOfBooleanValue': [true, false], + 'awsDateValue': '2021-07-07', + 'listOfAWSDateValue': ['2021-07-07', '2021-07-08'], + 'awsDateTimeValue': '2021-07-07T20:20:20.000000000Z', + 'listOfAWSDateTimeValue': [ + '2021-07-07T20:20:20.000000000Z', + '2021-07-08T20:20:20.000000000Z', + ], + 'awsTimeValue': '20:20:20Z', + 'listOfAWSTimeValue': ['20:20:20Z', '21:21:21Z'], + 'awsTimestampValue': 1625660420, + 'listOfAWSTimestampValue': [1625660420, 1625746820], + 'awsEmailValue': 'example@amazon.com', + 'listOfAWSEmailValue': [ + 'example+foo@amazon.com', + 'example+bar@amazon.com', + ], + 'awsJsonValue': '{"a":1,"b":3,"string":234}', + 'listOfAWSJsonValue': [ + '{"a":1,"b":3,"string":234}', + '{"a":2,"b":4,"string":567}', + ], + 'awsPhoneValue': '2234567890', + 'listOfAWSPhoneValue': ['2234567890', '2234567891'], + 'awsURLValue': 'https://aws.amazon.com', + 'listOfAWSURLValue': ['https://aws.amazon.com', 'https://flutter.dev'], + 'awsIPAddressValue': '1.0.0.1', + 'listOfAWSIPAddressValue': ['1.0.0.1', '1.0.0.2'], + 'enumValue': 'yes', + 'listOfEnumValue': ['yes', 'no'], + 'customTypeValue': {'foo': 'bar'}, + 'listOfCustomTypeValue': [ + {'foo': 'bar'}, + {'foo': 'baz'}, + ], + }, + 'listOfCustomTypeValue': [ + { + 'stringValue': 'foo', + 'listOfStringValue': ['foo', 'bar'], + 'intValue': 42, + 'listOfIntValue': [1, 2, 3], + 'floatValue': 3.14, + 'listOfFloatValue': [3.14, 6.28], + 'booleanValue': true, + 'listOfBooleanValue': [true, false], + 'awsDateValue': '2021-07-07', + 'listOfAWSDateValue': ['2021-07-07', '2021-07-08'], + 'awsDateTimeValue': '2021-07-07T20:20:20.000000000Z', + 'listOfAWSDateTimeValue': [ + '2021-07-07T20:20:20.000000000Z', + '2021-07-08T20:20:20.000000000Z', + ], + 'awsTimeValue': '20:20:20Z', + 'listOfAWSTimeValue': ['20:20:20Z', '21:21:21Z'], + 'awsTimestampValue': 1625660420, + 'listOfAWSTimestampValue': [1625660420, 1625746820], + 'awsEmailValue': 'example@amazon.com', + 'listOfAWSEmailValue': [ + 'example+foo@amazon.com', + 'example+bar@amazon.com', + ], + 'awsJsonValue': '{"a":1,"b":3,"string":234}', + 'listOfAWSJsonValue': [ + '{"a":1,"b":3,"string":234}', + '{"a":2,"b":4,"string":567}', + ], + 'awsPhoneValue': '2234567890', + 'listOfAWSPhoneValue': ['2234567890', '2234567891'], + 'awsURLValue': 'https://aws.amazon.com', + 'listOfAWSURLValue': [ + 'https://aws.amazon.com', + 'https://flutter.dev', + ], + 'awsIPAddressValue': '1.0.0.1', + 'listOfAWSIPAddressValue': ['1.0.0.1', '1.0.0.2'], + 'enumValue': 'yes', + 'listOfEnumValue': ['yes', 'no'], + 'customTypeValue': {'foo': 'bar'}, + 'listOfCustomTypeValue': [ + {'foo': 'bar'}, + {'foo': 'baz'}, + ], + } + ], + 'createdAt': '2024-05-14T22:00:30.605Z', + 'updatedAt': '2024-05-14T22:00:30.605Z', + }, + }, +}; + +// Error Mocks +const errorMessage = 'Unable to parse GraphQL query.'; +const errorLocations = [ + {'line': 2, 'column': 3}, + {'line': 4, 'column': 5}, +]; +const errorPath = ['a', 1, 'b']; +const errorExtensions = { + 'a': 'blah', + 'b': {'c': 'd'}, +}; +const errorType = 'DynamoDB:ConditionalCheckFailedException'; +const errorInfo = {'a': 'b'}; +const expectedErrorResponseBody = { + 'data': null, + 'errors': [ + { + 'message': errorMessage, + 'locations': errorLocations, + 'path': errorPath, + 'extensions': errorExtensions, + 'errorType': errorType, + 'errorInfo': errorInfo, + }, + ], +}; + +const authErrorMessage = 'Not authorized'; +const expectedAuthErrorResponseBody = { + 'data': null, + 'errors': [ + { + 'message': authErrorMessage, + }, + ], +}; + +/// Models +final customTypesSubModel1 = CustomTypeWithAppsyncScalarTypes( + stringValue: 'foo', + listOfStringValue: ['foo', 'bar'], + intValue: 42, + listOfIntValue: [1, 2, 3], + floatValue: 3.14, + listOfFloatValue: [3.14, 6.28], + booleanValue: true, + listOfBooleanValue: [true, false], + awsDateValue: TemporalDate.fromString('2021-07-07'), + listOfAWSDateValue: [ + TemporalDate.fromString('2021-07-07'), + TemporalDate.fromString('2021-07-08'), + ], + awsDateTimeValue: TemporalDateTime.fromString('2021-07-07T20:20:20Z'), + listOfAWSDateTimeValue: [ + TemporalDateTime.fromString('2021-07-07T20:20:20Z'), + TemporalDateTime.fromString('2021-07-08T20:20:20Z'), + ], + awsTimeValue: TemporalTime.fromString('20:20:20Z'), + listOfAWSTimeValue: [ + TemporalTime.fromString('20:20:20Z'), + TemporalTime.fromString('21:21:21Z'), + ], + awsTimestampValue: TemporalTimestamp.fromSeconds(1625660420), + listOfAWSTimestampValue: [ + TemporalTimestamp.fromSeconds(1625660420), + TemporalTimestamp.fromSeconds(1625746820), + ], + awsEmailValue: 'example@amazon.com', + listOfAWSEmailValue: ['example+foo@amazon.com', 'example+bar@amazon.com'], + awsJsonValue: '{"a":1,"b":3,"string":234}', + listOfAWSJsonValue: [ + '{"a":1,"b":3,"string":234}', + '{"a":2,"b":4,"string":567}', + ], + awsPhoneValue: '2234567890', + listOfAWSPhoneValue: ['2234567890', '2234567891'], + awsURLValue: 'https://aws.amazon.com', + listOfAWSURLValue: ['https://aws.amazon.com', 'https://flutter.dev'], + awsIPAddressValue: '1.0.0.1', + listOfAWSIPAddressValue: ['1.0.0.1', '1.0.0.2'], + enumValue: EnumField.yes, + listOfEnumValue: [EnumField.yes, EnumField.no], + customTypeValue: SimpleCustomType(foo: 'bar'), + listOfCustomTypeValue: [ + SimpleCustomType(foo: 'bar'), + SimpleCustomType(foo: 'baz'), + ], +); +final customTypesSubModel2 = customTypesSubModel1.copyWith(); +final modelWithCustomType = ModelWithCustomType( + id: modelCustomTypeId, + customTypeValue: customTypesSubModel1, + listOfCustomTypeValue: [customTypesSubModel2], +); diff --git a/packages/api/amplify_api_dart/test/test_models/CustomTypeWithAppsyncScalarTypes.dart b/packages/api/amplify_api_dart/test/test_models/CustomTypeWithAppsyncScalarTypes.dart index 1152c1b48b..52dd4d8d5b 100644 --- a/packages/api/amplify_api_dart/test/test_models/CustomTypeWithAppsyncScalarTypes.dart +++ b/packages/api/amplify_api_dart/test/test_models/CustomTypeWithAppsyncScalarTypes.dart @@ -738,14 +738,17 @@ class CustomTypeWithAppsyncScalarTypes { .toList() : null, _customTypeValue = json['customTypeValue'] != null - ? SimpleCustomType.fromJson( - new Map.from(json['customTypeValue'])) + ? json['customTypeValue']['serializedData'] != null + ? SimpleCustomType.fromJson(new Map.from( + json['customTypeValue']['serializedData'])) + : SimpleCustomType.fromJson( + new Map.from(json['customTypeValue'])) : null, _listOfCustomTypeValue = json['listOfCustomTypeValue'] is List ? (json['listOfCustomTypeValue'] as List) .where((e) => e != null) - .map((e) => - SimpleCustomType.fromJson(new Map.from(e))) + .map((e) => SimpleCustomType.fromJson( + new Map.from(e['serializedData'] ?? e))) .toList() : null; diff --git a/packages/api/amplify_api_dart/test/test_models/ModelWithCustomType.dart b/packages/api/amplify_api_dart/test/test_models/ModelWithCustomType.dart index bd5099344c..8387940e6d 100644 --- a/packages/api/amplify_api_dart/test/test_models/ModelWithCustomType.dart +++ b/packages/api/amplify_api_dart/test/test_models/ModelWithCustomType.dart @@ -152,14 +152,18 @@ class ModelWithCustomType extends amplify_core.Model { ModelWithCustomType.fromJson(Map json) : id = json['id'], _customTypeValue = json['customTypeValue'] != null - ? CustomTypeWithAppsyncScalarTypes.fromJson( - new Map.from(json['customTypeValue'])) + ? json['customTypeValue']['serializedData'] != null + ? CustomTypeWithAppsyncScalarTypes.fromJson( + new Map.from( + json['customTypeValue']['serializedData'])) + : CustomTypeWithAppsyncScalarTypes.fromJson( + new Map.from(json['customTypeValue'])) : null, _listOfCustomTypeValue = json['listOfCustomTypeValue'] is List ? (json['listOfCustomTypeValue'] as List) .where((e) => e != null) .map((e) => CustomTypeWithAppsyncScalarTypes.fromJson( - new Map.from(e))) + new Map.from(e['serializedData'] ?? e))) .toList() : null, _createdAt = json['createdAt'] != null