aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Example
diff options
context:
space:
mode:
authorGravatar Michael Lehenbauer <mikelehen@gmail.com>2018-04-13 14:22:41 -0700
committerGravatar GitHub <noreply@github.com>2018-04-13 14:22:41 -0700
commit60d43d7b0980719beac21811da712f1cb4881308 (patch)
tree268424fabe81a547ee17b737177f24130b1f4d89 /Firestore/Example
parentdfdab5bee001546b3f36638c00b96b381cb4c040 (diff)
Array Transforms public API and parsing
This includes the new FIRFieldValue sentinels, the FSTUserDataConverter code to parse them into internal ArrayTransform operations for use in an FSTTransformMutation, and some sanity testing in FSTMutationTests. I still need to implement FSTTransformMutation support for local application and serialization (and then integration tests).
Diffstat (limited to 'Firestore/Example')
-rw-r--r--Firestore/Example/SwiftBuildTest/main.swift4
-rw-r--r--Firestore/Example/Tests/Model/FSTMutationTests.mm62
-rw-r--r--Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm6
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.h8
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.mm24
5 files changed, 87 insertions, 17 deletions
diff --git a/Firestore/Example/SwiftBuildTest/main.swift b/Firestore/Example/SwiftBuildTest/main.swift
index 3087085..691adf6 100644
--- a/Firestore/Example/SwiftBuildTest/main.swift
+++ b/Firestore/Example/SwiftBuildTest/main.swift
@@ -100,6 +100,10 @@ func writeDocument(at docRef: DocumentReference) {
let updateData = [
"bar.baz": 42,
FieldPath(["foobar"]): 42,
+ "server_timestamp": FieldValue.serverTimestamp(),
+ "array_union": FieldValue.arrayUnion(["a", "b"]),
+ "array_remove": FieldValue.arrayRemove(["a", "b"]),
+ "field_delete": FieldValue.delete(),
] as [AnyHashable: Any]
docRef.setData(setData)
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) {