diff options
Diffstat (limited to 'Firestore/Example/Tests')
-rw-r--r-- | Firestore/Example/Tests/Model/FSTMutationTests.mm | 62 | ||||
-rw-r--r-- | Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm | 6 | ||||
-rw-r--r-- | Firestore/Example/Tests/Util/FSTHelpers.h | 8 | ||||
-rw-r--r-- | Firestore/Example/Tests/Util/FSTHelpers.mm | 24 |
4 files changed, 83 insertions, 17 deletions
diff --git a/Firestore/Example/Tests/Model/FSTMutationTests.mm b/Firestore/Example/Tests/Model/FSTMutationTests.mm index 60cb7b8..56bf1c2 100644 --- a/Firestore/Example/Tests/Model/FSTMutationTests.mm +++ b/Firestore/Example/Tests/Model/FSTMutationTests.mm @@ -16,9 +16,12 @@ #import "Firestore/Source/Model/FSTMutation.h" +#import <FirebaseFirestore/FIRFieldValue.h> #import <FirebaseFirestore/FIRTimestamp.h> #import <XCTest/XCTest.h> +#include <vector> + #import "Firestore/Source/Model/FSTDocument.h" #import "Firestore/Source/Model/FSTFieldValue.h" @@ -26,13 +29,19 @@ #include "Firestore/core/src/firebase/firestore/model/document_key.h" #include "Firestore/core/src/firebase/firestore/model/field_mask.h" +#include "Firestore/core/src/firebase/firestore/model/field_transform.h" #include "Firestore/core/src/firebase/firestore/model/precondition.h" +#include "Firestore/core/src/firebase/firestore/model/transform_operations.h" #include "Firestore/core/test/firebase/firestore/testutil/testutil.h" namespace testutil = firebase::firestore::testutil; +using firebase::firestore::model::ArrayTransform; using firebase::firestore::model::DocumentKey; using firebase::firestore::model::FieldMask; +using firebase::firestore::model::FieldPath; +using firebase::firestore::model::FieldTransform; using firebase::firestore::model::Precondition; +using firebase::firestore::model::TransformOperation; @interface FSTMutationTests : XCTestCase @end @@ -104,11 +113,12 @@ using firebase::firestore::model::Precondition; XCTAssertEqualObjects(patchedDoc, baseDoc); } -- (void)testAppliesLocalTransformsToDocuments { +- (void)testAppliesLocalServerTimestampTransformToDocuments { NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" }; FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO); - FSTMutation *transform = FSTTestTransformMutation(@"collection/key", @[ @"foo.bar" ]); + FSTMutation *transform = FSTTestTransformMutation( + @"collection/key", @{@"foo.bar" : [FIRFieldValue fieldValueForServerTimestamp]}); FSTMaybeDocument *transformedDoc = [transform applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp]; @@ -130,11 +140,57 @@ using firebase::firestore::model::Precondition; XCTAssertEqualObjects(transformedDoc, expectedDoc); } +// NOTE: This is more a test of FSTUserDataConverter code than FSTMutation code but we don't have +// unit tests for it currently. We could consider removing this test once we have integration tests. +- (void)testCreateArrayUnionTransform { + FSTTransformMutation *transform = FSTTestTransformMutation(@"collection/key", @{ + @"foo" : [FIRFieldValue fieldValueForArrayUnion:@[ @"tag" ]], + @"bar.baz" : [FIRFieldValue fieldValueForArrayUnion:@[ @YES, @[ @1, @2 ], @{@"a" : @"b"} ]] + }); + XCTAssertEqual(transform.fieldTransforms.size(), 2); + + const FieldTransform &first = transform.fieldTransforms[0]; + XCTAssertEqual(first.path(), FieldPath({"foo"})); + { + std::vector<FSTFieldValue *> expectedElements{FSTTestFieldValue(@"tag")}; + ArrayTransform expected(TransformOperation::Type::ArrayUnion, expectedElements); + XCTAssertEqual(static_cast<const ArrayTransform &>(first.transformation()), expected); + } + + const FieldTransform &second = transform.fieldTransforms[1]; + XCTAssertEqual(second.path(), FieldPath({"bar", "baz"})); + { + std::vector<FSTFieldValue *> expectedElements { + FSTTestFieldValue(@YES), FSTTestFieldValue(@[ @1, @2 ]), FSTTestFieldValue(@{@"a" : @"b"}) + }; + ArrayTransform expected(TransformOperation::Type::ArrayUnion, expectedElements); + XCTAssertEqual(static_cast<const ArrayTransform &>(second.transformation()), expected); + } +} + +// NOTE: This is more a test of FSTUserDataConverter code than FSTMutation code but we don't have +// unit tests for it currently. We could consider removing this test once we have integration tests. +- (void)testCreateArrayRemoveTransform { + FSTTransformMutation *transform = FSTTestTransformMutation(@"collection/key", @{ + @"foo" : [FIRFieldValue fieldValueForArrayRemove:@[ @"tag" ]], + }); + XCTAssertEqual(transform.fieldTransforms.size(), 1); + + const FieldTransform &first = transform.fieldTransforms[0]; + XCTAssertEqual(first.path(), FieldPath({"foo"})); + { + std::vector<FSTFieldValue *> expectedElements{FSTTestFieldValue(@"tag")}; + const ArrayTransform expected(TransformOperation::Type::ArrayRemove, expectedElements); + XCTAssertEqual(static_cast<const ArrayTransform &>(first.transformation()), expected); + } +} + - (void)testAppliesServerAckedTransformsToDocuments { NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" }; FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO); - FSTMutation *transform = FSTTestTransformMutation(@"collection/key", @[ @"foo.bar" ]); + FSTMutation *transform = FSTTestTransformMutation( + @"collection/key", @{@"foo.bar" : [FIRFieldValue fieldValueForServerTimestamp]}); FSTMutationResult *mutationResult = [[FSTMutationResult alloc] initWithVersion:FSTTestVersion(1) diff --git a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm index 454b108..a648cd8 100644 --- a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm +++ b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm @@ -17,6 +17,7 @@ #import "Firestore/Source/Remote/FSTSerializerBeta.h" #import <FirebaseFirestore/FIRFieldPath.h> +#import <FirebaseFirestore/FIRFieldValue.h> #import <FirebaseFirestore/FIRFirestoreErrors.h> #import <FirebaseFirestore/FIRGeoPoint.h> #import <FirebaseFirestore/FIRTimestamp.h> @@ -367,7 +368,10 @@ NS_ASSUME_NONNULL_BEGIN } - (void)testEncodesTransformMutation { - FSTTransformMutation *mutation = FSTTestTransformMutation(@"docs/1", @[ @"a", @"bar.baz" ]); + FSTTransformMutation *mutation = FSTTestTransformMutation(@"docs/1", @{ + @"a" : [FIRFieldValue fieldValueForServerTimestamp], + @"bar.baz" : [FIRFieldValue fieldValueForServerTimestamp] + }); GCFSWrite *proto = [GCFSWrite message]; proto.transform = [GCFSDocumentTransform message]; proto.transform.document = [self.serializer encodedDocumentKey:mutation.key]; diff --git a/Firestore/Example/Tests/Util/FSTHelpers.h b/Firestore/Example/Tests/Util/FSTHelpers.h index d05c1f1..9b5f96a 100644 --- a/Firestore/Example/Tests/Util/FSTHelpers.h +++ b/Firestore/Example/Tests/Util/FSTHelpers.h @@ -245,8 +245,12 @@ FSTPatchMutation *FSTTestPatchMutation( NSDictionary<NSString *, id> *values, const std::vector<firebase::firestore::model::FieldPath> &updateMask); -FSTTransformMutation *FSTTestTransformMutation(NSString *path, - NSArray<NSString *> *serverTimestampFields); +/** + * Creates a FSTTransformMutation by parsing any FIRFieldValue sentinels in the provided data. The + * data is expected to use dotted-notation for nested fields (i.e. + * @{ @"foo.bar": [FIRFieldValue ...] } and must not contain any non-sentinel data. + */ +FSTTransformMutation *FSTTestTransformMutation(NSString *path, NSDictionary<NSString *, id> *data); /** Creates a delete mutation for the document key at the given path. */ FSTDeleteMutation *FSTTestDeleteMutation(NSString *path); diff --git a/Firestore/Example/Tests/Util/FSTHelpers.mm b/Firestore/Example/Tests/Util/FSTHelpers.mm index 78b41a4..e1ed18c 100644 --- a/Firestore/Example/Tests/Util/FSTHelpers.mm +++ b/Firestore/Example/Tests/Util/FSTHelpers.mm @@ -122,7 +122,7 @@ NSDateComponents *FSTTestDateComponents( return comps; } -FSTFieldValue *FSTTestFieldValue(id _Nullable value) { +FSTUserDataConverter *FSTTestUserDataConverter() { // This owns the DatabaseIds since we do not have FirestoreClient instance to own them. static DatabaseId database_id{"project", DatabaseId::kDefault}; FSTUserDataConverter *converter = @@ -130,6 +130,11 @@ FSTFieldValue *FSTTestFieldValue(id _Nullable value) { preConverter:^id _Nullable(id _Nullable input) { return input; }]; + return converter; +} + +FSTFieldValue *FSTTestFieldValue(id _Nullable value) { + FSTUserDataConverter *converter = FSTTestUserDataConverter(); // HACK: We use parsedQueryValue: since it accepts scalars as well as arrays / objects, and // our tests currently use FSTTestFieldValue() pretty generically so we don't know the intent. return [converter parsedQueryValue:value]; @@ -279,17 +284,14 @@ FSTPatchMutation *FSTTestPatchMutation(const absl::string_view path, precondition:Precondition::Exists(true)]; } -// For now this only creates TransformMutations with server timestamps. -FSTTransformMutation *FSTTestTransformMutation(NSString *path, - NSArray<NSString *> *serverTimestampFields) { +FSTTransformMutation *FSTTestTransformMutation(NSString *path, NSDictionary<NSString *, id> *data) { FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource(util::MakeStringView(path))]; - std::vector<FieldTransform> fieldTransforms; - for (NSString *field in serverTimestampFields) { - FieldPath fieldPath = testutil::Field(util::MakeStringView(field)); - auto transformOp = absl::make_unique<ServerTimestampTransform>(ServerTimestampTransform::Get()); - fieldTransforms.emplace_back(std::move(fieldPath), std::move(transformOp)); - } - return [[FSTTransformMutation alloc] initWithKey:key fieldTransforms:std::move(fieldTransforms)]; + FSTUserDataConverter *converter = FSTTestUserDataConverter(); + FSTParsedUpdateData *result = [converter parsedUpdateData:data]; + FSTCAssert(result.data.value.count == 0, + @"FSTTestTransformMutation() only expects transforms; no other data"); + return [[FSTTransformMutation alloc] initWithKey:key + fieldTransforms:std::move(result.fieldTransforms)]; } FSTDeleteMutation *FSTTestDeleteMutation(NSString *path) { |