UNPKG

5.31 kBJavaScriptView Raw
1/* eslint-disable */
2'use strict';
3/* global describe, it */
4let assert = require('assert');
5let Cycle = require('../lib/index').default;
6let Rx = require('rx');
7let sinon = require('sinon');
8
9describe('Cycle', function () {
10 it('should have `run`', function () {
11 assert.strictEqual(typeof Cycle.run, 'function');
12 });
13
14 it('should throw if first argument is not a function', function () {
15 assert.throws(() => {
16 Cycle('not a function');
17 }, /First argument given to Cycle must be the 'main' function/i);
18 });
19
20 it('should throw if second argument is not an object', function () {
21 assert.throws(() => {
22 Cycle(() => {}, 'not an object');
23 }, /Second argument given to Cycle must be an object with driver functions/i);
24 });
25
26 it('should throw if second argument is an empty object', function () {
27 assert.throws(() => {
28 Cycle(() => {}, {});
29 }, /Second argument given to Cycle must be an object with at least one/i);
30 });
31
32 it('should return sinks object and sources object', function () {
33 function app(ext) {
34 return {
35 other: ext.other.take(1).startWith('a')
36 };
37 }
38 function driver() {
39 return Rx.Observable.just('b');
40 }
41 let {sinks, sources} = Cycle(app, {other: driver});
42 assert.strictEqual(typeof sinks, 'object');
43 assert.strictEqual(typeof sinks.other.subscribe, 'function');
44 assert.strictEqual(typeof sources, 'object');
45 assert.notStrictEqual(typeof sources.other, 'undefined');
46 assert.notStrictEqual(sources.other, null);
47 assert.strictEqual(typeof sources.other.subscribe, 'function');
48 });
49
50 it('should return a run() which in turn returns a dispose()', function (done) {
51 function app(sources) {
52 return {
53 other: sources.other.take(6).map(x => String(x)).startWith('a')
54 };
55 }
56 function driver(sink) {
57 return sink.map(x => x.charCodeAt(0)).delay(1);
58 }
59 let {sinks, sources, run} = Cycle(app, {other: driver});
60 let dispose;
61 sources.other.subscribe(x => {
62 assert.strictEqual(x, 97);
63 dispose();
64 done();
65 });
66 dispose = run();
67 });
68
69 it('should not work after has been disposed', function (done) {
70 let number$ = Rx.Observable.range(1, 3)
71 .concatMap(x => Rx.Observable.just(x).delay(50));
72 function app() {
73 return {other: number$};
74 }
75 let {sinks, sources, run} = Cycle(app, {
76 other: number$ => number$.map(number => 'x' + number)
77 });
78 let dispose;
79 sources.other.subscribe(function (x) {
80 assert.notStrictEqual(x, 'x3');
81 if (x === 'x2') {
82 dispose();
83 setTimeout(() => {
84 done();
85 }, 100);
86 }
87 });
88 dispose = run();
89 });
90
91 describe('run()', function () {
92 it('should throw if first argument is not a function', function () {
93 assert.throws(() => {
94 Cycle.run('not a function');
95 }, /First argument given to Cycle must be the 'main' function/i);
96 });
97
98 it('should throw if second argument is not an object', function () {
99 assert.throws(() => {
100 Cycle.run(() => {}, 'not an object');
101 }, /Second argument given to Cycle must be an object with driver functions/i);
102 });
103
104 it('should throw if second argument is an empty object', function () {
105 assert.throws(() => {
106 Cycle.run(() => {}, {});
107 }, /Second argument given to Cycle must be an object with at least one/i);
108 });
109
110 it('should return a dispose function', function () {
111 let sandbox = sinon.sandbox.create();
112 const spy = sandbox.spy();
113 function app(ext) {
114 return {
115 other: ext.other.take(1).startWith('a')
116 };
117 }
118 function driver() {
119 return Rx.Observable.just('b').doOnNext(spy);
120 }
121 let dispose = Cycle.run(app, {other: driver});
122 assert.strictEqual(typeof dispose, 'function');
123 sinon.assert.calledOnce(spy);
124 dispose();
125 });
126
127 it('should happen synchronously', function (done) {
128 let sandbox = sinon.sandbox.create();
129 const spy = sandbox.spy();
130 function app(sources) {
131 sources.other.subscribe();
132 return {
133 other: Rx.Observable.of(10),
134 };
135 }
136 let mutable = 'correct';
137 function driver(sink) {
138 return sink.map(x => 'a' + 10).doOnNext(x => {
139 assert.strictEqual(x, 'a10');
140 assert.strictEqual(mutable, 'correct');
141 spy();
142 });
143 }
144 Cycle.run(app, {other: driver});
145 mutable = 'wrong';
146 setTimeout(() => {
147 sinon.assert.calledOnce(spy);
148 done();
149 }, 20);
150 });
151
152 it('should report errors from main() in the console', function (done) {
153 let sandbox = sinon.sandbox.create();
154 sandbox.stub(console, "error");
155
156 function main(sources) {
157 return {
158 other: sources.other.take(1).startWith('a').map(() => {
159 throw new Error('malfunction');
160 })
161 };
162 }
163 function driver() {
164 return Rx.Observable.just('b');
165 }
166
167 Cycle.run(main, {other: driver});
168 setTimeout(() => {
169 sinon.assert.calledOnce(console.error);
170 sinon.assert.calledWithExactly(console.error, sinon.match("malfunction"));
171
172 sandbox.restore();
173 done();
174 }, 20);
175 });
176 });
177});