Skip to content

Commit

Permalink
fix(api): do not include null values for owner fields in ModelMutatio…
Browse files Browse the repository at this point in the history
…ns helpers
  • Loading branch information
Travis Sheppard committed Dec 21, 2022
1 parent 9e7e9ee commit dd58058
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 3 deletions.
1 change: 1 addition & 0 deletions packages/api/amplify_api/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ include: package:amplify_lints/library.yaml

analyzer:
exclude:
- test/test_models/**
- '**/*.mocks.dart'
Original file line number Diff line number Diff line change
Expand Up @@ -315,14 +315,28 @@ class GraphQLRequestFactory {
}
}

// Remove any relational fields or readonly.
final ownerFieldNames = (schema.authRules ?? [])
.where((authRule) => authRule.ownerField != null)
.map((authRule) => authRule.ownerField!)
.toSet();

// In some cases, remove values from the input JSON.
final fieldsToRemove = schema.fields!.entries
.where(
(entry) => entry.value.association != null || entry.value.isReadOnly,
(entry) =>
// relational fields
entry.value.association != null ||
// read-only
entry.value.isReadOnly ||
// owner fields with null value
(ownerFieldNames.contains(entry.value.name) &&
modelJson[entry.value.name] == null),
)
.map((entry) => entry.key)
.toSet();
modelJson.removeWhere((key, dynamic value) => fieldsToRemove.contains(key));
modelJson.removeWhere(
(key, dynamic value) => fieldsToRemove.contains(key),
);

return modelJson;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import 'package:amplify_api/src/api_plugin_impl.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:flutter_test/flutter_test.dart';

import 'test_models/owner_field/ModelProvider.dart';

class MockAmplifyAPI extends AmplifyAPIDart {
MockAmplifyAPI({
super.modelProvider,
});
}

void main() {
TestWidgetsFlutterBinding.ensureInitialized();

group('with ModelProvider manyToMany', () {
setUpAll(() async {
await Amplify.reset();
await Amplify.addPlugin(
// needed to fetch the schema from within the helper
MockAmplifyAPI(modelProvider: ModelProvider.instance),
);
});

test(
'ModelMutations.update() will not provide null for an owner field when omitted from model instance',
() {
final todo = Todo(name: 'mow lawn');
final updateReq = ModelMutations.update(todo);
final input = updateReq.variables['input'] as Map<String, dynamic>;
expect(input.containsKey('owners'), isFalse);
},
);

test(
'ModelMutations.update() will include an owner field when provided',
() {
const owners = ['bob'];
final todo = Todo(name: 'mow lawn', owners: owners);
final updateReq = ModelMutations.update(todo);
final input = updateReq.variables['input'] as Map<String, dynamic>;
expect(input['owners'], owners);
},
);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

// NOTE: This file is generated and may not follow lint rules defined in your app
// Generated files can be excluded from analysis in analysis_options.yaml
// For more info, see: https://dart.dev/guides/language/analysis-options#excluding-code-from-analysis

// 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, 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 'package:amplify_core/amplify_core.dart';

import 'Todo.dart';

export 'Todo.dart';

class ModelProvider implements ModelProviderInterface {
@override
String version = 'a75dcc30a1e877e7ad8b425e805e0eeb';
@override
List<ModelSchema> modelSchemas = [Todo.schema];
static final ModelProvider _instance = ModelProvider();
@override
List<ModelSchema> customTypeSchemas = [];

static ModelProvider get instance => _instance;

ModelType getModelTypeByModelName(String modelName) {
switch (modelName) {
case 'Todo':
return Todo.classType;
default:
throw Exception(
'Failed to find model in model provider for model name: ' +
modelName);
}
}
}

0 comments on commit dd58058

Please sign in to comment.