Переглянути джерело

Update spec tests from changes in the firebase-js-sdk respository (#5278)

Denver Coneybeare 6 роки тому
батько
коміт
b05e9eb68d

+ 35 - 11
Firestore/Example/Tests/SpecTests/FSTSpecTests.mm

@@ -18,6 +18,7 @@
 
 #import <FirebaseFirestore/FIRFirestoreErrors.h>
 
+#include <algorithm>
 #include <map>
 #include <memory>
 #include <string>
@@ -92,6 +93,7 @@ using firebase::firestore::remote::DocumentWatchChange;
 using firebase::firestore::remote::ExistenceFilterWatchChange;
 using firebase::firestore::remote::WatchTargetChange;
 using firebase::firestore::remote::WatchTargetChangeState;
+using firebase::firestore::util::MakeNSString;
 using firebase::firestore::util::MakeString;
 using firebase::firestore::util::Path;
 using firebase::firestore::util::Status;
@@ -150,6 +152,26 @@ ByteString MakeResumeToken(NSString *specString) {
   return MakeByteString([specString dataUsingEncoding:NSUTF8StringEncoding]);
 }
 
+NSString *ToDocumentListString(const std::map<DocumentKey, TargetId> &map) {
+  std::vector<std::string> strings;
+  strings.reserve(map.size());
+  for (const auto &kv : map) {
+    strings.push_back(kv.first.ToString());
+  }
+  std::sort(strings.begin(), strings.end());
+  return MakeNSString(absl::StrJoin(strings, ", "));
+}
+
+NSString *ToTargetIdListString(const ActiveTargetMap &map) {
+  std::vector<model::TargetId> targetIds;
+  targetIds.reserve(map.size());
+  for (const auto &kv : map) {
+    targetIds.push_back(kv.first);
+  }
+  std::sort(targetIds.begin(), targetIds.end());
+  return MakeNSString(absl::StrJoin(targetIds, ", "));
+}
+
 }  // namespace
 
 @interface FSTSpecTests ()
@@ -661,14 +683,14 @@ ByteString MakeResumeToken(NSString *specString) {
       XCTAssertEqual([self.driver watchStreamRequestCount],
                      [expectedState[@"watchStreamRequestCount"] intValue]);
     }
