@tldraw/store 5.2.0-next.ee0fa4d6244f → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +790 -0
- package/README.md +9 -1
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/ImmutableMap.js +0 -13
- package/dist-cjs/lib/ImmutableMap.js.map +2 -2
- package/dist-cjs/lib/RecordType.js +1 -1
- package/dist-cjs/lib/RecordType.js.map +2 -2
- package/dist-cjs/lib/RecordsDiff.js +26 -14
- package/dist-cjs/lib/RecordsDiff.js.map +2 -2
- package/dist-cjs/lib/Store.js +6 -5
- package/dist-cjs/lib/Store.js.map +2 -2
- package/dist-cjs/lib/StoreSchema.js +1 -1
- package/dist-cjs/lib/StoreSchema.js.map +2 -2
- package/dist-cjs/lib/executeQuery.js +1 -1
- package/dist-cjs/lib/executeQuery.js.map +2 -2
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/ImmutableMap.mjs +0 -13
- package/dist-esm/lib/ImmutableMap.mjs.map +2 -2
- package/dist-esm/lib/RecordType.mjs +1 -1
- package/dist-esm/lib/RecordType.mjs.map +2 -2
- package/dist-esm/lib/RecordsDiff.mjs +26 -14
- package/dist-esm/lib/RecordsDiff.mjs.map +2 -2
- package/dist-esm/lib/Store.mjs +7 -6
- package/dist-esm/lib/Store.mjs.map +2 -2
- package/dist-esm/lib/StoreSchema.mjs +1 -1
- package/dist-esm/lib/StoreSchema.mjs.map +2 -2
- package/dist-esm/lib/executeQuery.mjs +1 -1
- package/dist-esm/lib/executeQuery.mjs.map +2 -2
- package/package.json +9 -5
- package/src/lib/{test/AtomMap.test.ts → AtomMap.test.ts} +77 -111
- package/src/lib/AtomSet.test.ts +116 -0
- package/src/lib/BaseRecord.test.ts +10 -22
- package/src/lib/ImmutableMap.test.ts +114 -71
- package/src/lib/ImmutableMap.ts +1 -0
- package/src/lib/IncrementalSetConstructor.test.ts +76 -81
- package/src/lib/RecordType.test.ts +216 -0
- package/src/lib/RecordType.ts +1 -1
- package/src/lib/RecordsDiff.test.ts +112 -106
- package/src/lib/RecordsDiff.ts +43 -18
- package/src/lib/Store.test.ts +570 -630
- package/src/lib/Store.ts +9 -10
- package/src/lib/StoreListeners.test.ts +462 -0
- package/src/lib/StoreQueries.test.ts +586 -434
- package/src/lib/StoreSchema.test.ts +1012 -174
- package/src/lib/StoreSchema.ts +1 -1
- package/src/lib/StoreSideEffects.test.ts +546 -158
- package/src/lib/devFreeze.test.ts +94 -124
- package/src/lib/executeQuery.test.ts +77 -31
- package/src/lib/executeQuery.ts +3 -1
- package/src/lib/migrate.test.ts +273 -296
- package/src/lib/setUtils.test.ts +38 -79
- package/src/lib/test/createMigrations.test.ts +0 -75
- package/src/lib/test/dependsOn.test.ts +0 -166
- package/src/lib/test/getMigrationsSince.test.ts +0 -121
- package/src/lib/test/migrate.test.ts +0 -118
- package/src/lib/test/migratePersistedRecord.test.ts +0 -265
- package/src/lib/test/migrationCaching.test.ts +0 -209
- package/src/lib/test/recordStore.test.ts +0 -1567
- package/src/lib/test/recordStoreQueries.test.ts +0 -814
- package/src/lib/test/recordType.test.ts +0 -19
- package/src/lib/test/sortMigrations.test.ts +0 -83
- package/src/lib/test/upgradeSchema.test.ts +0 -80
- package/src/lib/test/validate.test.ts +0 -178
- package/src/lib/test/validateMigrations.test.ts +0 -165
|
@@ -1,814 +0,0 @@
|
|
|
1
|
-
import { atom, RESET_VALUE } from '@tldraw/state'
|
|
2
|
-
import { BaseRecord, RecordId } from '../BaseRecord'
|
|
3
|
-
import { createRecordType } from '../RecordType'
|
|
4
|
-
import { Store } from '../Store'
|
|
5
|
-
import { StoreSchema } from '../StoreSchema'
|
|
6
|
-
|
|
7
|
-
interface Author extends BaseRecord<'author', RecordId<Author>> {
|
|
8
|
-
name: string
|
|
9
|
-
age: number
|
|
10
|
-
}
|
|
11
|
-
const Author = createRecordType<Author>('author', {
|
|
12
|
-
validator: {
|
|
13
|
-
validate(value) {
|
|
14
|
-
const author = value as Author
|
|
15
|
-
if (author.typeName !== 'author') throw Error()
|
|
16
|
-
if (!author.id.startsWith('author:')) throw Error()
|
|
17
|
-
if (!Number.isFinite(author.age)) throw Error()
|
|
18
|
-
if (author.age < 0) throw Error()
|
|
19
|
-
return author
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
scope: 'document',
|
|
23
|
-
}).withDefaultProperties(() => ({ age: 23 }))
|
|
24
|
-
|
|
25
|
-
interface Book extends BaseRecord<'book', RecordId<Book>> {
|
|
26
|
-
title: string
|
|
27
|
-
authorId: RecordId<Author>
|
|
28
|
-
}
|
|
29
|
-
const Book = createRecordType<Book>('book', {
|
|
30
|
-
validator: {
|
|
31
|
-
validate(value) {
|
|
32
|
-
const book = value as Book
|
|
33
|
-
if (!book.id.startsWith('book:')) throw Error()
|
|
34
|
-
if (book.typeName !== 'book') throw Error()
|
|
35
|
-
if (typeof book.title !== 'string') throw Error()
|
|
36
|
-
if (!book.authorId.startsWith('author')) throw Error()
|
|
37
|
-
return book
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
scope: 'document',
|
|
41
|
-
})
|
|
42
|
-
const authors = {
|
|
43
|
-
tolkein: Author.create({ name: 'J.R.R. Tolkein' }),
|
|
44
|
-
bradbury: Author.create({ name: 'Ray Bradbury' }),
|
|
45
|
-
davidMitchellSerious: Author.create({ name: 'David Mitchell' }),
|
|
46
|
-
davidMitchellFunny: Author.create({ name: 'David Mitchell' }),
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const books = {
|
|
50
|
-
cloudAtlas: Book.create({ title: 'Cloud Atlas', authorId: authors.davidMitchellSerious.id }),
|
|
51
|
-
myLifeInComedy: Book.create({
|
|
52
|
-
title: 'My Life in Comedy',
|
|
53
|
-
authorId: authors.davidMitchellFunny.id,
|
|
54
|
-
}),
|
|
55
|
-
lotr: Book.create({ title: 'Lord of the Rings', authorId: authors.tolkein.id }),
|
|
56
|
-
farenheit: Book.create({ title: 'Farenheit 451', authorId: authors.bradbury.id }),
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let store: Store<Author | Book>
|
|
60
|
-
|
|
61
|
-
beforeEach(() => {
|
|
62
|
-
store = new Store({
|
|
63
|
-
props: {},
|
|
64
|
-
schema: StoreSchema.create<Author | Book>({
|
|
65
|
-
author: Author,
|
|
66
|
-
book: Book,
|
|
67
|
-
}),
|
|
68
|
-
})
|
|
69
|
-
store.put([
|
|
70
|
-
authors.tolkein,
|
|
71
|
-
authors.bradbury,
|
|
72
|
-
books.lotr,
|
|
73
|
-
books.farenheit,
|
|
74
|
-
authors.davidMitchellFunny,
|
|
75
|
-
authors.davidMitchellSerious,
|
|
76
|
-
books.cloudAtlas,
|
|
77
|
-
books.myLifeInComedy,
|
|
78
|
-
])
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
describe('indexes', () => {
|
|
82
|
-
it('are cached', () => {
|
|
83
|
-
const authorNameIndex1 = store.query.index('author', 'name')
|
|
84
|
-
const authorNameIndex2 = store.query.index('author', 'name')
|
|
85
|
-
expect(authorNameIndex1).toBe(authorNameIndex2)
|
|
86
|
-
})
|
|
87
|
-
it('can be made on any property', () => {
|
|
88
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
89
|
-
|
|
90
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
91
|
-
expect(authorNameIndex.get().get('David Mitchell')).toEqual(
|
|
92
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
const bookTitleIndex = store.query.index('book', 'title')
|
|
96
|
-
expect(bookTitleIndex.get().get('Cloud Atlas')).toEqual(new Set([books.cloudAtlas.id]))
|
|
97
|
-
expect(bookTitleIndex.get().get('Lord of the Rings')).toEqual(new Set([books.lotr.id]))
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
it('can have things added when records are added', () => {
|
|
101
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
102
|
-
// deref to make it compute once
|
|
103
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
104
|
-
|
|
105
|
-
let lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
106
|
-
const newAuthor = Author.create({ name: 'New Author' })
|
|
107
|
-
|
|
108
|
-
store.put([newAuthor])
|
|
109
|
-
|
|
110
|
-
expect(authorNameIndex.get().get('New Author')).toEqual(new Set([newAuthor.id]))
|
|
111
|
-
|
|
112
|
-
const diff = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
113
|
-
if (diff === RESET_VALUE) throw new Error('should not be reset')
|
|
114
|
-
expect(diff).toHaveLength(1)
|
|
115
|
-
expect(diff[0].get('New Author')).toEqual({
|
|
116
|
-
added: new Set([newAuthor.id]),
|
|
117
|
-
})
|
|
118
|
-
expect(diff[0].size).toBe(1)
|
|
119
|
-
|
|
120
|
-
const moreNewAuthors = [
|
|
121
|
-
Author.create({ name: 'New Author' }),
|
|
122
|
-
Author.create({ name: 'New Author' }),
|
|
123
|
-
Author.create({ name: 'New Author' }),
|
|
124
|
-
]
|
|
125
|
-
|
|
126
|
-
lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
127
|
-
store.put(moreNewAuthors)
|
|
128
|
-
|
|
129
|
-
expect(authorNameIndex.get().get('New Author')).toEqual(
|
|
130
|
-
new Set([newAuthor.id, ...moreNewAuthors.map((a) => a.id)])
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
const diff2 = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
134
|
-
|
|
135
|
-
if (diff2 === RESET_VALUE) throw new Error('should not be reset')
|
|
136
|
-
|
|
137
|
-
expect(diff2).toHaveLength(1)
|
|
138
|
-
expect(diff2[0].get('New Author')).toEqual({ added: new Set(moreNewAuthors.map((a) => a.id)) })
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
it('can have things added when records are updated', () => {
|
|
142
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
143
|
-
|
|
144
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
145
|
-
|
|
146
|
-
let lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
147
|
-
|
|
148
|
-
store.put([{ ...authors.bradbury, name: 'J.R.R. Tolkein' }])
|
|
149
|
-
|
|
150
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(
|
|
151
|
-
new Set([authors.tolkein.id, authors.bradbury.id])
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
const diff = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
155
|
-
if (diff === RESET_VALUE) throw new Error('should not be reset')
|
|
156
|
-
expect(diff).toHaveLength(1)
|
|
157
|
-
expect(diff[0].size).toBe(2)
|
|
158
|
-
expect(diff[0].get('J.R.R. Tolkein')).toEqual({
|
|
159
|
-
added: new Set([authors.bradbury.id]),
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
expect(diff[0].get('Ray Bradbury')).toEqual({
|
|
163
|
-
removed: new Set([authors.bradbury.id]),
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
167
|
-
store.put([
|
|
168
|
-
{ ...authors.davidMitchellFunny, name: 'J.R.R. Tolkein' },
|
|
169
|
-
{ ...authors.davidMitchellSerious, name: 'J.R.R. Tolkein' },
|
|
170
|
-
])
|
|
171
|
-
|
|
172
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(
|
|
173
|
-
new Set([
|
|
174
|
-
authors.tolkein.id,
|
|
175
|
-
authors.bradbury.id,
|
|
176
|
-
authors.davidMitchellFunny.id,
|
|
177
|
-
authors.davidMitchellSerious.id,
|
|
178
|
-
])
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
const diff2 = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
182
|
-
|
|
183
|
-
if (diff2 === RESET_VALUE) throw new Error('should not be reset')
|
|
184
|
-
|
|
185
|
-
expect(diff2).toHaveLength(1)
|
|
186
|
-
expect(diff2[0].size).toBe(2)
|
|
187
|
-
|
|
188
|
-
expect(diff2[0].get('J.R.R. Tolkein')).toEqual({
|
|
189
|
-
added: new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id]),
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
expect(diff2[0].get('David Mitchell')).toEqual({
|
|
193
|
-
removed: new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id]),
|
|
194
|
-
})
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('can have things removed when records are removed', () => {
|
|
198
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
199
|
-
|
|
200
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
201
|
-
|
|
202
|
-
let lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
203
|
-
|
|
204
|
-
store.remove([authors.tolkein.id])
|
|
205
|
-
|
|
206
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(undefined)
|
|
207
|
-
|
|
208
|
-
const diff = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
209
|
-
if (diff === RESET_VALUE) throw new Error('should not be reset')
|
|
210
|
-
expect(diff).toHaveLength(1)
|
|
211
|
-
expect(diff[0].size).toBe(1)
|
|
212
|
-
expect(diff[0].get('J.R.R. Tolkein')).toEqual({
|
|
213
|
-
removed: new Set([authors.tolkein.id]),
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
217
|
-
store.remove([
|
|
218
|
-
authors.bradbury.id,
|
|
219
|
-
authors.davidMitchellFunny.id,
|
|
220
|
-
authors.davidMitchellSerious.id,
|
|
221
|
-
])
|
|
222
|
-
|
|
223
|
-
expect(authorNameIndex.get().get('Ray Bradbury')).toEqual(undefined)
|
|
224
|
-
expect(authorNameIndex.get().get('David Mitchell')).toEqual(undefined)
|
|
225
|
-
|
|
226
|
-
const diff2 = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
227
|
-
|
|
228
|
-
if (diff2 === RESET_VALUE) throw new Error('should not be reset')
|
|
229
|
-
|
|
230
|
-
expect(diff2).toHaveLength(1)
|
|
231
|
-
expect(diff2[0].size).toBe(2)
|
|
232
|
-
|
|
233
|
-
expect(diff2[0].get('Ray Bradbury')).toEqual({
|
|
234
|
-
removed: new Set([authors.bradbury.id]),
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
expect(diff2[0].get('David Mitchell')).toEqual({
|
|
238
|
-
removed: new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id]),
|
|
239
|
-
})
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('can have things removed when records are updated', () => {
|
|
243
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
244
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
245
|
-
|
|
246
|
-
let lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
247
|
-
|
|
248
|
-
store.put([{ ...authors.tolkein, name: 'Ray Bradbury' }])
|
|
249
|
-
|
|
250
|
-
expect(authorNameIndex.get().get('Ray Bradbury')).toEqual(
|
|
251
|
-
new Set([authors.tolkein.id, authors.bradbury.id])
|
|
252
|
-
)
|
|
253
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(undefined)
|
|
254
|
-
|
|
255
|
-
const diff = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
256
|
-
if (diff === RESET_VALUE) throw new Error('should not be reset')
|
|
257
|
-
expect(diff).toHaveLength(1)
|
|
258
|
-
expect(diff[0].size).toBe(2)
|
|
259
|
-
expect(diff[0].get('J.R.R. Tolkein')).toEqual({
|
|
260
|
-
removed: new Set([authors.tolkein.id]),
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
expect(diff[0].get('Ray Bradbury')).toEqual({
|
|
264
|
-
added: new Set([authors.tolkein.id]),
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
268
|
-
store.put([
|
|
269
|
-
{ ...authors.davidMitchellFunny, name: 'Ray Bradbury' },
|
|
270
|
-
{ ...authors.davidMitchellSerious, name: 'Ray Bradbury' },
|
|
271
|
-
])
|
|
272
|
-
|
|
273
|
-
expect(authorNameIndex.get().get('Ray Bradbury')).toEqual(
|
|
274
|
-
new Set([
|
|
275
|
-
authors.tolkein.id,
|
|
276
|
-
authors.bradbury.id,
|
|
277
|
-
authors.davidMitchellFunny.id,
|
|
278
|
-
authors.davidMitchellSerious.id,
|
|
279
|
-
])
|
|
280
|
-
)
|
|
281
|
-
expect(authorNameIndex.get().get('David Mitchell')).toEqual(undefined)
|
|
282
|
-
|
|
283
|
-
const diff2 = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
284
|
-
|
|
285
|
-
if (diff2 === RESET_VALUE) throw new Error('should not be reset')
|
|
286
|
-
|
|
287
|
-
expect(diff2).toHaveLength(1)
|
|
288
|
-
expect(diff2[0].size).toBe(2)
|
|
289
|
-
|
|
290
|
-
expect(diff2[0].get('David Mitchell')).toEqual({
|
|
291
|
-
removed: new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id]),
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
expect(diff2[0].get('Ray Bradbury')).toEqual({
|
|
295
|
-
added: new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id]),
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
it('handles things being removed and added for the same value at the same time', () => {
|
|
300
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
301
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
302
|
-
|
|
303
|
-
let lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
304
|
-
|
|
305
|
-
// do remove first
|
|
306
|
-
store.remove([authors.tolkein.id])
|
|
307
|
-
const newAuthor = Author.create({ name: 'J.R.R. Tolkein' })
|
|
308
|
-
store.put([newAuthor])
|
|
309
|
-
|
|
310
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([newAuthor.id]))
|
|
311
|
-
|
|
312
|
-
const diff = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
313
|
-
|
|
314
|
-
if (diff === RESET_VALUE) throw new Error('should not be reset')
|
|
315
|
-
|
|
316
|
-
expect(diff).toHaveLength(1)
|
|
317
|
-
expect(diff[0].size).toBe(1)
|
|
318
|
-
|
|
319
|
-
expect(diff[0].get('J.R.R. Tolkein')).toEqual({
|
|
320
|
-
removed: new Set([authors.tolkein.id]),
|
|
321
|
-
added: new Set([newAuthor.id]),
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
325
|
-
// do updates
|
|
326
|
-
store.put([{ ...authors.davidMitchellFunny, name: 'Ray Bradbury' }])
|
|
327
|
-
store.put([{ ...authors.bradbury, name: 'David Mitchell' }])
|
|
328
|
-
|
|
329
|
-
expect(authorNameIndex.get().get('Ray Bradbury')).toEqual(
|
|
330
|
-
new Set([authors.davidMitchellFunny.id])
|
|
331
|
-
)
|
|
332
|
-
expect(authorNameIndex.get().get('David Mitchell')).toEqual(
|
|
333
|
-
new Set([authors.bradbury.id, authors.davidMitchellSerious.id])
|
|
334
|
-
)
|
|
335
|
-
|
|
336
|
-
const diff2 = authorNameIndex.getDiffSince(lastChangedEpoch)
|
|
337
|
-
|
|
338
|
-
if (diff2 === RESET_VALUE) throw new Error('should not be reset')
|
|
339
|
-
|
|
340
|
-
expect(diff2).toHaveLength(1)
|
|
341
|
-
expect(diff2[0].size).toBe(2)
|
|
342
|
-
|
|
343
|
-
expect(diff2[0].get('Ray Bradbury')).toEqual({
|
|
344
|
-
added: new Set([authors.davidMitchellFunny.id]),
|
|
345
|
-
removed: new Set([authors.bradbury.id]),
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
expect(diff2[0].get('David Mitchell')).toEqual({
|
|
349
|
-
added: new Set([authors.bradbury.id]),
|
|
350
|
-
removed: new Set([authors.davidMitchellFunny.id]),
|
|
351
|
-
})
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
it('has the same value if nothing changed', () => {
|
|
355
|
-
const authorNameIndex = store.query.index('author', 'name')
|
|
356
|
-
|
|
357
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
358
|
-
|
|
359
|
-
const lastChangedEpoch = authorNameIndex.lastChangedEpoch
|
|
360
|
-
|
|
361
|
-
store.put([{ ...authors.tolkein, age: 23 }])
|
|
362
|
-
|
|
363
|
-
expect(authorNameIndex.get().get('J.R.R. Tolkein')).toEqual(new Set([authors.tolkein.id]))
|
|
364
|
-
|
|
365
|
-
expect(lastChangedEpoch).toBe(authorNameIndex.lastChangedEpoch)
|
|
366
|
-
})
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
describe('queries for ids', () => {
|
|
370
|
-
it('can query for all values of a given type', () => {
|
|
371
|
-
const bookQuery = store.query.ids('book')
|
|
372
|
-
|
|
373
|
-
expect(bookQuery.get()).toEqual(
|
|
374
|
-
new Set([books.cloudAtlas.id, books.farenheit.id, books.lotr.id, books.myLifeInComedy.id])
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
const authorQuery = store.query.ids('author')
|
|
378
|
-
|
|
379
|
-
expect(authorQuery.get()).toEqual(
|
|
380
|
-
new Set([
|
|
381
|
-
authors.bradbury.id,
|
|
382
|
-
authors.davidMitchellFunny.id,
|
|
383
|
-
authors.davidMitchellSerious.id,
|
|
384
|
-
authors.tolkein.id,
|
|
385
|
-
])
|
|
386
|
-
)
|
|
387
|
-
|
|
388
|
-
const newAuthor = Author.create({ name: 'J.R.R. Tolkein' })
|
|
389
|
-
const newBook = Book.create({ title: 'The Hobbit', authorId: newAuthor.id })
|
|
390
|
-
store.put([newAuthor, newBook])
|
|
391
|
-
|
|
392
|
-
expect(bookQuery.get()).toEqual(
|
|
393
|
-
new Set([
|
|
394
|
-
books.cloudAtlas.id,
|
|
395
|
-
books.farenheit.id,
|
|
396
|
-
books.lotr.id,
|
|
397
|
-
books.myLifeInComedy.id,
|
|
398
|
-
newBook.id,
|
|
399
|
-
])
|
|
400
|
-
)
|
|
401
|
-
|
|
402
|
-
expect(authorQuery.get()).toEqual(
|
|
403
|
-
new Set([
|
|
404
|
-
authors.bradbury.id,
|
|
405
|
-
authors.davidMitchellFunny.id,
|
|
406
|
-
authors.davidMitchellSerious.id,
|
|
407
|
-
authors.tolkein.id,
|
|
408
|
-
newAuthor.id,
|
|
409
|
-
])
|
|
410
|
-
)
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
it('can query for a single value', () => {
|
|
414
|
-
const jrr = store.query.ids('author', () => ({
|
|
415
|
-
name: { eq: 'J.R.R. Tolkein' },
|
|
416
|
-
}))
|
|
417
|
-
|
|
418
|
-
expect(jrr.get()).toEqual(new Set([authors.tolkein.id]))
|
|
419
|
-
|
|
420
|
-
const mitchell = store.query.ids('author', () => ({
|
|
421
|
-
name: { eq: 'David Mitchell' },
|
|
422
|
-
}))
|
|
423
|
-
|
|
424
|
-
expect(mitchell.get()).toEqual(
|
|
425
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
426
|
-
)
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
it('can query for multiple values', () => {
|
|
430
|
-
store.put([{ ...authors.davidMitchellFunny, age: 30 }])
|
|
431
|
-
|
|
432
|
-
const mitchell30 = store.query.ids('author', () => ({
|
|
433
|
-
name: { eq: 'David Mitchell' },
|
|
434
|
-
age: { eq: 30 },
|
|
435
|
-
}))
|
|
436
|
-
|
|
437
|
-
expect(mitchell30.get()).toEqual(new Set([authors.davidMitchellFunny.id]))
|
|
438
|
-
})
|
|
439
|
-
|
|
440
|
-
it('can use a reactive query', () => {
|
|
441
|
-
store.put([{ ...authors.davidMitchellFunny, age: 30 }])
|
|
442
|
-
|
|
443
|
-
const currentAuthor = atom('currentAuthor', 'David Mitchell')
|
|
444
|
-
const currentAge = atom('currentAge', 30)
|
|
445
|
-
|
|
446
|
-
const mitchell30 = store.query.ids('author', () => ({
|
|
447
|
-
name: { eq: currentAuthor.get() },
|
|
448
|
-
age: { eq: currentAge.get() },
|
|
449
|
-
}))
|
|
450
|
-
|
|
451
|
-
expect(mitchell30.get()).toEqual(new Set([authors.davidMitchellFunny.id]))
|
|
452
|
-
|
|
453
|
-
let lastChangedEpoch = mitchell30.lastChangedEpoch
|
|
454
|
-
currentAge.set(23)
|
|
455
|
-
|
|
456
|
-
expect(mitchell30.get()).toEqual(new Set([authors.davidMitchellSerious.id]))
|
|
457
|
-
|
|
458
|
-
const diff = mitchell30.getDiffSince(lastChangedEpoch)
|
|
459
|
-
|
|
460
|
-
if (diff === RESET_VALUE) throw new Error('should not be reset')
|
|
461
|
-
|
|
462
|
-
expect(diff).toHaveLength(1)
|
|
463
|
-
expect(diff[0]).toEqual({
|
|
464
|
-
added: new Set([authors.davidMitchellSerious.id]),
|
|
465
|
-
removed: new Set([authors.davidMitchellFunny.id]),
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
currentAuthor.set('J.R.R. Tolkein')
|
|
469
|
-
|
|
470
|
-
lastChangedEpoch = mitchell30.lastChangedEpoch
|
|
471
|
-
|
|
472
|
-
expect(mitchell30.get()).toEqual(new Set([authors.tolkein.id]))
|
|
473
|
-
|
|
474
|
-
const diff2 = mitchell30.getDiffSince(lastChangedEpoch)
|
|
475
|
-
|
|
476
|
-
if (diff2 === RESET_VALUE) throw new Error('should not be reset')
|
|
477
|
-
|
|
478
|
-
expect(diff2).toHaveLength(1)
|
|
479
|
-
|
|
480
|
-
expect(diff2[0]).toEqual({
|
|
481
|
-
added: new Set([authors.tolkein.id]),
|
|
482
|
-
removed: new Set([authors.davidMitchellSerious.id]),
|
|
483
|
-
})
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
it('supports not-equals matches', () => {
|
|
487
|
-
store.put([{ ...authors.davidMitchellFunny, age: 30 }])
|
|
488
|
-
const mitchell = store.query.ids('author', () => ({
|
|
489
|
-
name: { neq: 'David Mitchell' },
|
|
490
|
-
}))
|
|
491
|
-
|
|
492
|
-
expect(mitchell.get()).toEqual(new Set([authors.tolkein.id, authors.bradbury.id]))
|
|
493
|
-
|
|
494
|
-
const ageNot23 = store.query.ids('author', () => ({
|
|
495
|
-
age: { neq: 23 },
|
|
496
|
-
}))
|
|
497
|
-
|
|
498
|
-
expect(ageNot23.get()).toEqual(new Set([authors.davidMitchellFunny.id]))
|
|
499
|
-
})
|
|
500
|
-
|
|
501
|
-
it('supports records being added', () => {
|
|
502
|
-
const mitchell = store.query.ids('author', () => ({
|
|
503
|
-
name: { eq: 'David Mitchell' },
|
|
504
|
-
}))
|
|
505
|
-
|
|
506
|
-
expect(mitchell.get()).toEqual(
|
|
507
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
const newAuthor = Author.create({ name: 'David Mitchell' })
|
|
511
|
-
store.put([newAuthor])
|
|
512
|
-
|
|
513
|
-
expect(mitchell.get()).toEqual(
|
|
514
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id, newAuthor.id])
|
|
515
|
-
)
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
it('supports records being removed', () => {
|
|
519
|
-
const mitchell = store.query.ids('author', () => ({
|
|
520
|
-
name: { eq: 'David Mitchell' },
|
|
521
|
-
}))
|
|
522
|
-
|
|
523
|
-
expect(mitchell.get()).toEqual(
|
|
524
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
525
|
-
)
|
|
526
|
-
|
|
527
|
-
store.remove([authors.davidMitchellFunny.id])
|
|
528
|
-
|
|
529
|
-
expect(mitchell.get()).toEqual(new Set([authors.davidMitchellSerious.id]))
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
it('supports records being updated', () => {
|
|
533
|
-
const mitchell = store.query.ids('author', () => ({
|
|
534
|
-
name: { eq: 'David Mitchell' },
|
|
535
|
-
age: { neq: 30 },
|
|
536
|
-
}))
|
|
537
|
-
|
|
538
|
-
expect(mitchell.get()).toEqual(
|
|
539
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
540
|
-
)
|
|
541
|
-
|
|
542
|
-
store.put([{ ...authors.davidMitchellFunny, age: 30 }])
|
|
543
|
-
|
|
544
|
-
expect(mitchell.get()).toEqual(new Set([authors.davidMitchellSerious.id]))
|
|
545
|
-
|
|
546
|
-
store.put([{ ...authors.davidMitchellFunny, age: 23 }])
|
|
547
|
-
|
|
548
|
-
expect(mitchell.get()).toEqual(
|
|
549
|
-
new Set([authors.davidMitchellSerious.id, authors.davidMitchellFunny.id])
|
|
550
|
-
)
|
|
551
|
-
})
|
|
552
|
-
|
|
553
|
-
it('does not update if unrelated records are added, upated, or removed', () => {
|
|
554
|
-
const mitchell = store.query.ids('author', () => ({
|
|
555
|
-
name: { eq: 'David Mitchell' },
|
|
556
|
-
}))
|
|
557
|
-
|
|
558
|
-
expect(mitchell.get()).toEqual(
|
|
559
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
560
|
-
)
|
|
561
|
-
|
|
562
|
-
const lastChangedEpoch = mitchell.lastChangedEpoch
|
|
563
|
-
|
|
564
|
-
const newAuthor = Author.create({ name: 'William Shakespeare' })
|
|
565
|
-
store.put([newAuthor])
|
|
566
|
-
|
|
567
|
-
mitchell.get()
|
|
568
|
-
|
|
569
|
-
expect(mitchell.lastChangedEpoch).toEqual(lastChangedEpoch)
|
|
570
|
-
|
|
571
|
-
store.remove([authors.tolkein.id])
|
|
572
|
-
|
|
573
|
-
mitchell.get()
|
|
574
|
-
|
|
575
|
-
expect(mitchell.lastChangedEpoch).toEqual(lastChangedEpoch)
|
|
576
|
-
})
|
|
577
|
-
|
|
578
|
-
it('doesnt change if related records are updated', () => {
|
|
579
|
-
const mitchell = store.query.ids('author', () => ({
|
|
580
|
-
name: { eq: 'David Mitchell' },
|
|
581
|
-
}))
|
|
582
|
-
|
|
583
|
-
expect(mitchell.get()).toEqual(
|
|
584
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
585
|
-
)
|
|
586
|
-
|
|
587
|
-
const lastChangedEpoch = mitchell.lastChangedEpoch
|
|
588
|
-
|
|
589
|
-
store.put([{ ...authors.davidMitchellFunny, age: 30 }])
|
|
590
|
-
|
|
591
|
-
mitchell.get()
|
|
592
|
-
|
|
593
|
-
expect(mitchell.lastChangedEpoch).toEqual(lastChangedEpoch)
|
|
594
|
-
|
|
595
|
-
// make a change that does affect the query just to check
|
|
596
|
-
store.put([{ ...authors.davidMitchellFunny, name: 'steve' }])
|
|
597
|
-
|
|
598
|
-
mitchell.get()
|
|
599
|
-
expect(mitchell.lastChangedEpoch).toBeGreaterThan(lastChangedEpoch)
|
|
600
|
-
})
|
|
601
|
-
|
|
602
|
-
it('supports items being removed and then added back', () => {
|
|
603
|
-
const mitchell = store.query.ids('author', () => ({
|
|
604
|
-
name: { eq: 'David Mitchell' },
|
|
605
|
-
}))
|
|
606
|
-
|
|
607
|
-
expect(mitchell.get()).toEqual(
|
|
608
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
609
|
-
)
|
|
610
|
-
|
|
611
|
-
const lastChangedEpoch = mitchell.lastChangedEpoch
|
|
612
|
-
|
|
613
|
-
store.remove([authors.davidMitchellFunny.id])
|
|
614
|
-
store.put([authors.davidMitchellFunny])
|
|
615
|
-
|
|
616
|
-
mitchell.get()
|
|
617
|
-
|
|
618
|
-
expect(mitchell.lastChangedEpoch).toEqual(lastChangedEpoch)
|
|
619
|
-
})
|
|
620
|
-
|
|
621
|
-
it('supports items being added and then removed', () => {
|
|
622
|
-
const mitchell = store.query.ids('author', () => ({
|
|
623
|
-
name: { eq: 'David Mitchell' },
|
|
624
|
-
}))
|
|
625
|
-
|
|
626
|
-
expect(mitchell.get()).toEqual(
|
|
627
|
-
new Set([authors.davidMitchellFunny.id, authors.davidMitchellSerious.id])
|
|
628
|
-
)
|
|
629
|
-
|
|
630
|
-
const lastChangedEpoch = mitchell.lastChangedEpoch
|
|
631
|
-
|
|
632
|
-
const newMitchell = Author.create({ name: 'David Mitchell' })
|
|
633
|
-
|
|
634
|
-
store.put([newMitchell])
|
|
635
|
-
store.remove([newMitchell.id])
|
|
636
|
-
|
|
637
|
-
mitchell.get()
|
|
638
|
-
|
|
639
|
-
expect(mitchell.lastChangedEpoch).toEqual(lastChangedEpoch)
|
|
640
|
-
})
|
|
641
|
-
})
|
|
642
|
-
|
|
643
|
-
const bookComparator = (a: Book, b: Book) => a.title.localeCompare(b.title)
|
|
644
|
-
|
|
645
|
-
describe('queries for records', () => {
|
|
646
|
-
it('can query for all values of a given type', () => {
|
|
647
|
-
const allBooks = store.query.records('book')
|
|
648
|
-
|
|
649
|
-
expect(allBooks.get().sort(bookComparator)).toEqual(
|
|
650
|
-
[books.cloudAtlas, books.farenheit, books.lotr, books.myLifeInComedy].sort(bookComparator)
|
|
651
|
-
)
|
|
652
|
-
|
|
653
|
-
const newBook = Book.create({ title: 'The Hobbit', authorId: authors.tolkein.id })
|
|
654
|
-
|
|
655
|
-
store.put([newBook])
|
|
656
|
-
|
|
657
|
-
expect(allBooks.get().sort(bookComparator)).toEqual(
|
|
658
|
-
[books.cloudAtlas, books.farenheit, books.lotr, books.myLifeInComedy, newBook].sort(
|
|
659
|
-
bookComparator
|
|
660
|
-
)
|
|
661
|
-
)
|
|
662
|
-
})
|
|
663
|
-
|
|
664
|
-
it('can query for a single value', () => {
|
|
665
|
-
const farenheit = store.query.records('book', () => ({
|
|
666
|
-
title: { eq: 'Farenheit 451' },
|
|
667
|
-
}))
|
|
668
|
-
|
|
669
|
-
expect(farenheit.get()).toEqual([books.farenheit])
|
|
670
|
-
})
|
|
671
|
-
|
|
672
|
-
it('can query for multiple values', () => {
|
|
673
|
-
const funnyGuide = Book.create({
|
|
674
|
-
title: 'How to be a funny man',
|
|
675
|
-
authorId: authors.davidMitchellFunny.id,
|
|
676
|
-
})
|
|
677
|
-
store.put([funnyGuide])
|
|
678
|
-
const mitchell = store.query.records('book', () => ({
|
|
679
|
-
authorId: { eq: authors.davidMitchellFunny.id },
|
|
680
|
-
}))
|
|
681
|
-
|
|
682
|
-
expect(mitchell.get().sort(bookComparator)).toEqual(
|
|
683
|
-
[books.myLifeInComedy, funnyGuide].sort(bookComparator)
|
|
684
|
-
)
|
|
685
|
-
})
|
|
686
|
-
|
|
687
|
-
it('supports reactive queries', () => {
|
|
688
|
-
const currentAuthor = atom('currentAuthor', authors.davidMitchellFunny.id)
|
|
689
|
-
const booksQuery = store.query.records('book', () => ({
|
|
690
|
-
authorId: { eq: currentAuthor.get() },
|
|
691
|
-
}))
|
|
692
|
-
|
|
693
|
-
expect(booksQuery.get()).toEqual([books.myLifeInComedy])
|
|
694
|
-
|
|
695
|
-
currentAuthor.set(authors.tolkein.id)
|
|
696
|
-
|
|
697
|
-
expect(booksQuery.get()).toEqual([books.lotr])
|
|
698
|
-
})
|
|
699
|
-
})
|
|
700
|
-
|
|
701
|
-
describe('filtering history', () => {
|
|
702
|
-
it('caches filters', () => {
|
|
703
|
-
const filter = store.query.filterHistory('author')
|
|
704
|
-
const filter2 = store.query.filterHistory('author')
|
|
705
|
-
|
|
706
|
-
expect(filter).toBe(filter2)
|
|
707
|
-
})
|
|
708
|
-
it('allows filtering history', () => {
|
|
709
|
-
const authorHistory = store.query.filterHistory('author')
|
|
710
|
-
|
|
711
|
-
authorHistory.get()
|
|
712
|
-
|
|
713
|
-
let lastChangedEpoch = authorHistory.lastChangedEpoch
|
|
714
|
-
|
|
715
|
-
expect(authorHistory.getDiffSince(lastChangedEpoch - 1)).toBe(RESET_VALUE)
|
|
716
|
-
|
|
717
|
-
// updating an author should change the history
|
|
718
|
-
store.put([{ ...authors.davidMitchellFunny, age: 30 }])
|
|
719
|
-
|
|
720
|
-
authorHistory.get()
|
|
721
|
-
|
|
722
|
-
expect(lastChangedEpoch).toBeLessThan(authorHistory.lastChangedEpoch)
|
|
723
|
-
|
|
724
|
-
expect(authorHistory.getDiffSince(lastChangedEpoch)).toMatchObject([
|
|
725
|
-
{ updated: { [authors.davidMitchellFunny.id]: [{ age: 23 }, { age: 30 }] } },
|
|
726
|
-
])
|
|
727
|
-
|
|
728
|
-
lastChangedEpoch = authorHistory.lastChangedEpoch
|
|
729
|
-
|
|
730
|
-
// updating a book should not change the history
|
|
731
|
-
|
|
732
|
-
store.put([
|
|
733
|
-
{ ...books.lotr, title: 'The Lord of the Rings Part I: The Fellowship of the Ring' },
|
|
734
|
-
])
|
|
735
|
-
|
|
736
|
-
authorHistory.get()
|
|
737
|
-
|
|
738
|
-
expect(authorHistory.lastChangedEpoch).toEqual(lastChangedEpoch)
|
|
739
|
-
expect(authorHistory.getDiffSince(lastChangedEpoch)).toMatchObject([])
|
|
740
|
-
})
|
|
741
|
-
|
|
742
|
-
it('should not update if changes in a window of time cancel each other out', () => {
|
|
743
|
-
const authorHistory = store.query.filterHistory('author')
|
|
744
|
-
|
|
745
|
-
const epoch = authorHistory.get()
|
|
746
|
-
const newAuthor = Author.create({ name: 'Stanley Briggs' })
|
|
747
|
-
|
|
748
|
-
store.put([newAuthor])
|
|
749
|
-
store.put([{ ...newAuthor, age: 38 }])
|
|
750
|
-
store.remove([newAuthor.id])
|
|
751
|
-
|
|
752
|
-
expect(authorHistory.get()).toEqual(epoch)
|
|
753
|
-
|
|
754
|
-
store.remove([authors.tolkein.id])
|
|
755
|
-
store.put([authors.tolkein])
|
|
756
|
-
|
|
757
|
-
expect(authorHistory.get()).toEqual(epoch)
|
|
758
|
-
})
|
|
759
|
-
|
|
760
|
-
it('removes update entries if a thing was deleted', () => {
|
|
761
|
-
const authorHistory = store.query.filterHistory('author')
|
|
762
|
-
|
|
763
|
-
authorHistory.get()
|
|
764
|
-
|
|
765
|
-
const lastChangedEpoch = authorHistory.lastChangedEpoch
|
|
766
|
-
|
|
767
|
-
store.put([{ ...authors.davidMitchellFunny, age: 38 }])
|
|
768
|
-
store.put([{ ...authors.davidMitchellFunny, age: 343 }])
|
|
769
|
-
store.remove([authors.davidMitchellFunny.id])
|
|
770
|
-
|
|
771
|
-
expect(authorHistory.getDiffSince(lastChangedEpoch)).toMatchObject([
|
|
772
|
-
{
|
|
773
|
-
// shows the original, not the updated version
|
|
774
|
-
removed: { [authors.davidMitchellFunny.id]: { age: 23 } },
|
|
775
|
-
},
|
|
776
|
-
])
|
|
777
|
-
})
|
|
778
|
-
|
|
779
|
-
it('collapses multiple updated entries into one', () => {
|
|
780
|
-
const authorHistory = store.query.filterHistory('author')
|
|
781
|
-
|
|
782
|
-
authorHistory.get()
|
|
783
|
-
|
|
784
|
-
const lastChangedEpoch = authorHistory.lastChangedEpoch
|
|
785
|
-
|
|
786
|
-
store.put([{ ...authors.davidMitchellFunny, age: 38 }])
|
|
787
|
-
store.put([{ ...authors.davidMitchellFunny, age: 343 }])
|
|
788
|
-
|
|
789
|
-
expect(authorHistory.getDiffSince(lastChangedEpoch)).toMatchObject([
|
|
790
|
-
{
|
|
791
|
-
updated: { [authors.davidMitchellFunny.id]: [{ age: 23 }, { age: 343 }] },
|
|
792
|
-
},
|
|
793
|
-
])
|
|
794
|
-
})
|
|
795
|
-
|
|
796
|
-
it('collapeses an add + update entry into just an add entry', () => {
|
|
797
|
-
const authorHistory = store.query.filterHistory('author')
|
|
798
|
-
|
|
799
|
-
authorHistory.get()
|
|
800
|
-
|
|
801
|
-
const lastChangedEpoch = authorHistory.lastChangedEpoch
|
|
802
|
-
|
|
803
|
-
const newAuthor = Author.create({ name: 'Stanley Briggs' })
|
|
804
|
-
|
|
805
|
-
store.put([newAuthor])
|
|
806
|
-
store.put([{ ...newAuthor, age: 38 }])
|
|
807
|
-
|
|
808
|
-
expect(authorHistory.getDiffSince(lastChangedEpoch)).toMatchObject([
|
|
809
|
-
{
|
|
810
|
-
added: { [newAuthor.id]: { age: 38 } },
|
|
811
|
-
},
|
|
812
|
-
])
|
|
813
|
-
})
|
|
814
|
-
})
|