UNPKG

11.4 kBJavaScriptView Raw
1var Runtime = require('../lib/runtime');
2var assert = require('assert');
3var Registry = require('./fixture/mem_registry');
4var EventEmitter = require('events').EventEmitter;
5EventEmitter.prototype._sendLogStreamEvent = function(topic, args, cb) {
6 if(cb) {
7 cb()
8 }
9};
10
11describe('Runtime', function(){
12 describe('Reactive', function(done){
13 var runtime = null;
14 beforeEach(function() {
15 var reg = new Registry();
16 runtime = new Runtime({registry: reg});
17 });
18
19 it('implements the filter method.', function() {
20 assert.ok(runtime.filter);
21 });
22
23 it('implements the map method.', function() {
24 assert.ok(runtime.map);
25 });
26
27 it('implements the zip method.', function() {
28 assert.ok(runtime.zip);
29 });
30
31 it('implements the subscribe method.', function() {
32 assert.ok(runtime.subscribe);
33 });
34
35 it('implements the observe method.', function() {
36 assert.ok(runtime.observe);
37 });
38
39 it('calls the calls the filter method on deviceready', function() {
40 var d = new EventEmitter();
41 d.type = 'test';
42
43 runtime
44 .filter(function(e) {
45 assert.equal(e.type, 'test');
46 done();
47 });
48
49 runtime.emit('deviceready', d);
50 });
51
52 it('calls subscribe when the observable chain is complete.', function(done) {
53 var d = new EventEmitter();
54 d.type = 'test';
55 runtime
56 .subscribe(function(d) {
57 assert.equal(d.type, 'test');
58 done();
59 });
60
61 runtime.emit('deviceready', d);
62 });
63
64 it('calls map on the observable chain when an event occurs', function(done) {
65 var d = new EventEmitter();
66 d.type = 'test';
67
68 runtime
69 .map(function(d) {
70 assert.equal(d.type, 'test');
71 return d;
72 })
73 .subscribe(function(x) {
74 assert.equal(x.type, 'test');
75 done();
76 });
77
78 runtime.emit('deviceready', d);
79
80 });
81
82 it('only calls zip when all conditions are fulfilled.', function(done) {
83 var d1 = new EventEmitter();
84 d1.type = 'test';
85 var d2 = new EventEmitter();
86 d2.type = 'test2';
87
88 var filter2 = runtime.filter(function(d) {
89 return d.type == 'test2';
90 });
91
92 runtime
93 .filter(function(d) {
94 return d.type == 'test';
95 }).zip(filter2, function(){
96 return arguments;
97 })
98 .subscribe(function(x) {
99 assert.equal(x[0].type, 'test');
100 assert.equal(x[1].type, 'test2');
101 done();
102 });
103
104 runtime.emit('deviceready', d1);
105 runtime.emit('deviceready', d2);
106 });
107
108 describe('Runtime#observe', function() {
109 it('returns a Subscription when a subscribe function is provided', function() {
110 var q = runtime.where({ type: 'test' });
111
112 var sub = runtime.observe(q, function(device) {
113 // do nothing
114 });
115
116 assert(typeof(sub.dispose) === 'function');
117 });
118
119 it('returns an Observable when a subscribe function is not provided', function() {
120 var q = runtime.where({ type: 'test' });
121
122 var obs = runtime.observe(q);
123
124 assert(typeof(obs.subscribe) === 'function');
125 });
126
127 it('will take a single query as the first argument', function(done) {
128 var q = runtime.where({ type: 'test' });
129 var d = new EventEmitter();
130 d.type = 'test';
131
132 runtime.observe(q, function(device) {
133 assert.equal(device.type, 'test');
134 done();
135 });
136
137 runtime.emit('deviceready', d);
138 });
139
140 it('will call the observe callback when the query is fullfilled.', function(done) {
141 var q = runtime.where({type: 'test'});
142 var d = new EventEmitter();
143 d.type = 'test';
144 runtime.observe([q], function(device) {
145 assert.equal(device.type, 'test');
146 done();
147 });
148
149 runtime.emit('deviceready', d);
150 });
151
152 it('will call the observe callback when all queries are fullfilled.', function(done) {
153 var q1 = runtime.where({ type: 'test1' });
154 var q2 = runtime.where({ type: 'test2' });
155
156 var d1 = new EventEmitter();
157 d1.type = 'test1';
158 var d2 = new EventEmitter();
159 d2.type = 'test2';
160
161 runtime.observe([q1, q2], function(one, two) {
162 assert.equal(one.type, 'test1');
163 assert.equal(two.type, 'test2');
164 done();
165 });
166
167 runtime.emit('deviceready', d1);
168 runtime.emit('deviceready', d2);
169 });
170
171 it('will call the observe callback when all queries are fullfilled, and when events happen in any order', function(done) {
172 var q1 = runtime.where({ type: 'test1' });
173 var q2 = runtime.where({ type: 'test2' });
174
175 var d1 = new EventEmitter();
176 d1.type = 'test1';
177 var d2 = new EventEmitter();
178 d2.type = 'test2';
179 runtime.observe([q1, q2], function(one, two) {
180 assert.equal(one.type, 'test1');
181 assert.equal(two.type, 'test2');
182 done();
183 });
184
185 runtime.emit('deviceready', d2);
186 runtime.emit('deviceready', d1);
187 });
188
189 it('will fire if a device exists in the registry and doesn\'t call deviceready', function(done) {
190 runtime._jsDevices['1'] = { id: '1', type: 'test1' };
191
192 var q1 = runtime.where({ type: 'test1' });
193 var q2 = runtime.where({ type: 'test2' });
194
195 var d2 = new EventEmitter();
196 d2.type = 'test2';
197
198 runtime.observe([q1, q2], function(one, two) {
199 assert.equal(one.type, 'test1');
200 assert.equal(two.type, 'test2');
201 done();
202 });
203
204 runtime.emit('deviceready', d2);
205 });
206 });
207
208 describe('Device deletion from runtime', function() {
209 it('will delete a remote device from the runtime', function(done) {
210 var peerName = 'hub';
211 var id = '1';
212 var peer = new EventEmitter();
213 peer.subscribe = function() {};
214 peer.name = peerName;
215 var data = { 'properties': { 'id': id }, 'actions': [], 'links': [{'title': 'logs', 'href': 'http://localhost/servers/hub/devices/1?topic=logs', 'rel': []}]};
216 runtime._remoteDevices[peerName] = {};
217 var virtualDevice = runtime._createRemoteDevice(peer, data);
218 virtualDevice._eventEmitter.emit('zetta-device-destroy');
219 setTimeout(function() {
220 assert.ok(!runtime._remoteDevices[peerName][id]);
221 done();
222 }, 100);
223 });
224
225
226 it('will delete a device from the runtime', function(done) {
227 var emitter = new EventEmitter();
228 emitter.id = '1';
229 emitter.type = 'test1';
230 runtime._jsDevices['1'] = emitter;
231 runtime.registry.db.put('1', {'id': '1', 'type': 'test1'}, {valueEncoding: 'json'}, function() {
232 runtime.emit('deviceready', emitter);
233 emitter.emit('destroy', emitter);
234 setTimeout(function() {
235 assert.ok(!runtime._jsDevices.hasOwnProperty('1'));
236 done();
237 }, 100);
238 });
239 });
240
241 it('will delete a device from the runtime using _destroyDevice', function(done) {
242 var emitter = new EventEmitter();
243 emitter.id = '1';
244 emitter.type = 'test1';
245 runtime._jsDevices['1'] = emitter;
246 runtime.registry.db.put('1', {'id': '1', 'type': 'test1'}, {valueEncoding: 'json'}, function() {
247 runtime.emit('deviceready', emitter);
248 runtime._destroyDevice(emitter, function(err) {
249 assert.ok(!err);
250 assert.ok(!runtime._jsDevices.hasOwnProperty('1'));
251 done();
252 });
253 });
254 });
255
256 it('_destroyDevice callback will pass an error if _sendLogStreamEvent is not a function on the device prototype.', function(done) {
257 var emitter = new EventEmitter();
258 emitter.id = '1';
259 emitter.type = 'test1';
260 emitter._sendLogStreamEvent = null;
261 runtime._jsDevices['1'] = emitter;
262 runtime.registry.db.put('1', {'id': '1', 'type': 'test1'}, {valueEncoding: 'json'}, function() {
263 runtime.emit('deviceready', emitter);
264 runtime._destroyDevice(emitter, function(err) {
265 assert.ok(err);
266 assert.equal(err.message, 'Device not compatible');
267 done();
268 });
269 });
270 });
271 });
272
273 describe('Extended reactive syntax', function() {
274 it('will respond the same way using the extended reactive syntax.', function(done) {
275 runtime
276 .filter(function(d) {
277 return d.type === 'test1';
278 })
279 .zip(runtime.filter(function(d){
280 return d.type === 'test2';
281 }), function() {
282 return Array.prototype.slice.call(arguments);
283 })
284 .subscribe(function(x) {
285 var devOne = x[0];
286 var devTwo = x[1];
287 assert.equal(devOne.type, 'test1');
288 assert.equal(devTwo.type, 'test2');
289 done();
290 });
291
292 var d1 = new EventEmitter();
293 d1.type = 'test1';
294 var d2 = new EventEmitter();
295 d2.type = 'test2';
296
297 runtime.emit('deviceready', d1);
298 runtime.emit('deviceready', d2);
299 });
300
301 it('take will only fire with one pair.', function(done) {
302 var emitter = new EventEmitter();
303 var fired = 0;
304 runtime
305 .filter(function(d) {
306 return d.type === 'test1';
307 })
308 .zip(runtime.filter(function(d){
309 return d.type === 'test2';
310 }), function() {
311 return Array.prototype.slice.call(arguments);
312 })
313 .take(1)
314 .subscribe(function(x) {
315 var devOne = x[0];
316 var devTwo = x[1];
317 assert.equal(devOne.type, 'test1');
318 assert.equal(devTwo.type, 'test2');
319 fired++;
320 emitter.on('complete', function() {
321 assert.equal(fired, 1);
322 done();
323 });
324 });
325
326 var d1 = new EventEmitter();
327 d1.type = 'test1';
328 var d2 = new EventEmitter();
329 d2.type = 'test2';
330
331 runtime.emit('deviceready', d1);
332 runtime.emit('deviceready', d2);
333 runtime.emit('deviceready', d1);
334 runtime.emit('deviceready', d2);
335 emitter.emit('complete');
336 });
337
338 it('will only fire take one time', function(done) {
339 var d = new EventEmitter();
340 d.type = 'test';
341 var fired = 0;
342 var emitter = new EventEmitter();
343 runtime
344 .take(1)
345 .subscribe(function(x) {
346 assert.equal(x.type, 'test');
347 fired++;
348 emitter.on('complete', function(){
349 assert.equal(fired, 1);
350 done();
351 });
352 });
353
354 runtime.emit('deviceready', d);
355 emitter.emit('complete');
356 });
357
358 it('will only fire take twice.', function(done) {
359 var d = new EventEmitter();
360 d.type = 'test';
361 var fired = 0;
362 var emitter = new EventEmitter();
363 runtime
364 .take(2)
365 .subscribe(function(x) {
366 assert.equal(x.type, 'test');
367 fired++;
368 if(fired > 1) {
369 emitter.on('complete', function(){
370 assert.equal(fired, 2);
371 done();
372 });
373 }
374 });
375
376 runtime.emit('deviceready', d);
377 runtime.emit('deviceready', d);
378 runtime.emit('deviceready', d);
379 emitter.emit('complete');
380 });
381 });
382 });
383});
384