-    if (expectedState[@"limboDocs"]) {
-      DocumentKeySet expectedLimboDocuments;
-      NSArray *docNames = expectedState[@"limboDocs"];
+    if (expectedState[@"activeLimboDocs"]) {
+      DocumentKeySet expectedActiveLimboDocuments;
+      NSArray *docNames = expectedState[@"activeLimboDocs"];
       for (NSString *name in docNames) {
-        expectedLimboDocuments = expectedLimboDocuments.insert(FSTTestDocKey(name));
+        expectedActiveLimboDocuments = expectedActiveLimboDocuments.insert(FSTTestDocKey(name));
       }
       // Update the expected limbo documents
-      [self.driver setExpectedLimboDocuments:std::move(expectedLimboDocuments)];
+      [self.driver setExpectedActiveLimboDocuments:std::move(expectedActiveLimboDocuments)];
     }
     if (expectedState[@"activeTargets"]) {
       __block ActiveTargetMap expectedActiveTargets;
@@ -726,21 +748,23 @@ ByteString MakeResumeToken(NSString *specString) {
   // Make a copy so it can modified while checking against the expected limbo docs.
   std::map<DocumentKey, TargetId> actualLimboDocs = self.driver.currentLimboDocuments;
 
-  // Validate that each limbo doc has an expected active target
+  // Validate that each active limbo doc has an expected active target
   for (const auto &kv : actualLimboDocs) {
     const auto &expected = [self.driver expectedActiveTargets];
     XCTAssertTrue(expected.find(kv.second) != expected.end(),
-                  @"Found limbo doc without an expected active target");
+                  @"Found limbo doc %s, but its target ID %d was not in the "
+                  @"set of expected active target IDs %@",
+                  kv.first.ToString().c_str(), kv.second, ToTargetIdListString(expected));
   }
 
-  for (const DocumentKey &expectedLimboDoc : self.driver.expectedLimboDocuments) {
+  for (const DocumentKey &expectedLimboDoc : self.driver.expectedActiveLimboDocuments) {
     XCTAssert(actualLimboDocs.find(expectedLimboDoc) != actualLimboDocs.end(),
               @"Expected doc to be in limbo, but was not: %s", expectedLimboDoc.ToString().c_str());
     actualLimboDocs.erase(expectedLimboDoc);
   }
-  XCTAssertTrue(actualLimboDocs.empty(), "%lu Unexpected docs in limbo, the first one is <%s, %d>",
-                actualLimboDocs.size(), actualLimboDocs.begin()->first.ToString().c_str(),
-                actualLimboDocs.begin()->second);
+
+  XCTAssertTrue(actualLimboDocs.empty(), @"Unexpected active docs in limbo: %@",
+                ToDocumentListString(actualLimboDocs));
 }
 
 - (void)validateActiveTargets {

+ 4 - 4
Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h

@@ -292,11 +292,11 @@ typedef std::unordered_map<auth::User, NSMutableArray<FSTOutstandingWrite *> *,
 /** The current set of documents in limbo. */
 - (std::map<model::DocumentKey, model::TargetId>)currentLimboDocuments;
 
-/** The expected set of documents in limbo. */
-- (const model::DocumentKeySet &)expectedLimboDocuments;
+/** The expected set of documents in limbo with an active target. */
+- (const model::DocumentKeySet &)expectedActiveLimboDocuments;
 
-/** Sets the expected set of documents in limbo. */
-- (void)setExpectedLimboDocuments:(model::DocumentKeySet)docs;
+/** Sets the expected set of documents in limbo with an active target. */
+- (void)setExpectedActiveLimboDocuments:(model::DocumentKeySet)docs;
 
 /**
  * The writes that have been sent to the FSTSyncEngine via writeUserMutation: but not yet

+ 5 - 5
Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm

@@ -172,7 +172,7 @@ NS_ASSUME_NONNULL_BEGIN
 
   // ivar is declared as mutable.
   std::unordered_map<User, NSMutableArray<FSTOutstandingWrite *> *, HashUser> _outstandingWrites;
-  DocumentKeySet _expectedLimboDocuments;
+  DocumentKeySet _expectedActiveLimboDocuments;
 
   /** A dictionary for tracking the listens on queries. */
   std::unordered_map<Query, std::shared_ptr<QueryListener>> _queryListeners;
@@ -243,12 +243,12 @@ NS_ASSUME_NONNULL_BEGIN
   return _outstandingWrites;
 }
 
-- (const DocumentKeySet &)expectedLimboDocuments {
-  return _expectedLimboDocuments;
+- (const DocumentKeySet &)expectedActiveLimboDocuments {
+  return _expectedActiveLimboDocuments;
 }
 
-- (void)setExpectedLimboDocuments:(DocumentKeySet)docs {
-  _expectedLimboDocuments = std::move(docs);
+- (void)setExpectedActiveLimboDocuments:(DocumentKeySet)docs {
+  _expectedActiveLimboDocuments = std::move(docs);
 }
 
 - (void)drainQueue {

+ 62 - 47
Firestore/Example/Tests/SpecTests/json/collection_spec_test.json

@@ -2,19 +2,22 @@
   "Events are raised after watch ack": {
     "describeName": "Collections:",
     "itName": "Events are raised after watch ack",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": true,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": true
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -22,9 +25,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -42,14 +47,14 @@
           "docs": [
             {
               "key": "collection/key",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "foo": "bar"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -67,32 +72,35 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/key",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "foo": "bar"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
         ]
       }
@@ -101,19 +109,22 @@
   "Events are raised for local sets before watch ack": {
     "describeName": "Collections:",
     "itName": "Events are raised for local sets before watch ack",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": true,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": true
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -121,9 +132,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -140,27 +153,29 @@
         ],
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/key",
-                "version": 0,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": true
+                },
                 "value": {
                   "foo": "bar"
                 },
-                "options": {
-                  "hasLocalMutations": true,
-                  "hasCommittedMutations": false
-                }
+                "version": 0
               }
             ],
             "errorCode": 0,
             "fromCache": true,
-            "hasPendingWrites": true
+            "hasPendingWrites": true,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
         ]
       }

Різницю між файлами не показано, бо вона завелика
+ 369 - 380
Firestore/Example/Tests/SpecTests/json/existence_filter_spec_test.json


Різницю між файлами не показано, бо вона завелика
+ 387 - 430
Firestore/Example/Tests/SpecTests/json/limbo_spec_test.json


Різницю між файлами не показано, бо вона завелика
+ 440 - 443
Firestore/Example/Tests/SpecTests/json/limit_spec_test.json


Різницю між файлами не показано, бо вона завелика
+ 621 - 339
Firestore/Example/Tests/SpecTests/json/listen_spec_test.json


Різницю між файлами не показано, бо вона завелика
+ 471 - 260
Firestore/Example/Tests/SpecTests/json/offline_spec_test.json


+ 183 - 164
Firestore/Example/Tests/SpecTests/json/orderby_spec_test.json

@@ -2,10 +2,11 @@
   "orderBy applies filtering based on local state": {
     "describeName": "OrderBy:",
     "itName": "orderBy applies filtering based on local state",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": true,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": true
     },
     "steps": [
       {
@@ -37,14 +38,47 @@
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
+            "filters": [
+            ],
             "orderBys": [
               [
                 "sort",
                 "asc"
               ]
-            ]
+            ],
+            "path": "collection"
+          }
+        ],
+        "expectedSnapshotEvents": [
+          {
+            "added": [
+              {
+                "key": "collection/a",
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": true
+                },
+                "value": {
+                  "key": "a",
+                  "sort": 1
+                },
+                "version": 0
+              }
+            ],
+            "errorCode": 0,
+            "fromCache": true,
+            "hasPendingWrites": true,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+                [
+                  "sort",
+                  "asc"
+                ]
+              ],
+              "path": "collection"
+            }
           }
         ],
         "expectedState": {
@@ -52,51 +86,21 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
+                  "filters": [
+                  ],
                   "orderBys": [
                     [
                       "sort",
                       "asc"
                     ]
-                  ]
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
             }
           }
