1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | 'use strict';
|
8 |
|
9 |
|
10 | const should = require('./init.js');
|
11 | const async = require('async');
|
12 | let db, User, options, filter;
|
13 |
|
14 | describe('crud-with-options', function() {
|
15 | before(function(done) {
|
16 | db = getSchema();
|
17 | User = db.define('User', {
|
18 | id: {type: Number, id: true},
|
19 | seq: {type: Number, index: true},
|
20 | name: {type: String, index: true, sort: true},
|
21 | email: {type: String, index: true},
|
22 | birthday: {type: Date, index: true},
|
23 | role: {type: String, index: true},
|
24 | order: {type: Number, index: true, sort: true},
|
25 | vip: {type: Boolean},
|
26 | address: {type: {city: String, area: String}},
|
27 | });
|
28 | options = {};
|
29 | filter = {fields: ['name', 'id']};
|
30 |
|
31 | db.automigrate(['User'], done);
|
32 | });
|
33 |
|
34 | describe('findById', function() {
|
35 | before(function(done) {
|
36 | User.destroyAll(done);
|
37 | });
|
38 |
|
39 | it('should allow findById(id, options, cb)', function(done) {
|
40 | User.findById(1, options, function(err, u) {
|
41 | should.not.exist(u);
|
42 | should.not.exist(err);
|
43 | done();
|
44 | });
|
45 | });
|
46 |
|
47 | it('should allow findById(id, filter, cb)', function(done) {
|
48 | User.findById(1, filter, function(err, u) {
|
49 | should.not.exist(u);
|
50 | should.not.exist(err);
|
51 | done();
|
52 | });
|
53 | });
|
54 |
|
55 | it('should allow findById(id)', function() {
|
56 | User.findById(1);
|
57 | });
|
58 |
|
59 | it('should allow findById(id, filter)', function() {
|
60 | User.findById(1, filter);
|
61 | });
|
62 |
|
63 | it('should allow findById(id, options)', function() {
|
64 | User.findById(1, options);
|
65 | });
|
66 |
|
67 | it('should allow findById(id, filter, options)', function() {
|
68 | User.findById(1, filter, options);
|
69 | });
|
70 |
|
71 | it('should throw when invalid filter are provided for findById',
|
72 | function(done) {
|
73 | (function() {
|
74 | User.findById(1, '123', function(err, u) {
|
75 | });
|
76 | }).should.throw('The filter argument must be an object');
|
77 | done();
|
78 | });
|
79 |
|
80 | it('should throw when invalid options are provided for findById',
|
81 | function(done) {
|
82 | (function() {
|
83 | User.findById(1, filter, '123', function(err, u) {
|
84 | });
|
85 | }).should.throw('The options argument must be an object');
|
86 | done();
|
87 | });
|
88 |
|
89 | it('should report an invalid id via callback for findById',
|
90 | function(done) {
|
91 | User.findById(undefined, {}, function(err, u) {
|
92 | err.should.be.eql(
|
93 | new Error('Model::findById requires the id argument'),
|
94 | );
|
95 | done();
|
96 | });
|
97 | });
|
98 |
|
99 | it('should allow findById(id, filter, cb) for a matching id',
|
100 | function(done) {
|
101 | User.create({name: 'x', email: 'x@y.com'}, function(err, u) {
|
102 | should.not.exist(err);
|
103 | should.exist(u.id);
|
104 | User.findById(u.id, filter, function(err, u) {
|
105 | should.exist(u);
|
106 | should.not.exist(err);
|
107 | u.should.be.an.instanceOf(User);
|
108 | u.should.have.property('name', 'x');
|
109 | u.should.have.property('email', undefined);
|
110 | done();
|
111 | });
|
112 | });
|
113 | });
|
114 |
|
115 | it('should allow findById(id, options, cb) for a matching id',
|
116 | function(done) {
|
117 | User.create({name: 'y', email: 'y@y.com'}, function(err, u) {
|
118 | should.not.exist(err);
|
119 | should.exist(u.id);
|
120 | User.findById(u.id, options, function(err, u) {
|
121 | should.exist(u);
|
122 | should.not.exist(err);
|
123 | u.should.be.an.instanceOf(User);
|
124 | u.should.have.property('name', 'y');
|
125 | u.should.have.property('email', 'y@y.com');
|
126 | done();
|
127 | });
|
128 | });
|
129 | });
|
130 |
|
131 | it('should allow findById(id, filter, options, cb) for a matching id',
|
132 | function(done) {
|
133 | User.create({name: 'z', email: 'z@y.com'}, function(err, u) {
|
134 | should.not.exist(err);
|
135 | should.exist(u.id);
|
136 | User.findById(u.id, filter, options, function(err, u) {
|
137 | should.exist(u);
|
138 | should.not.exist(err);
|
139 | u.should.be.an.instanceOf(User);
|
140 | u.should.have.property('name', 'z');
|
141 | u.should.have.property('email', undefined);
|
142 | done();
|
143 | });
|
144 | });
|
145 | });
|
146 |
|
147 | it('should allow promise-style findById',
|
148 | function(done) {
|
149 | User.create({id: 15, name: 'w', email: 'w@y.com'}).then(function(u) {
|
150 | should.exist(u.id);
|
151 | return User.findById(u.id).then(function(u) {
|
152 | should.exist(u);
|
153 | u.should.be.an.instanceOf(User);
|
154 | u.should.have.property('name', 'w');
|
155 | u.should.have.property('email', 'w@y.com');
|
156 | return u;
|
157 | });
|
158 | }).then(function(u) {
|
159 | should.exist(u);
|
160 | should.exist(u.id);
|
161 | return User.findById(u.id, filter).then(function(u) {
|
162 | should.exist(u);
|
163 | u.should.be.an.instanceOf(User);
|
164 | u.should.have.property('name', 'w');
|
165 | u.should.have.property('email', undefined);
|
166 | return u;
|
167 | });
|
168 | }).then(function(u) {
|
169 | should.exist(u);
|
170 | should.exist(u.id);
|
171 | return User.findById(u.id, options).then(function(u) {
|
172 | should.exist(u);
|
173 | u.should.be.an.instanceOf(User);
|
174 | u.should.have.property('name', 'w');
|
175 | u.should.have.property('email', 'w@y.com');
|
176 | return u;
|
177 | });
|
178 | }).then(function(u) {
|
179 | should.exist(u);
|
180 | should.exist(u.id);
|
181 | return User.findById(u.id, filter, options).then(function(u) {
|
182 | should.exist(u);
|
183 | u.should.be.an.instanceOf(User);
|
184 | u.should.have.property('name', 'w');
|
185 | u.should.have.property('email', undefined);
|
186 | done();
|
187 | });
|
188 | }).catch(function(err) {
|
189 | done(err);
|
190 | });
|
191 | });
|
192 | });
|
193 |
|
194 | describe('findByIds', function() {
|
195 | before(function(done) {
|
196 | const people = [
|
197 | {id: 1, name: 'a', vip: true},
|
198 | {id: 2, name: 'b'},
|
199 | {id: 3, name: 'c'},
|
200 | {id: 4, name: 'd', vip: true},
|
201 | {id: 5, name: 'e'},
|
202 | {id: 6, name: 'f'},
|
203 | ];
|
204 |
|
205 | db.automigrate(['User'], function(err) {
|
206 | User.create(people, options, function(err, users) {
|
207 | done();
|
208 | });
|
209 | });
|
210 | });
|
211 |
|
212 | it('should allow findByIds(ids, cb)', function(done) {
|
213 | User.findByIds([3, 2, 1], function(err, users) {
|
214 | should.exist(users);
|
215 | should.not.exist(err);
|
216 | const names = users.map(function(u) { return u.name; });
|
217 | names.should.eql(['c', 'b', 'a']);
|
218 | done();
|
219 | });
|
220 | });
|
221 |
|
222 | it('should allow findByIds(ids, filter, options, cb)',
|
223 | function(done) {
|
224 | User.findByIds([4, 3, 2, 1],
|
225 | {where: {vip: true}}, options, function(err, users) {
|
226 | should.exist(users);
|
227 | should.not.exist(err);
|
228 | const names = users.map(function(u) {
|
229 | return u.name;
|
230 | });
|
231 | names.should.eql(['d', 'a']);
|
232 | done();
|
233 | });
|
234 | });
|
235 | });
|
236 |
|
237 | describe('find', function() {
|
238 | before(seed);
|
239 |
|
240 | it('should allow find(cb)', function(done) {
|
241 | User.find(function(err, users) {
|
242 | should.exists(users);
|
243 | should.not.exists(err);
|
244 | users.should.have.lengthOf(6);
|
245 | done();
|
246 | });
|
247 | });
|
248 |
|
249 | it('should allow find(filter, cb)', function(done) {
|
250 | User.find({limit: 3}, function(err, users) {
|
251 | should.exists(users);
|
252 | should.not.exists(err);
|
253 | users.should.have.lengthOf(3);
|
254 | done();
|
255 | });
|
256 | });
|
257 |
|
258 | it('should allow find(filter, options, cb)', function(done) {
|
259 | User.find({}, options, function(err, users) {
|
260 | should.exists(users);
|
261 | should.not.exists(err);
|
262 | users.should.have.lengthOf(6);
|
263 | done();
|
264 | });
|
265 | });
|
266 |
|
267 | it('should allow find(filter, options)', function() {
|
268 | User.find({limit: 3}, options);
|
269 | });
|
270 |
|
271 | it('should allow find(filter)', function() {
|
272 | User.find({limit: 3});
|
273 | });
|
274 |
|
275 | it('should skip trailing undefined args', function(done) {
|
276 | User.find({limit: 3}, function(err, users) {
|
277 | should.exists(users);
|
278 | should.not.exists(err);
|
279 | users.should.have.lengthOf(3);
|
280 | done();
|
281 | }, undefined, undefined);
|
282 | });
|
283 |
|
284 | it('should throw on an invalid query arg', function() {
|
285 | (function() {
|
286 | User.find('invalid query', function(err, users) {
|
287 |
|
288 | });
|
289 | }).should.throw('The query argument must be an object');
|
290 | });
|
291 |
|
292 | it('should throw on an invalid options arg', function() {
|
293 | (function() {
|
294 | User.find({limit: 3}, 'invalid option', function(err, users) {
|
295 |
|
296 | });
|
297 | }).should.throw('The options argument must be an object');
|
298 | });
|
299 |
|
300 | it('should throw on an invalid cb arg', function() {
|
301 | (function() {
|
302 | User.find({limit: 3}, {}, 'invalid cb');
|
303 | }).should.throw('The cb argument must be a function');
|
304 | });
|
305 | });
|
306 |
|
307 | describe('count', function() {
|
308 | before(seed);
|
309 |
|
310 | it('should allow count(cb)', function(done) {
|
311 | User.count(function(err, n) {
|
312 | should.not.exist(err);
|
313 | should.exist(n);
|
314 | n.should.equal(6);
|
315 | done();
|
316 | });
|
317 | });
|
318 |
|
319 | it('should allow count(where, cb)', function(done) {
|
320 | User.count({role: 'lead'}, function(err, n) {
|
321 | should.not.exist(err);
|
322 | should.exist(n);
|
323 | n.should.equal(2);
|
324 | done();
|
325 | });
|
326 | });
|
327 |
|
328 | it('should allow count(where, options, cb)', function(done) {
|
329 | User.count({role: 'lead'}, options, function(err, n) {
|
330 | should.not.exist(err);
|
331 | should.exist(n);
|
332 | n.should.equal(2);
|
333 | done();
|
334 | });
|
335 | });
|
336 | });
|
337 |
|
338 | describe('findOne', function() {
|
339 | before(seed);
|
340 |
|
341 | it('should allow findOne(cb)', function(done) {
|
342 | User.find({order: 'id'}, function(err, users) {
|
343 | User.findOne(function(e, u) {
|
344 | should.not.exist(e);
|
345 | should.exist(u);
|
346 | u.id.toString().should.equal(users[0].id.toString());
|
347 | done();
|
348 | });
|
349 | });
|
350 | });
|
351 |
|
352 | it('should allow findOne(filter, options, cb)', function(done) {
|
353 | User.findOne({order: 'order'}, options, function(e, u) {
|
354 | should.not.exist(e);
|
355 | should.exist(u);
|
356 | u.order.should.equal(1);
|
357 | u.name.should.equal('Paul McCartney');
|
358 | done();
|
359 | });
|
360 | });
|
361 |
|
362 | it('should allow findOne(filter, cb)', function(done) {
|
363 | User.findOne({order: 'order'}, function(e, u) {
|
364 | should.not.exist(e);
|
365 | should.exist(u);
|
366 | u.order.should.equal(1);
|
367 | u.name.should.equal('Paul McCartney');
|
368 | done();
|
369 | });
|
370 | });
|
371 |
|
372 | it('should allow trailing undefined args', function(done) {
|
373 | User.findOne({order: 'order'}, function(e, u) {
|
374 | should.not.exist(e);
|
375 | should.exist(u);
|
376 | u.order.should.equal(1);
|
377 | u.name.should.equal('Paul McCartney');
|
378 | done();
|
379 | }, undefined);
|
380 | });
|
381 | });
|
382 |
|
383 | describe('exists', function() {
|
384 | before(seed);
|
385 |
|
386 | it('should allow exists(id, cb)', function(done) {
|
387 | User.findOne(function(e, u) {
|
388 | User.exists(u.id, function(err, exists) {
|
389 | should.not.exist(err);
|
390 | should.exist(exists);
|
391 | exists.should.be.ok;
|
392 | done();
|
393 | });
|
394 | });
|
395 | });
|
396 |
|
397 | it('should allow exists(id, options, cb)', function(done) {
|
398 | User.destroyAll(function() {
|
399 | User.exists(42, options, function(err, exists) {
|
400 | should.not.exist(err);
|
401 | exists.should.not.be.ok;
|
402 | done();
|
403 | });
|
404 | });
|
405 | });
|
406 | });
|
407 |
|
408 | describe('save', function() {
|
409 | it('should allow save(options, cb)', function(done) {
|
410 | const options = {foo: 'bar'};
|
411 | let opts;
|
412 |
|
413 | User.observe('after save', function(ctx, next) {
|
414 | opts = ctx.options;
|
415 | next();
|
416 | });
|
417 |
|
418 | const u = new User();
|
419 | u.save(options, function(err) {
|
420 | should.not.exist(err);
|
421 | options.should.equal(opts);
|
422 | done();
|
423 | });
|
424 | });
|
425 | });
|
426 |
|
427 | describe('destroyAll with options', function() {
|
428 | beforeEach(seed);
|
429 |
|
430 | it('should allow destroyAll(where, options, cb)', function(done) {
|
431 | User.destroyAll({name: 'John Lennon'}, options, function(err) {
|
432 | should.not.exist(err);
|
433 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
434 | should.not.exist(err);
|
435 | data.length.should.equal(0);
|
436 | User.find({where: {name: 'Paul McCartney'}}, function(err, data) {
|
437 | should.not.exist(err);
|
438 | data.length.should.equal(1);
|
439 | done();
|
440 | });
|
441 | });
|
442 | });
|
443 | });
|
444 |
|
445 | it('should allow destroyAll(where, cb)', function(done) {
|
446 | User.destroyAll({name: 'John Lennon'}, function(err) {
|
447 | should.not.exist(err);
|
448 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
449 | should.not.exist(err);
|
450 | data.length.should.equal(0);
|
451 | User.find({where: {name: 'Paul McCartney'}}, function(err, data) {
|
452 | should.not.exist(err);
|
453 | data.length.should.equal(1);
|
454 | done();
|
455 | });
|
456 | });
|
457 | });
|
458 | });
|
459 |
|
460 | it('should allow destroyAll(cb)', function(done) {
|
461 | User.destroyAll(function(err) {
|
462 | should.not.exist(err);
|
463 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
464 | should.not.exist(err);
|
465 | data.length.should.equal(0);
|
466 | User.find({where: {name: 'Paul McCartney'}}, function(err, data) {
|
467 | should.not.exist(err);
|
468 | data.length.should.equal(0);
|
469 | done();
|
470 | });
|
471 | });
|
472 | });
|
473 | });
|
474 | });
|
475 |
|
476 | describe('updateAll ', function() {
|
477 | beforeEach(seed);
|
478 |
|
479 | it('should allow updateAll(where, data, cb)', function(done) {
|
480 | User.update({name: 'John Lennon'}, {name: 'John Smith'}, function(err) {
|
481 | should.not.exist(err);
|
482 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
483 | should.not.exist(err);
|
484 | data.length.should.equal(0);
|
485 | User.find({where: {name: 'John Smith'}}, function(err, data) {
|
486 | should.not.exist(err);
|
487 | data.length.should.equal(1);
|
488 | done();
|
489 | });
|
490 | });
|
491 | });
|
492 | });
|
493 |
|
494 | it('should allow updateAll(where, data, options, cb)', function(done) {
|
495 | User.update({name: 'John Lennon'}, {name: 'John Smith'}, options,
|
496 | function(err) {
|
497 | should.not.exist(err);
|
498 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
499 | should.not.exist(err);
|
500 | data.length.should.equal(0);
|
501 | User.find({where: {name: 'John Smith'}}, function(err, data) {
|
502 | should.not.exist(err);
|
503 | data.length.should.equal(1);
|
504 | done();
|
505 | });
|
506 | });
|
507 | });
|
508 | });
|
509 |
|
510 | it('should allow updateAll(data, cb)', function(done) {
|
511 | User.update({name: 'John Smith'}, function() {
|
512 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
513 | should.not.exist(err);
|
514 | data.length.should.equal(0);
|
515 | User.find({where: {name: 'John Smith'}}, function(err, data) {
|
516 | should.not.exist(err);
|
517 | data.length.should.equal(6);
|
518 | done();
|
519 | });
|
520 | });
|
521 | });
|
522 | });
|
523 | });
|
524 |
|
525 | describe('updateAttributes', function() {
|
526 | beforeEach(seed);
|
527 | it('preserves document properties not modified by the patch', function() {
|
528 | return User.findOne({where: {name: 'John Lennon'}})
|
529 | .then(function(user) {
|
530 | return user.updateAttributes({address: {city: 'Volos'}});
|
531 | })
|
532 | .then(function() {
|
533 | return User.findOne({where: {name: 'John Lennon'}});
|
534 | })
|
535 | .then(function(updatedUser) {
|
536 | updatedUser.address.city.should.equal('Volos');
|
537 | should(updatedUser.address.area).not.be.exactly(null);
|
538 | should(updatedUser.address.area).be.undefined();
|
539 | });
|
540 | });
|
541 | });
|
542 | });
|
543 |
|
544 | describe('upsertWithWhere', function() {
|
545 | beforeEach(seed);
|
546 | it('rejects upsertWithWhere (options,cb)', function(done) {
|
547 | try {
|
548 | User.upsertWithWhere({}, function(err) {
|
549 | if (err) return done(err);
|
550 | });
|
551 | } catch (ex) {
|
552 | ex.message.should.equal('The data argument must be an object');
|
553 | done();
|
554 | }
|
555 | });
|
556 |
|
557 | it('rejects upsertWithWhere (cb)', function(done) {
|
558 | try {
|
559 | User.upsertWithWhere(function(err) {
|
560 | if (err) return done(err);
|
561 | });
|
562 | } catch (ex) {
|
563 | ex.message.should.equal('The where argument must be an object');
|
564 | done();
|
565 | }
|
566 | });
|
567 |
|
568 | it('allows upsertWithWhere by accepting where,data and cb as arguments', function(done) {
|
569 | User.upsertWithWhere({name: 'John Lennon'}, {name: 'John Smith'}, function(err) {
|
570 | if (err) return done(err);
|
571 | User.find({where: {name: 'John Lennon'}}, function(err, data) {
|
572 | if (err) return done(err);
|
573 | data.length.should.equal(0);
|
574 | User.find({where: {name: 'John Smith'}}, function(err, data) {
|
575 | if (err) return done(err);
|
576 | data.length.should.equal(1);
|
577 | data[0].name.should.equal('John Smith');
|
578 | data[0].email.should.equal('john@b3atl3s.co.uk');
|
579 | data[0].role.should.equal('lead');
|
580 | data[0].order.should.equal(2);
|
581 | data[0].vip.should.equal(true);
|
582 | done();
|
583 | });
|
584 | });
|
585 | });
|
586 | });
|
587 |
|
588 | it('allows upsertWithWhere by accepting where, data, options, and cb as arguments', function(done) {
|
589 | options = {};
|
590 | User.upsertWithWhere({name: 'John Lennon'}, {name: 'John Smith'}, options, function(err) {
|
591 | if (err) return done(err);
|
592 | User.find({where: {name: 'John Smith'}}, function(err, data) {
|
593 | if (err) return done(err);
|
594 | data.length.should.equal(1);
|
595 | data[0].name.should.equal('John Smith');
|
596 | data[0].seq.should.equal(0);
|
597 | data[0].email.should.equal('john@b3atl3s.co.uk');
|
598 | data[0].role.should.equal('lead');
|
599 | data[0].order.should.equal(2);
|
600 | data[0].vip.should.equal(true);
|
601 | done();
|
602 | });
|
603 | });
|
604 | });
|
605 | });
|
606 |
|
607 | function seed(done) {
|
608 | const beatles = [
|
609 | {
|
610 | id: 0,
|
611 | seq: 0,
|
612 | name: 'John Lennon',
|
613 | email: 'john@b3atl3s.co.uk',
|
614 | role: 'lead',
|
615 | birthday: new Date('1980-12-08'),
|
616 | order: 2,
|
617 | vip: true,
|
618 | },
|
619 | {
|
620 | id: 1,
|
621 | seq: 1,
|
622 | name: 'Paul McCartney',
|
623 | email: 'paul@b3atl3s.co.uk',
|
624 | role: 'lead',
|
625 | birthday: new Date('1942-06-18'),
|
626 | order: 1,
|
627 | vip: true,
|
628 | },
|
629 | {id: 2, seq: 2, name: 'George Harrison', order: 5, vip: false},
|
630 | {id: 3, seq: 3, name: 'Ringo Starr', order: 6, vip: false},
|
631 | {id: 4, seq: 4, name: 'Pete Best', order: 4},
|
632 | {id: 5, seq: 5, name: 'Stuart Sutcliffe', order: 3, vip: true},
|
633 | ];
|
634 |
|
635 | async.series([
|
636 | User.destroyAll.bind(User),
|
637 | function(cb) {
|
638 | async.each(beatles, User.create.bind(User), cb);
|
639 | },
|
640 | ], done);
|
641 | }
|