|
70 | 70 | """ |
71 | 71 | } |
72 | 72 | } |
73 | | - |
| 73 | + |
74 | 74 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
75 | | - @Test func deleteAndReinsertInSingleWrite_saves() async throws { |
| 75 | + @Test func deleteThenReinsertThenDelete_deletes() async throws { |
76 | 76 | try await userDatabase.userWrite { db in |
77 | | - try db.seed { |
78 | | - RemindersList(id: 1, title: "Original") |
79 | | - } |
| 77 | + try db.seed { RemindersList(id: 1, title: "Original") } |
80 | 78 | } |
81 | 79 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
82 | 80 |
|
83 | 81 | try await userDatabase.userWrite { db in |
84 | 82 | try RemindersList.find(1).delete().execute(db) |
85 | 83 | try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
| 84 | + try RemindersList.find(1).delete().execute(db) |
86 | 85 | } |
87 | 86 |
|
88 | 87 | let pending = syncEngine.private.state.pendingRecordZoneChanges |
89 | | - #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
| 88 | + #expect(pending == [.deleteRecord(RemindersList.recordID(for: 1))]) |
| 89 | + |
| 90 | + try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
| 91 | + |
| 92 | + assertInlineSnapshot(of: container, as: .customDump) { |
| 93 | + """ |
| 94 | + MockCloudContainer( |
| 95 | + privateCloudDatabase: MockCloudDatabase( |
| 96 | + databaseScope: .private, |
| 97 | + storage: [] |
| 98 | + ), |
| 99 | + sharedCloudDatabase: MockCloudDatabase( |
| 100 | + databaseScope: .shared, |
| 101 | + storage: [] |
| 102 | + ) |
| 103 | + ) |
| 104 | + """ |
| 105 | + } |
| 106 | + } |
90 | 107 |
|
| 108 | + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
| 109 | + @Test(.printTimestamps) func deleteThenReinsertInSingleWrite_savesWithUpdatedTimestamps() |
| 110 | + async throws |
| 111 | + { |
| 112 | + try await userDatabase.userWrite { db in |
| 113 | + try db.seed { |
| 114 | + RemindersList(id: 1, title: "Original") |
| 115 | + } |
| 116 | + } |
91 | 117 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
92 | 118 |
|
| 119 | + try await withDependencies { |
| 120 | + $0.currentTime.now += 1 |
| 121 | + } operation: { |
| 122 | + try await userDatabase.userWrite { db in |
| 123 | + try RemindersList.find(1).delete().execute(db) |
| 124 | + try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
| 125 | + } |
| 126 | + |
| 127 | + let pending = syncEngine.private.state.pendingRecordZoneChanges |
| 128 | + #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
| 129 | + |
| 130 | + try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
| 131 | + } |
| 132 | + |
93 | 133 | assertInlineSnapshot(of: container, as: .customDump) { |
94 | 134 | """ |
95 | 135 | MockCloudContainer( |
|
102 | 142 | parent: nil, |
103 | 143 | share: nil, |
104 | 144 | id: 1, |
105 | | - title: "Reinserted" |
| 145 | + id🗓️: 1, |
| 146 | + title: "Reinserted", |
| 147 | + title🗓️: 1, |
| 148 | + 🗓️: 1 |
106 | 149 | ) |
107 | 150 | ] |
108 | 151 | ), |
|
116 | 159 | } |
117 | 160 |
|
118 | 161 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
119 | | - @Test func deleteAndReinsertInSeparateWrites_saves() async throws { |
| 162 | + @Test(.printTimestamps) func deleteThenReinsertInSeparateWrites_savesWithUpdatedTimestamps() |
| 163 | + async throws |
| 164 | + { |
120 | 165 | try await userDatabase.userWrite { db in |
121 | 166 | try db.seed { |
122 | 167 | RemindersList(id: 1, title: "Original") |
123 | 168 | } |
124 | 169 | } |
125 | 170 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
126 | 171 |
|
127 | | - try await userDatabase.userWrite { db in |
128 | | - try RemindersList.find(1).delete().execute(db) |
129 | | - } |
130 | | - try await userDatabase.userWrite { db in |
131 | | - try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
132 | | - } |
| 172 | + try await withDependencies { |
| 173 | + $0.currentTime.now += 1 |
| 174 | + } operation: { |
| 175 | + try await userDatabase.userWrite { db in |
| 176 | + try RemindersList.find(1).delete().execute(db) |
| 177 | + } |
| 178 | + try await withDependencies { |
| 179 | + $0.currentTime.now += 1 |
| 180 | + } operation: { |
| 181 | + try await userDatabase.userWrite { db in |
| 182 | + try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
| 183 | + } |
133 | 184 |
|
134 | | - let pending = syncEngine.private.state.pendingRecordZoneChanges |
135 | | - #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
| 185 | + let pending = syncEngine.private.state.pendingRecordZoneChanges |
| 186 | + #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
136 | 187 |
|
137 | | - try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
| 188 | + try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
| 189 | + } |
| 190 | + } |
138 | 191 |
|
139 | 192 | assertInlineSnapshot(of: container, as: .customDump) { |
140 | 193 | """ |
|
148 | 201 | parent: nil, |
149 | 202 | share: nil, |
150 | 203 | id: 1, |
151 | | - title: "Reinserted" |
| 204 | + id🗓️: 2, |
| 205 | + title: "Reinserted", |
| 206 | + title🗓️: 2, |
| 207 | + 🗓️: 2 |
152 | 208 | ) |
153 | 209 | ] |
154 | 210 | ), |
|
162 | 218 | } |
163 | 219 |
|
164 | 220 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
165 | | - @Test func updateThenDeleteThenReinsert_saves() async throws { |
| 221 | + @Test(.printTimestamps) func updateThenDeleteThenReinsert_savesWithUpdatedTimestamps() |
| 222 | + async throws |
| 223 | + { |
166 | 224 | try await userDatabase.userWrite { db in |
167 | 225 | try db.seed { RemindersList(id: 1, title: "Original") } |
168 | 226 | } |
169 | 227 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
170 | 228 |
|
171 | | - try await userDatabase.userWrite { db in |
172 | | - try RemindersList.find(1).update { $0.title = "Updated" }.execute(db) |
173 | | - try RemindersList.find(1).delete().execute(db) |
174 | | - try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
175 | | - } |
| 229 | + try await withDependencies { |
| 230 | + $0.currentTime.now += 1 |
| 231 | + } operation: { |
| 232 | + try await userDatabase.userWrite { db in |
| 233 | + try RemindersList.find(1).update { $0.title = "Updated" }.execute(db) |
| 234 | + try RemindersList.find(1).delete().execute(db) |
| 235 | + try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
| 236 | + } |
176 | 237 |
|
177 | | - let pending = syncEngine.private.state.pendingRecordZoneChanges |
178 | | - #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
| 238 | + let pending = syncEngine.private.state.pendingRecordZoneChanges |
| 239 | + #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
179 | 240 |
|
180 | | - try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
| 241 | + try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
| 242 | + } |
181 | 243 |
|
182 | 244 | assertInlineSnapshot(of: container, as: .customDump) { |
183 | 245 | """ |
|
191 | 253 | parent: nil, |
192 | 254 | share: nil, |
193 | 255 | id: 1, |
194 | | - title: "Reinserted" |
| 256 | + id🗓️: 1, |
| 257 | + title: "Reinserted", |
| 258 | + title🗓️: 1, |
| 259 | + 🗓️: 1 |
195 | 260 | ) |
196 | 261 | ] |
197 | 262 | ), |
|
203 | 268 | """ |
204 | 269 | } |
205 | 270 | } |
206 | | - |
| 271 | + |
207 | 272 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
208 | | - @Test func deleteReinsertThenDeleteAgain_deletes() async throws { |
| 273 | + @Test(.printTimestamps) func deleteThenReinsertWithSameValue_savesWithUpdatedTimestamps() |
| 274 | + async throws |
| 275 | + { |
209 | 276 | try await userDatabase.userWrite { db in |
210 | 277 | try db.seed { RemindersList(id: 1, title: "Original") } |
211 | 278 | } |
212 | 279 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
213 | 280 |
|
214 | | - try await userDatabase.userWrite { db in |
215 | | - try RemindersList.find(1).delete().execute(db) |
216 | | - try RemindersList.insert { RemindersList(id: 1, title: "Reinserted") }.execute(db) |
217 | | - try RemindersList.find(1).delete().execute(db) |
| 281 | + try await withDependencies { |
| 282 | + $0.currentTime.now += 1 |
| 283 | + } operation: { |
| 284 | + try await userDatabase.userWrite { db in |
| 285 | + try RemindersList.find(1).delete().execute(db) |
| 286 | + try RemindersList.insert { RemindersList(id: 1, title: "Original") }.execute(db) |
| 287 | + } |
| 288 | + let pending = syncEngine.private.state.pendingRecordZoneChanges |
| 289 | + #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
| 290 | + try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
218 | 291 | } |
219 | 292 |
|
220 | | - let pending = syncEngine.private.state.pendingRecordZoneChanges |
221 | | - #expect(pending == [.deleteRecord(RemindersList.recordID(for: 1))]) |
222 | | - |
223 | | - try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
224 | | - |
225 | 293 | assertInlineSnapshot(of: container, as: .customDump) { |
226 | 294 | """ |
227 | 295 | MockCloudContainer( |
228 | 296 | privateCloudDatabase: MockCloudDatabase( |
229 | 297 | databaseScope: .private, |
230 | | - storage: [] |
| 298 | + storage: [ |
| 299 | + [0]: CKRecord( |
| 300 | + recordID: CKRecord.ID(1:remindersLists/zone/__defaultOwner__), |
| 301 | + recordType: "remindersLists", |
| 302 | + parent: nil, |
| 303 | + share: nil, |
| 304 | + id: 1, |
| 305 | + id🗓️: 1, |
| 306 | + title: "Original", |
| 307 | + title🗓️: 1, |
| 308 | + 🗓️: 1 |
| 309 | + ) |
| 310 | + ] |
231 | 311 | ), |
232 | 312 | sharedCloudDatabase: MockCloudDatabase( |
233 | 313 | databaseScope: .shared, |
|
239 | 319 | } |
240 | 320 |
|
241 | 321 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
242 | | - @Test(.printTimestamps) func twoDeleteReinsertCyclesInSameWrite_propagatesLatestValueAndTimestamp() |
| 322 | + @Test(.printTimestamps) func twoDeleteReinsertCyclesInSameWrite_savesLatestWithUpdatedTimestamps() |
243 | 323 | async throws |
244 | 324 | { |
245 | 325 | try await userDatabase.userWrite { db in |
|
248 | 328 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
249 | 329 |
|
250 | 330 | try await withDependencies { |
251 | | - $0.currentTime.now = 1 |
| 331 | + $0.currentTime.now += 1 |
252 | 332 | } operation: { |
253 | 333 | try await userDatabase.userWrite { db in |
254 | 334 | try RemindersList.find(1).delete().execute(db) |
|
273 | 353 | parent: nil, |
274 | 354 | share: nil, |
275 | 355 | id: 1, |
276 | | - id🗓️: 0, |
| 356 | + id🗓️: 1, |
277 | 357 | title: "Final", |
278 | 358 | title🗓️: 1, |
279 | 359 | 🗓️: 1 |
|
290 | 370 | } |
291 | 371 |
|
292 | 372 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
293 | | - @Test(.printTimestamps) func twoDeleteReinsertCyclesInSeparateBatches_propagatesLatestValueAndTimestamp() |
| 373 | + @Test(.printTimestamps) func twoDeleteReinsertCyclesInSeparateBatches_savesLatestWithUpdatedTimestamps() |
294 | 374 | async throws |
295 | 375 | { |
296 | 376 | try await userDatabase.userWrite { db in |
|
299 | 379 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
300 | 380 |
|
301 | 381 | try await withDependencies { |
302 | | - $0.currentTime.now = 1 |
| 382 | + $0.currentTime.now += 1 |
303 | 383 | } operation: { |
304 | 384 | try await userDatabase.userWrite { db in |
305 | 385 | try RemindersList.find(1).delete().execute(db) |
|
308 | 388 | let pending = syncEngine.private.state.pendingRecordZoneChanges |
309 | 389 | #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
310 | 390 | try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
311 | | - } |
312 | | - |
313 | | - try await withDependencies { |
314 | | - $0.currentTime.now = 2 |
315 | | - } operation: { |
316 | | - try await userDatabase.userWrite { db in |
317 | | - try RemindersList.find(1).delete().execute(db) |
318 | | - try RemindersList.insert { RemindersList(id: 1, title: "Cycle2") }.execute(db) |
| 391 | + |
| 392 | + try await withDependencies { |
| 393 | + $0.currentTime.now += 1 |
| 394 | + } operation: { |
| 395 | + try await userDatabase.userWrite { db in |
| 396 | + try RemindersList.find(1).delete().execute(db) |
| 397 | + try RemindersList.insert { RemindersList(id: 1, title: "Cycle2") }.execute(db) |
| 398 | + } |
| 399 | + let pending = syncEngine.private.state.pendingRecordZoneChanges |
| 400 | + #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
| 401 | + try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
319 | 402 | } |
320 | | - let pending = syncEngine.private.state.pendingRecordZoneChanges |
321 | | - #expect(pending == [.saveRecord(RemindersList.recordID(for: 1))]) |
322 | | - try await syncEngine.processPendingRecordZoneChanges(scope: .private) |
323 | 403 | } |
324 | 404 |
|
325 | 405 | assertInlineSnapshot(of: container, as: .customDump) { |
|
334 | 414 | parent: nil, |
335 | 415 | share: nil, |
336 | 416 | id: 1, |
337 | | - id🗓️: 0, |
| 417 | + id🗓️: 2, |
338 | 418 | title: "Cycle2", |
339 | 419 | title🗓️: 2, |
340 | 420 | 🗓️: 2 |
|
0 commit comments