-        },
-        "expectedSnapshotEvents": [
-          {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": [
-                [
-                  "sort",
-                  "asc"
-                ]
-              ]
-            },
-            "added": [
-              {
-                "key": "collection/a",
-                "version": 0,
-                "value": {
-                  "key": "a",
-                  "sort": 1
-                },
-                "options": {
-                  "hasLocalMutations": true,
-                  "hasCommittedMutations": false
-                }
-              }
-            ],
-            "errorCode": 0,
-            "fromCache": true,
-            "hasPendingWrites": true
-          }
-        ]
+        }
       },
       {
         "watchAck": [
@@ -108,14 +112,14 @@
           "docs": [
             {
               "key": "collection/b",
-              "version": 1001,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "b"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1001
             }
           ],
           "targets": [
@@ -133,38 +137,40 @@
       },
       {
         "watchSnapshot": {
-          "version": 2000,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 2000
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": [
-                [
-                  "sort",
-                  "asc"
-                ]
-              ]
-            },
             "added": [
               {
                 "key": "collection/b",
-                "version": 1001,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": true
+                },
                 "value": {
                   "key": "b",
                   "sort": 2
                 },
-                "options": {
-                  "hasLocalMutations": true,
-                  "hasCommittedMutations": false
-                }
+                "version": 1001
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": true
+            "hasPendingWrites": true,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+                [
+                  "sort",
+                  "asc"
+                ]
+              ],
+              "path": "collection"
+            }
           }
         ]
       }
