| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- /*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License 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 "FOrderByTests.h"
- @interface FOrderByTests ()
- @end
- @implementation FOrderByTests
- - (void)testCanDefineAndUseAnIndex {
- __block FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSArray *users = @[
- @{@"name" : @"Andrew", @"nuggets" : @35}, @{@"name" : @"Rob", @"nuggets" : @40},
- @{@"name" : @"Greg", @"nuggets" : @38}
- ];
- __block int setCount = 0;
- [users enumerateObjectsUsingBlock:^(NSDictionary *user, NSUInteger idx, BOOL *stop) {
- [[ref childByAutoId] setValue:user
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- setCount++;
- }];
- }];
- [self waitUntil:^BOOL {
- return setCount == users.count;
- }];
- __block NSMutableArray *byNuggets = [[NSMutableArray alloc] init];
- [[ref queryOrderedByChild:@"nuggets"] observeEventType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSDictionary *user = snapshot.value;
- [byNuggets addObject:user[@"name"]];
- }];
- [self waitUntil:^BOOL {
- return byNuggets.count == users.count;
- }];
- NSArray *expected = @[ @"Andrew", @"Greg", @"Rob" ];
- XCTAssertEqualObjects(byNuggets, expected, @"Correct by-nugget ordering.");
- }
- - (void)testCanDefineAndUseDeepIndex {
- __block FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSArray *users = @[
- @{@"name" : @"Andrew", @"deep" : @{@"nuggets" : @35}},
- @{@"name" : @"Rob", @"deep" : @{@"nuggets" : @40}},
- @{@"name" : @"Greg", @"deep" : @{@"nuggets" : @38}}
- ];
- __block int setCount = 0;
- [users enumerateObjectsUsingBlock:^(NSDictionary *user, NSUInteger idx, BOOL *stop) {
- [[ref childByAutoId] setValue:user
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- setCount++;
- }];
- }];
- [self waitUntil:^BOOL {
- return setCount == users.count;
- }];
- __block NSMutableArray *byNuggets = [[NSMutableArray alloc] init];
- [[ref queryOrderedByChild:@"deep/nuggets"] observeEventType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSDictionary *user = snapshot.value;
- [byNuggets addObject:user[@"name"]];
- }];
- [self waitUntil:^BOOL {
- return byNuggets.count == users.count;
- }];
- NSArray *expected = @[ @"Andrew", @"Greg", @"Rob" ];
- XCTAssertEqualObjects(byNuggets, expected, @"Correct by-nugget ordering.");
- }
- - (void)testCanUsaAFallbackThenDefineTheSpecifiedIndex {
- FTupleFirebase *tuple = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *reader = tuple.one, *writer = tuple.two;
- NSDictionary *foo1 = @{
- @"a" : @{@"order" : @2, @"foo" : @1},
- @"b" : @{@"order" : @0},
- @"c" : @{@"order" : @1, @"foo" : @NO},
- @"d" : @{@"order" : @3, @"foo" : @"hello"}
- };
- NSDictionary *foo_e = @{@"order" : @1.5, @"foo" : @YES};
- NSDictionary *foo_f = @{@"order" : @4, @"foo" : @{@"bar" : @"baz"}};
- [self waitForCompletionOf:writer setValue:foo1];
- NSMutableArray *snaps = [[NSMutableArray alloc] init];
- [[[reader queryOrderedByChild:@"order"] queryLimitedToLast:2]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- [snaps addObject:snapshot.value];
- }];
- WAIT_FOR(snaps.count == 1);
- NSDictionary *expected =
- @{@"d" : @{@"order" : @3, @"foo" : @"hello"}, @"a" : @{@"order" : @2, @"foo" : @1}};
- XCTAssertEqualObjects(snaps[0], expected, @"Got correct result");
- [self waitForCompletionOf:[writer child:@"e"] setValue:foo_e];
- [self waitForRoundTrip:reader];
- NSLog(@"snaps: %@", snaps);
- NSLog(@"snaps.count: %ld", (unsigned long)snaps.count);
- XCTAssertEqual(snaps.count, (NSUInteger)1, @"Should still have one event.");
- [self waitForCompletionOf:[writer child:@"f"] setValue:foo_f];
- [self waitForRoundTrip:reader];
- XCTAssertEqual(snaps.count, (NSUInteger)2, @"Should have gotten another event.");
- expected = @{@"f" : foo_f, @"d" : @{@"order" : @3, @"foo" : @"hello"}};
- XCTAssertEqualObjects(snaps[1], expected, @"Correct event.");
- }
- - (void)testSnapshotsAreIteratedInOrder {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *initial = @{
- @"alex" : @{@"nuggets" : @60},
- @"rob" : @{@"nuggets" : @56},
- @"vassili" : @{@"nuggets" : @55.5},
- @"tony" : @{@"nuggets" : @52},
- @"greg" : @{@"nuggets" : @52}
- };
- NSArray *expectedOrder = @[ @"greg", @"tony", @"vassili", @"rob", @"alex" ];
- NSArray *expectedPrevNames = @[ [NSNull null], @"greg", @"tony", @"vassili", @"rob" ];
- NSMutableArray *valueOrder = [[NSMutableArray alloc] init];
- NSMutableArray *addedOrder = [[NSMutableArray alloc] init];
- NSMutableArray *addedPrevNames = [[NSMutableArray alloc] init];
- FIRDatabaseQuery *orderedRef = [ref queryOrderedByChild:@"nuggets"];
- [orderedRef observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [valueOrder addObject:child.key];
- }
- }];
- [orderedRef observeEventType:FIRDataEventTypeChildAdded
- andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *prevName) {
- [addedOrder addObject:snapshot.key];
- [addedPrevNames addObject:prevName ? prevName : [NSNull null]];
- }];
- [ref setValue:initial];
- WAIT_FOR(addedOrder.count == expectedOrder.count && valueOrder.count == expectedOrder.count);
- XCTAssertEqualObjects(addedOrder, expectedOrder, @"child_added events in correct order.");
- XCTAssertEqualObjects(addedPrevNames, expectedPrevNames,
- @"Got correct prevnames for child_added events.");
- XCTAssertEqualObjects(valueOrder, expectedOrder,
- @"enumerated snapshot children in correct order.");
- }
- - (void)testSnapshotsAreIteratedInOrderForValueIndex {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *initial =
- @{@"alex" : @60, @"rob" : @56, @"vassili" : @55.5, @"tony" : @52, @"greg" : @52};
- NSArray *expectedOrder = @[ @"greg", @"tony", @"vassili", @"rob", @"alex" ];
- NSArray *expectedPrevNames = @[ [NSNull null], @"greg", @"tony", @"vassili", @"rob" ];
- NSMutableArray *valueOrder = [[NSMutableArray alloc] init];
- NSMutableArray *addedOrder = [[NSMutableArray alloc] init];
- NSMutableArray *addedPrevNames = [[NSMutableArray alloc] init];
- FIRDatabaseQuery *orderedRef = [ref queryOrderedByValue];
- [orderedRef observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [valueOrder addObject:child.key];
- }
- }];
- [orderedRef observeEventType:FIRDataEventTypeChildAdded
- andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *prevName) {
- [addedOrder addObject:snapshot.key];
- [addedPrevNames addObject:prevName ? prevName : [NSNull null]];
- }];
- [ref setValue:initial];
- WAIT_FOR(addedOrder.count == expectedOrder.count && valueOrder.count == expectedOrder.count);
- XCTAssertEqualObjects(addedOrder, expectedOrder, @"child_added events in correct order.");
- XCTAssertEqualObjects(addedPrevNames, expectedPrevNames,
- @"Got correct prevnames for child_added events.");
- XCTAssertEqualObjects(valueOrder, expectedOrder,
- @"enumerated snapshot children in correct order.");
- }
- - (void)testFiresChildMovedEvents {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *initial = @{
- @"alex" : @{@"nuggets" : @60},
- @"rob" : @{@"nuggets" : @56},
- @"vassili" : @{@"nuggets" : @55.5},
- @"tony" : @{@"nuggets" : @52},
- @"greg" : @{@"nuggets" : @52}
- };
- FIRDatabaseQuery *orderedRef = [ref queryOrderedByChild:@"nuggets"];
- __block BOOL moved = NO;
- [orderedRef observeEventType:FIRDataEventTypeChildMoved
- andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *prevName) {
- moved = YES;
- XCTAssertEqualObjects(snapshot.key, @"greg", @"");
- XCTAssertEqualObjects(prevName, @"rob", @"");
- XCTAssertEqualObjects(
- snapshot.value,
- @{@"nuggets" : @57}, @"");
- }];
- [ref setValue:initial];
- [[ref child:@"greg/nuggets"] setValue:@57];
- WAIT_FOR(moved);
- }
- - (void)testDefineMultipleIndexesAtALocation {
- FTupleFirebase *tuple = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *reader = tuple.one, *writer = tuple.two;
- NSDictionary *foo1 = @{
- @"a" : @{@"order" : @2, @"foo" : @2},
- @"b" : @{@"order" : @0},
- @"c" : @{@"order" : @1, @"foo" : @NO},
- @"d" : @{@"order" : @3, @"foo" : @"hello"}
- };
- [self waitForCompletionOf:writer setValue:foo1];
- FIRDatabaseQuery *fooOrder = [reader queryOrderedByChild:@"foo"];
- FIRDatabaseQuery *orderOrder = [reader queryOrderedByChild:@"order"];
- NSMutableArray *fooSnaps = [[NSMutableArray alloc] init];
- NSMutableArray *orderSnaps = [[NSMutableArray alloc] init];
- [[[fooOrder queryStartingAtValue:nil] queryEndingAtValue:@1]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- [fooSnaps addObject:snapshot.value];
- }];
- [[orderOrder queryLimitedToLast:2] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- [orderSnaps addObject:snapshot.value];
- }];
- WAIT_FOR(fooSnaps.count == 1 && orderSnaps.count == 1);
- NSDictionary *expected = @{@"b" : @{@"order" : @0}, @"c" : @{@"order" : @1, @"foo" : @NO}};
- XCTAssertEqualObjects(fooSnaps[0], expected, @"");
- expected = @{
- @"d" : @{@"order" : @3, @"foo" : @"hello"},
- @"a" : @{@"order" : @2, @"foo" : @2},
- };
- XCTAssertEqualObjects(orderSnaps[0], expected, @"");
- [[writer child:@"a"] setValue:@{@"order" : @-1, @"foo" : @1}];
- WAIT_FOR(fooSnaps.count == 2 && orderSnaps.count == 2);
- expected = @{
- @"a" : @{@"order" : @-1, @"foo" : @1},
- @"b" : @{@"order" : @0},
- @"c" : @{@"order" : @1, @"foo" : @NO}
- };
- XCTAssertEqualObjects(fooSnaps[1], expected, @"");
- expected = @{@"d" : @{@"order" : @3, @"foo" : @"hello"}, @"c" : @{@"order" : @1, @"foo" : @NO}};
- XCTAssertEqualObjects(orderSnaps[1], expected, @"");
- }
- - (void)testCallbackRemovalWorks {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- __block int reads = 0;
- FIRDatabaseHandle fooHandle, bazHandle;
- fooHandle = [[ref queryOrderedByChild:@"foo"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- reads++;
- }];
- [[ref queryOrderedByChild:@"bar"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- reads++;
- }];
- bazHandle = [[ref queryOrderedByChild:@"baz"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- reads++;
- }];
- [ref observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- reads++;
- }];
- [self waitForCompletionOf:ref setValue:@1];
- XCTAssertEqual(reads, 4, @"");
- [ref removeObserverWithHandle:fooHandle];
- [self waitForCompletionOf:ref setValue:@2];
- XCTAssertEqual(reads, 7, @"");
- // should be a no-op, resulting in 3 more reads.
- [[ref queryOrderedByChild:@"foo"] removeObserverWithHandle:bazHandle];
- [self waitForCompletionOf:ref setValue:@3];
- XCTAssertEqual(reads, 10, @"");
- [[ref queryOrderedByChild:@"bar"] removeAllObservers];
- [self waitForCompletionOf:ref setValue:@4];
- XCTAssertEqual(reads, 12, @"");
- // Now, remove everything.
- [ref removeAllObservers];
- [self waitForCompletionOf:ref setValue:@5];
- XCTAssertEqual(reads, 12, @"");
- }
- - (void)testChildAddedEventsAreInTheCorrectOrder {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *initial = @{@"a" : @{@"value" : @5}, @"c" : @{@"value" : @3}};
- NSMutableArray *added = [[NSMutableArray alloc] init];
- [[ref queryOrderedByChild:@"value"] observeEventType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot *snapshot) {
- [added addObject:snapshot.key];
- }];
- [ref setValue:initial];
- WAIT_FOR(added.count == 2);
- NSArray *expected = @[ @"c", @"a" ];
- XCTAssertEqualObjects(added, expected, @"");
- [ref updateChildValues:@{@"b" : @{@"value" : @4}, @"d" : @{@"value" : @2}}];
- WAIT_FOR(added.count == 4);
- expected = @[ @"c", @"a", @"d", @"b" ];
- XCTAssertEqualObjects(added, expected, @"");
- }
- - (void)testCanUseKeyIndex {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *data = @{
- @"a" : @{@".priority" : @10, @".value" : @"a"},
- @"b" : @{@".priority" : @5, @".value" : @"b"},
- @"c" : @{@".priority" : @20, @".value" : @"c"},
- @"d" : @{@".priority" : @7, @".value" : @"d"},
- @"e" : @{@".priority" : @30, @".value" : @"e"},
- @"f" : @{@".priority" : @8, @".value" : @"f"}
- };
- [self waitForCompletionOf:ref setValue:data];
- __block BOOL valueDone = NO;
- [[[ref queryOrderedByKey] queryStartingAtValue:@"c"]
- observeSingleEventOfType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSMutableArray *keys = [[NSMutableArray alloc] init];
- for (FIRDataSnapshot *child in snapshot.children) {
- [keys addObject:child.key];
- }
- NSArray *expected = @[ @"c", @"d", @"e", @"f" ];
- XCTAssertEqualObjects(keys, expected, @"");
- valueDone = YES;
- }];
- WAIT_FOR(valueDone);
- NSMutableArray *keys = [[NSMutableArray alloc] init];
- [[[ref queryOrderedByKey] queryLimitedToLast:5]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [keys addObject:child.key];
- }
- }];
- WAIT_FOR(keys.count == 5);
- NSArray *expected = @[ @"b", @"c", @"d", @"e", @"f" ];
- XCTAssertEqualObjects(keys, expected, @"");
- }
- - (void)testQueriesWorkOnLeafNodes {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- [self waitForCompletionOf:ref setValue:@"leaf-node"];
- __block BOOL valueDone = NO;
- [[[ref queryOrderedByChild:@"foo"] queryLimitedToLast:1]
- observeSingleEventOfType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- XCTAssertEqual(snapshot.value, [NSNull null]);
- valueDone = YES;
- }];
- WAIT_FOR(valueDone);
- }
- - (void)testUpdatesForUnindexedQuery {
- FTupleFirebase *refs = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *reader = refs.one;
- FIRDatabaseReference *writer = refs.two;
- __block BOOL done = NO;
- NSDictionary *value = @{
- @"one" : @{@"index" : @1, @"value" : @"one"},
- @"two" : @{@"index" : @2, @"value" : @"two"},
- @"three" : @{@"index" : @3, @"value" : @"three"}
- };
- [writer setValue:value
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- WAIT_FOR(done);
- done = NO;
- NSMutableArray *snapshots = [NSMutableArray array];
- [[[reader queryOrderedByChild:@"index"] queryLimitedToLast:2]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- [snapshots addObject:snapshot.value];
- done = YES;
- }];
- WAIT_FOR(done);
- NSDictionary *expected = @{
- @"two" : @{@"index" : @2, @"value" : @"two"},
- @"three" : @{@"index" : @3, @"value" : @"three"}
- };
- XCTAssertEqual(snapshots.count, (NSUInteger)1);
- XCTAssertEqualObjects(snapshots[0], expected);
- done = NO;
- [[writer child:@"one/index"] setValue:@4];
- WAIT_FOR(done);
- expected = @{
- @"one" : @{@"index" : @4, @"value" : @"one"},
- @"three" : @{@"index" : @3, @"value" : @"three"}
- };
- XCTAssertEqual(snapshots.count, (NSUInteger)2);
- XCTAssertEqualObjects(snapshots[1], expected);
- }
- - (void)testServerRespectsKeyIndex {
- FTupleFirebase *refs = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *writer = refs.one;
- FIRDatabaseReference *reader = refs.two;
- NSDictionary *initial = @{@"a" : @1, @"b" : @2, @"c" : @3};
- // If the server doesn't respect the index, it will send down limited data, but with no offset, so
- // the expected and actual data don't match
- FIRDatabaseQuery *query =
- [[[reader queryOrderedByKey] queryStartingAtValue:@"b"] queryLimitedToFirst:2];
- NSArray *expectedChildren = @[ @"b", @"c" ];
- [self waitForCompletionOf:writer setValue:initial];
- NSMutableArray *children = [[NSMutableArray alloc] init];
- __block BOOL done = NO;
- [query observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [children addObject:child.key];
- }
- done = YES;
- }];
- WAIT_FOR(done);
- XCTAssertEqualObjects(expectedChildren, children, @"Got correct children");
- }
- - (void)testServerRespectsValueIndex {
- FTupleFirebase *refs = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *writer = refs.one;
- FIRDatabaseReference *reader = refs.two;
- NSDictionary *initial = @{@"a" : @1, @"c" : @2, @"b" : @3};
- // If the server doesn't respect the index, it will send down limited data, but with no offset, so
- // the expected and actual data don't match
- FIRDatabaseQuery *query =
- [[[reader queryOrderedByValue] queryStartingAtValue:@2] queryLimitedToFirst:2];
- NSArray *expectedChildren = @[ @"c", @"b" ];
- [self waitForCompletionOf:writer setValue:initial];
- NSMutableArray *children = [[NSMutableArray alloc] init];
- __block BOOL done = NO;
- [query observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [children addObject:child.key];
- }
- done = YES;
- }];
- WAIT_FOR(done);
- XCTAssertEqualObjects(expectedChildren, children, @"Got correct children");
- }
- - (void)testDeepUpdatesWorkWithQueries {
- FTupleFirebase *refs = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *writer = refs.one;
- FIRDatabaseReference *reader = refs.two;
- NSDictionary *initial = @{
- @"a" : @{@"data" : @"foo", @"idx" : @YES},
- @"b" : @{@"data" : @"bar", @"idx" : @YES},
- @"c" : @{@"data" : @"baz", @"idx" : @NO}
- };
- [self waitForCompletionOf:writer setValue:initial];
- FIRDatabaseQuery *query = [[reader queryOrderedByChild:@"idx"] queryEqualToValue:@YES];
- NSDictionary *expected =
- @{@"a" : @{@"data" : @"foo", @"idx" : @YES}, @"b" : @{@"data" : @"bar", @"idx" : @YES}};
- [self waitForExportValueOf:query toBe:expected];
- NSDictionary *update = @{@"a/idx" : @NO, @"b/data" : @"blah", @"c/idx" : @YES};
- [self waitForCompletionOf:writer updateChildValues:update];
- expected =
- @{@"b" : @{@"data" : @"blah", @"idx" : @YES}, @"c" : @{@"data" : @"baz", @"idx" : @YES}};
- [self waitForExportValueOf:query toBe:expected];
- }
- - (void)testServerRespectsDeepIndex {
- FTupleFirebase *refs = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference *writer = refs.one;
- FIRDatabaseReference *reader = refs.two;
- NSDictionary *initial = @{
- @"a" : @{@"deep" : @{@"index" : @1}},
- @"c" : @{@"deep" : @{@"index" : @2}},
- @"b" : @{@"deep" : @{@"index" : @3}}
- };
- // If the server doesn't respect the index, it will send down limited data, but with no offset, so
- // the expected and actual data don't match
- FIRDatabaseQuery *query =
- [[[reader queryOrderedByChild:@"deep/index"] queryStartingAtValue:@2] queryLimitedToFirst:2];
- NSArray *expectedChildren = @[ @"c", @"b" ];
- [self waitForCompletionOf:writer setValue:initial];
- NSMutableArray *children = [[NSMutableArray alloc] init];
- __block BOOL done = NO;
- [query observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [children addObject:child.key];
- }
- done = YES;
- }];
- WAIT_FOR(done);
- XCTAssertEqualObjects(expectedChildren, children, @"Got correct children");
- }
- - (void)testStartAtEndAtWorksWithValueIndex {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *initial =
- @{@"alex" : @60, @"rob" : @56, @"vassili" : @55.5, @"tony" : @52, @"greg" : @52};
- NSArray *expectedOrder = @[ @"tony", @"vassili", @"rob" ];
- NSArray *expectedPrevNames = @[ [NSNull null], @"tony", @"vassili" ];
- NSMutableArray *valueOrder = [[NSMutableArray alloc] init];
- NSMutableArray *addedOrder = [[NSMutableArray alloc] init];
- NSMutableArray *addedPrevNames = [[NSMutableArray alloc] init];
- FIRDatabaseQuery *orderedRef =
- [[[ref queryOrderedByValue] queryStartingAtValue:@52
- childKey:@"tony"] queryEndingAtValue:@59];
- [orderedRef observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- for (FIRDataSnapshot *child in snapshot.children) {
- [valueOrder addObject:child.key];
- }
- }];
- [orderedRef observeEventType:FIRDataEventTypeChildAdded
- andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *prevName) {
- [addedOrder addObject:snapshot.key];
- [addedPrevNames addObject:prevName ? prevName : [NSNull null]];
- }];
- [ref setValue:initial];
- WAIT_FOR(addedOrder.count == expectedOrder.count && valueOrder.count == expectedOrder.count);
- XCTAssertEqualObjects(addedOrder, expectedOrder, @"child_added events in correct order.");
- XCTAssertEqualObjects(addedPrevNames, expectedPrevNames,
- @"Got correct prevnames for child_added events.");
- XCTAssertEqualObjects(valueOrder, expectedOrder,
- @"enumerated snapshot children in correct order.");
- }
- - (void)testRemovingDefaultListenerRemovesNonDefaultListenWithLoadsAllData {
- FIRDatabaseReference *ref = [FTestHelpers getRandomNode];
- NSDictionary *initialData = @{@"key" : @"value"};
- [self waitForCompletionOf:ref setValue:initialData];
- [[ref queryOrderedByKey] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot){
- }];
- [ref observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot){
- }];
- // Should remove both listener and should remove the listen sent to the server
- [ref removeAllObservers];
- __block id result = nil;
- // This used to crash because a listener for [ref queryOrderedByKey] existed already
- [[ref queryOrderedByKey] observeSingleEventOfType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- result = snapshot.value;
- }];
- WAIT_FOR(result);
- XCTAssertEqualObjects(result, initialData);
- }
- @end
|