Skip to content

Commit

Permalink
chore(datastore): add custom primary key integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
HuiSF committed Jul 8, 2022
1 parent 429354f commit 1a50262
Show file tree
Hide file tree
Showing 21 changed files with 1,624 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
/*
* Copyright 2022 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:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:tuple/tuple.dart';

import '../utils/setup_utils.dart';
import '../utils/test_cloud_synced_model_operation.dart';
import 'models/basic_custom_pk_model_operation/ModelProvider.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

final enableCloudSync = shouldEnableCloudSync();
const delayDuration = Duration(seconds: 1);
group(
'Basic model (with Custom PK) operation${enableCloudSync ? ' with API sync 🌩 enabled' : ''} -',
() {
// schema
// type CpkInventory @model {
// productId: ID! @primaryKey(sortKeyFields: ["productName", "warehouseId"])
// productName: String!
// warehouseId: String!
// description: String
// }

final testModel = CpkInventory(
productId: UUID.getUUID(),
productName: 'test product',
warehouseId: UUID.getUUID(),
);

setUpAll(() async {
await configureDataStore(
enableCloudSync: enableCloudSync,
modelProvider: ModelProvider.instance,
);
});

testWidgets(
'should save a new model ${enableCloudSync ? 'and sync to cloud' : ''}',
(WidgetTester tester) async {
if (enableCloudSync) {
await testCloudSyncedModelOperation(
rootModels: [testModel],
expectedRootModelVersion: 1,
rootModelOperator: Amplify.DataStore.save,
rootModelEventsAssertor: (events) {
events.forEach((event) {
expect(event.element.deleted, isFalse);
});
},
);
} else {
await Amplify.DataStore.save(testModel);
}

var queriedBlogs = await Amplify.DataStore.query(CpkInventory.classType);
expect(queriedBlogs, contains(testModel));
});

testWidgets('query by eq(modelIdentifier) should return a single model',
(WidgetTester tester) async {
final eqResult = await Amplify.DataStore.query(
CpkInventory.classType,
where: CpkInventory.MODEL_IDENTIFIER.eq(testModel.modelIdentifier),
);

expect(eqResult.length, 1);
expect(eqResult.first, testModel);
});

testWidgets('query by ne(modelIdentifier) should return empty list',
(WidgetTester tester) async {
final eqResult = await Amplify.DataStore.query(
CpkInventory.classType,
where: CpkInventory.MODEL_IDENTIFIER.ne(testModel.modelIdentifier),
);

expect(eqResult, isEmpty);
});

// TODO: enable after amplify-ios fix the not operator
// testWidgets('query by not(eq(modelIdentifier)) should return empty list',
// (WidgetTester tester) async {
// final eqResult = await Amplify.DataStore.query(
// CpkInventory.classType,
// where: not(CpkInventory.MODEL_IDENTIFIER.eq(testModel.modelIdentifier)),
// );

// expect(eqResult, isEmpty);
// });

// testWidgets(
// 'query by not(ne(modelIdentifier)) should return a single model',
// (WidgetTester tester) async {
// final eqResult = await Amplify.DataStore.query(
// CpkInventory.classType,
// where: not(CpkInventory.MODEL_IDENTIFIER.ne(testModel.modelIdentifier)),
// );

// expect(eqResult.length, 1);
// expect(eqResult.first, testModel);
// });

testWidgets(
'should update existing model ${enableCloudSync ? 'and sync to cloud' : ''}',
(WidgetTester tester) async {
var updatedTestModel =
testModel.copyWith(description: "Newly added description");

if (enableCloudSync) {
await testCloudSyncedModelOperation(
rootModels: [updatedTestModel],
expectedRootModelVersion: 2,
rootModelOperator: Amplify.DataStore.save,
rootModelEventsAssertor: (events) {
events.forEach((event) {
expect(event.element.deleted, isFalse);
});
},
);
} else {
await Amplify.DataStore.save(updatedTestModel);
}

var queriedBlogs = await Amplify.DataStore.query(
CpkInventory.classType,
where: CpkInventory.MODEL_IDENTIFIER.eq(
updatedTestModel.modelIdentifier,
),
);

expect(queriedBlogs.length, 1);
expect(queriedBlogs.first, updatedTestModel);
},
);

testWidgets(
'should delete existing model ${enableCloudSync ? 'and sync to cloud' : ''}',
(WidgetTester tester) async {
if (enableCloudSync) {
await testCloudSyncedModelOperation(
rootModels: [testModel],
expectedRootModelVersion: 3,
rootModelOperator: Amplify.DataStore.delete,
rootModelEventsAssertor: (events) {
events.forEach((event) {
expect(event.element.deleted, isTrue);
});
},
);
} else {
await Amplify.DataStore.delete(testModel);
}

var queriedBlogs =
await Amplify.DataStore.query(CpkInventory.classType);

// verify blog was deleted
expect(queriedBlogs, isNot(contains(testModel)));
},
);

testWidgets('observe by model identifier should work',
(WidgetTester tester) async {
final updatedTestModel =
testModel.copyWith(description: "updated description");
final modelWithDifferentIdentifier = CpkInventory(
productId: UUID.getUUID(),
productName: 'product with different model identifier',
warehouseId: UUID.getUUID(),
);

final observeStream = Amplify.DataStore.observe(
CpkInventory.classType,
where: CpkInventory.MODEL_IDENTIFIER.eq(testModel.modelIdentifier),
).map((event) => Tuple2(event.eventType, event.item));

expectLater(
observeStream,
emitsInOrder([
Tuple2(EventType.create, testModel),
Tuple2(EventType.update, updatedTestModel),
Tuple2(EventType.delete, updatedTestModel),
]),
);

await Future.delayed(delayDuration);
await Amplify.DataStore.save(testModel);
await Amplify.DataStore.save(modelWithDifferentIdentifier);
await Future.delayed(delayDuration);
await Amplify.DataStore.save(updatedTestModel);
await Amplify.DataStore.delete(modelWithDifferentIdentifier);
await Future.delayed(delayDuration);
await Amplify.DataStore.delete(updatedTestModel);
});

testWidgets('observeQuery by model identifier should work',
(WidgetTester tester) async {
final updatedTestModel =
testModel.copyWith(description: "updated description");
final modelWithDifferentIdentifier = CpkInventory(
productId: UUID.getUUID(),
productName: 'product with different model identifier',
warehouseId: UUID.getUUID(),
);

final observeStream = Amplify.DataStore.observeQuery(
CpkInventory.classType,
where: CpkInventory.MODEL_IDENTIFIER.eq(testModel.modelIdentifier),
).map(
(querySnapshot) => Tuple2(
querySnapshot.isSynced,
querySnapshot.items.length > 0 ? querySnapshot.items.first : null,
),
);

expectLater(
observeStream,
emitsInOrder([
Tuple2(enableCloudSync, null),
Tuple2(enableCloudSync, testModel),
Tuple2(enableCloudSync, updatedTestModel),
Tuple2(enableCloudSync, null),
]),
);

await Future.delayed(delayDuration);
await Amplify.DataStore.save(testModel);
await Amplify.DataStore.save(modelWithDifferentIdentifier);
await Future.delayed(delayDuration);
await Amplify.DataStore.save(updatedTestModel);
await Amplify.DataStore.delete(modelWithDifferentIdentifier);
await Future.delayed(delayDuration);
await Amplify.DataStore.delete(updatedTestModel);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';

import '../utils/setup_utils.dart';
import '../utils/test_cloud_synced_model_operation.dart';
import 'models/cpk_has_many_bidirectional/ModelProvider.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('HasMany (bi-directional with implicit connection field', () {
// schema
// type HasManyParentBiDirectionalExplicit @model {
// id: ID!
// name: String
// biDirectionalExplicitChildren: [HasManyChildBiDirectionalExplicit]
// @hasMany(indexName: "byHasManyParent", fields: ["id"])
// }

// type HasManyChildBiDirectionalExplicit @model {
// id: ID!
// name: String
// hasManyParentId: ID! @index(name: "byHasManyParent", sortKeyFields: ["name"])
// hasManyParent: HasManyParentBiDirectionalExplicit
// @belongsTo(fields: ["hasManyParentId"])
// }
final enableCloudSync = shouldEnableCloudSync();
var rootModels = [
CpkHasManyParentBidirectionalExplicit(name: 'has many parent (explicit)')
];
var associatedModels = List.generate(
5,
(i) => CpkHasManyChildBidirectionalExplicit(
name: 'has many child $i (explicit)',
hasManyParent: rootModels.first,
),
);

testRootAndAssociatedModelsRelationship(
modelProvider: ModelProvider.instance,
rootModelType: CpkHasManyParentBidirectionalExplicit.classType,
rootModels: rootModels,
associatedModelType: CpkHasManyChildBidirectionalExplicit.classType,
associatedModels: associatedModels,
supportCascadeDelete: true,
enableCloudSync: enableCloudSync,
);
});
}
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:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';

import '../utils/setup_utils.dart';
import '../utils/test_cloud_synced_model_operation.dart';
import 'models/cpk_has_many_bidirectional/ModelProvider.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('HasMany (bi-directional with implicit connection field', () {
// schema
// type CpkHasManyParentBidirectionalImplicit @model {
// id: ID! @primaryKey(sortKeyFields: ["name"])
// name: String!
// bidirectionalImplicitChildren: [CpkHasManyChildBidirectionalImplicit] @hasMany
// }

// type CpkHasManyChildBidirectionalImplicit @model {
// id: ID! @primaryKey(sortKeyFields: ["name"])
// name: String!
// hasManyParent: CpkHasManyParentBidirectionalImplicit @belongsTo
// }
final enableCloudSync = shouldEnableCloudSync();
var rootModels = [
CpkHasManyParentBidirectionalImplicit(name: 'has many parent (explicit)')
];
var associatedModels = List.generate(
5,
(i) => CpkHasManyChildBidirectionalImplicit(
name: 'has many child $i (explicit)',
hasManyParent: rootModels.first,
),
);

testRootAndAssociatedModelsRelationship(
modelProvider: ModelProvider.instance,
rootModelType: CpkHasManyParentBidirectionalImplicit.classType,
rootModels: rootModels,
associatedModelType: CpkHasManyChildBidirectionalImplicit.classType,
associatedModels: associatedModels,
supportCascadeDelete: true,
enableCloudSync: enableCloudSync,
);
});
}
Loading

0 comments on commit 1a50262

Please sign in to comment.