@@ -173,24 +179,26 @@
   "orderBy applies to existing documents": {
     "describeName": "OrderBy:",
     "itName": "orderBy applies to existing documents",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": false,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": false
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
+            "filters": [
+            ],
             "orderBys": [
               [
                 "sort",
                 "asc"
               ]
-            ]
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -198,14 +206,15 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
+                  "filters": [
+                  ],
                   "orderBys": [
                     [
                       "sort",
                       "asc"
                     ]
-                  ]
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -223,27 +232,27 @@
           "docs": [
             {
               "key": "collection/a",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "a",
                 "sort": 2
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             },
             {
               "key": "collection/b",
-              "version": 1001,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "b",
                 "sort": 1
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1001
             }
           ],
           "targets": [
@@ -261,50 +270,52 @@
       },
       {
         "watchSnapshot": {
-          "version": 1002,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1002
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": [
-                [
-                  "sort",
-                  "asc"
-                ]
-              ]
-            },
             "added": [
               {
                 "key": "collection/b",
-                "version": 1001,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "b",
                   "sort": 1
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1001
               },
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a",
                   "sort": 2
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+                [
+                  "sort",
+                  "asc"
+                ]
+              ],
+              "path": "collection"
+            }
           }
         ]
       },
@@ -312,18 +323,20 @@
         "userUnlisten": [
           2,
           {
-            "path": "collection",
-            "filters": [],
+            "filters": [
+            ],
             "orderBys": [
               [
                 "sort",
                 "asc"
               ]
-            ]
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
-          "activeTargets": {}
+          "activeTargets": {
+          }
         }
       },
       {
@@ -337,78 +350,81 @@
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
+            "filters": [
+            ],
             "orderBys": [
               [
                 "sort",
                 "asc"
               ]
-            ]
+            ],
+            "path": "collection"
           }
         ],
-        "expectedState": {
-          "activeTargets": {
-            "2": {
-              "queries": [
-                {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": [
-                    [
-                      "sort",
-                      "asc"
-                    ]
-                  ]
-                }
-              ],
-              "resumeToken": "resume-token-1002"
-            }
-          }
-        },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": [
-                [
-                  "sort",
-                  "asc"
-                ]
-              ]
-            },
             "added": [
               {
                 "key": "collection/b",
-                "version": 1001,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "b",
                   "sort": 1
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1001
               },
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a",
                   "sort": 2
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": true,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+                [
+                  "sort",
+                  "asc"
+                ]
+              ],
+              "path": "collection"
+            }
           }
-        ]
+        ],
+        "expectedState": {
+          "activeTargets": {
+            "2": {
+              "queries": [
+                {
+                  "filters": [
+                  ],
+                  "orderBys": [
+                    [
+                      "sort",
+                      "asc"
+                    ]
+                  ],
+                  "path": "collection"
+                }
+              ],
+              "resumeToken": "resume-token-1002"
+            }
+          }
+        }
       },
       {
         "watchAck": [
@@ -417,7 +433,8 @@
       },
       {
         "watchEntity": {
-          "docs": [],
+          "docs": [
+          ],
           "targets": [
             2
           ]
@@ -433,24 +450,26 @@
       },
       {
         "watchSnapshot": {
-          "version": 1002,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1002
         },
         "expectedSnapshotEvents": [
           {
+            "errorCode": 0,
+            "fromCache": false,
+            "hasPendingWrites": false,
             "query": {
-              "path": "collection",
-              "filters": [],
+              "filters": [
+              ],
               "orderBys": [
                 [
                   "sort",
                   "asc"
                 ]
-              ]
-            },
-            "errorCode": 0,
-            "fromCache": false,
-            "hasPendingWrites": false
+              ],
+              "path": "collection"
+            }
           }
         ]
       }

Різницю між файлами не показано, бо вона завелика
+ 13455 - 12719
Firestore/Example/Tests/SpecTests/json/perf_spec_test.json


Різницю між файлами не показано, бо вона завелика
+ 582 - 452
Firestore/Example/Tests/SpecTests/json/persistence_spec_test.json


Різницю між файлами не показано, бо вона завелика
+ 408 - 318
Firestore/Example/Tests/SpecTests/json/query_spec_test.json


+ 381 - 314
Firestore/Example/Tests/SpecTests/json/remote_store_spec_test.json

