FIRFieldsTests.m 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. @import FirebaseFirestore;
  17. #import <XCTest/XCTest.h>
  18. #import "Firestore/Source/Core/FSTFirestoreClient.h"
  19. #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h"
  20. @interface FIRFieldsTests : FSTIntegrationTestCase
  21. @end
  22. @implementation FIRFieldsTests
  23. - (NSDictionary<NSString *, id> *)testNestedDataNumbered:(int)number {
  24. return @{
  25. @"name" : [NSString stringWithFormat:@"room %d", number],
  26. @"metadata" : @{
  27. @"createdAt" : @(number),
  28. @"deep" : @{@"field" : [NSString stringWithFormat:@"deep-field-%d", number]}
  29. }
  30. };
  31. }
  32. - (void)testNestedFieldsCanBeWrittenWithSet {
  33. NSDictionary<NSString *, id> *testData = [self testNestedDataNumbered:1];
  34. FIRDocumentReference *doc = [self documentRef];
  35. [self writeDocumentRef:doc data:testData];
  36. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  37. XCTAssertEqualObjects(result.data, testData);
  38. }
  39. - (void)testNestedFieldsCanBeReadDirectly {
  40. NSDictionary<NSString *, id> *testData = [self testNestedDataNumbered:1];
  41. FIRDocumentReference *doc = [self documentRef];
  42. [self writeDocumentRef:doc data:testData];
  43. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  44. XCTAssertEqualObjects(result[@"name"], testData[@"name"]);
  45. XCTAssertEqualObjects(result[@"metadata"], testData[@"metadata"]);
  46. XCTAssertEqualObjects(result[@"metadata.deep.field"], testData[@"metadata"][@"deep"][@"field"]);
  47. XCTAssertNil(result[@"metadata.nofield"]);
  48. XCTAssertNil(result[@"nometadata.nofield"]);
  49. }
  50. - (void)testNestedFieldsCanBeUpdated {
  51. NSDictionary<NSString *, id> *testData = [self testNestedDataNumbered:1];
  52. FIRDocumentReference *doc = [self documentRef];
  53. [self writeDocumentRef:doc data:testData];
  54. [self updateDocumentRef:doc data:@{ @"metadata.deep.field" : @100, @"metadata.added" : @200 }];
  55. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  56. XCTAssertEqualObjects(
  57. result.data, (@{
  58. @"name" : @"room 1",
  59. @"metadata" : @{@"createdAt" : @1, @"deep" : @{@"field" : @100}, @"added" : @200}
  60. }));
  61. }
  62. - (void)testNestedFieldsCanBeUsedInQueryFilters {
  63. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *testDocs = @{
  64. @"1" : [self testNestedDataNumbered:300],
  65. @"2" : [self testNestedDataNumbered:100],
  66. @"3" : [self testNestedDataNumbered:200]
  67. };
  68. // inequality adds implicit sort on field
  69. NSArray<NSDictionary<NSString *, id> *> *expected =
  70. @[ [self testNestedDataNumbered:200], [self testNestedDataNumbered:300] ];
  71. FIRCollectionReference *coll = [self collectionRefWithDocuments:testDocs];
  72. FIRQuery *q = [coll queryWhereField:@"metadata.createdAt" isGreaterThanOrEqualTo:@200];
  73. FIRQuerySnapshot *results = [self readDocumentSetForRef:q];
  74. XCTAssertEqualObjects(FIRQuerySnapshotGetData(results), (expected));
  75. }
  76. - (void)testNestedFieldsCanBeUsedInOrderBy {
  77. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *testDocs = @{
  78. @"1" : [self testNestedDataNumbered:300],
  79. @"2" : [self testNestedDataNumbered:100],
  80. @"3" : [self testNestedDataNumbered:200]
  81. };
  82. FIRCollectionReference *coll = [self collectionRefWithDocuments:testDocs];
  83. XCTestExpectation *queryCompletion = [self expectationWithDescription:@"query"];
  84. FIRQuery *q = [coll queryOrderedByField:@"metadata.createdAt"];
  85. [q getDocumentsWithCompletion:^(FIRQuerySnapshot *results, NSError *error) {
  86. XCTAssertNil(error);
  87. XCTAssertEqualObjects(FIRQuerySnapshotGetData(results), (@[
  88. [self testNestedDataNumbered:100], [self testNestedDataNumbered:200],
  89. [self testNestedDataNumbered:300]
  90. ]));
  91. [queryCompletion fulfill];
  92. }];
  93. [self awaitExpectations];
  94. }
  95. /**
  96. * Creates test data with special characters in field names. Datastore currently prohibits mixing
  97. * nested data with special characters so tests that use this data must be separate.
  98. */
  99. - (NSDictionary<NSString *, id> *)testDottedDataNumbered:(int)number {
  100. return @{
  101. @"a" : [NSString stringWithFormat:@"field %d", number],
  102. @"b.dot" : @(number),
  103. @"c\\slash" : @(number)
  104. };
  105. }
  106. - (void)testFieldsWithSpecialCharsCanBeWrittenWithSet {
  107. NSDictionary<NSString *, id> *testData = [self testDottedDataNumbered:1];
  108. FIRDocumentReference *doc = [self documentRef];
  109. [self writeDocumentRef:doc data:testData];
  110. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  111. XCTAssertEqualObjects(result.data, testData);
  112. }
  113. - (void)testFieldsWithSpecialCharsCanBeReadDirectly {
  114. NSDictionary<NSString *, id> *testData = [self testDottedDataNumbered:1];
  115. FIRDocumentReference *doc = [self documentRef];
  116. [self writeDocumentRef:doc data:testData];
  117. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  118. XCTAssertEqualObjects(result[@"a"], testData[@"a"]);
  119. XCTAssertEqualObjects(result[[[FIRFieldPath alloc] initWithFields:@[ @"b.dot" ]]],
  120. testData[@"b.dot"]);
  121. XCTAssertEqualObjects(result[@"c\\slash"], testData[@"c\\slash"]);
  122. }
  123. - (void)testFieldsWithSpecialCharsCanBeUpdated {
  124. NSDictionary<NSString *, id> *testData = [self testDottedDataNumbered:1];
  125. FIRDocumentReference *doc = [self documentRef];
  126. [self writeDocumentRef:doc data:testData];
  127. [self updateDocumentRef:doc
  128. data:@{
  129. [[FIRFieldPath alloc] initWithFields:@[ @"b.dot" ]] : @100,
  130. @"c\\slash" : @200
  131. }];
  132. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  133. XCTAssertEqualObjects(result.data, (@{ @"a" : @"field 1", @"b.dot" : @100, @"c\\slash" : @200 }));
  134. }
  135. - (void)testFieldsWithSpecialCharsCanBeUsedInQueryFilters {
  136. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *testDocs = @{
  137. @"1" : [self testDottedDataNumbered:300],
  138. @"2" : [self testDottedDataNumbered:100],
  139. @"3" : [self testDottedDataNumbered:200]
  140. };
  141. // inequality adds implicit sort on field
  142. NSArray<NSDictionary<NSString *, id> *> *expected =
  143. @[ [self testDottedDataNumbered:200], [self testDottedDataNumbered:300] ];
  144. FIRCollectionReference *coll = [self collectionRefWithDocuments:testDocs];
  145. XCTestExpectation *queryCompletion = [self expectationWithDescription:@"query"];
  146. FIRQuery *q = [coll queryWhereFieldPath:[[FIRFieldPath alloc] initWithFields:@[ @"b.dot" ]]
  147. isGreaterThanOrEqualTo:@200];
  148. [q getDocumentsWithCompletion:^(FIRQuerySnapshot *results, NSError *error) {
  149. XCTAssertNil(error);
  150. XCTAssertEqualObjects(FIRQuerySnapshotGetData(results), expected);
  151. [queryCompletion fulfill];
  152. }];
  153. [self awaitExpectations];
  154. }
  155. - (void)testFieldsWithSpecialCharsCanBeUsedInOrderBy {
  156. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *testDocs = @{
  157. @"1" : [self testDottedDataNumbered:300],
  158. @"2" : [self testDottedDataNumbered:100],
  159. @"3" : [self testDottedDataNumbered:200]
  160. };
  161. NSArray<NSDictionary<NSString *, id> *> *expected = @[
  162. [self testDottedDataNumbered:100], [self testDottedDataNumbered:200],
  163. [self testDottedDataNumbered:300]
  164. ];
  165. FIRCollectionReference *coll = [self collectionRefWithDocuments:testDocs];
  166. FIRQuery *q = [coll queryOrderedByFieldPath:[[FIRFieldPath alloc] initWithFields:@[ @"b.dot" ]]];
  167. XCTestExpectation *queryDot = [self expectationWithDescription:@"query dot"];
  168. [q getDocumentsWithCompletion:^(FIRQuerySnapshot *results, NSError *error) {
  169. XCTAssertNil(error);
  170. XCTAssertEqualObjects(FIRQuerySnapshotGetData(results), expected);
  171. [queryDot fulfill];
  172. }];
  173. [self awaitExpectations];
  174. XCTestExpectation *querySlash = [self expectationWithDescription:@"query slash"];
  175. q = [coll queryOrderedByField:@"c\\slash"];
  176. [q getDocumentsWithCompletion:^(FIRQuerySnapshot *results, NSError *error) {
  177. XCTAssertNil(error);
  178. XCTAssertEqualObjects(FIRQuerySnapshotGetData(results), expected);
  179. [querySlash fulfill];
  180. }];
  181. [self awaitExpectations];
  182. }
  183. @end