|
15 | 15 | * limitations under the License. |
16 | 16 | */ |
17 | 17 |
|
18 | | -import {doc, filter, query} from '../../util/helpers'; |
| 18 | +import {newQueryForPath} from "../../../src/core/query"; |
| 19 | +import {deletedDoc, doc, filter, query} from '../../util/helpers'; |
19 | 20 |
|
20 | 21 | import { describeSpec, specTest } from './describe_spec'; |
21 | 22 | import { spec } from './spec_builder'; |
22 | | -import {newQueryForPath} from "../../../src/core/query"; |
23 | 23 |
|
24 | 24 | describeSpec('Collections:', [], () => { |
25 | 25 |
|
26 | | - specTest('8474', ['exclusive', 'durable-persistence'], () => { |
| 26 | + specTest('8474', [], () => { |
27 | 27 |
|
28 | 28 | // onSnapshot(fullQuery) |
29 | 29 | const fullQuery = query('collection'); |
@@ -90,36 +90,104 @@ describeSpec('Collections:', [], () => { |
90 | 90 | // All changes are current and we get a global snapshot |
91 | 91 | .watchSnapshots(1010, []) |
92 | 92 |
|
93 | | - // UNEXPECTED docC is still in limbo |
94 | | - .expectLimboDocs(docC.key) |
| 93 | + // Now docC is out of limbo |
| 94 | + .expectLimboDocs() |
| 95 | + .expectEvents(fullQuery, { |
| 96 | + fromCache: false, |
| 97 | + modified: [docA2], |
| 98 | + removed: [docC] |
| 99 | + }) |
| 100 | + // Now getDocs(filterQuery) can be resolved |
| 101 | + .expectEvents(filterQuery, { |
| 102 | + fromCache: false, |
| 103 | + removed: [docC], |
| 104 | + added: [docA2] |
| 105 | + }); |
| 106 | + }); |
| 107 | + specTest('8474-deleted', [], () => { |
95 | 108 |
|
96 | | - // This causes snapshots for fullQuery and filterQuery |
97 | | - // to be raised as from cache |
| 109 | + // onSnapshot(fullQuery) |
| 110 | + const fullQuery = query('collection'); |
| 111 | + |
| 112 | + // getDocs(filterQuery) |
| 113 | + const filterQuery = query('collection', filter('included', '==', true)); |
| 114 | + |
| 115 | + const docA = doc('collection/a', 1000, {key: 'a', included: false}); |
| 116 | + const docA2 = doc('collection/a', 1007, {key: 'a', included: true}); |
| 117 | + const docC = doc('collection/c', 1002, {key: 'c', included: true}); |
| 118 | + const docCDeleted = deletedDoc('collection/c', 1009); |
| 119 | + |
| 120 | + const limboQueryC = newQueryForPath(docC.key.path); |
| 121 | + |
| 122 | + return spec() |
| 123 | + // onSnapshot(fullQuery) - fullQuery is listening to documents in the collection for the full test |
| 124 | + .userListens(fullQuery) |
| 125 | + .watchAcksFull(fullQuery, 1001, docA, docC) |
| 126 | + .expectEvents(fullQuery, { |
| 127 | + fromCache: false, |
| 128 | + added: [docA, docC] |
| 129 | + }) |
| 130 | + |
| 131 | + // docC was deleted, this puts docC in limbo and causes a snapshot from cache (metadata-only change) |
| 132 | + .watchSends({removed: [fullQuery]}, docC) |
| 133 | + .watchCurrents(fullQuery, 'resume-token-1002') |
| 134 | + .watchSnapshots(1002) |
| 135 | + .expectLimboDocs(docC.key) |
98 | 136 | .expectEvents(fullQuery, { |
99 | 137 | fromCache: true, |
100 | | - modified: [docA2] |
101 | 138 | }) |
102 | 139 |
|
103 | | - // getDocs(filterQuery) will not be resolved with this snapsho |
104 | | - // because it is from cache |
| 140 | + // User begins getDocs(filterQuery) |
| 141 | + .userListensForGet(filterQuery) |
| 142 | + |
| 143 | + // getDocs(filterQuery) will not resolve on the snapshot from cache |
105 | 144 | .expectEvents(filterQuery, { |
106 | 145 | fromCache: true, |
107 | | - added: [docA2] |
| 146 | + added: [docC] |
108 | 147 | }) |
109 | 148 |
|
110 | | - // 45-seconds later on heartbeat/global-snapshot |
111 | | - .watchSnapshots(1100, []) |
| 149 | + // Watch acks limbo and filter queries |
| 150 | + .watchAcks(limboQueryC) |
| 151 | + .watchAcks(filterQuery) |
| 152 | + |
| 153 | + // Watch responds to limboQueryC - docC was deleted |
| 154 | + .watchSends({affects: [limboQueryC]}, docCDeleted) |
| 155 | + .watchCurrents(limboQueryC, 'resume-token-1009') |
| 156 | + .watchSnapshots(1009, [limboQueryC, fullQuery]) |
| 157 | + |
| 158 | + // However, docC is still in limbo because there has not been a global snapshot |
| 159 | + .expectLimboDocs(docC.key) |
| 160 | + |
| 161 | + // Rapid events of document update and delete caused by application |
| 162 | + .watchSends({removed: [filterQuery]}, docA) |
| 163 | + .watchCurrents(filterQuery, 'resume-token-1004') |
| 164 | + .watchSends({affects: [filterQuery]}, docC) |
| 165 | + .watchCurrents(filterQuery, 'resume-token-1005') |
| 166 | + .watchSends({removed: [filterQuery]}, docC) |
| 167 | + .watchSends({affects: [filterQuery]}, docA2) |
| 168 | + .watchCurrents(filterQuery, 'resume-token-1007') |
| 169 | + |
| 170 | + .watchSnapshots(1010, [fullQuery, limboQueryC]) |
| 171 | + |
| 172 | + // All changes are current and we get a global snapshot |
| 173 | + .watchSnapshots(1010, []) |
| 174 | + |
112 | 175 | // Now docC is out of limbo |
113 | 176 | .expectLimboDocs() |
114 | 177 | .expectEvents(fullQuery, { |
115 | 178 | fromCache: false, |
| 179 | + modified: [docA2], |
116 | 180 | removed: [docC] |
117 | 181 | }) |
118 | 182 | // Now getDocs(filterQuery) can be resolved |
119 | 183 | .expectEvents(filterQuery, { |
120 | 184 | fromCache: false, |
121 | | - removed: [docC] |
122 | | - }); |
| 185 | + removed: [docC], |
| 186 | + added: [docA2] |
| 187 | + }) |
| 188 | + |
| 189 | + // No more expected events |
| 190 | + .watchSnapshots(1100, []); |
123 | 191 | }); |
124 | 192 |
|
125 | 193 | specTest('Events are raised after watch ack', [], () => { |
|
0 commit comments