@@ -1,20 +1,23 @@
 {
-  "Waits for watch to remove targets": {
+  "Cleans up watch state correctly": {
     "describeName": "Remote store:",
-    "itName": "Waits for watch to remove targets",
-    "tags": [],
+    "itName": "Cleans up watch state correctly",
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": false,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": false
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -22,9 +25,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -33,88 +38,28 @@
         }
       },
       {
-        "watchAck": [
-          2
-        ]
-      },
-      {
-        "userUnlisten": [
-          2,
-          {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
-          }
-        ],
-        "expectedState": {
-          "activeTargets": {}
-        }
-      },
-      {
-        "userListen": [
-          2,
+        "watchStreamClose": {
+          "error": {
+            "code": 14,
+            "message": "Simulated Backend Error"
+          },
+          "runBackoffTimer": true
+        },
+        "expectedSnapshotEvents": [
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
-          }
-        ],
-        "expectedState": {
-          "activeTargets": {
-            "2": {
-              "queries": [
-                {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
-                }
+            "errorCode": 0,
+            "fromCache": true,
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
               ],
-              "resumeToken": ""
+              "orderBys": [
+              ],
+              "path": "collection"
             }
           }
-        }
-      },
-      {
-        "watchEntity": {
-          "docs": [
-            {
-              "key": "collection/a",
-              "version": 1000,
-              "value": {
-                "key": "a"
-              },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
-            }
-          ],
-          "targets": [
-            2
-          ]
-        }
-      },
-      {
-        "watchCurrent": [
-          [
-            2
-          ],
-          "resume-token"
         ]
       },
-      {
-        "watchSnapshot": {
-          "version": 1000,
-          "targetIds": []
-        }
-      },
-      {
-        "watchRemove": {
-          "targetIds": [
-            2
-          ]
-        }
-      },
       {
         "watchAck": [
           2
@@ -125,14 +70,14 @@
           "docs": [
             {
               "key": "collection/a",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "a"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -150,53 +95,156 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
         ]
       }
     ]
   },
+  "Handles user changes while offline (b/74749605).": {
+    "describeName": "Remote store:",
+    "itName": "Handles user changes while offline (b/74749605).",
+    "tags": [
+      "no-android",
+      "no-ios"
+    ],
+    "config": {
+      "numClients": 1,
+      "useGarbageCollection": true
+    },
+    "steps": [
+      {
+        "userListen": [
+          2,
+          {
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
+          }
+        ],
+        "expectedState": {
+          "activeTargets": {
+            "2": {
+              "queries": [
+                {
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
+                }
+              ],
+              "resumeToken": ""
+            }
+          }
+        }
+      },
+      {
+        "watchStreamClose": {
+          "error": {
+            "code": 14,
+            "message": "Simulated Backend Error"
+          },
+          "runBackoffTimer": false
+        },
+        "expectedSnapshotEvents": [
+          {
+            "errorCode": 0,
+            "fromCache": true,
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
+          }
+        ],
+        "expectedState": {
+          "activeTargets": {
+          }
+        }
+      },
+      {
+        "changeUser": "abc",
+        "expectedState": {
+          "activeTargets": {
+            "2": {
+              "queries": [
+                {
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
+                }
+              ],
+              "resumeToken": ""
+            }
+          }
+        }
+      },
+      {
+        "watchStreamClose": {
+          "error": {
+            "code": 14,
+            "message": "Simulated Backend Error"
+          },
+          "runBackoffTimer": true
+        }
+      }
+    ]
+  },
   "Waits for watch to ack last target add": {
     "describeName": "Remote store:",
     "itName": "Waits for watch to ack last target add",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": false,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": false
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -204,9 +252,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -223,22 +273,27 @@
         "userUnlisten": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
-          "activeTargets": {}
+          "activeTargets": {
+          }
         }
       },
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -246,9 +301,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -260,22 +317,27 @@
         "userUnlisten": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
-          "activeTargets": {}
+          "activeTargets": {
+          }
         }
       },
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -283,9 +345,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -297,22 +361,27 @@
         "userUnlisten": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
