diff --git a/packages/firestore/test/unit/specs/offline_spec.test.ts b/packages/firestore/test/unit/specs/offline_spec.test.ts index 5ea9a8e6125..34112db8b30 100644 --- a/packages/firestore/test/unit/specs/offline_spec.test.ts +++ b/packages/firestore/test/unit/specs/offline_spec.test.ts @@ -23,45 +23,53 @@ import { spec } from './spec_builder'; import { TimerId } from '../../../src/util/async_queue'; describeSpec('Offline:', [], () => { - specTest('Empty queries are resolved if client goes offline', [], () => { - const query = Query.atPath(path('collection')); - return ( - spec() - .userListens(query) - .watchStreamCloses(Code.UNAVAILABLE) - .expectEvents(query, { - fromCache: true, - hasPendingWrites: false - }) - // no further events - .watchStreamCloses(Code.UNAVAILABLE) - .watchStreamCloses(Code.UNAVAILABLE) - ); - }); + specTest( + 'Empty queries are resolved if client goes offline', + ['no-android', 'no-ios'], + () => { + const query = Query.atPath(path('collection')); + return ( + spec() + .userListens(query) + .watchStreamCloses(Code.UNAVAILABLE) + .expectEvents(query, { + fromCache: true, + hasPendingWrites: false + }) + // no further events + .watchStreamCloses(Code.UNAVAILABLE) + .watchStreamCloses(Code.UNAVAILABLE) + ); + } + ); - specTest('A successful message delays offline status', [], () => { - const query = Query.atPath(path('collection')); - return ( - spec() - .userListens(query) - .watchAcks(query) - // first error triggers unknown state - .watchStreamCloses(Code.UNAVAILABLE) - // second error triggers offline state - .watchStreamCloses(Code.UNAVAILABLE) - .expectEvents(query, { - fromCache: true, - hasPendingWrites: false - }) - // no further events - .watchStreamCloses(Code.UNAVAILABLE) - .watchStreamCloses(Code.UNAVAILABLE) - ); - }); + specTest( + 'A successful message delays offline status', + ['no-android', 'no-ios'], + () => { + const query = Query.atPath(path('collection')); + return ( + spec() + .userListens(query) + .watchAcks(query) + // first error triggers unknown state + .watchStreamCloses(Code.UNAVAILABLE) + // second error triggers offline state + .watchStreamCloses(Code.UNAVAILABLE) + .expectEvents(query, { + fromCache: true, + hasPendingWrites: false + }) + // no further events + .watchStreamCloses(Code.UNAVAILABLE) + .watchStreamCloses(Code.UNAVAILABLE) + ); + } + ); specTest( 'Removing all listeners delays "Offline" status on next listen', - ['eager-gc'], + ['eager-gc', 'no-android', 'no-ios'], 'Marked as no-lru because when a listen is re-added, it gets a new target id rather than reusing one', () => { const query = Query.atPath(path('collection')); @@ -91,54 +99,62 @@ describeSpec('Offline:', [], () => { } ); - specTest('Queries revert to fromCache=true when offline.', [], () => { - const query = Query.atPath(path('collection')); - const docA = doc('collection/a', 1000, { key: 'a' }); - return ( - spec() - .userListens(query) - .watchAcksFull(query, 1000, docA) - .expectEvents(query, { added: [docA] }) - // first error triggers unknown state - .watchStreamCloses(Code.UNAVAILABLE) - .restoreListen(query, 'resume-token-1000') - // second error triggers offline state and fromCache: true - .watchStreamCloses(Code.UNAVAILABLE) - .expectEvents(query, { fromCache: true }) - // Going online and getting a CURRENT message triggers fromCache: false - .watchAcksFull(query, 1000) - .expectEvents(query, { fromCache: false }) - ); - }); + specTest( + 'Queries revert to fromCache=true when offline.', + ['no-android', 'no-ios'], + () => { + const query = Query.atPath(path('collection')); + const docA = doc('collection/a', 1000, { key: 'a' }); + return ( + spec() + .userListens(query) + .watchAcksFull(query, 1000, docA) + .expectEvents(query, { added: [docA] }) + // first error triggers unknown state + .watchStreamCloses(Code.UNAVAILABLE) + .restoreListen(query, 'resume-token-1000') + // second error triggers offline state and fromCache: true + .watchStreamCloses(Code.UNAVAILABLE) + .expectEvents(query, { fromCache: true }) + // Going online and getting a CURRENT message triggers fromCache: false + .watchAcksFull(query, 1000) + .expectEvents(query, { fromCache: false }) + ); + } + ); - specTest('Queries with limbo documents handle going offline.', [], () => { - const query = Query.atPath(path('collection')); - const docA = doc('collection/a', 1000, { key: 'a' }); - const limboQuery = Query.atPath(docA.key.path); - return ( - spec() - .userListens(query) - .watchAcksFull(query, 1000, docA) - .expectEvents(query, { added: [docA] }) - .watchResets(query) - // No more documents - .watchCurrents(query, 'resume-token-1001') - .watchSnapshots(1001) - // docA will now be in limbo (triggering fromCache=true) - .expectLimboDocs(docA.key) - .expectEvents(query, { fromCache: true }) - // first error triggers unknown state - .watchStreamCloses(Code.UNAVAILABLE) - .restoreListen(query, 'resume-token-1001') - // second error triggers offline state. - .watchStreamCloses(Code.UNAVAILABLE) - .watchAcksFull(query, 1001) - .watchAcksFull(limboQuery, 1001) - // Limbo document is resolved. No longer from cache. - .expectEvents(query, { removed: [docA], fromCache: false }) - .expectLimboDocs() - ); - }); + specTest( + 'Queries with limbo documents handle going offline.', + ['no-android', 'no-ios'], + () => { + const query = Query.atPath(path('collection')); + const docA = doc('collection/a', 1000, { key: 'a' }); + const limboQuery = Query.atPath(docA.key.path); + return ( + spec() + .userListens(query) + .watchAcksFull(query, 1000, docA) + .expectEvents(query, { added: [docA] }) + .watchResets(query) + // No more documents + .watchCurrents(query, 'resume-token-1001') + .watchSnapshots(1001) + // docA will now be in limbo (triggering fromCache=true) + .expectLimboDocs(docA.key) + .expectEvents(query, { fromCache: true }) + // first error triggers unknown state + .watchStreamCloses(Code.UNAVAILABLE) + .restoreListen(query, 'resume-token-1001') + // second error triggers offline state. + .watchStreamCloses(Code.UNAVAILABLE) + .watchAcksFull(query, 1001) + .watchAcksFull(limboQuery, 1001) + // Limbo document is resolved. No longer from cache. + .expectEvents(query, { removed: [docA], fromCache: false }) + .expectLimboDocs() + ); + } + ); specTest('OnlineState timeout triggers offline behavior', [], () => { const query = Query.atPath(path('collection')); @@ -177,7 +193,7 @@ describeSpec('Offline:', [], () => { specTest( 'New queries return immediately with fromCache=true when offline due to ' + 'stream failures.', - [], + ['no-android', 'no-ios'], () => { const query1 = Query.atPath(path('collection')); const query2 = Query.atPath(path('collection2')); diff --git a/packages/firestore/test/unit/specs/remote_store_spec.test.ts b/packages/firestore/test/unit/specs/remote_store_spec.test.ts index a9b978a022d..71f8d884976 100644 --- a/packages/firestore/test/unit/specs/remote_store_spec.test.ts +++ b/packages/firestore/test/unit/specs/remote_store_spec.test.ts @@ -67,7 +67,7 @@ describeSpec('Remote store:', [], () => { .expectEvents(query, { added: [doc4] }); // This should work now. }); - specTest('Cleans up watch state correctly', [], () => { + specTest('Cleans up watch state correctly', ['no-android', 'no-ios'], () => { const query = Query.atPath(path('collection')); const doc1 = doc('collection/a', 1000, { key: 'a' }); return (