ts-patch-mongoose 3.1.0 → 3.1.2

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.
@@ -1,545 +0,0 @@
1
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
2
-
3
- import mongoose, { model } from 'mongoose'
4
- import em from '../src/em'
5
- import { patchHistoryPlugin } from '../src/index'
6
- import { HistoryModel } from '../src/model'
7
- import { GLOBAL_CREATED, GLOBAL_DELETED, GLOBAL_UPDATED } from './constants/events'
8
- import server from './mongo/server'
9
- import { type Product, ProductSchema } from './schemas/Product'
10
- import { type User, UserSchema } from './schemas/User'
11
-
12
- vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
13
-
14
- describe('plugin - global', () => {
15
- const instance = server('plugin-global')
16
-
17
- mongoose.plugin(patchHistoryPlugin, {
18
- eventCreated: GLOBAL_CREATED,
19
- eventUpdated: GLOBAL_UPDATED,
20
- eventDeleted: GLOBAL_DELETED,
21
- omit: ['__v', 'createdAt', 'updatedAt'],
22
- })
23
-
24
- const UserModel = model<User>('User', UserSchema)
25
- const ProductModel = model<Product>('Product', ProductSchema)
26
-
27
- beforeAll(async () => {
28
- await instance.create()
29
- })
30
-
31
- afterAll(async () => {
32
- await instance.destroy()
33
- })
34
-
35
- beforeEach(async () => {
36
- await mongoose.connection.collection('users').deleteMany({})
37
- await mongoose.connection.collection('products').deleteMany({})
38
- await mongoose.connection.collection('history').deleteMany({})
39
- })
40
-
41
- afterEach(() => {
42
- vi.resetAllMocks()
43
- })
44
-
45
- it('should save array', async () => {
46
- const product = await ProductModel.create({ name: 'paper', groups: [] })
47
- expect(product.name).toBe('paper')
48
-
49
- product.groups = ['office']
50
- await product.save()
51
-
52
- product.groups.push('school')
53
- await product.save()
54
-
55
- const history = await HistoryModel.find({})
56
- expect(history).toHaveLength(3)
57
-
58
- const [first, second, third] = history
59
-
60
- // 1 create
61
- expect(first.version).toBe(0)
62
- expect(first.op).toBe('create')
63
- expect(first.modelName).toBe('Product')
64
- expect(first.collectionName).toBe('products')
65
- expect(first.collectionId).toEqual(product._id)
66
-
67
- expect(first.doc).toHaveProperty('_id', product._id)
68
- expect(first.doc).toHaveProperty('name', 'paper')
69
- expect(first.doc).toHaveProperty('groups', [])
70
- expect(first.doc).not.toHaveProperty('createdAt')
71
- expect(first.doc).not.toHaveProperty('updatedAt')
72
-
73
- expect(first.patch).toHaveLength(0)
74
-
75
- // 2 update
76
- expect(second.version).toBe(1)
77
- expect(second.op).toBe('update')
78
- expect(second.modelName).toBe('Product')
79
- expect(second.collectionName).toBe('products')
80
- expect(second.collectionId).toEqual(product._id)
81
-
82
- expect(second.doc).toBeUndefined()
83
-
84
- expect(second.patch).toHaveLength(1)
85
- expect(second.patch).toMatchObject([{ op: 'add', path: '/groups/0', value: 'office' }])
86
-
87
- // 3 update
88
- expect(third.version).toBe(2)
89
- expect(third.op).toBe('update')
90
- expect(third.modelName).toBe('Product')
91
- expect(third.collectionName).toBe('products')
92
- expect(third.collectionId).toEqual(product._id)
93
-
94
- expect(third.doc).toBeUndefined()
95
-
96
- expect(third.patch).toHaveLength(1)
97
- expect(third.patch).toMatchObject([{ op: 'add', path: '/groups/1', value: 'school' }])
98
-
99
- expect(em.emit).toHaveBeenCalledTimes(3)
100
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: first.doc })
101
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
102
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', groups: [] }),
103
- doc: expect.objectContaining({ _id: product._id, name: 'paper', groups: ['office'] }),
104
- patch: second.patch,
105
- })
106
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
107
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', groups: ['office'] }),
108
- doc: expect.objectContaining({ _id: product._id, name: 'paper', groups: ['office', 'school'] }),
109
- patch: third.patch,
110
- })
111
- })
112
-
113
- it('should update array', async () => {
114
- const product = await ProductModel.create({ name: 'paper', groups: [] })
115
- expect(product.name).toBe('paper')
116
-
117
- await product
118
- .updateOne({
119
- groups: ['office'],
120
- })
121
- .exec()
122
-
123
- await product
124
- .updateOne({
125
- $push: { groups: 'school' },
126
- })
127
- .exec()
128
-
129
- const history = await HistoryModel.find({})
130
- expect(history).toHaveLength(3)
131
-
132
- const [first, second, third] = history
133
-
134
- // 1 create
135
- expect(first.version).toBe(0)
136
- expect(first.op).toBe('create')
137
- expect(first.modelName).toBe('Product')
138
- expect(first.collectionName).toBe('products')
139
- expect(first.collectionId).toEqual(product._id)
140
-
141
- expect(first.doc).toHaveProperty('_id', product._id)
142
- expect(first.doc).toHaveProperty('name', 'paper')
143
- expect(first.doc).toHaveProperty('groups', [])
144
- expect(first.doc).not.toHaveProperty('createdAt')
145
- expect(first.doc).not.toHaveProperty('updatedAt')
146
-
147
- expect(first.patch).toHaveLength(0)
148
-
149
- // 2 update
150
- expect(second.version).toBe(1)
151
- expect(second.op).toBe('updateOne')
152
- expect(second.modelName).toBe('Product')
153
- expect(second.collectionName).toBe('products')
154
- expect(second.collectionId).toEqual(product._id)
155
-
156
- expect(second.doc).toBeUndefined()
157
-
158
- expect(second.patch).toHaveLength(1)
159
- expect(second.patch).toMatchObject([{ op: 'add', path: '/groups/0', value: 'office' }])
160
-
161
- // 3 update
162
- expect(third.version).toBe(2)
163
- expect(third.op).toBe('updateOne')
164
- expect(third.modelName).toBe('Product')
165
- expect(third.collectionName).toBe('products')
166
- expect(third.collectionId).toEqual(product._id)
167
-
168
- expect(third.doc).toBeUndefined()
169
-
170
- expect(third.patch).toHaveLength(1)
171
- expect(third.patch).toMatchObject([{ op: 'add', path: '/groups/1', value: 'school' }])
172
-
173
- expect(em.emit).toHaveBeenCalledTimes(3)
174
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: first.doc })
175
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
176
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', groups: [] }),
177
- doc: expect.objectContaining({ _id: product._id, name: 'paper', groups: ['office'] }),
178
- patch: second.patch,
179
- })
180
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
181
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', groups: ['office'] }),
182
- doc: expect.objectContaining({ _id: product._id, name: 'paper', groups: ['office', 'school'] }),
183
- patch: third.patch,
184
- })
185
- })
186
-
187
- it('should save nested schema', async () => {
188
- const product = await ProductModel.create({ name: 'paper', description: { summary: 'test1' } })
189
- expect(product.name).toBe('paper')
190
-
191
- product.description = { summary: 'test2' }
192
- await product.save()
193
-
194
- product.description.summary = 'test3'
195
- await product.save()
196
-
197
- const history = await HistoryModel.find({})
198
- expect(history).toHaveLength(3)
199
-
200
- const [first, second, third] = history
201
-
202
- // 1 create
203
- expect(first.version).toBe(0)
204
- expect(first.op).toBe('create')
205
- expect(first.modelName).toBe('Product')
206
- expect(first.collectionName).toBe('products')
207
- expect(first.collectionId).toEqual(product._id)
208
-
209
- expect(first.doc).toHaveProperty('_id', product._id)
210
- expect(first.doc).toHaveProperty('name', 'paper')
211
- expect(first.doc).toHaveProperty('description', { summary: 'test1' })
212
- expect(first.doc).not.toHaveProperty('createdAt')
213
- expect(first.doc).not.toHaveProperty('updatedAt')
214
-
215
- expect(first.patch).toHaveLength(0)
216
-
217
- // 2 update
218
- expect(second.version).toBe(1)
219
- expect(second.op).toBe('update')
220
- expect(second.modelName).toBe('Product')
221
- expect(second.collectionName).toBe('products')
222
- expect(second.collectionId).toEqual(product._id)
223
-
224
- expect(second.doc).toBeUndefined()
225
-
226
- expect(second.patch).toHaveLength(2)
227
- expect(second.patch).toMatchObject([
228
- { op: 'test', path: '/description/summary', value: 'test1' },
229
- { op: 'replace', path: '/description/summary', value: 'test2' },
230
- ])
231
-
232
- // 3 update
233
- expect(third.version).toBe(2)
234
- expect(third.op).toBe('update')
235
- expect(third.modelName).toBe('Product')
236
- expect(third.collectionName).toBe('products')
237
- expect(third.collectionId).toEqual(product._id)
238
-
239
- expect(third.doc).toBeUndefined()
240
-
241
- expect(third.patch).toHaveLength(2)
242
- expect(third.patch).toMatchObject([
243
- { op: 'test', path: '/description/summary', value: 'test2' },
244
- { op: 'replace', path: '/description/summary', value: 'test3' },
245
- ])
246
-
247
- expect(em.emit).toHaveBeenCalledTimes(3)
248
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: first.doc })
249
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
250
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test1' } }),
251
- doc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test2' } }),
252
- patch: second.patch,
253
- })
254
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
255
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test2' } }),
256
- doc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test3' } }),
257
- patch: third.patch,
258
- })
259
- })
260
-
261
- it('should update nested schema', async () => {
262
- const product = await ProductModel.create({ name: 'paper', description: { summary: 'test1' } })
263
- expect(product.name).toBe('paper')
264
-
265
- await product
266
- .updateOne({
267
- description: { summary: 'test2' },
268
- })
269
- .exec()
270
-
271
- await product
272
- .updateOne({
273
- $set: { 'description.summary': 'test3' },
274
- })
275
- .exec()
276
-
277
- const history = await HistoryModel.find({})
278
- expect(history).toHaveLength(3)
279
-
280
- const [first, second, third] = history
281
-
282
- // 1 create
283
- expect(first.version).toBe(0)
284
- expect(first.op).toBe('create')
285
- expect(first.modelName).toBe('Product')
286
- expect(first.collectionName).toBe('products')
287
- expect(first.collectionId).toEqual(product._id)
288
-
289
- expect(first.doc).toHaveProperty('_id', product._id)
290
- expect(first.doc).toHaveProperty('name', 'paper')
291
- expect(first.doc).toHaveProperty('description', { summary: 'test1' })
292
- expect(first.doc).not.toHaveProperty('createdAt')
293
- expect(first.doc).not.toHaveProperty('updatedAt')
294
-
295
- expect(first.patch).toHaveLength(0)
296
-
297
- // 2 update
298
- expect(second.version).toBe(1)
299
- expect(second.op).toBe('updateOne')
300
- expect(second.modelName).toBe('Product')
301
- expect(second.collectionName).toBe('products')
302
- expect(second.collectionId).toEqual(product._id)
303
-
304
- expect(second.doc).toBeUndefined()
305
-
306
- expect(second.patch).toHaveLength(2)
307
- expect(second.patch).toMatchObject([
308
- { op: 'test', path: '/description/summary', value: 'test1' },
309
- { op: 'replace', path: '/description/summary', value: 'test2' },
310
- ])
311
-
312
- // 3 update
313
- expect(third.version).toBe(2)
314
- expect(third.op).toBe('updateOne')
315
- expect(third.modelName).toBe('Product')
316
- expect(third.collectionName).toBe('products')
317
- expect(third.collectionId).toEqual(product._id)
318
-
319
- expect(third.doc).toBeUndefined()
320
-
321
- expect(third.patch).toHaveLength(2)
322
- expect(third.patch).toMatchObject([
323
- { op: 'test', path: '/description/summary', value: 'test2' },
324
- { op: 'replace', path: '/description/summary', value: 'test3' },
325
- ])
326
-
327
- expect(em.emit).toHaveBeenCalledTimes(3)
328
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: first.doc })
329
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
330
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test1' } }),
331
- doc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test2' } }),
332
- patch: second.patch,
333
- })
334
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
335
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test2' } }),
336
- doc: expect.objectContaining({ _id: product._id, name: 'paper', description: { summary: 'test3' } }),
337
- patch: third.patch,
338
- })
339
- })
340
-
341
- it('should save objectID', async () => {
342
- const john = await UserModel.create({ name: 'John', role: 'user' })
343
- expect(john.name).toBe('John')
344
- const alice = await UserModel.create({ name: 'Alice', role: 'user' })
345
- expect(alice.name).toBe('Alice')
346
- const product = await ProductModel.create({ name: 'paper', addedBy: john })
347
- expect(product.name).toBe('paper')
348
-
349
- product.addedBy = alice._id
350
- await product.save()
351
-
352
- const history = await HistoryModel.find({})
353
- expect(history).toHaveLength(4)
354
-
355
- const [first, second, third, fourth] = history
356
-
357
- // 1 create
358
- expect(first.version).toBe(0)
359
- expect(first.op).toBe('create')
360
- expect(first.modelName).toBe('User')
361
- expect(first.collectionName).toBe('users')
362
- expect(first.collectionId).toEqual(john._id)
363
-
364
- expect(first.doc).toHaveProperty('_id', john._id)
365
- expect(first.doc).toHaveProperty('name', 'John')
366
- expect(first.doc).toHaveProperty('role', 'user')
367
- expect(first.doc).not.toHaveProperty('createdAt')
368
- expect(first.doc).not.toHaveProperty('updatedAt')
369
-
370
- expect(first.patch).toHaveLength(0)
371
-
372
- // 2 create
373
-
374
- expect(second.version).toBe(0)
375
- expect(second.op).toBe('create')
376
- expect(second.modelName).toBe('User')
377
- expect(second.collectionName).toBe('users')
378
- expect(second.collectionId).toEqual(alice._id)
379
-
380
- expect(second.doc).toHaveProperty('_id', alice._id)
381
- expect(second.doc).toHaveProperty('name', 'Alice')
382
- expect(second.doc).toHaveProperty('role', 'user')
383
- expect(second.doc).not.toHaveProperty('createdAt')
384
- expect(second.doc).not.toHaveProperty('updatedAt')
385
-
386
- expect(second.patch).toHaveLength(0)
387
-
388
- // 3 create
389
- expect(third.version).toBe(0)
390
- expect(third.op).toBe('create')
391
- expect(third.modelName).toBe('Product')
392
- expect(third.collectionName).toBe('products')
393
- expect(third.collectionId).toEqual(product._id)
394
-
395
- expect(third.doc).toHaveProperty('_id', product._id)
396
- expect(third.doc).toHaveProperty('name', 'paper')
397
- expect(third.doc).toHaveProperty('addedBy', john._id)
398
- expect(third.doc).not.toHaveProperty('createdAt')
399
- expect(third.doc).not.toHaveProperty('updatedAt')
400
-
401
- expect(third.patch).toHaveLength(0)
402
-
403
- // 4 update
404
- expect(fourth.version).toBe(1)
405
- expect(fourth.op).toBe('update')
406
- expect(fourth.modelName).toBe('Product')
407
- expect(fourth.collectionName).toBe('products')
408
- expect(fourth.collectionId).toEqual(product._id)
409
-
410
- expect(fourth.doc).toBeUndefined()
411
-
412
- expect(fourth.patch).toHaveLength(2)
413
- expect(fourth.patch).toMatchObject([
414
- { op: 'test', path: '/addedBy', value: john._id.toString() },
415
- { op: 'replace', path: '/addedBy', value: alice._id.toString() },
416
- ])
417
-
418
- expect(em.emit).toHaveBeenCalledTimes(4)
419
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: first.doc })
420
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: second.doc })
421
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: third.doc })
422
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
423
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', addedBy: john._id }),
424
- doc: expect.objectContaining({ _id: product._id, name: 'paper', addedBy: alice._id }),
425
- patch: fourth.patch,
426
- })
427
- })
428
-
429
- it('should update objectID', async () => {
430
- const john = await UserModel.create({ name: 'John', role: 'user' })
431
- expect(john.name).toBe('John')
432
- const alice = await UserModel.create({ name: 'Alice', role: 'user' })
433
- expect(alice.name).toBe('Alice')
434
- const product = await ProductModel.create({ name: 'paper', addedBy: john })
435
- expect(product.name).toBe('paper')
436
-
437
- await product
438
- .updateOne({
439
- addedBy: alice,
440
- })
441
- .exec()
442
-
443
- await product
444
- .updateOne({
445
- addedBy: { _id: john._id, name: 'John', role: 'manager' },
446
- })
447
- .exec()
448
-
449
- const history = await HistoryModel.find({})
450
- expect(history).toHaveLength(5)
451
-
452
- const [first, second, third, fourth, fifth] = history
453
-
454
- // 1 create
455
- expect(first.version).toBe(0)
456
- expect(first.op).toBe('create')
457
- expect(first.modelName).toBe('User')
458
- expect(first.collectionName).toBe('users')
459
- expect(first.collectionId).toEqual(john._id)
460
-
461
- expect(first.doc).toHaveProperty('_id', john._id)
462
- expect(first.doc).toHaveProperty('name', 'John')
463
- expect(first.doc).toHaveProperty('role', 'user')
464
- expect(first.doc).not.toHaveProperty('createdAt')
465
- expect(first.doc).not.toHaveProperty('updatedAt')
466
-
467
- expect(first.patch).toHaveLength(0)
468
-
469
- // 2 create
470
-
471
- expect(second.version).toBe(0)
472
- expect(second.op).toBe('create')
473
- expect(second.modelName).toBe('User')
474
- expect(second.collectionName).toBe('users')
475
- expect(second.collectionId).toEqual(alice._id)
476
-
477
- expect(second.doc).toHaveProperty('_id', alice._id)
478
- expect(second.doc).toHaveProperty('name', 'Alice')
479
- expect(second.doc).toHaveProperty('role', 'user')
480
- expect(second.doc).not.toHaveProperty('createdAt')
481
- expect(second.doc).not.toHaveProperty('updatedAt')
482
-
483
- expect(second.patch).toHaveLength(0)
484
-
485
- // 3 create
486
- expect(third.version).toBe(0)
487
- expect(third.op).toBe('create')
488
- expect(third.modelName).toBe('Product')
489
- expect(third.collectionName).toBe('products')
490
- expect(third.collectionId).toEqual(product._id)
491
-
492
- expect(third.doc).toHaveProperty('_id', product._id)
493
- expect(third.doc).toHaveProperty('name', 'paper')
494
- expect(third.doc).toHaveProperty('addedBy', john._id)
495
- expect(third.doc).not.toHaveProperty('createdAt')
496
- expect(third.doc).not.toHaveProperty('updatedAt')
497
-
498
- expect(third.patch).toHaveLength(0)
499
-
500
- // 4 update
501
- expect(fourth.version).toBe(1)
502
- expect(fourth.op).toBe('updateOne')
503
- expect(fourth.modelName).toBe('Product')
504
- expect(fourth.collectionName).toBe('products')
505
- expect(fourth.collectionId).toEqual(product._id)
506
-
507
- expect(fourth.doc).toBeUndefined()
508
-
509
- expect(fourth.patch).toHaveLength(2)
510
- expect(fourth.patch).toMatchObject([
511
- { op: 'test', path: '/addedBy', value: john._id.toString() },
512
- { op: 'replace', path: '/addedBy', value: alice._id.toString() },
513
- ])
514
-
515
- // 5 update
516
- expect(fifth.version).toBe(2)
517
- expect(fifth.op).toBe('updateOne')
518
- expect(fifth.modelName).toBe('Product')
519
- expect(fifth.collectionName).toBe('products')
520
- expect(fifth.collectionId).toEqual(product._id)
521
-
522
- expect(fifth.doc).toBeUndefined()
523
-
524
- expect(fifth.patch).toHaveLength(2)
525
- expect(fifth.patch).toMatchObject([
526
- { op: 'test', path: '/addedBy', value: alice._id.toString() },
527
- { op: 'replace', path: '/addedBy', value: john._id.toString() },
528
- ])
529
-
530
- expect(em.emit).toHaveBeenCalledTimes(5)
531
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: first.doc })
532
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: second.doc })
533
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_CREATED, { doc: third.doc })
534
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
535
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', addedBy: john._id }),
536
- doc: expect.objectContaining({ _id: product._id, name: 'paper', addedBy: alice._id }),
537
- patch: fourth.patch,
538
- })
539
- expect(em.emit).toHaveBeenCalledWith(GLOBAL_UPDATED, {
540
- oldDoc: expect.objectContaining({ _id: product._id, name: 'paper', addedBy: alice._id }),
541
- doc: expect.objectContaining({ _id: product._id, name: 'paper', addedBy: john._id }),
542
- patch: fifth.patch,
543
- })
544
- })
545
- })