-          "activeTargets": {}
+          "activeTargets": {
+          }
         }
       },
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -320,9 +389,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -335,14 +406,14 @@
           "docs": [
             {
               "key": "collection/a",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "a"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -360,8 +431,9 @@
       },
       {
         "watchSnapshot": {
-          "version": 1000,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1000
         }
       },
       {
@@ -381,14 +453,14 @@
           "docs": [
             {
               "key": "collection/b",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "b"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -406,8 +478,9 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         }
       },
       {
@@ -427,14 +500,14 @@
           "docs": [
             {
               "key": "collection/c",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "c"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -452,8 +525,9 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         }
       },
       {
@@ -473,14 +547,14 @@
           "docs": [
             {
               "key": "collection/d",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "d"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -498,53 +572,59 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/d",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "d"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
         ]
       }
     ]
   },
-  "Cleans up watch state correctly": {
+  "Waits for watch to remove targets": {
     "describeName": "Remote store:",
-    "itName": "Cleans up watch state correctly",
-    "tags": [],
+    "itName": "Waits for watch to remove targets",
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": false,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": false
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -552,9 +632,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -563,26 +645,96 @@
         }
       },
       {
-        "watchStreamClose": {
-          "error": {
-            "code": 14,
-            "message": "Simulated Backend Error"
-          },
-          "runBackoffTimer": true
-        },
-        "expectedSnapshotEvents": [
+        "watchAck": [
+          2
+        ]
+      },
+      {
+        "userUnlisten": [
+          2,
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
-            "errorCode": 0,
-            "fromCache": true,
-            "hasPendingWrites": false
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
+          }
+        ],
+        "expectedState": {
+          "activeTargets": {
+          }
+        }
+      },
+      {
+        "userListen": [
+          2,
+          {
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
+          }
+        ],
+        "expectedState": {
+          "activeTargets": {
+            "2": {
+              "queries": [
+                {
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
+                }
+              ],
+              "resumeToken": ""
+            }
           }
+        }
+      },
+      {
+        "watchEntity": {
+          "docs": [
+            {
+              "key": "collection/a",
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
+              "value": {
+                "key": "a"
+              },
+              "version": 1000
+            }
+          ],
+          "targets": [
+            2
+          ]
+        }
+      },
+      {
+        "watchCurrent": [
+          [
+            2
+          ],
+          "resume-token"
         ]
       },
+      {
+        "watchSnapshot": {
+          "targetIds": [
+          ],
+          "version": 1000
+        }
+      },
+      {
+        "watchRemove": {
+          "targetIds": [
+            2
+          ]
+        }
+      },
       {
         "watchAck": [
           2
@@ -593,14 +745,14 @@
           "docs": [
             {
               "key": "collection/a",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "a"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -618,122 +770,37 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
-          }
-        ]
-      }
-    ]
-  },
-  "Handles user changes while offline (b/74749605).": {
-    "describeName": "Remote store:",
-    "itName": "Handles user changes while offline (b/74749605).",
-    "tags": [
-      "no-android",
-      "no-ios"
-    ],
-    "config": {
-      "useGarbageCollection": true,
-      "numClients": 1
-    },
-    "steps": [
-      {
-        "userListen": [
-          2,
-          {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
-          }
-        ],
-        "expectedState": {
-          "activeTargets": {
-            "2": {
-              "queries": [
-                {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
-                }
-              ],
-              "resumeToken": ""
-            }
-          }
-        }
-      },
-      {
-        "watchStreamClose": {
-          "error": {
-            "code": 14,
-            "message": "Simulated Backend Error"
-          },
-          "runBackoffTimer": false
-        },
-        "expectedSnapshotEvents": [
-          {
+            "hasPendingWrites": false,
             "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
-            "errorCode": 0,
-            "fromCache": true,
-            "hasPendingWrites": false
-          }
-        ],
-        "expectedState": {
-          "activeTargets": {}
-        }
-      },
-      {
-        "changeUser": "abc",
-        "expectedState": {
-          "activeTargets": {
-            "2": {
-              "queries": [
-                {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
-                }
+              "filters": [
               ],
-              "resumeToken": ""
+              "orderBys": [
+              ],
+              "path": "collection"
             }
           }
-        }
-      },
-      {
-        "watchStreamClose": {
-          "error": {
-            "code": 14,
-            "message": "Simulated Backend Error"
-          },
-          "runBackoffTimer": true
-        }
+        ]
       }
     ]
   }

+ 120 - 92
Firestore/Example/Tests/SpecTests/json/resume_token_spec_test.json

@@ -2,19 +2,22 @@
   "Resume tokens are sent after watch stream restarts": {
     "describeName": "Resume tokens:",
     "itName": "Resume tokens are sent after watch stream restarts",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": true,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": true
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -22,9 +25,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -42,14 +47,14 @@
           "docs": [
             {
               "key": "collection/a",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "a"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -67,32 +72,35 @@
       },
       {
         "watchSnapshot": {
-          "version": 1000,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1000
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
         ]
       },
@@ -109,9 +117,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": "custom-query-resume-token"
@@ -124,19 +134,22 @@
   "Resume tokens are used across new listens": {
     "describeName": "Resume tokens:",
     "itName": "Resume tokens are used across new listens",
-    "tags": [],
+    "tags": [
+    ],
     "config": {
-      "useGarbageCollection": false,
-      "numClients": 1
+      "numClients": 1,
+      "useGarbageCollection": false
     },
     "steps": [
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
@@ -144,9 +157,11 @@
             "2": {
               "queries": [
                 {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
                 }
               ],
               "resumeToken": ""
@@ -164,14 +179,14 @@
           "docs": [
             {
               "key": "collection/a",
-              "version": 1000,
+              "options": {
+                "hasCommittedMutations": false,
+                "hasLocalMutations": false
+              },
               "value": {
                 "key": "a"
               },
-              "options": {
-                "hasLocalMutations": false,
-                "hasCommittedMutations": false
-              }
+              "version": 1000
             }
           ],
           "targets": [
@@ -189,32 +204,35 @@
       },
       {
         "watchSnapshot": {
-          "version": 1000,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1000
         },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": false,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
         ]
       },
@@ -222,63 +240,72 @@
         "userUnlisten": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
         "expectedState": {
-          "activeTargets": {}
+          "activeTargets": {
+          }
         }
       },
       {
         "userListen": [
           2,
           {
-            "path": "collection",
-            "filters": [],
-            "orderBys": []
+            "filters": [
+            ],
+            "orderBys": [
+            ],
+            "path": "collection"
           }
         ],
-        "expectedState": {
-          "activeTargets": {
-            "2": {
-              "queries": [
-                {
-                  "path": "collection",
-                  "filters": [],
-                  "orderBys": []
-                }
-              ],
-              "resumeToken": "custom-query-resume-token"
-            }
-          }
-        },
         "expectedSnapshotEvents": [
           {
-            "query": {
-              "path": "collection",
-              "filters": [],
-              "orderBys": []
-            },
             "added": [
               {
                 "key": "collection/a",
-                "version": 1000,
+                "options": {
+                  "hasCommittedMutations": false,
+                  "hasLocalMutations": false
+                },
                 "value": {
                   "key": "a"
                 },
-                "options": {
-                  "hasLocalMutations": false,
-                  "hasCommittedMutations": false
-                }
+                "version": 1000
               }
             ],
             "errorCode": 0,
             "fromCache": true,
-            "hasPendingWrites": false
+            "hasPendingWrites": false,
+            "query": {
+              "filters": [
+              ],
+              "orderBys": [
+              ],
+              "path": "collection"
+            }
           }
-        ]
+        ],
+        "expectedState": {
+          "activeTargets": {
+            "2": {
+              "queries": [
+                {
+                  "filters": [
+                  ],
+                  "orderBys": [
+                  ],
+                  "path": "collection"
+                }
+              ],
+              "resumeToken": "custom-query-resume-token"
+            }
+          }
+        }
       },
       {
         "watchAck": [
@@ -287,8 +314,9 @@
       },
       {
         "watchSnapshot": {
-          "version": 1001,
-          "targetIds": []
+          "targetIds": [
+          ],
+          "version": 1001
         }
       }
     ]

Різницю між файлами не показано, бо вона завелика
+ 452 - 339
Firestore/Example/Tests/SpecTests/json/write_spec_test.json


Деякі файли не було показано, через те що забагато файлів було змінено