monastery 2.2.2 → 3.0.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/.eslintrc.json +10 -1
- package/changelog.md +2 -0
- package/docs/_config.yml +2 -2
- package/docs/assets/imgs/monastery.jpg +0 -0
- package/docs/definition/index.md +1 -2
- package/docs/manager/index.md +19 -11
- package/docs/manager/model.md +1 -1
- package/docs/manager/models.md +2 -3
- package/docs/model/...rawMethods.md +289 -0
- package/docs/model/count.md +25 -0
- package/docs/model/find.md +5 -9
- package/docs/model/findOne.md +1 -1
- package/docs/model/findOneAndUpdate.md +1 -1
- package/docs/model/index.md +5 -30
- package/docs/model/insert.md +4 -6
- package/docs/model/remove.md +4 -6
- package/docs/model/update.md +4 -6
- package/docs/readme.md +78 -45
- package/lib/collection.js +324 -0
- package/lib/index.js +207 -67
- package/lib/model-crud.js +605 -619
- package/lib/model-validate.js +227 -245
- package/lib/model.js +70 -91
- package/lib/rules.js +36 -35
- package/lib/util.js +69 -15
- package/package.json +12 -11
- package/plugins/images/index.js +11 -11
- package/test/blacklisting.js +506 -537
- package/test/collection.js +445 -0
- package/test/crud.js +810 -730
- package/test/index.test.js +26 -0
- package/test/manager.js +77 -0
- package/test/mock/blacklisting.js +23 -23
- package/test/model.js +611 -572
- package/test/plugin-images.js +880 -965
- package/test/populate.js +249 -262
- package/test/util.js +126 -45
- package/test/validate.js +1074 -1121
- package/test/virtuals.js +222 -227
- package/lib/monk-monkey-patches.js +0 -90
- package/test/monk.js +0 -40
- package/test/test.js +0 -38
package/test/crud.js
CHANGED
|
@@ -1,779 +1,859 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
// todo: test defaultObejcts=true, milliseconds=true, timestamps=true, nullObjects=true in seperate tests
|
|
2
|
+
const monastery = require('../lib/index.js')
|
|
3
|
+
|
|
4
|
+
let db
|
|
5
|
+
beforeAll(async () => { db = monastery('127.0.0.1/monastery', { timestamps: false }) })
|
|
6
|
+
afterAll(async () => { db.close() })
|
|
7
|
+
|
|
8
|
+
test('insert basics', async () => {
|
|
9
|
+
let db2 = monastery('127.0.0.1/monastery', { timestamps: false })
|
|
10
|
+
let user = db2.model('user', { fields: {
|
|
11
|
+
name: { type: 'string' },
|
|
12
|
+
names: [{ type: 'string' }],
|
|
13
|
+
animals: {
|
|
14
|
+
dog: { type: 'string' },
|
|
15
|
+
dogs: [{ name: { type: 'string' } }],
|
|
16
|
+
},
|
|
17
|
+
}})
|
|
18
|
+
|
|
19
|
+
// pass: insert one
|
|
20
|
+
let inserted = await user.insert({ data: { name: 'Martin Luther' }})
|
|
21
|
+
expect(inserted).toEqual({
|
|
22
|
+
_id: expect.any(Object),
|
|
23
|
+
name: 'Martin Luther',
|
|
24
|
+
})
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
// pass: insert multiple
|
|
27
|
+
let inserted2 = await user.insert({ data: [{ name: 'Martin Luther1' }, { name: 'Martin Luther2' }]})
|
|
28
|
+
expect(inserted2).toEqual([
|
|
29
|
+
{ _id: inserted2[0]._id, name: 'Martin Luther1' },
|
|
30
|
+
{ _id: inserted2[1]._id, name: 'Martin Luther2' },
|
|
31
|
+
])
|
|
32
|
+
|
|
33
|
+
// pass: empty data object
|
|
34
|
+
let inserted3 = await user.insert({ data: {} })
|
|
35
|
+
expect(inserted3).toEqual({
|
|
36
|
+
_id: inserted3._id,
|
|
37
|
+
})
|
|
18
38
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Find (id)
|
|
40
|
-
let find3 = await user.find({ query: inserted._id })
|
|
41
|
-
expect(find3).toEqual({ _id: inserted._id, name: 'Martin Luther' })
|
|
42
|
-
|
|
43
|
-
// Find (id string)
|
|
44
|
-
let find4 = await user.find({ query: inserted._id.toString() })
|
|
45
|
-
expect(find4).toEqual({ _id: inserted._id, name: 'Martin Luther' })
|
|
46
|
-
|
|
47
|
-
// Find (id expansion)
|
|
48
|
-
let find5 = await user.find(inserted2[0]._id)
|
|
49
|
-
expect(find5).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
50
|
-
|
|
51
|
-
// Find (id string expansion)
|
|
52
|
-
let find6 = await user.find(inserted2[0]._id.toString())
|
|
53
|
-
expect(find6).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
54
|
-
|
|
55
|
-
// Bad ids
|
|
56
|
-
let badIdOrQuery = 'Please pass an object or MongoId to options.query'
|
|
57
|
-
await expect(user.find()).rejects.toThrow(badIdOrQuery)
|
|
58
|
-
await expect(user.find(1)).rejects.toThrow(badIdOrQuery)
|
|
59
|
-
await expect(user.find(null)).rejects.toThrow(badIdOrQuery)
|
|
60
|
-
await expect(user.find(undefined)).rejects.toThrow(badIdOrQuery)
|
|
61
|
-
await expect(user.find({})).rejects.toThrow(badIdOrQuery)
|
|
62
|
-
await expect(user.find({ query: null })).rejects.toThrow(badIdOrQuery)
|
|
63
|
-
await expect(user.find({ query: undefined })).rejects.toThrow(badIdOrQuery)
|
|
64
|
-
await expect(user.find({ query: { _id: undefined }})).rejects.toThrow(badIdOrQuery)
|
|
65
|
-
|
|
66
|
-
// Parseable
|
|
67
|
-
await expect(user.find('')).resolves.toEqual(null)
|
|
68
|
-
await expect(user.find('invalid-id')).resolves.toEqual(null)
|
|
69
|
-
await expect(user.find({ query: '' })).resolves.toEqual(null)
|
|
70
|
-
await expect(user.find({ query: { _id: '' }})).resolves.toEqual(null)
|
|
71
|
-
await expect(user.find({ query: { _id: null }})).resolves.toEqual([]) // should throw error
|
|
72
|
-
|
|
73
|
-
// FindOne (query id)
|
|
74
|
-
let findOne = await user.findOne({ query: inserted._id })
|
|
75
|
-
expect(findOne).toEqual({ _id: inserted._id, name: 'Martin Luther' })
|
|
76
|
-
|
|
77
|
-
// Findone (id)
|
|
78
|
-
let findOne2 = await user.findOne(inserted2[0]._id)
|
|
79
|
-
expect(findOne2).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
80
|
-
|
|
81
|
-
// Findone (id string)
|
|
82
|
-
let findOne3 = await user.findOne(inserted2[0]._id.toString())
|
|
83
|
-
expect(findOne3).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
84
|
-
|
|
85
|
-
// Remove
|
|
86
|
-
let remove = await user.remove({ query: inserted._id })
|
|
87
|
-
expect(remove.result).toEqual({ n: 1, ok: 1 })
|
|
88
|
-
|
|
89
|
-
db.close()
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
test('insert defaults', async () => {
|
|
93
|
-
let db = (await opendb(null, { defaultObjects: true, serverSelectionTimeoutMS: 2000 })).db
|
|
94
|
-
let db2 = (await opendb(null, { useMilliseconds: true, serverSelectionTimeoutMS: 2000 })).db
|
|
95
|
-
let user = db.model('user', { fields: {
|
|
39
|
+
// pass: No data object
|
|
40
|
+
let inserted4 = await user.insert({})
|
|
41
|
+
expect(inserted4).toEqual({
|
|
42
|
+
_id: inserted4._id,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// pass: No arguments
|
|
46
|
+
let inserted5 = await user.insert()
|
|
47
|
+
expect(inserted5).toEqual({
|
|
48
|
+
_id: inserted5._id,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
db2.close()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('insert option defaultObjects', async () => {
|
|
55
|
+
let db2 = monastery('127.0.0.1/monastery', { defaultObjects: true, timestamps: false })
|
|
56
|
+
let schema = {
|
|
57
|
+
fields: {
|
|
96
58
|
name: { type: 'string' },
|
|
97
59
|
names: [{ type: 'string' }],
|
|
98
60
|
animals: {
|
|
99
61
|
dog: { type: 'string' },
|
|
100
|
-
dogs: [{ name: { type: 'string' } }]
|
|
101
|
-
},
|
|
102
|
-
}})
|
|
103
|
-
let user2 = db2.model('user2', { fields: {}})
|
|
104
|
-
|
|
105
|
-
let inserted = await user.insert({ data: {} })
|
|
106
|
-
expect(inserted).toEqual({
|
|
107
|
-
_id: inserted._id,
|
|
108
|
-
names: [],
|
|
109
|
-
animals: { dogs: [] },
|
|
110
|
-
createdAt: expect.any(Number),
|
|
111
|
-
updatedAt: expect.any(Number)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
// No data object
|
|
115
|
-
let inserted2 = await user.insert({})
|
|
116
|
-
expect(inserted2).toEqual({
|
|
117
|
-
_id: inserted2._id,
|
|
118
|
-
names: [],
|
|
119
|
-
animals: { dogs: [] },
|
|
120
|
-
createdAt: expect.any(Number),
|
|
121
|
-
updatedAt: expect.any(Number)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
// No arguments
|
|
125
|
-
let inserted3 = await user.insert()
|
|
126
|
-
expect(inserted3).toEqual({
|
|
127
|
-
_id: inserted3._id,
|
|
128
|
-
names: [],
|
|
129
|
-
animals: { dogs: [] },
|
|
130
|
-
createdAt: expect.any(Number),
|
|
131
|
-
updatedAt: expect.any(Number)
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
// Milliseconds
|
|
135
|
-
let inserted4 = await user2.insert()
|
|
136
|
-
expect(inserted4).toEqual({
|
|
137
|
-
_id: inserted4._id,
|
|
138
|
-
createdAt: expect.any(Number),
|
|
139
|
-
updatedAt: expect.any(Number)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
db.close()
|
|
143
|
-
db2.close()
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
test('update general', async () => {
|
|
147
|
-
let db = (await opendb(null)).db
|
|
148
|
-
let user = db.model('user', {
|
|
149
|
-
fields: {
|
|
150
|
-
name: { type: 'string' },
|
|
62
|
+
dogs: [{ name: { type: 'string' } }],
|
|
151
63
|
},
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
let inserted2 = await user.insert({ data: [{ name: 'Martin Luther1' }, { name: 'Martin Luther2' }]})
|
|
163
|
-
expect(inserted2).toEqual([
|
|
164
|
-
{
|
|
165
|
-
_id: expect.any(Object),
|
|
166
|
-
name: 'Martin Luther1'
|
|
167
|
-
}, {
|
|
168
|
-
_id: expect.any(Object),
|
|
169
|
-
name: 'Martin Luther2'
|
|
170
|
-
}
|
|
171
|
-
])
|
|
172
|
-
|
|
173
|
-
// Update
|
|
174
|
-
await expect(user.update({ query: inserted._id, data: { name: 'Martin Luther2' }}))
|
|
175
|
-
.resolves.toEqual({ name: 'Martin Luther2' })
|
|
176
|
-
|
|
177
|
-
// Update (no/empty data object)
|
|
178
|
-
await expect(user.update({ query: inserted._id, data: {}}))
|
|
179
|
-
.rejects.toThrow('No valid data passed to user.update({ data: .. })')
|
|
180
|
-
|
|
181
|
-
await expect(user.update({ query: inserted._id }))
|
|
182
|
-
.rejects.toThrow('Please pass an update operator to user.update(), e.g. data, $unset, etc')
|
|
183
|
-
|
|
184
|
-
// Update multiple
|
|
185
|
-
await user.update({
|
|
186
|
-
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }},
|
|
187
|
-
data: { name: 'Martin Luther3' },
|
|
188
|
-
multi: true
|
|
189
|
-
})
|
|
190
|
-
let findUpdated2 = await user.find({
|
|
191
|
-
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }}
|
|
192
|
-
})
|
|
193
|
-
expect(findUpdated2).toEqual([
|
|
194
|
-
{
|
|
195
|
-
_id: expect.any(Object),
|
|
196
|
-
name: 'Martin Luther3'
|
|
197
|
-
}, {
|
|
198
|
-
_id: expect.any(Object),
|
|
199
|
-
name: 'Martin Luther3'
|
|
200
|
-
}
|
|
201
|
-
])
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
let user1 = db.model('user', schema)
|
|
67
|
+
let user2 = db2.model('user', schema)
|
|
68
|
+
|
|
69
|
+
// defaultObjects off (default)
|
|
70
|
+
let inserted1 = await user1.insert({ data: {} })
|
|
71
|
+
expect(inserted1).toEqual({
|
|
72
|
+
_id: inserted1._id,
|
|
73
|
+
})
|
|
202
74
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
75
|
+
// defaultObjects on
|
|
76
|
+
let inserted2 = await user2.insert({ data: {} })
|
|
77
|
+
expect(inserted2).toEqual({
|
|
78
|
+
_id: inserted2._id,
|
|
79
|
+
names: [],
|
|
80
|
+
animals: { dogs: [] },
|
|
81
|
+
})
|
|
82
|
+
db2.close()
|
|
83
|
+
})
|
|
207
84
|
|
|
208
|
-
|
|
209
|
-
|
|
85
|
+
test('insert option timestamps', async () => {
|
|
86
|
+
let db2 = monastery('127.0.0.1/monastery', { timestamps: true })
|
|
87
|
+
let schema = {
|
|
88
|
+
fields: {
|
|
89
|
+
name: { type: 'string' },
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
let user1 = db.model('user', schema)
|
|
93
|
+
let user2 = db2.model('user', schema)
|
|
94
|
+
|
|
95
|
+
// timestamps off (default)
|
|
96
|
+
let inserted1 = await user1.insert({ data: {} })
|
|
97
|
+
expect(inserted1).toEqual({
|
|
98
|
+
_id: inserted1._id,
|
|
99
|
+
})
|
|
210
100
|
|
|
211
|
-
|
|
101
|
+
// timestamps on
|
|
102
|
+
let inserted2 = await user2.insert({ data: {} })
|
|
103
|
+
expect(inserted2).toEqual({
|
|
104
|
+
_id: inserted2._id,
|
|
105
|
+
createdAt: expect.any(Number),
|
|
106
|
+
updatedAt: expect.any(Number),
|
|
212
107
|
})
|
|
108
|
+
db2.close()
|
|
109
|
+
})
|
|
213
110
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
111
|
+
test('insert id casting', async () => {
|
|
112
|
+
db.model('company', {
|
|
113
|
+
fields: {
|
|
114
|
+
name: { type: 'string' },
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
let user = db.model('user', { fields: {
|
|
118
|
+
randomId: { type: 'id' },
|
|
119
|
+
company: { model: 'company' },
|
|
120
|
+
companies: [{ model: 'company' }],
|
|
121
|
+
}})
|
|
122
|
+
|
|
123
|
+
let id = '5edf17ff7e2d5020913f98cc'
|
|
124
|
+
let inserted = await user.insert({ data: { randomId: id, company: id, companies: [id] } })
|
|
125
|
+
|
|
126
|
+
expect(inserted).toEqual({
|
|
127
|
+
_id: inserted._id,
|
|
128
|
+
randomId: db.id(id),
|
|
129
|
+
company: db.id(id),
|
|
130
|
+
companies: [db.id(id)],
|
|
131
|
+
})
|
|
132
|
+
})
|
|
222
133
|
|
|
223
|
-
|
|
224
|
-
|
|
134
|
+
test('find defaults', async () => {
|
|
135
|
+
// Todo: take out and group query/id parsing tests
|
|
136
|
+
let user = db.model('user-find', {
|
|
137
|
+
fields: {
|
|
138
|
+
name: { type: 'string' },
|
|
139
|
+
},
|
|
140
|
+
})
|
|
225
141
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
142
|
+
// Insert one
|
|
143
|
+
let inserted = await user._insert({ name: 'Martin Luther' })
|
|
144
|
+
// Insert multiple
|
|
145
|
+
let inserted2 = await user._insert([{ name: 'Martin Luther1' }, { name: 'Martin Luther2' }])
|
|
146
|
+
|
|
147
|
+
// Find (basic match)
|
|
148
|
+
let find = await user.find({ query: { name: 'Martin Luther' }})
|
|
149
|
+
expect(find[0]).toEqual({ _id: find[0]._id, name: 'Martin Luther' }) // no timestamps
|
|
150
|
+
|
|
151
|
+
// Find (empty query)
|
|
152
|
+
let find2 = await user.find({ query: {} })
|
|
153
|
+
expect(find2.length).toBeGreaterThan(0)
|
|
154
|
+
|
|
155
|
+
// Find (id)
|
|
156
|
+
let find3 = await user.find({ query: inserted._id })
|
|
157
|
+
expect(find3).toEqual({ _id: inserted._id, name: 'Martin Luther' })
|
|
158
|
+
|
|
159
|
+
// Find (id string)
|
|
160
|
+
let find4 = await user.find({ query: inserted._id.toString() })
|
|
161
|
+
expect(find4).toEqual({ _id: inserted._id, name: 'Martin Luther' })
|
|
162
|
+
|
|
163
|
+
// Find (id expansion)
|
|
164
|
+
let find5 = await user.find(inserted2[0]._id)
|
|
165
|
+
expect(find5).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
166
|
+
|
|
167
|
+
// Find (id string expansion)
|
|
168
|
+
let find6 = await user.find(inserted2[0]._id.toString())
|
|
169
|
+
expect(find6).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
170
|
+
|
|
171
|
+
// Bad ids
|
|
172
|
+
let badIdOrQuery = 'Please pass an object or MongoId to options.query'
|
|
173
|
+
await expect(user.find()).rejects.toThrow(badIdOrQuery)
|
|
174
|
+
await expect(user.find(1)).rejects.toThrow(badIdOrQuery)
|
|
175
|
+
await expect(user.find(null)).rejects.toThrow(badIdOrQuery)
|
|
176
|
+
await expect(user.find(undefined)).rejects.toThrow(badIdOrQuery)
|
|
177
|
+
await expect(user.find({})).rejects.toThrow(badIdOrQuery)
|
|
178
|
+
await expect(user.find({ query: null })).rejects.toThrow(badIdOrQuery)
|
|
179
|
+
await expect(user.find({ query: undefined })).rejects.toThrow(badIdOrQuery)
|
|
180
|
+
await expect(user.find({ query: { _id: undefined }})).rejects.toThrow(badIdOrQuery)
|
|
181
|
+
|
|
182
|
+
// Parseable
|
|
183
|
+
await expect(user.find('')).resolves.toEqual(null)
|
|
184
|
+
await expect(user.find('invalid-id')).resolves.toEqual(null)
|
|
185
|
+
await expect(user.find({ query: '' })).resolves.toEqual(null)
|
|
186
|
+
await expect(user.find({ query: { _id: '' }})).resolves.toEqual(null)
|
|
187
|
+
await expect(user.find({ query: { _id: null }})).resolves.toEqual([]) // should throw error
|
|
188
|
+
|
|
189
|
+
// FindOne (query id)
|
|
190
|
+
let findOne = await user.findOne({ query: inserted._id })
|
|
191
|
+
expect(findOne).toEqual({ _id: inserted._id, name: 'Martin Luther' })
|
|
192
|
+
|
|
193
|
+
// Findone (id)
|
|
194
|
+
let findOne2 = await user.findOne(inserted2[0]._id)
|
|
195
|
+
expect(findOne2).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
196
|
+
|
|
197
|
+
// Findone (id string)
|
|
198
|
+
let findOne3 = await user.findOne(inserted2[0]._id.toString())
|
|
199
|
+
expect(findOne3).toEqual({ _id: inserted2[0]._id, name: 'Martin Luther1' })
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
test('find default field population', async () => {
|
|
203
|
+
db.model('user', {
|
|
204
|
+
fields: {
|
|
205
|
+
name: { type: 'string', default: 'Martin Luther' },
|
|
206
|
+
addresses: [{ city: { type: 'string' }, country: { type: 'string', default: 'Germany' } }],
|
|
207
|
+
address: { country: { type: 'string', default: 'Germany' }},
|
|
208
|
+
pet: { dog: { model: 'dog' }},
|
|
209
|
+
pets: { dog: [{ model: 'dog' }]},
|
|
210
|
+
dogs: [{ model: 'dog' }], // virtual association
|
|
211
|
+
},
|
|
212
|
+
})
|
|
213
|
+
db.model('dog', {
|
|
214
|
+
fields: {
|
|
215
|
+
name: { type: 'string', default: 'Scruff' },
|
|
216
|
+
user: { model: 'user' },
|
|
217
|
+
},
|
|
218
|
+
})
|
|
230
219
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
220
|
+
// Default field doesn't override null
|
|
221
|
+
let nulldoc1 = await db.dog.insert({ data: { name: null }})
|
|
222
|
+
let nullfind1 = await db.dog.findOne({ query: nulldoc1._id })
|
|
223
|
+
expect(nullfind1).toEqual({ _id: nulldoc1._id, name: null })
|
|
224
|
+
|
|
225
|
+
// Default field doesn't override empty string
|
|
226
|
+
let nulldoc2 = await db.dog.insert({ data: { name: '' }})
|
|
227
|
+
let nullfind2 = await db.dog.findOne({ query: nulldoc2._id })
|
|
228
|
+
expect(nullfind2).toEqual({ _id: nulldoc2._id, name: '' })
|
|
229
|
+
|
|
230
|
+
// Default field overrides undefined
|
|
231
|
+
let nulldoc3 = await db.dog.insert({ data: { name: undefined }})
|
|
232
|
+
let nullfind3 = await db.dog.findOne({ query: nulldoc3._id })
|
|
233
|
+
expect(nullfind3).toEqual({ _id: nullfind3._id, name: 'Scruff' })
|
|
234
|
+
|
|
235
|
+
// Default field population test
|
|
236
|
+
// Note that addresses.1.country shouldn't be overridden
|
|
237
|
+
// Insert documents (without defaults)
|
|
238
|
+
let dog1 = await db.dog._insert({})
|
|
239
|
+
let dog2 = await db.dog._insert({})
|
|
240
|
+
let user1 = await db.user._insert({
|
|
241
|
+
addresses: [
|
|
242
|
+
{ city: 'Frankfurt' },
|
|
243
|
+
{ city: 'Christchurch', country: 'New Zealand' },
|
|
244
|
+
],
|
|
245
|
+
pet: { dog: dog1._id },
|
|
246
|
+
pets: { dog: [dog1._id, dog2._id]},
|
|
247
|
+
})
|
|
248
|
+
await db.dog._update(dog1._id, { $set: { user: user1._id }})
|
|
249
|
+
|
|
250
|
+
let find1 = await db.user.findOne({
|
|
251
|
+
query: user1._id,
|
|
252
|
+
populate: ['pet.dog', 'pets.dog', {
|
|
253
|
+
from: 'dog',
|
|
254
|
+
localField: '_id',
|
|
255
|
+
foreignField: 'user',
|
|
256
|
+
as: 'dogs',
|
|
257
|
+
}],
|
|
258
|
+
})
|
|
259
|
+
expect(find1).toEqual({
|
|
260
|
+
_id: user1._id,
|
|
261
|
+
name: 'Martin Luther',
|
|
262
|
+
addresses: [
|
|
263
|
+
{ city: 'Frankfurt', country: 'Germany' },
|
|
264
|
+
{ city: 'Christchurch', country: 'New Zealand' },
|
|
265
|
+
],
|
|
266
|
+
address: { country: 'Germany' },
|
|
267
|
+
pet: { dog: { _id: dog1._id, name: 'Scruff', user: user1._id }},
|
|
268
|
+
pets: {
|
|
269
|
+
dog: [
|
|
270
|
+
{ _id: dog1._id, name: 'Scruff', user: user1._id },
|
|
271
|
+
{ _id: dog2._id, name: 'Scruff' },
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
dogs: [{ _id: dog1._id, name: 'Scruff', user: user1._id }],
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
test('find default field blacklisted', async () => {
|
|
279
|
+
db.model('user', {
|
|
280
|
+
fields: {
|
|
281
|
+
name: { type: 'string', default: 'Martin Luther' },
|
|
282
|
+
addresses: [{ city: { type: 'string' }, country: { type: 'string', default: 'Germany' } }],
|
|
283
|
+
address: { country: { type: 'string', default: 'Germany' }},
|
|
284
|
+
pet: { dog: { model: 'dog' }},
|
|
285
|
+
pets: { dog: [{ model: 'dog' }]},
|
|
286
|
+
dogs: [{ model: 'dog' }], // virtual association
|
|
287
|
+
},
|
|
288
|
+
})
|
|
289
|
+
db.model('dog', {
|
|
290
|
+
fields: {
|
|
291
|
+
age: { type: 'number', default: 12 },
|
|
292
|
+
name: { type: 'string', default: 'Scruff' },
|
|
293
|
+
user: { model: 'user' },
|
|
294
|
+
},
|
|
295
|
+
findBL: ['age'],
|
|
296
|
+
})
|
|
297
|
+
let dog1 = await db.dog._insert({})
|
|
298
|
+
let dog2 = await db.dog._insert({})
|
|
299
|
+
let user1 = await db.user._insert({
|
|
300
|
+
addresses: [
|
|
301
|
+
{ city: 'Frankfurt' },
|
|
302
|
+
{ city: 'Christchurch', country: 'New Zealand' },
|
|
303
|
+
],
|
|
304
|
+
pet: { dog: dog1._id },
|
|
305
|
+
pets: { dog: [dog1._id, dog2._id]},
|
|
306
|
+
})
|
|
307
|
+
await db.dog._update(dog1._id, { $set: { user: user1._id }})
|
|
308
|
+
|
|
309
|
+
// Blacklisted direct/populated default fields (should be removed)
|
|
310
|
+
let find2 = await db.user.findOne({
|
|
311
|
+
query: user1._id,
|
|
312
|
+
populate: [
|
|
313
|
+
'pet.dog',
|
|
314
|
+
'pets.dog',
|
|
315
|
+
{
|
|
316
|
+
from: 'dog',
|
|
317
|
+
localField: '_id',
|
|
318
|
+
foreignField: 'user',
|
|
319
|
+
as: 'dogs',
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
blacklist: ['address', 'addresses.country', 'pets.dog.name', 'dogs.name'],
|
|
323
|
+
// ^ great test (address should cancel addresses if not stopping at the .)
|
|
324
|
+
})
|
|
325
|
+
expect(find2).toEqual({
|
|
326
|
+
_id: user1._id,
|
|
327
|
+
name: 'Martin Luther',
|
|
328
|
+
addresses: [{ city: 'Frankfurt' }, { city: 'Christchurch' }],
|
|
329
|
+
pet: { dog: { _id: dog1._id, name: 'Scruff', user: user1._id }},
|
|
330
|
+
dogs: [{ _id: dog1._id, user: user1._id }],
|
|
331
|
+
pets: {
|
|
332
|
+
dog: [
|
|
333
|
+
{ _id: dog1._id, user: user1._id }, //, age, name
|
|
334
|
+
{ _id: dog2._id }, //, age, name
|
|
335
|
+
],
|
|
336
|
+
},
|
|
337
|
+
})
|
|
338
|
+
})
|
|
236
339
|
|
|
237
|
-
|
|
340
|
+
test('update general', async () => {
|
|
341
|
+
let user = db.model('user', {
|
|
342
|
+
fields: {
|
|
343
|
+
name: { type: 'string' },
|
|
344
|
+
},
|
|
345
|
+
})
|
|
238
346
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
)
|
|
347
|
+
// Insert
|
|
348
|
+
let inserted = await user.insert({ data: { name: 'Martin Luther' }})
|
|
349
|
+
expect(inserted).toEqual({
|
|
350
|
+
_id: expect.any(Object),
|
|
351
|
+
name: 'Martin Luther',
|
|
352
|
+
})
|
|
243
353
|
|
|
354
|
+
// Insert multiple
|
|
355
|
+
let inserted2 = await user.insert({ data: [{ name: 'Martin Luther1' }, { name: 'Martin Luther2' }]})
|
|
356
|
+
expect(inserted2).toEqual([
|
|
357
|
+
{
|
|
358
|
+
_id: expect.any(Object),
|
|
359
|
+
name: 'Martin Luther1',
|
|
360
|
+
}, {
|
|
361
|
+
_id: expect.any(Object),
|
|
362
|
+
name: 'Martin Luther2',
|
|
363
|
+
},
|
|
364
|
+
])
|
|
365
|
+
|
|
366
|
+
// Update
|
|
367
|
+
await expect(user.update({ query: inserted._id, data: { name: 'Martin Luther2' }}))
|
|
368
|
+
.resolves.toEqual({ name: 'Martin Luther2' })
|
|
369
|
+
|
|
370
|
+
// Update (no/empty data object)
|
|
371
|
+
await expect(user.update({ query: inserted._id, data: {}}))
|
|
372
|
+
.rejects.toThrow('No valid data passed to user.update({ data: .. })')
|
|
373
|
+
|
|
374
|
+
await expect(user.update({ query: inserted._id }))
|
|
375
|
+
.rejects.toThrow('Please pass an update operator to user.update(), e.g. data, $unset, etc')
|
|
376
|
+
|
|
377
|
+
// Update multiple
|
|
378
|
+
await user.update({
|
|
379
|
+
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }},
|
|
380
|
+
data: { name: 'Martin Luther3' },
|
|
381
|
+
multi: true,
|
|
382
|
+
})
|
|
383
|
+
let findUpdated2 = await user.find({
|
|
384
|
+
query: { _id: { $in: [inserted2[0]._id, inserted2[1]._id] }},
|
|
385
|
+
})
|
|
386
|
+
expect(findUpdated2).toEqual([
|
|
387
|
+
{
|
|
388
|
+
_id: expect.any(Object),
|
|
389
|
+
name: 'Martin Luther3',
|
|
390
|
+
}, {
|
|
391
|
+
_id: expect.any(Object),
|
|
392
|
+
name: 'Martin Luther3',
|
|
393
|
+
},
|
|
394
|
+
])
|
|
395
|
+
|
|
396
|
+
// Upsert
|
|
397
|
+
let newId = db.id()
|
|
398
|
+
await expect(user.update({ query: newId, data: { name: 'Martin Luther3' }, upsert: true }))
|
|
399
|
+
.resolves.toEqual({ _id: newId, name: 'Martin Luther3' }) // inserted
|
|
400
|
+
|
|
401
|
+
await expect(user.update({ query: inserted._id, data: { name: 'Martin Luther4' }, upsert: true }))
|
|
402
|
+
.resolves.toEqual({ name: 'Martin Luther4' }) // updated
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
test('update defaults', async () => {
|
|
406
|
+
const db2 = monastery('127.0.0.1/monastery', { useMilliseconds: true })
|
|
407
|
+
let user = db2.model('user', {
|
|
408
|
+
fields: {
|
|
409
|
+
name: { type: 'string' },
|
|
410
|
+
},
|
|
411
|
+
})
|
|
412
|
+
let inserted = await user.insert({
|
|
413
|
+
data: {},
|
|
414
|
+
})
|
|
415
|
+
expect(inserted).toEqual({
|
|
416
|
+
_id: inserted._id,
|
|
417
|
+
createdAt: expect.any(Number),
|
|
418
|
+
updatedAt: expect.any(Number),
|
|
419
|
+
})
|
|
420
|
+
// Default field
|
|
421
|
+
// await util.wait(1000)
|
|
422
|
+
let updated = await user.update({
|
|
423
|
+
query: inserted._id,
|
|
424
|
+
data: { name: 'Bruce' },
|
|
425
|
+
})
|
|
426
|
+
expect(updated).toEqual({
|
|
427
|
+
name: 'Bruce',
|
|
428
|
+
updatedAt: expect.any(Number),
|
|
429
|
+
})
|
|
430
|
+
expect(updated.updatedAt && updated.updatedAt != inserted.updatedAt).toEqual(true)
|
|
244
431
|
|
|
245
|
-
|
|
432
|
+
// Empty data (still contains updatedAt)
|
|
433
|
+
let updated2 = await user.update({
|
|
434
|
+
query: inserted._id,
|
|
435
|
+
data: {},
|
|
436
|
+
})
|
|
437
|
+
expect(updated2).toEqual({
|
|
438
|
+
updatedAt: expect.any(Number),
|
|
439
|
+
})
|
|
246
440
|
|
|
247
|
-
|
|
248
|
-
|
|
441
|
+
// Empty data (with no timestamps)
|
|
442
|
+
await expect(user.update({
|
|
443
|
+
query: inserted._id,
|
|
444
|
+
data: {},
|
|
445
|
+
timestamps: false,
|
|
446
|
+
})).rejects.toThrow('No valid data passed to user.update({ data: .. })')
|
|
447
|
+
|
|
448
|
+
// UpdatedAt override (wont work)
|
|
449
|
+
let updated4 = await user.update({
|
|
450
|
+
query: inserted._id,
|
|
451
|
+
data: { updatedAt: 1 },
|
|
452
|
+
})
|
|
453
|
+
expect(updated4.updatedAt > 1).toEqual(true)
|
|
249
454
|
|
|
250
|
-
|
|
455
|
+
// UpdatedAt override
|
|
456
|
+
let updated5 = await user.update({
|
|
457
|
+
query: inserted._id,
|
|
458
|
+
data: { updatedAt: 1 },
|
|
459
|
+
timestamps: false,
|
|
460
|
+
})
|
|
461
|
+
expect(updated5.updatedAt).toEqual(1)
|
|
462
|
+
db2.close()
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
test('update operators', async () => {
|
|
466
|
+
let user = db.model('userOperators', {
|
|
467
|
+
fields: {
|
|
468
|
+
name: { type: 'string', minLength: 5 },
|
|
469
|
+
age: { type: 'number' },
|
|
470
|
+
},
|
|
471
|
+
beforeValidate: [(data, next) => { beforeValidateHookCalled = true; next() }],
|
|
251
472
|
})
|
|
252
473
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
fields: {
|
|
257
|
-
name: { type: 'string' }
|
|
258
|
-
}
|
|
259
|
-
})
|
|
260
|
-
let inserted = await user.insert({
|
|
261
|
-
data: {}
|
|
262
|
-
})
|
|
263
|
-
expect(inserted).toEqual({
|
|
264
|
-
_id: inserted._id,
|
|
265
|
-
createdAt: expect.any(Number),
|
|
266
|
-
updatedAt: expect.any(Number)
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
// Default field
|
|
270
|
-
let updated = await user.update({
|
|
271
|
-
query: inserted._id,
|
|
272
|
-
data: { name: 'Bruce' }
|
|
273
|
-
})
|
|
274
|
-
expect(updated).toEqual({
|
|
275
|
-
name: 'Bruce',
|
|
276
|
-
updatedAt: expect.any(Number)
|
|
277
|
-
})
|
|
278
|
-
expect(updated.updatedAt && updated.updatedAt != inserted.updatedAt).toEqual(true)
|
|
279
|
-
|
|
280
|
-
// Empty data (still contains updatedAt)
|
|
281
|
-
let updated2 = await user.update({
|
|
282
|
-
query: inserted._id,
|
|
283
|
-
data: {}
|
|
284
|
-
})
|
|
285
|
-
expect(updated2).toEqual({
|
|
286
|
-
updatedAt: expect.any(Number)
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
// Empty data (with no timestamps)
|
|
290
|
-
await expect(user.update({
|
|
291
|
-
query: inserted._id,
|
|
292
|
-
data: {},
|
|
293
|
-
timestamps: false
|
|
294
|
-
})).rejects.toThrow('No valid data passed to user.update({ data: .. })')
|
|
295
|
-
|
|
296
|
-
// UpdatedAt override (wont work)
|
|
297
|
-
let updated4 = await user.update({
|
|
298
|
-
query: inserted._id,
|
|
299
|
-
data: { updatedAt: 1 }
|
|
300
|
-
})
|
|
301
|
-
expect(updated4.updatedAt > 1).toEqual(true)
|
|
302
|
-
|
|
303
|
-
// UpdatedAt override
|
|
304
|
-
let updated5 = await user.update({
|
|
305
|
-
query: inserted._id,
|
|
306
|
-
data: { updatedAt: 1 },
|
|
307
|
-
timestamps: false
|
|
308
|
-
})
|
|
309
|
-
expect(updated5.updatedAt).toEqual(1)
|
|
310
|
-
|
|
311
|
-
db.close()
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
test('update operators', async () => {
|
|
315
|
-
let db = (await opendb(null)).db
|
|
316
|
-
let user = db.model('userOperators', {
|
|
317
|
-
fields: {
|
|
318
|
-
name: { type: 'string', minLength: 5 },
|
|
319
|
-
age: { type: 'number' },
|
|
320
|
-
},
|
|
321
|
-
beforeValidate: [(data, next) => { beforeValidateHookCalled = true; next() }]
|
|
322
|
-
})
|
|
474
|
+
let inserted = await user.insert({
|
|
475
|
+
data: { name: 'Bruce', age: 12 },
|
|
476
|
+
})
|
|
323
477
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
})
|
|
478
|
+
// No data object, but has another update operators
|
|
479
|
+
await expect(user.update({ query: inserted._id, $set: { name: 'bruce' }}))
|
|
480
|
+
.resolves.toEqual({ name: 'bruce' })
|
|
327
481
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
482
|
+
// Mixing data and $set, and $set skips validation (minLength)
|
|
483
|
+
await expect(user.update({ query: inserted._id, data: { name: 'bruce2', age: 12 }, $set: { name: 'john' }}))
|
|
484
|
+
.resolves.toEqual({ age: 12, name: 'john' })
|
|
331
485
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
486
|
+
// Two operators
|
|
487
|
+
await user.update({ query: inserted._id, $set: { name: 'john' }, $unset: { age: 1 }})
|
|
488
|
+
await expect(user.findOne({ query: inserted._id })).resolves.toEqual({
|
|
489
|
+
_id: expect.any(Object),
|
|
490
|
+
name: 'john',
|
|
491
|
+
})
|
|
335
492
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
text: { type: 'string' },
|
|
365
|
-
createdAt: { type: 'date' },
|
|
366
|
-
updatedByName: { type: 'string' },
|
|
367
|
-
importance: { type: 'string' },
|
|
368
|
-
}],
|
|
369
|
-
},
|
|
370
|
-
})
|
|
371
|
-
let inserted = await consignment.insert({
|
|
372
|
-
data: {
|
|
373
|
-
specialInstructions: [{
|
|
374
|
-
text: 'filler',
|
|
375
|
-
createdAt: 1653601752472,
|
|
376
|
-
updatedByName: 'Paul',
|
|
377
|
-
importance: 'low'
|
|
378
|
-
}]
|
|
379
|
-
}
|
|
380
|
-
})
|
|
381
|
-
let specialInstructions = [
|
|
382
|
-
{
|
|
383
|
-
text: 'POD added by driver',
|
|
384
|
-
createdAt: 1653603212886,
|
|
385
|
-
updatedByName: 'Paul Driver 3',
|
|
386
|
-
importance: 'low'
|
|
387
|
-
}, {
|
|
493
|
+
// $pull on a non array (also gets passed no valid data check)
|
|
494
|
+
await expect(user.update({ query: inserted._id, $pull: { name: 'bruce' }}))
|
|
495
|
+
.rejects.toThrow('Cannot apply $pull to a non-array value')
|
|
496
|
+
|
|
497
|
+
// Non-data operators don't call beforeValidate
|
|
498
|
+
var beforeValidateHookCalled = false
|
|
499
|
+
await user.update({ query: inserted._id, data: { name: 'bruce' }})
|
|
500
|
+
expect(beforeValidateHookCalled).toEqual(true)
|
|
501
|
+
beforeValidateHookCalled = false
|
|
502
|
+
await user.update({ query: inserted._id, $set: { name: 'bruce' }})
|
|
503
|
+
expect(beforeValidateHookCalled).toEqual(false)
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
test('update mixing formData', async() => {
|
|
507
|
+
// Mixing data
|
|
508
|
+
let consignment = db.model('consignment', {
|
|
509
|
+
fields: {
|
|
510
|
+
specialInstructions: [{
|
|
511
|
+
text: { type: 'string' },
|
|
512
|
+
createdAt: { type: 'date' },
|
|
513
|
+
updatedByName: { type: 'string' },
|
|
514
|
+
importance: { type: 'string' },
|
|
515
|
+
}],
|
|
516
|
+
},
|
|
517
|
+
})
|
|
518
|
+
let inserted = await consignment.insert({
|
|
519
|
+
data: {
|
|
520
|
+
specialInstructions: [{
|
|
388
521
|
text: 'filler',
|
|
389
522
|
createdAt: 1653601752472,
|
|
390
523
|
updatedByName: 'Paul',
|
|
391
|
-
importance: 'low'
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
_id: expect.any(Object),
|
|
423
|
-
specialInstructions: [specialInstructions[1], specialInstructions[1]],
|
|
424
|
-
})
|
|
425
|
-
|
|
426
|
-
db.close()
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
test('insert with id casting', async () => {
|
|
430
|
-
let db = (await opendb(null)).db
|
|
431
|
-
db.model('company', { fields: {
|
|
432
|
-
name: { type: 'string' }
|
|
433
|
-
}})
|
|
434
|
-
let user = db.model('user', { fields: {
|
|
435
|
-
randomId: { type: 'id' },
|
|
436
|
-
company: { model: 'company' },
|
|
437
|
-
companies: [{ model: 'company' }]
|
|
438
|
-
}})
|
|
439
|
-
|
|
440
|
-
let id = '5edf17ff7e2d5020913f98cc'
|
|
441
|
-
let inserted = await user.insert({ data: { randomId: id, company: id, companies: [id] } })
|
|
442
|
-
|
|
443
|
-
expect(inserted).toEqual({
|
|
444
|
-
_id: inserted._id,
|
|
445
|
-
randomId: db.id(id),
|
|
446
|
-
company: db.id(id),
|
|
447
|
-
companies: [db.id(id)]
|
|
448
|
-
})
|
|
449
|
-
|
|
450
|
-
db.close()
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
test('find default field population', async () => {
|
|
454
|
-
let db = (await opendb(null)).db
|
|
455
|
-
db.model('user', {
|
|
456
|
-
fields: {
|
|
457
|
-
name: { type: 'string', default: 'Martin Luther' },
|
|
458
|
-
addresses: [{ city: { type: 'string' }, country: { type: 'string', default: 'Germany' } }],
|
|
459
|
-
address: { country: { type: 'string', default: 'Germany' }},
|
|
460
|
-
pet: { dog: { model: 'dog' }},
|
|
461
|
-
pets: { dog: [{ model: 'dog' }]},
|
|
462
|
-
dogs: [{ model: 'dog' }], // virtual association
|
|
463
|
-
}
|
|
464
|
-
})
|
|
465
|
-
db.model('dog', {
|
|
466
|
-
fields: {
|
|
467
|
-
name: { type: 'string', default: 'Scruff' },
|
|
468
|
-
user: { model: 'user' }
|
|
469
|
-
}
|
|
470
|
-
})
|
|
471
|
-
|
|
472
|
-
// Default field doesn't override null
|
|
473
|
-
let nulldoc1 = await db.dog.insert({ data: { name: null }})
|
|
474
|
-
let nullfind1 = await db.dog.findOne({ query: nulldoc1._id })
|
|
475
|
-
expect(nullfind1).toEqual({ _id: nulldoc1._id, name: null })
|
|
476
|
-
|
|
477
|
-
// Default field doesn't override empty string
|
|
478
|
-
let nulldoc2 = await db.dog.insert({ data: { name: '' }})
|
|
479
|
-
let nullfind2 = await db.dog.findOne({ query: nulldoc2._id })
|
|
480
|
-
expect(nullfind2).toEqual({ _id: nulldoc2._id, name: '' })
|
|
481
|
-
|
|
482
|
-
// Default field overrides undefined
|
|
483
|
-
let nulldoc3 = await db.dog.insert({ data: { name: undefined }})
|
|
484
|
-
let nullfind3 = await db.dog.findOne({ query: nulldoc3._id })
|
|
485
|
-
expect(nullfind3).toEqual({ _id: nullfind3._id, name: 'Scruff' })
|
|
486
|
-
|
|
487
|
-
// Default field population test
|
|
488
|
-
// Note that addresses.1.country shouldn't be overridden
|
|
489
|
-
// Insert documents (without defaults)
|
|
490
|
-
let dog1 = await db.dog._insert({})
|
|
491
|
-
let dog2 = await db.dog._insert({})
|
|
492
|
-
let user1 = await db.user._insert({
|
|
493
|
-
addresses: [
|
|
494
|
-
{ city: 'Frankfurt' },
|
|
495
|
-
{ city: 'Christchurch', country: 'New Zealand' }
|
|
496
|
-
],
|
|
497
|
-
pet: { dog: dog1._id },
|
|
498
|
-
pets: { dog: [dog1._id, dog2._id]},
|
|
499
|
-
})
|
|
500
|
-
await db.dog._update(dog1._id, { $set: { user: user1._id }})
|
|
501
|
-
|
|
502
|
-
let find1 = await db.user.findOne({
|
|
503
|
-
query: user1._id,
|
|
504
|
-
populate: ['pet.dog', 'pets.dog', {
|
|
505
|
-
from: 'dog',
|
|
506
|
-
localField: '_id',
|
|
507
|
-
foreignField: 'user',
|
|
508
|
-
as: 'dogs'
|
|
509
|
-
}]
|
|
510
|
-
})
|
|
511
|
-
expect(find1).toEqual({
|
|
512
|
-
_id: user1._id,
|
|
513
|
-
name: 'Martin Luther',
|
|
514
|
-
addresses: [
|
|
515
|
-
{ city: 'Frankfurt', country: 'Germany' },
|
|
516
|
-
{ city: 'Christchurch', country: 'New Zealand' }
|
|
517
|
-
],
|
|
518
|
-
address: { country: 'Germany' },
|
|
519
|
-
pet: { dog: { _id: dog1._id, name: 'Scruff', user: user1._id }},
|
|
520
|
-
pets: {
|
|
521
|
-
dog: [
|
|
522
|
-
{ _id: dog1._id, name: 'Scruff', user: user1._id },
|
|
523
|
-
{ _id: dog2._id, name: 'Scruff' },
|
|
524
|
-
]
|
|
525
|
-
},
|
|
526
|
-
dogs: [{ _id: dog1._id, name: 'Scruff', user: user1._id }]
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
db.close()
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
test('find default field blacklisted', async () => {
|
|
533
|
-
let db = (await opendb(null)).db
|
|
534
|
-
db.model('user', {
|
|
535
|
-
fields: {
|
|
536
|
-
name: { type: 'string', default: 'Martin Luther' },
|
|
537
|
-
addresses: [{ city: { type: 'string' }, country: { type: 'string', default: 'Germany' } }],
|
|
538
|
-
address: { country: { type: 'string', default: 'Germany' }},
|
|
539
|
-
pet: { dog: { model: 'dog' }},
|
|
540
|
-
pets: { dog: [{ model: 'dog' }]},
|
|
541
|
-
dogs: [{ model: 'dog' }], // virtual association
|
|
542
|
-
}
|
|
543
|
-
})
|
|
544
|
-
db.model('dog', {
|
|
545
|
-
fields: {
|
|
546
|
-
age: { type: 'number', default: 12 },
|
|
547
|
-
name: { type: 'string', default: 'Scruff' },
|
|
548
|
-
user: { model: 'user' }
|
|
549
|
-
},
|
|
550
|
-
findBL: ['age']
|
|
551
|
-
})
|
|
552
|
-
let dog1 = await db.dog._insert({})
|
|
553
|
-
let dog2 = await db.dog._insert({})
|
|
554
|
-
let user1 = await db.user._insert({
|
|
555
|
-
addresses: [
|
|
556
|
-
{ city: 'Frankfurt' },
|
|
557
|
-
{ city: 'Christchurch', country: 'New Zealand' }
|
|
558
|
-
],
|
|
559
|
-
pet: { dog: dog1._id },
|
|
560
|
-
pets: { dog: [dog1._id, dog2._id]},
|
|
561
|
-
})
|
|
562
|
-
await db.dog._update(dog1._id, { $set: { user: user1._id }})
|
|
563
|
-
|
|
564
|
-
// Blacklisted direct/populated default fields (should be removed)
|
|
565
|
-
let find2 = await db.user.findOne({
|
|
566
|
-
query: user1._id,
|
|
567
|
-
populate: [
|
|
568
|
-
'pet.dog',
|
|
569
|
-
'pets.dog',
|
|
570
|
-
{
|
|
571
|
-
from: 'dog',
|
|
572
|
-
localField: '_id',
|
|
573
|
-
foreignField: 'user',
|
|
574
|
-
as: 'dogs',
|
|
575
|
-
}
|
|
576
|
-
],
|
|
577
|
-
blacklist: ['address', 'addresses.country', 'pets.dog.name', 'dogs.name'],
|
|
578
|
-
// ^ great test (address should cancel addresses if not stopping at the .)
|
|
579
|
-
})
|
|
580
|
-
expect(find2).toEqual({
|
|
581
|
-
_id: user1._id,
|
|
582
|
-
name: 'Martin Luther',
|
|
583
|
-
addresses: [{ city: 'Frankfurt' }, { city: 'Christchurch' }],
|
|
584
|
-
pet: { dog: { _id: dog1._id, name: 'Scruff', user: user1._id }},
|
|
585
|
-
dogs: [{ _id: dog1._id, user: user1._id }],
|
|
586
|
-
pets: {
|
|
587
|
-
dog: [
|
|
588
|
-
{ _id: dog1._id, user: user1._id, /*age, name*/ },
|
|
589
|
-
{ _id: dog2._id, /*age, name*/ },
|
|
590
|
-
]
|
|
591
|
-
},
|
|
592
|
-
})
|
|
593
|
-
|
|
594
|
-
db.close()
|
|
524
|
+
importance: 'low',
|
|
525
|
+
}],
|
|
526
|
+
},
|
|
527
|
+
})
|
|
528
|
+
let specialInstructions = [
|
|
529
|
+
{
|
|
530
|
+
text: 'POD added by driver',
|
|
531
|
+
createdAt: 1653603212886,
|
|
532
|
+
updatedByName: 'Paul Driver 3',
|
|
533
|
+
importance: 'low',
|
|
534
|
+
}, {
|
|
535
|
+
text: 'filler',
|
|
536
|
+
createdAt: 1653601752472,
|
|
537
|
+
updatedByName: 'Paul',
|
|
538
|
+
importance: 'low',
|
|
539
|
+
},
|
|
540
|
+
]
|
|
541
|
+
// Key order maintained (not always guaranteed in browsers)
|
|
542
|
+
await consignment.update({
|
|
543
|
+
query: inserted._id,
|
|
544
|
+
data: {
|
|
545
|
+
'specialInstructions[0][text]': 'filler',
|
|
546
|
+
'specialInstructions[0][createdAt]': 1653601752472,
|
|
547
|
+
'specialInstructions[0][updatedByName]': 'Paul',
|
|
548
|
+
'specialInstructions[0][importance]': 'low',
|
|
549
|
+
specialInstructions: specialInstructions.map(o => ({ ...o })),
|
|
550
|
+
},
|
|
551
|
+
})
|
|
552
|
+
await expect(consignment.findOne({ query: inserted._id })).resolves.toEqual({
|
|
553
|
+
_id: expect.any(Object),
|
|
554
|
+
specialInstructions: specialInstructions,
|
|
595
555
|
})
|
|
596
556
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
_id: user1._id,
|
|
629
|
-
name: 'Martin2',
|
|
630
|
-
dog: {
|
|
631
|
-
_id: dog1._id,
|
|
632
|
-
name: 'Scruff'
|
|
633
|
-
},
|
|
634
|
-
})
|
|
635
|
-
|
|
636
|
-
// Error finding document to update
|
|
637
|
-
expect(await user.findOneAndUpdate({
|
|
638
|
-
query: { _id: db.id() },
|
|
639
|
-
data: { name: 'Martin2' },
|
|
640
|
-
})).toEqual(null)
|
|
557
|
+
// Key order maintained (not always guaranteed in browsers)
|
|
558
|
+
await consignment.update({
|
|
559
|
+
query: inserted._id,
|
|
560
|
+
data: {
|
|
561
|
+
specialInstructions: specialInstructions.map(o => ({ ...o })),
|
|
562
|
+
'specialInstructions[0][text]': 'filler',
|
|
563
|
+
'specialInstructions[0][createdAt]': 1653601752472,
|
|
564
|
+
'specialInstructions[0][updatedByName]': 'Paul',
|
|
565
|
+
'specialInstructions[0][importance]': 'low',
|
|
566
|
+
},
|
|
567
|
+
})
|
|
568
|
+
await expect(consignment.findOne({ query: inserted._id })).resolves.toEqual({
|
|
569
|
+
_id: expect.any(Object),
|
|
570
|
+
specialInstructions: [specialInstructions[1], specialInstructions[1]],
|
|
571
|
+
})
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
test('findOneAndUpdate general', async () => {
|
|
575
|
+
// todo: test all findOneAndUpdate options (e.g. array population)
|
|
576
|
+
// todo: test find & update hooks
|
|
577
|
+
let dog = db.model('dog', {
|
|
578
|
+
fields: {
|
|
579
|
+
name: { type: 'string', default: 'Scruff' },
|
|
580
|
+
},
|
|
581
|
+
})
|
|
582
|
+
let user = db.model('user', {
|
|
583
|
+
fields: {
|
|
584
|
+
name: { type: 'string', default: 'Martin' },
|
|
585
|
+
dog: { model: 'dog' },
|
|
586
|
+
},
|
|
587
|
+
})
|
|
641
588
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
589
|
+
// Returns omitted field after update, i.e. dog
|
|
590
|
+
let dog1 = await dog.insert({ data: {} })
|
|
591
|
+
let user1 = await user.insert({ data: { dog: dog1._id }})
|
|
592
|
+
expect(await user.findOneAndUpdate({ query: { _id: user1._id }, data: { name: 'Martin2' }})).toEqual({
|
|
593
|
+
_id: user1._id,
|
|
594
|
+
name: 'Martin2',
|
|
595
|
+
dog: dog1._id,
|
|
596
|
+
})
|
|
648
597
|
|
|
649
|
-
|
|
598
|
+
// Returns omitted field requiring population after update, i.e. dog
|
|
599
|
+
expect(await user.findOneAndUpdate({
|
|
600
|
+
query: { _id: user1._id },
|
|
601
|
+
data: { name: 'Martin2' },
|
|
602
|
+
populate: ['dog'],
|
|
603
|
+
})).toEqual({
|
|
604
|
+
_id: user1._id,
|
|
605
|
+
name: 'Martin2',
|
|
606
|
+
dog: {
|
|
607
|
+
_id: dog1._id,
|
|
608
|
+
name: 'Scruff',
|
|
609
|
+
},
|
|
650
610
|
})
|
|
651
611
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
612
|
+
// Error finding document to update
|
|
613
|
+
expect(await user.findOneAndUpdate({
|
|
614
|
+
query: { _id: db.id() },
|
|
615
|
+
data: { name: 'Martin2' },
|
|
616
|
+
})).toEqual(null)
|
|
617
|
+
|
|
618
|
+
// Error finding document to update (populate)
|
|
619
|
+
expect(await user.findOneAndUpdate({
|
|
620
|
+
query: { _id: db.id() },
|
|
621
|
+
data: { name: 'Martin2' },
|
|
622
|
+
populate: ['dog'],
|
|
623
|
+
})).toEqual(null)
|
|
624
|
+
})
|
|
625
|
+
|
|
626
|
+
test('remove defaults', async () => {
|
|
627
|
+
let user = db.model('userRemove', {
|
|
628
|
+
fields: {
|
|
629
|
+
name: { type: 'string' },
|
|
630
|
+
},
|
|
631
|
+
})
|
|
659
632
|
|
|
660
|
-
|
|
661
|
-
|
|
633
|
+
// Clear (incase of failed a test)
|
|
634
|
+
user._remove({}, { multi: true })
|
|
635
|
+
|
|
636
|
+
// Insert multiple
|
|
637
|
+
let inserted = await user.insert({ data: [
|
|
638
|
+
{ name: 'Martin' },
|
|
639
|
+
{ name: 'Martin' },
|
|
640
|
+
{ name: 'Martin' },
|
|
641
|
+
{ name: 'Martin' },
|
|
642
|
+
]})
|
|
643
|
+
expect(inserted).toEqual([
|
|
644
|
+
{ _id: expect.any(Object), name: 'Martin' },
|
|
645
|
+
{ _id: expect.any(Object), name: 'Martin' },
|
|
646
|
+
{ _id: expect.any(Object), name: 'Martin' },
|
|
647
|
+
{ _id: expect.any(Object), name: 'Martin' },
|
|
648
|
+
])
|
|
649
|
+
|
|
650
|
+
// Remove one by id
|
|
651
|
+
await expect(user.remove({ query: inserted[0]._id }))
|
|
652
|
+
.resolves.toEqual({ acknowledged: true, deletedCount: 1 })
|
|
653
|
+
|
|
654
|
+
// Remove one
|
|
655
|
+
await expect(user.remove({ query: { name: 'Martin' }, multi: false }))
|
|
656
|
+
.resolves.toEqual({ acknowledged: true, deletedCount: 1 })
|
|
657
|
+
|
|
658
|
+
// Remove many (default)
|
|
659
|
+
await expect(user.remove({ query: { name: 'Martin' } }))
|
|
660
|
+
.resolves.toEqual({ acknowledged: true, deletedCount: 2 })
|
|
661
|
+
})
|
|
662
|
+
|
|
663
|
+
test('count defaults', async () => {
|
|
664
|
+
let user = db.model('userCount', {
|
|
665
|
+
fields: {
|
|
666
|
+
name: { type: 'string' },
|
|
667
|
+
},
|
|
668
|
+
})
|
|
662
669
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
670
|
+
// Clear
|
|
671
|
+
await user._remove({}, { multi: true })
|
|
672
|
+
|
|
673
|
+
// Insert multiple
|
|
674
|
+
let inserted = await user.insert({ data: [
|
|
675
|
+
{ name: 'Martin' },
|
|
676
|
+
{ name: 'Martin' },
|
|
677
|
+
{ name: 'Martin2' },
|
|
678
|
+
{ name: 'Martin2' },
|
|
679
|
+
]})
|
|
680
|
+
|
|
681
|
+
// Count one by id
|
|
682
|
+
await expect(user.count({ query: inserted[0]._id }))
|
|
683
|
+
.resolves.toEqual(1)
|
|
684
|
+
|
|
685
|
+
// Count many (default)
|
|
686
|
+
await expect(user.count({ query: { name: 'Martin' } }))
|
|
687
|
+
.resolves.toEqual(2)
|
|
688
|
+
})
|
|
689
|
+
|
|
690
|
+
test('hooks', async () => {
|
|
691
|
+
let user = db.model('user', {
|
|
692
|
+
fields: {
|
|
693
|
+
first: { type: 'string'},
|
|
694
|
+
last: { type: 'string'},
|
|
695
|
+
},
|
|
696
|
+
beforeInsert: [(data, next) => {
|
|
697
|
+
if (!data.first) {
|
|
698
|
+
next(new Error('beforeInsert error 1..'))
|
|
699
|
+
} else if (!data.last) {
|
|
700
|
+
setTimeout(function() {
|
|
701
|
+
next(new Error('beforeInsert error 2..'))
|
|
702
|
+
}, 100)
|
|
703
|
+
} else {
|
|
704
|
+
next()
|
|
705
|
+
}
|
|
706
|
+
}],
|
|
707
|
+
beforeUpdate: [(data, next) => {
|
|
708
|
+
if (!data.first) {
|
|
709
|
+
next(new Error('beforeUpdate error 1..'))
|
|
710
|
+
} else if (!data.last) {
|
|
711
|
+
setTimeout(function() {
|
|
712
|
+
next(new Error('beforeUpdate error 2..'))
|
|
713
|
+
}, 100)
|
|
714
|
+
} else {
|
|
715
|
+
next()
|
|
675
716
|
}
|
|
676
|
-
]
|
|
717
|
+
}],
|
|
718
|
+
beforeRemove: [(next) => {
|
|
719
|
+
next(new Error('beforeRemove error..'))
|
|
720
|
+
}],
|
|
721
|
+
afterFind: [(data, next) => {
|
|
722
|
+
next()
|
|
723
|
+
}],
|
|
724
|
+
})
|
|
725
|
+
let userDoc = await user.insert({ data: { first: 'Martin', last: 'Luther' }})
|
|
726
|
+
|
|
727
|
+
// Catch insert (a)synchronous errors thrown in function or through `next(err)`
|
|
728
|
+
await expect(user.insert({ data: { first: '' } })).rejects.toThrow('beforeInsert error 1..')
|
|
729
|
+
await expect(user.insert({ data: { first: 'Martin' } })).rejects.toThrow('beforeInsert error 2..')
|
|
730
|
+
await expect(user.insert({ data: { first: 'Martin', last: 'Luther' } })).resolves.toEqual({
|
|
731
|
+
_id: expect.any(Object),
|
|
732
|
+
first: 'Martin',
|
|
733
|
+
last: 'Luther',
|
|
734
|
+
})
|
|
677
735
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
736
|
+
// Catch update (a)synchronous errors thrown in function or through `next(err)`
|
|
737
|
+
await expect(user.update({ query: userDoc._id, data: { first: '' } }))
|
|
738
|
+
.rejects.toThrow('beforeUpdate error 1..')
|
|
739
|
+
await expect(user.update({ query: userDoc._id, data: { first: 'Martin' } }))
|
|
740
|
+
.rejects.toThrow('beforeUpdate error 2..')
|
|
741
|
+
await expect(user.update({ query: userDoc._id, data: { first: 'Martin', last: 'Luther' } })).resolves.toEqual({
|
|
742
|
+
first: 'Martin',
|
|
743
|
+
last: 'Luther',
|
|
744
|
+
})
|
|
681
745
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
.resolves.toMatchObject({ deletedCount: 2, result: { n: 2, ok: 1 }})
|
|
746
|
+
// Catch remove synchronous errors through `next(err)`
|
|
747
|
+
await expect(user.remove({ query: userDoc._id })).rejects.toThrow('beforeRemove error..')
|
|
685
748
|
|
|
686
|
-
|
|
749
|
+
// After find continues series
|
|
750
|
+
await expect(user.find({ query: userDoc._id })).resolves.toEqual({
|
|
751
|
+
_id: expect.any(Object),
|
|
752
|
+
first: 'Martin',
|
|
753
|
+
last: 'Luther',
|
|
687
754
|
})
|
|
688
755
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
756
|
+
// beforeUpdate/beforeInsert should have access to the original non-validated data
|
|
757
|
+
let user2 = db.model('user2', {
|
|
758
|
+
fields: {
|
|
759
|
+
first: { type: 'string' },
|
|
760
|
+
},
|
|
761
|
+
beforeInsert: [function (data, next) {
|
|
762
|
+
if (this.data.bad === true && !data.bad) next(new Error('error1'))
|
|
763
|
+
else next()
|
|
764
|
+
}],
|
|
765
|
+
beforeUpdate: [function (data, next) {
|
|
766
|
+
if (this.data.bad === true && !data.bad) next(new Error('error2'))
|
|
767
|
+
else next()
|
|
768
|
+
}],
|
|
769
|
+
})
|
|
770
|
+
let userDoc2 = await user2._insert({ first: 'M' })
|
|
771
|
+
await expect(user2.insert({ data: { first: 'M' } })).resolves.toEqual({ _id: expect.any(Object), first: 'M' })
|
|
772
|
+
await expect(user2.insert({ data: { first: 'M', bad: true } })).rejects.toThrow('error1')
|
|
773
|
+
await expect(user2.update({ query: userDoc2._id, data: { first: 'MM' } })).resolves.toEqual({ first: 'MM' })
|
|
774
|
+
await expect(user2.update({ query: userDoc2._id, data: { first: 'M', bad: true } })).rejects.toThrow('error2')
|
|
775
|
+
})
|
|
776
|
+
|
|
777
|
+
test('hooks > async', async () => {
|
|
778
|
+
let user = db.model('user', {
|
|
779
|
+
fields: {
|
|
780
|
+
first: { type: 'string'},
|
|
781
|
+
},
|
|
782
|
+
afterFind: [
|
|
783
|
+
async (data) => {
|
|
784
|
+
return new Promise((resolve, reject) => {
|
|
785
|
+
if (data.first === 'Martin1') {
|
|
786
|
+
setTimeout(() => {
|
|
787
|
+
data.first = 'Martin1 delayed'
|
|
788
|
+
resolve(data)
|
|
789
|
+
}, 100)
|
|
790
|
+
} else {
|
|
791
|
+
resolve(data)
|
|
792
|
+
}
|
|
793
|
+
})
|
|
695
794
|
},
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
795
|
+
async (data) => {
|
|
796
|
+
return new Promise((resolve, reject) => {
|
|
797
|
+
if (data.first === 'Martin2') {
|
|
798
|
+
setTimeout(() => {
|
|
799
|
+
data.first = 'Martin2 delayed'
|
|
800
|
+
resolve(data)
|
|
801
|
+
}, 100)
|
|
802
|
+
} else {
|
|
803
|
+
resolve(data)
|
|
804
|
+
}
|
|
805
|
+
})
|
|
806
|
+
},
|
|
807
|
+
async (data) => {
|
|
808
|
+
return new Promise((resolve, reject) => {
|
|
809
|
+
setTimeout(() => {
|
|
810
|
+
if (data.first === 'Martin3') {
|
|
811
|
+
reject(new Error('An async error occurred with Martin3'))
|
|
812
|
+
} else {
|
|
813
|
+
resolve(data)
|
|
814
|
+
}
|
|
713
815
|
}, 100)
|
|
714
|
-
}
|
|
715
|
-
next()
|
|
716
|
-
}
|
|
717
|
-
}],
|
|
718
|
-
beforeRemove: [(next) => {
|
|
719
|
-
next(new Error('beforeRemove error..'))
|
|
720
|
-
}],
|
|
721
|
-
afterFind: [(data, next) => {
|
|
722
|
-
next()
|
|
723
|
-
}],
|
|
724
|
-
})
|
|
725
|
-
let userDoc = await user.insert({ data: { first: 'Martin', last: 'Luther' }})
|
|
726
|
-
|
|
727
|
-
// Catch insert (a)synchronous errors thrown in function or through `next(err)`
|
|
728
|
-
await expect(user.insert({ data: { first: '' } })).rejects.toThrow('beforeInsert error 1..')
|
|
729
|
-
await expect(user.insert({ data: { first: 'Martin' } })).rejects.toThrow('beforeInsert error 2..')
|
|
730
|
-
await expect(user.insert({ data: { first: 'Martin', last: 'Luther' } })).resolves.toEqual({
|
|
731
|
-
_id: expect.any(Object),
|
|
732
|
-
first: 'Martin',
|
|
733
|
-
last: 'Luther'
|
|
734
|
-
})
|
|
735
|
-
|
|
736
|
-
// Catch update (a)synchronous errors thrown in function or through `next(err)`
|
|
737
|
-
await expect(user.update({ query: userDoc._id, data: { first: '' } }))
|
|
738
|
-
.rejects.toThrow('beforeUpdate error 1..')
|
|
739
|
-
await expect(user.update({ query: userDoc._id, data: { first: 'Martin' } }))
|
|
740
|
-
.rejects.toThrow('beforeUpdate error 2..')
|
|
741
|
-
await expect(user.update({ query: userDoc._id, data: { first: 'Martin', last: 'Luther' } })).resolves.toEqual({
|
|
742
|
-
first: 'Martin',
|
|
743
|
-
last: 'Luther'
|
|
744
|
-
})
|
|
745
|
-
|
|
746
|
-
// Catch remove synchronous errors through `next(err)`
|
|
747
|
-
await expect(user.remove({ query: userDoc._id })).rejects.toThrow('beforeRemove error..')
|
|
748
|
-
|
|
749
|
-
// After find continues series
|
|
750
|
-
await expect(user.find({ query: userDoc._id })).resolves.toEqual({
|
|
751
|
-
_id: expect.any(Object),
|
|
752
|
-
first: 'Martin',
|
|
753
|
-
last: 'Luther'
|
|
754
|
-
})
|
|
755
|
-
|
|
756
|
-
// beforeUpdate/beforeInsert should have access to the original non-validated data
|
|
757
|
-
let user2 = db.model('user2', {
|
|
758
|
-
fields: {
|
|
759
|
-
first: { type: 'string' },
|
|
816
|
+
})
|
|
760
817
|
},
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
818
|
+
async (data, next) => { // next is ignored, no error
|
|
819
|
+
return new Promise((resolve, reject) => {
|
|
820
|
+
data.last = 'Luther'
|
|
821
|
+
resolve(data)
|
|
822
|
+
})
|
|
823
|
+
},
|
|
824
|
+
(data, next) => { // normal next() callbacks can be mixed with async
|
|
825
|
+
setTimeout(() => {
|
|
826
|
+
data.age = 32
|
|
827
|
+
next()
|
|
828
|
+
}, 100)
|
|
829
|
+
},
|
|
830
|
+
],
|
|
831
|
+
})
|
|
832
|
+
let user1Doc = await user.insert({
|
|
833
|
+
data: { first: 'Martin1' },
|
|
834
|
+
})
|
|
835
|
+
let user2Doc = await user.insert({
|
|
836
|
+
data: { first: 'Martin2' },
|
|
837
|
+
})
|
|
838
|
+
let user3Doc = await user.insert({
|
|
839
|
+
data: { first: 'Martin3' },
|
|
777
840
|
})
|
|
778
841
|
|
|
779
|
-
|
|
842
|
+
// First async hook is delayed
|
|
843
|
+
await expect(user.find({ query: user1Doc._id })).resolves.toEqual({
|
|
844
|
+
_id: expect.any(Object),
|
|
845
|
+
first: 'Martin1 delayed',
|
|
846
|
+
last: 'Luther',
|
|
847
|
+
age: 32,
|
|
848
|
+
})
|
|
849
|
+
// Second async hook is delayed
|
|
850
|
+
await expect(user.find({ query: user2Doc._id })).resolves.toEqual({
|
|
851
|
+
_id: expect.any(Object),
|
|
852
|
+
first: 'Martin2 delayed',
|
|
853
|
+
last: 'Luther',
|
|
854
|
+
age: 32,
|
|
855
|
+
})
|
|
856
|
+
// Third async hook throws an error
|
|
857
|
+
await expect(user.find({ query: user3Doc._id }))
|
|
858
|
+
.rejects.toThrow('An async error occurred with Martin3')
|
|
859
|
+
})
|