1 | var Combine = require('../')
|
2 | var test = require('tape')
|
3 |
|
4 | test('combine is a function', function (t) {
|
5 | t.equal(typeof Combine, 'function')
|
6 | t.end()
|
7 | })
|
8 |
|
9 | test('combine one module', function (t) {
|
10 | const cats = {
|
11 | gives: 'cats',
|
12 | create: () => {
|
13 | t.ok(true, 'create is called')
|
14 | return () => () => true
|
15 | }
|
16 | }
|
17 |
|
18 | var api = Combine([cats])
|
19 |
|
20 | t.ok(api.cats, 'Combine returns an object with keys that match the keys given by all the modules')
|
21 | t.end()
|
22 | })
|
23 |
|
24 | test('combine two modules', function (t) {
|
25 | const cats = {
|
26 | gives: 'cats',
|
27 | create: () => {
|
28 | t.ok(true, 'create is called')
|
29 | return () => () => true
|
30 | }
|
31 | }
|
32 |
|
33 | const client = {
|
34 | needs: {cats: 'first'},
|
35 | gives: 'client',
|
36 | create: (api) => {
|
37 | t.ok(api.cats, 'create is called with object that has keys given by other modules')
|
38 | return () => () => true
|
39 | }
|
40 | }
|
41 |
|
42 | var api = Combine([client, cats])
|
43 |
|
44 | t.ok(api.cats && api.client, 'Combine returns an object with keys that match the keys given by all the modules')
|
45 | t.end()
|
46 | })
|
47 |
|
48 | test('combine can take a single module', function (t) {
|
49 | t.plan(1)
|
50 |
|
51 | const cats = {
|
52 | gives: 'cats',
|
53 | create: () => {
|
54 | return () => () => true
|
55 | }
|
56 | }
|
57 |
|
58 | const sockets = Combine(cats)
|
59 |
|
60 | t.ok(sockets.cats, 'Combine returns an object with keys that match the keys given by all the modules')
|
61 | t.end()
|
62 | })
|
63 |
|
64 | test('one module depends on a module that depends on another', function (t) {
|
65 | const a = {
|
66 | needs: {b: 'first'},
|
67 | gives: 'a',
|
68 | create: (api) => api.b
|
69 | }
|
70 | const b = {
|
71 | needs: {c: 'first'},
|
72 | gives: 'b',
|
73 | create: (api) => api.c
|
74 | }
|
75 | const c = {
|
76 | gives: 'c',
|
77 | create: () => () => true
|
78 | }
|
79 |
|
80 | var api = Combine([a, c, b])
|
81 | t.ok(api.a[0]())
|
82 | api = Combine([a, b, c])
|
83 | t.ok(api.a[0]())
|
84 | api = Combine([c, b, a])
|
85 | t.ok(api.a[0]())
|
86 | t.end()
|
87 | })
|
88 |
|
89 | test('two modules depend on each other', function (t) {
|
90 | const cats = {
|
91 | needs: {dogs: 'first'},
|
92 | gives: 'cats',
|
93 | create: (api) => {
|
94 | t.ok(api.dogs, 'api provides the needed dep')
|
95 | return () => true
|
96 | }
|
97 | }
|
98 |
|
99 | const dogs = {
|
100 | needs: {cats: 'first'},
|
101 | gives: 'dogs',
|
102 | create: (api) => {
|
103 | t.ok(api.cats, 'api provides the needed dep')
|
104 | return () => true
|
105 | }
|
106 | }
|
107 | var api = Combine([cats, dogs])
|
108 | t.ok(api.cats && api.dogs, 'Combine returns an object with keys that match the keys given by all the modules')
|
109 | t.end()
|
110 | })
|
111 |
|
112 | test('a module depends on itself', function (t) {
|
113 | const factorial = {
|
114 | needs: {factorial: 'first'},
|
115 | gives: 'factorial',
|
116 | create: (api) => {
|
117 | t.ok(api.factorial, 'api provides the needed dep')
|
118 | return (num) => {
|
119 | if (num === 1) return 1
|
120 | else return num * api.factorial(num - 1)
|
121 | }
|
122 | }
|
123 | }
|
124 |
|
125 | var api = Combine([factorial])
|
126 | t.ok(api.factorial, 'Combine returns an object with keys that match the keys given by all the modules')
|
127 | t.equal(api.factorial[0](4), 24)
|
128 | t.end()
|
129 | })
|
130 |
|
131 | test('throws if need type is not first, map or reduce', function (t) {
|
132 | const cats = {
|
133 | gives: 'cats',
|
134 | create: () => {
|
135 | t.ok(true, 'create is called')
|
136 | return () => () => true
|
137 | }
|
138 | }
|
139 |
|
140 | const client = {
|
141 | needs: {cats: 'nope'},
|
142 | gives: 'client',
|
143 | create: (api) => {
|
144 | t.ok(api.cats, 'create is called with object that has keys given by other modules')
|
145 | return () => ({ client: api.cats })
|
146 | }
|
147 | }
|
148 |
|
149 | t.throws(() => Combine([client, cats]))
|
150 |
|
151 | client.needs.cats = 'first'
|
152 | var api = Combine([client, cats])
|
153 | t.ok(api, 'needs first is ok')
|
154 |
|
155 | client.needs.cats = 'map'
|
156 | api = Combine([client, cats])
|
157 | t.ok(api, 'needs map is ok')
|
158 |
|
159 | client.needs.cats = 'reduce'
|
160 | api = Combine([client, cats])
|
161 | t.ok(api, 'needs reduce is ok')
|
162 |
|
163 | t.end()
|
164 | })
|
165 |
|
166 | test('when a module needs a map of dependencies it receives an array of all the modules', function (t) {
|
167 | const a = {
|
168 | needs: {ideas: 'map'},
|
169 | gives: 'a',
|
170 | create: (api) => api.ideas
|
171 | }
|
172 | const b = {
|
173 | gives: 'ideas',
|
174 | create: () => () => 'sink'
|
175 | }
|
176 | const c = {
|
177 | gives: 'ideas',
|
178 | create: () => () => 'swim'
|
179 | }
|
180 |
|
181 | var api = Combine([a, b, c])
|
182 | t.ok(Array.isArray(api.a[0]()))
|
183 | t.end()
|
184 | })
|
185 |
|
186 | test('when a module needs the first of dependencies it receives the first module to return a value', function (t) {
|
187 | const a = {
|
188 | needs: {ideas: 'first'},
|
189 | gives: 'a',
|
190 | create: (api) => api.ideas
|
191 | }
|
192 | const b = {
|
193 | gives: 'ideas',
|
194 | create: () => () => {}
|
195 | }
|
196 | const c = {
|
197 | gives: 'ideas',
|
198 | create: () => () => 'swim'
|
199 | }
|
200 |
|
201 | var api = Combine([a, b, c])
|
202 | t.equal(api.a[0](), 'swim')
|
203 | t.end()
|
204 | })
|
205 |
|
206 | test('when a module needs the first of dependencies it receives the first module to return a value. Depends on order passed to combine', function (t) {
|
207 | const a = {
|
208 | needs: {ideas: 'first'},
|
209 | gives: 'a',
|
210 | create: (api) => api.ideas
|
211 | }
|
212 | const b = {
|
213 | gives: 'ideas',
|
214 | create: () => () => 'sink'
|
215 | }
|
216 | const c = {
|
217 | gives: 'ideas',
|
218 | create: () => () => 'swim'
|
219 | }
|
220 |
|
221 | var api = Combine([a, b, c])
|
222 | t.equal(api.a[0](), 'sink')
|
223 | t.end()
|
224 | })
|
225 |
|
226 | test('when a module needs the reduce of dependencies it receives the result of applying all', function (t) {
|
227 | const a = {
|
228 | needs: {ideas: 'reduce'},
|
229 | gives: 'a',
|
230 | create: (api) => api.ideas
|
231 | }
|
232 | const b = {
|
233 | gives: 'ideas',
|
234 | create: () => (ideas) => ideas + 'sink'
|
235 | }
|
236 | const c = {
|
237 | gives: 'ideas',
|
238 | create: () => (ideas) => ideas + 'swim'
|
239 | }
|
240 |
|
241 | var api = Combine([a, b, c])
|
242 | t.equal(api.a[0](''), 'sinkswim')
|
243 | api = Combine([a, c, b])
|
244 | t.equal(api.a[0](''), 'swimsink', 'ordering works correctly')
|
245 | t.end()
|
246 | })
|
247 |
|
248 | test('a module can give multiple exports', function (t) {
|
249 | const a = {
|
250 | gives: {ideas: true, thoughts: true},
|
251 | create: () => ({
|
252 | ideas: () => 'idea',
|
253 | thoughts: () => 'thought'
|
254 | })
|
255 | }
|
256 |
|
257 | var api = Combine([a])
|
258 | t.ok(api.ideas && api.thoughts)
|
259 | t.end()
|
260 | })
|
261 |
|
262 | test('a module can need multiple imports', function (t) {
|
263 | const a = {
|
264 | needs: {ideas: 'first', thoughts: 'first'},
|
265 | gives: 'a',
|
266 | create: (api) => () => api.ideas() + api.thoughts()
|
267 | }
|
268 |
|
269 | const b = {
|
270 | gives: 'ideas',
|
271 | create: () => () => 'idea'
|
272 | }
|
273 | const c = {
|
274 | gives: 'thoughts',
|
275 | create: () => () => 'thought'
|
276 | }
|
277 |
|
278 | var api = Combine([a, b, c])
|
279 | t.equal(api.a[0](), 'ideathought')
|
280 | t.end()
|
281 | })
|
282 |
|
283 | test('a needed module can return 0', function (t) {
|
284 | t.plan(2)
|
285 |
|
286 | const decrement = {
|
287 | gives: 'decrement',
|
288 | create: () => i => i - 1
|
289 | }
|
290 |
|
291 | const decrementOne = {
|
292 | gives: 'decrementOne',
|
293 | needs: {decrement: 'first'},
|
294 | create: api => () => api.decrement(1)
|
295 | }
|
296 |
|
297 | const sockets = Combine([decrement, decrementOne])
|
298 |
|
299 | t.equal(sockets.decrement[0](1), 0, 'decrement returns zero')
|
300 | t.equal(sockets.decrementOne[0](), 0, 'decrementOne returns zero')
|
301 | t.end()
|
302 | })
|
303 |
|
304 | test('throws an error when a needed module is not given', function (t) {
|
305 | const a = {
|
306 | needs: {ideas: 'first'},
|
307 | create: (api) => api.b
|
308 | }
|
309 | t.throws(() => Combine([a]), /unmet need/)
|
310 | t.end()
|
311 | })
|
312 |
|
313 | test('map throws an error when no functions are provided to map', function (t) {
|
314 | const a = {
|
315 | gives: 'a',
|
316 | needs: {ideas: 'map'},
|
317 | create: (api) => api.ideas()
|
318 | }
|
319 | const b = {
|
320 | gives: 'ideas',
|
321 | create: (api) => null
|
322 | }
|
323 | t.throws(() => Combine([a, b]), /no functions available/)
|
324 |
|
325 | t.end()
|
326 | })
|
327 |
|
328 | test('reduce throws an error when no functions are provided to reduce', function (t) {
|
329 | const a = {
|
330 | gives: 'a',
|
331 | needs: {ideas: 'reduce'},
|
332 | create: (api) => api.ideas()
|
333 | }
|
334 | const b = {
|
335 | gives: 'ideas',
|
336 | create: (api) => null
|
337 | }
|
338 | t.throws(() => Combine([a, b]), /no functions available/)
|
339 |
|
340 | t.end()
|
341 | })
|
342 |
|
343 | test('first throws an error when no functions are provided to take first', function (t) {
|
344 | const a = {
|
345 | needs: {ideas: 'first'},
|
346 | create: (api) => api.ideas()
|
347 | }
|
348 | const b = {
|
349 | gives: 'ideas',
|
350 | create: (api) => null
|
351 | }
|
352 | t.throws(() => Combine([a, b]), /no functions available/)
|
353 |
|
354 | t.end()
|
355 | })
|
356 |
|
357 | test('combine throws an error when module does not have a create function', function (t) {
|
358 | t.throws(() => Combine([{}]), /could not resolve any modules/)
|
359 | t.end()
|
360 | })
|
361 |
|
362 | test('combine throws an error when not passed anything', function (t) {
|
363 | t.throws(() => Combine(), /could not resolve any modules/)
|
364 | t.end()
|
365 | })
|
366 |
|
367 | test('combine throws an error when passed a module with a create but no gives', function (t) {
|
368 | const a = {
|
369 | create: (api) => () => true
|
370 | }
|
371 | t.throws(() => Combine([a]), /could not resolve any modules/)
|
372 | t.end()
|
373 | })
|
374 |
|
375 | test('combine throws an error when passed a module with a create when gives a string', function (t) {
|
376 | const a = {
|
377 | gives: 'nope',
|
378 | create: (api) => {}
|
379 | }
|
380 | t.throws(() => Combine([a]), /create function should return a function or an object/)
|
381 | t.end()
|
382 | })
|
383 |
|
384 | test('combine throws an error when passed a module with a create when gives is an object', function (t) {
|
385 | const a = {
|
386 | gives: {nope: true},
|
387 | create: (api) => {}
|
388 | }
|
389 | t.throws(() => Combine([a]), /create function should return a function or an object/)
|
390 | t.end()
|
391 | })
|
392 |
|
\ | No newline at end of file |