UNPKG

12.4 kBJavaScriptView Raw
1// Copyright IBM Corp. 2013,2019. All Rights Reserved.
2// Node module: loopback-datasource-juggler
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6// This test written in mocha+should.js
7'use strict';
8
9/* global getSchema:false */
10const should = require('./init.js');
11
12let db, Railway, Station;
13
14describe('scope', function() {
15 before(function() {
16 db = getSchema();
17 Railway = db.define('Railway', {
18 URID: {type: String, index: true},
19 }, {
20 scopes: {
21 highSpeed: {
22 where: {
23 highSpeed: true,
24 },
25 },
26 },
27 });
28 Station = db.define('Station', {
29 USID: {type: String, index: true},
30 capacity: {type: Number, index: true},
31 thoughput: {type: Number, index: true},
32 isActive: {type: Boolean, index: true},
33 isUndeground: {type: Boolean, index: true},
34 });
35 });
36
37 beforeEach(function(done) {
38 Railway.destroyAll(function() {
39 Station.destroyAll(done);
40 });
41 });
42
43 it('should define scope using options.scopes', function() {
44 Railway.scopes.should.have.property('highSpeed');
45 Railway.highSpeed.should.be.function;
46 });
47
48 it('should define scope with query', function(done) {
49 Station.scope('active', {where: {isActive: true}});
50 Station.scopes.should.have.property('active');
51 Station.active.create(function(err, station) {
52 if (err) return done(err);
53 should.exist(station);
54 should.exist(station.isActive);
55 station.isActive.should.be.true;
56 done();
57 });
58 });
59
60 it('should allow scope chaining', function(done) {
61 Station.scope('active', {where: {isActive: true}});
62 Station.scope('subway', {where: {isUndeground: true}});
63 Station.active.subway.create(function(err, station) {
64 if (err) return done(err);
65 should.exist(station);
66 station.isActive.should.be.true;
67 station.isUndeground.should.be.true;
68 done();
69 });
70 });
71
72 it('should query all', function(done) {
73 Station.scope('active', {where: {isActive: true}});
74 Station.scope('inactive', {where: {isActive: false}});
75 Station.scope('ground', {where: {isUndeground: true}});
76 Station.active.ground.create(function() {
77 Station.inactive.ground.create(function() {
78 Station.ground.inactive(function(err, ss) {
79 if (err) return done(err);
80 ss.should.have.lengthOf(1);
81 done();
82 });
83 });
84 });
85 });
86
87 it('should not cache any results', function(done) {
88 Station.scope('active', {where: {isActive: true}});
89 Station.active.create(function(err, s) {
90 if (err) return done(err);
91 s.isActive.should.be.true;
92 Station.active(function(err, ss) {
93 if (err) return done(err);
94 ss.should.have.lengthOf(1);
95 ss[0].id.should.eql(s.id);
96 s.updateAttribute('isActive', false, function(err, s) {
97 if (err) return done(err);
98 s.isActive.should.be.false;
99 Station.active(function(err, ss) {
100 if (err) return done(err);
101 ss.should.have.lengthOf(0);
102 done();
103 });
104 });
105 });
106 });
107 });
108});
109
110describe('scope - order', function() {
111 before(function() {
112 db = getSchema();
113 Station = db.define('Station', {
114 name: {type: String, index: true},
115 order: {type: Number, index: true},
116 });
117 Station.scope('reverse', {order: 'order DESC'});
118 });
119
120 beforeEach(function(done) {
121 Station.destroyAll(done);
122 });
123
124 beforeEach(function(done) {
125 Station.create({name: 'a', order: 1}, done);
126 });
127
128 beforeEach(function(done) {
129 Station.create({name: 'b', order: 2}, done);
130 });
131
132 beforeEach(function(done) {
133 Station.create({name: 'c', order: 3}, done);
134 });
135
136 it('should define scope with default order', function(done) {
137 Station.reverse(function(err, stations) {
138 if (err) return done(err);
139 stations[0].name.should.equal('c');
140 stations[0].order.should.equal(3);
141 stations[1].name.should.equal('b');
142 stations[1].order.should.equal(2);
143 stations[2].name.should.equal('a');
144 stations[2].order.should.equal(1);
145 done();
146 });
147 });
148
149 it('should override default scope order', function(done) {
150 Station.reverse({order: 'order ASC'}, function(err, stations) {
151 if (err) return done(err);
152 stations[0].name.should.equal('a');
153 stations[0].order.should.equal(1);
154 stations[1].name.should.equal('b');
155 stations[1].order.should.equal(2);
156 stations[2].name.should.equal('c');
157 stations[2].order.should.equal(3);
158 done();
159 });
160 });
161});
162
163describe('scope - filtered count, updateAll and destroyAll', function() {
164 let stationA;
165
166 before(function() {
167 db = getSchema();
168 Station = db.define('Station', {
169 name: {type: String, index: true},
170 order: {type: Number, index: true},
171 active: {type: Boolean, index: true, default: true},
172 flagged: {type: Boolean, index: true, default: false},
173 });
174 Station.scope('ordered', {order: 'order'});
175 Station.scope('active', {where: {active: true}});
176 Station.scope('inactive', {where: {active: false}});
177 Station.scope('flagged', {where: {flagged: true}});
178 });
179
180 beforeEach(function(done) {
181 Station.destroyAll(done);
182 });
183
184 beforeEach(function(done) {
185 Station.create({name: 'b', order: 2, active: false}, done);
186 });
187
188 beforeEach(function(done) {
189 Station.create({name: 'a', order: 1}, function(err, inst) {
190 if (err) return done(err);
191 stationA = inst;
192 done();
193 });
194 });
195
196 beforeEach(function(done) {
197 Station.create({name: 'd', order: 4, active: false}, done);
198 });
199
200 beforeEach(function(done) {
201 Station.create({name: 'c', order: 3}, done);
202 });
203
204 it('should find all - verify', function(done) {
205 Station.ordered(function(err, stations) {
206 if (err) return done(err);
207 stations.should.have.length(4);
208 stations[0].name.should.equal('a');
209 stations[1].name.should.equal('b');
210 stations[2].name.should.equal('c');
211 stations[3].name.should.equal('d');
212 done();
213 });
214 });
215
216 it('should find one', function(done) {
217 Station.active.findOne(function(err, station) {
218 if (err) return done(err);
219 station.name.should.equal('a');
220 done();
221 });
222 });
223
224 it('should find one - with filter', function(done) {
225 Station.active.findOne({where: {name: 'c'}}, function(err, station) {
226 if (err) return done(err);
227 station.name.should.equal('c');
228 done();
229 });
230 });
231
232 it('should find by id - match', function(done) {
233 Station.active.findById(stationA.id, function(err, station) {
234 if (err) return done(err);
235 station.name.should.equal('a');
236 done();
237 });
238 });
239
240 it('should find by id - no match', function(done) {
241 Station.inactive.findById(stationA.id, function(err, station) {
242 if (err) return done(err);
243 should.not.exist(station);
244 done();
245 });
246 });
247
248 it('should count all in scope - active', function(done) {
249 Station.active.count(function(err, count) {
250 if (err) return done(err);
251 count.should.equal(2);
252 done();
253 });
254 });
255
256 it('should count all in scope - inactive', function(done) {
257 Station.inactive.count(function(err, count) {
258 if (err) return done(err);
259 count.should.equal(2);
260 done();
261 });
262 });
263
264 it('should count filtered - active', function(done) {
265 Station.active.count({order: {gt: 1}}, function(err, count) {
266 if (err) return done(err);
267 count.should.equal(1);
268 done();
269 });
270 });
271
272 it('should count filtered - inactive', function(done) {
273 Station.inactive.count({order: 2}, function(err, count) {
274 if (err) return done(err);
275 count.should.equal(1);
276 done();
277 });
278 });
279
280 it('should allow updateAll', function(done) {
281 Station.inactive.updateAll({flagged: true}, function(err, result) {
282 if (err) return done(err);
283 result.count.should.equal(2);
284 verify();
285 });
286
287 function verify() {
288 Station.flagged.count(function(err, count) {
289 if (err) return done(err);
290 count.should.equal(2);
291 done();
292 });
293 }
294 });
295
296 it('should allow filtered updateAll', function(done) {
297 Station.ordered.updateAll({active: true}, {flagged: true}, function(err, result) {
298 if (err) return done(err);
299 result.count.should.equal(2);
300 verify();
301 });
302
303 function verify() {
304 Station.flagged.count(function(err, count) {
305 if (err) return done(err);
306 count.should.equal(2);
307 done();
308 });
309 }
310 });
311
312 it('should allow filtered destroyAll', function(done) {
313 Station.ordered.destroyAll({active: false}, function(err) {
314 if (err) return done(err);
315 verify();
316 });
317
318 function verify() {
319 Station.ordered.count(function(err, count) {
320 if (err) return done(err);
321 count.should.equal(2);
322 Station.inactive.count(function(err, count) {
323 if (err) return done(err);
324 count.should.equal(0);
325 done();
326 });
327 });
328 }
329 });
330});
331
332describe('scope - dynamic target class', function() {
333 let Collection, Image, Video;
334
335 before(function() {
336 db = getSchema();
337 Image = db.define('Image', {name: String});
338 Video = db.define('Video', {name: String});
339
340 Collection = db.define('Collection', {name: String, modelName: String});
341 Collection.scope('items', function() {
342 return {}; // could return a scope based on `this` (receiver)
343 }, null, {}, {isStatic: false, modelTo: function(receiver) {
344 return db.models[receiver.modelName];
345 }});
346 });
347
348 beforeEach(function(done) {
349 Collection.destroyAll(function() {
350 Image.destroyAll(function() {
351 Video.destroyAll(done);
352 });
353 });
354 });
355
356 beforeEach(function(done) {
357 Collection.create({name: 'Images', modelName: 'Image'}, done);
358 });
359
360 beforeEach(function(done) {
361 Collection.create({name: 'Videos', modelName: 'Video'}, done);
362 });
363
364 beforeEach(function(done) {
365 Collection.create({name: 'Things', modelName: 'Unknown'}, done);
366 });
367
368 beforeEach(function(done) {
369 Image.create({name: 'Image A'}, done);
370 });
371
372 beforeEach(function(done) {
373 Video.create({name: 'Video A'}, done);
374 });
375
376 it('should deduce modelTo at runtime - Image', function(done) {
377 Collection.findOne({where: {modelName: 'Image'}}, function(err, coll) {
378 if (err) return done(err);
379 coll.name.should.equal('Images');
380 coll.items(function(err, items) {
381 if (err) return done(err);
382 items.length.should.equal(1);
383 items[0].name.should.equal('Image A');
384 items[0].should.be.instanceof(Image);
385 done();
386 });
387 });
388 });
389
390 it('should deduce modelTo at runtime - Video', function(done) {
391 Collection.findOne({where: {modelName: 'Video'}}, function(err, coll) {
392 if (err) return done(err);
393 coll.name.should.equal('Videos');
394 coll.items(function(err, items) {
395 if (err) return done(err);
396 items.length.should.equal(1);
397 items[0].name.should.equal('Video A');
398 items[0].should.be.instanceof(Video);
399 done();
400 });
401 });
402 });
403
404 it('should throw if modelTo is invalid', function(done) {
405 Collection.findOne({where: {name: 'Things'}}, function(err, coll) {
406 if (err) return done(err);
407 coll.modelName.should.equal('Unknown');
408 (function() {
409 coll.items(function(err, items) {});
410 }).should.throw();
411 done();
412 });
413 });
414});
415
416describe('scope - dynamic function', function() {
417 let Item, seed = 0;
418
419 before(function() {
420 db = getSchema();
421 Item = db.define('Item', {title: Number, creator: Number});
422 Item.scope('dynamicQuery', function() {
423 seed++;
424 return {where: {creator: seed}};
425 });
426 });
427
428 beforeEach(function(done) {
429 Item.create({title: 1, creator: 1}, function() {
430 Item.create({title: 2, creator: 2}, done);
431 });
432 });
433
434 it('should deduce item by runtime creator', function(done) {
435 Item.dynamicQuery.findOne(function(err, firstQuery) {
436 if (err) return done(err);
437 firstQuery.title.should.equal(1);
438 Item.dynamicQuery.findOne(function(err, secondQuery) {
439 if (err) return done(err);
440 secondQuery.title.should.equal(2);
441 done();
442 });
443 });
444 });
445});