1 |
|
2 | 'use strict';
|
3 |
|
4 | let assert = require('chai').assert;
|
5 | let File = require('../lib/file');
|
6 | let Tree = require('../lib/tree');
|
7 |
|
8 | describe('Tree()', function () {
|
9 | it('should be a constructor function', function () {
|
10 | assert.instanceOf(new Tree(), Tree);
|
11 | });
|
12 |
|
13 | it('should be empty by default', function () {
|
14 | let tree = new Tree();
|
15 | assert.equal(tree.size(), 0);
|
16 | });
|
17 |
|
18 | describe('#hasFile(location)', function () {
|
19 | let tree = new Tree();
|
20 | tree.addFile('a');
|
21 |
|
22 | it('should return false for a missing node', function () {
|
23 | assert.isFalse(tree.hasFile('z'));
|
24 | });
|
25 |
|
26 | it('should return true for an existing node', function () {
|
27 | assert.isTrue(tree.hasFile('a'));
|
28 | });
|
29 | });
|
30 |
|
31 | describe('#addFile(location, [entry])', function () {
|
32 | it('should add a new vertex', function () {
|
33 | let tree = new Tree();
|
34 | tree.addFile('a');
|
35 |
|
36 | assert.isTrue(tree.hasFile('a'));
|
37 | });
|
38 |
|
39 | it('should not overwrite the file object', function () {
|
40 | let tree = new Tree();
|
41 | let file1 = tree.addFile('a');
|
42 | let file2 = tree.addFile('a');
|
43 |
|
44 | assert.strictEqual(file1, file2);
|
45 | });
|
46 |
|
47 | context('with entry', function () {
|
48 | it('should set the file as an entry', function () {
|
49 | let tree = new Tree();
|
50 | let a = tree.addFile('a', true);
|
51 |
|
52 | assert.isTrue(a.entry);
|
53 | });
|
54 |
|
55 | it('should leave the file as not an entry by default', function () {
|
56 | let tree = new Tree();
|
57 | let a = tree.addFile('a');
|
58 |
|
59 | assert.isFalse(a.entry);
|
60 | });
|
61 | });
|
62 | });
|
63 |
|
64 | describe('#getFile(location)', function () {
|
65 | let tree = new Tree();
|
66 | tree.addFile('a');
|
67 |
|
68 | it('should return a file instance', function () {
|
69 | let file = tree.getFile('a');
|
70 | assert.instanceOf(file, File);
|
71 | assert.strictEqual(file.path, 'a');
|
72 | });
|
73 |
|
74 | it('should throw when the file does not exist', function () {
|
75 | assert.isUndefined(tree.getFile('z'));
|
76 | });
|
77 | });
|
78 |
|
79 | describe('#getFiles([options])', function () {
|
80 |
|
81 |
|
82 | let tree = new Tree();
|
83 | tree.addFile('a');
|
84 | tree.addFile('b');
|
85 | tree.addFile('c');
|
86 | tree.addFile('d');
|
87 | tree.addFile('e');
|
88 | tree.addDependency('a', 'b');
|
89 | tree.addDependency('a', 'e');
|
90 | tree.addDependency('b', 'c');
|
91 | tree.addDependency('c', 'd');
|
92 |
|
93 | it('should return a list of all the files in the tree', function () {
|
94 | assert.deepEqual(tree.getFiles(), [ 'a', 'b', 'c', 'd', 'e' ]);
|
95 | });
|
96 |
|
97 | context('with options', function () {
|
98 | context('.topological', function () {
|
99 | it('should sort the results topologically', function () {
|
100 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'd', 'e', 'c', 'b', 'a' ]);
|
101 | });
|
102 | });
|
103 |
|
104 | context('.objects', function () {
|
105 | it('should return the file objects', function () {
|
106 | tree.getFiles({ objects: true }).forEach(file => assert.instanceOf(file, File));
|
107 | });
|
108 |
|
109 | it('should even work with options.topological', function () {
|
110 | tree.getFiles({ topological: true, objects: true }).forEach(file => assert.instanceOf(file, File));
|
111 | });
|
112 | });
|
113 | });
|
114 | });
|
115 |
|
116 | describe('#removeFile(location, [options])', function () {
|
117 | it('should remove the file from the tree', function () {
|
118 | let tree = new Tree();
|
119 | tree.addFile('a');
|
120 | tree.removeFile('a');
|
121 |
|
122 | assert.isFalse(tree.hasFile('a'));
|
123 | });
|
124 |
|
125 | it('should fail if there are still dependencies defined', function () {
|
126 |
|
127 | let tree = new Tree();
|
128 | tree.addFile('a');
|
129 | tree.addFile('b');
|
130 | tree.addDependency('a', 'b');
|
131 |
|
132 | assert.throws(function () {
|
133 | tree.removeFile('a');
|
134 | });
|
135 | });
|
136 |
|
137 | context('with options', function () {
|
138 | context('.force', function () {
|
139 |
|
140 | let tree = new Tree();
|
141 | tree.addFile('a');
|
142 | tree.addFile('b');
|
143 | tree.addDependency('a', 'b');
|
144 |
|
145 | tree.removeFile('a', { force: true });
|
146 | assert.isFalse(tree.hasFile('a'));
|
147 | assert.isTrue(tree.hasFile('b'));
|
148 | });
|
149 | });
|
150 | });
|
151 |
|
152 | describe('#getEntries([options])', function () {
|
153 | it('should return an empty list', function () {
|
154 | let tree = new Tree();
|
155 | assert.deepEqual(tree.getEntries(), []);
|
156 | });
|
157 |
|
158 | it('should return only the top-level entry', function () {
|
159 |
|
160 |
|
161 | let tree = new Tree();
|
162 | tree.addFile('a', true);
|
163 | tree.addFile('b');
|
164 | tree.addFile('c');
|
165 | tree.addFile('d');
|
166 | tree.addDependency('a', 'b');
|
167 | tree.addDependency('a', 'd');
|
168 | tree.addDependency('b', 'c');
|
169 |
|
170 | assert.deepEqual(tree.getEntries(), [ 'a' ]);
|
171 | });
|
172 |
|
173 | it('should return all the top-level entries', function () {
|
174 |
|
175 |
|
176 | let tree = new Tree();
|
177 | tree.addFile('a', true);
|
178 | tree.addFile('b');
|
179 | tree.addFile('c', true);
|
180 | tree.addFile('d');
|
181 | tree.addFile('e');
|
182 | tree.addDependency('a', 'b');
|
183 | tree.addDependency('c', 'd');
|
184 | tree.addDependency('d', 'e');
|
185 |
|
186 | assert.deepEqual(tree.getEntries(), [ 'a', 'c' ]);
|
187 | });
|
188 |
|
189 | context('with options', function () {
|
190 |
|
191 |
|
192 | let tree = new Tree();
|
193 | tree.addFile('a', true);
|
194 | tree.addFile('b');
|
195 | tree.addFile('c', true);
|
196 | tree.addFile('d');
|
197 | tree.addFile('e');
|
198 | tree.addDependency('a', 'b');
|
199 | tree.addDependency('c', 'd');
|
200 | tree.addDependency('d', 'e');
|
201 |
|
202 | context('.from', function () {
|
203 | it('should only return all the linked entries', function () {
|
204 | assert.deepEqual(tree.getEntries({ from: 'e' }), [ 'c' ]);
|
205 | });
|
206 | });
|
207 |
|
208 | context('.objects', function () {
|
209 | it('should return the file objects', function () {
|
210 | tree.getEntries({ objects: true }).forEach(file => assert.instanceOf(file, File));
|
211 | });
|
212 | });
|
213 | });
|
214 | });
|
215 |
|
216 | describe('#isEntry(location)', function () {
|
217 |
|
218 | let tree = new Tree();
|
219 | tree.addFile('a', true);
|
220 | tree.addFile('b');
|
221 | tree.addDependency('a', 'b');
|
222 |
|
223 | it('should return true when the file is flagged as an entry', function () {
|
224 | assert.isTrue(tree.isEntry('a'));
|
225 | });
|
226 |
|
227 | it('should return false when the file is not flagged as an entry', function () {
|
228 | assert.isFalse(tree.isEntry('b'));
|
229 | });
|
230 | });
|
231 |
|
232 | describe('#hasDependency(parent, child)', function () {
|
233 |
|
234 | let tree = new Tree();
|
235 | tree.addFile('a');
|
236 | tree.addFile('b');
|
237 | tree.addDependency('a', 'b');
|
238 |
|
239 | it('should return false for a missing dependency', function () {
|
240 | assert.isFalse(tree.hasDependency('a', 'z'));
|
241 | });
|
242 |
|
243 | it('should return true for an existing dependency', function () {
|
244 | assert.isTrue(tree.hasDependency('a', 'b'));
|
245 | });
|
246 | });
|
247 |
|
248 | describe('#addDependency(parent, child)', function () {
|
249 | it('should create an edge between the parent and child', function () {
|
250 | let tree = new Tree();
|
251 | tree.addFile('a');
|
252 | tree.addFile('b');
|
253 | tree.addDependency('a', 'b');
|
254 |
|
255 | assert.isTrue(tree.hasDependency('a', 'b'));
|
256 | });
|
257 |
|
258 | it('should throw if the parent was not already defined', function () {
|
259 | let tree = new Tree();
|
260 |
|
261 | assert.throws(function () {
|
262 | tree.addDependency('a', 'b');
|
263 | });
|
264 | });
|
265 |
|
266 | it('should automatically create the child if not previously defined', function () {
|
267 | let tree = new Tree();
|
268 | tree.addFile('a');
|
269 | tree.addDependency('a', 'b');
|
270 |
|
271 | assert.isTrue(tree.hasFile('b'));
|
272 | });
|
273 |
|
274 | it('should return the new child object', function () {
|
275 | let tree = new Tree();
|
276 | tree.addFile('a');
|
277 | let child = tree.addDependency('a', 'b');
|
278 |
|
279 | assert.strictEqual(tree.getFile('b'), child);
|
280 | });
|
281 |
|
282 | it('should not clobber the child object', function () {
|
283 | let tree = new Tree();
|
284 | tree.addFile('a');
|
285 | let file1 = tree.addFile('b');
|
286 | let file2 = tree.addDependency('a', 'b');
|
287 |
|
288 | assert.strictEqual(file1, file2);
|
289 | });
|
290 | });
|
291 |
|
292 | describe('#removeDependency(parent, child)', function () {
|
293 | it('should remove the edge from the graph', function () {
|
294 |
|
295 | let tree = new Tree();
|
296 | tree.addFile('a');
|
297 | tree.addFile('b');
|
298 | tree.addDependency('a', 'b');
|
299 |
|
300 |
|
301 | tree.removeDependency('a', 'b');
|
302 |
|
303 | assert.isFalse(tree.hasDependency('a', 'b'));
|
304 | });
|
305 | });
|
306 |
|
307 | describe('#removeDependencies(parent)', function () {
|
308 | it('should remove the link between parent and all children', function () {
|
309 |
|
310 |
|
311 | let tree = new Tree();
|
312 | tree.addFile('a', true);
|
313 | tree.addFile('b');
|
314 | tree.addFile('c');
|
315 | tree.addDependency('a', 'b');
|
316 | tree.addDependency('a', 'c');
|
317 |
|
318 | tree.removeDependencies('a');
|
319 |
|
320 | assert.isTrue(tree.hasFile('a'));
|
321 | assert.isTrue(tree.hasFile('b'));
|
322 | assert.isTrue(tree.hasFile('c'));
|
323 | assert.isFalse(tree.hasDependency('a', 'b'));
|
324 | assert.isFalse(tree.hasDependency('a', 'c'));
|
325 | });
|
326 | });
|
327 |
|
328 | describe('#dependenciesOf(node, [options])', function () {
|
329 |
|
330 | let tree = new Tree();
|
331 | tree.addFile('a');
|
332 | tree.addFile('b');
|
333 | tree.addFile('c');
|
334 | tree.addFile('d');
|
335 | tree.addDependency('a', 'b');
|
336 | tree.addDependency('b', 'c');
|
337 | tree.addDependency('c', 'd');
|
338 |
|
339 | it('should return the direct dependencies of node', function () {
|
340 | assert.deepEqual(tree.dependenciesOf('a'), [ 'b' ]);
|
341 | });
|
342 |
|
343 | context('with options', function () {
|
344 | context('.recursive', function () {
|
345 | it('should all the dependencies of node', function () {
|
346 | assert.deepEqual(tree.dependenciesOf('a', { recursive: true }), [ 'b', 'c', 'd' ]);
|
347 | });
|
348 | });
|
349 |
|
350 | context('.objects', function () {
|
351 | it('should return the file objects', function () {
|
352 | tree.dependenciesOf('a', { objects: true }).forEach(file => assert.instanceOf(file, File));
|
353 | });
|
354 | });
|
355 | });
|
356 | });
|
357 |
|
358 | describe('#hasDependant(child, parent)', function () {
|
359 |
|
360 | let tree = new Tree();
|
361 | tree.addFile('a');
|
362 | tree.addFile('b');
|
363 | tree.addDependant('b', 'a');
|
364 |
|
365 | it('should return false for a missing dependency', function () {
|
366 | assert.isFalse(tree.hasDependant('b', 'z'));
|
367 | });
|
368 |
|
369 | it('should return true for an existing dependency', function () {
|
370 | assert.isTrue(tree.hasDependant('b', 'a'));
|
371 | });
|
372 | });
|
373 |
|
374 | describe('#addDependant(child, parent)', function () {
|
375 | it('should create an edge between the child and parent', function () {
|
376 |
|
377 | let tree = new Tree();
|
378 | tree.addFile('a');
|
379 | tree.addFile('b');
|
380 | tree.addDependant('b', 'a');
|
381 |
|
382 | assert.isTrue(tree.hasDependant('b', 'a'));
|
383 | });
|
384 |
|
385 | it('should throw if the parent was not already defined', function () {
|
386 | let tree = new Tree();
|
387 |
|
388 | assert.throws(function () {
|
389 | tree.addDependant('b', 'a');
|
390 | });
|
391 | });
|
392 |
|
393 | it('should automatically create the parent if not previously defined', function () {
|
394 | let tree = new Tree();
|
395 | tree.addFile('b');
|
396 | tree.addDependant('b', 'a');
|
397 |
|
398 | assert.isTrue(tree.hasFile('a'));
|
399 | });
|
400 |
|
401 | it('should return the new parent object', function () {
|
402 | let tree = new Tree();
|
403 | tree.addFile('b');
|
404 | let child = tree.addDependant('b', 'a');
|
405 |
|
406 | assert.strictEqual(tree.getFile('a'), child);
|
407 | });
|
408 |
|
409 | it('should not clobber the child object', function () {
|
410 |
|
411 | let tree = new Tree();
|
412 | tree.addFile('b');
|
413 | let file1 = tree.addFile('a');
|
414 | let file2 = tree.addDependant('b', 'a');
|
415 |
|
416 | assert.strictEqual(file1, file2);
|
417 | });
|
418 | });
|
419 |
|
420 | describe('#removeDependant(child, parent)', function () {
|
421 | it('should remove the edge from the graph', function () {
|
422 |
|
423 | let tree = new Tree();
|
424 | tree.addFile('a');
|
425 | tree.addFile('b');
|
426 | tree.addDependant('b', 'a');
|
427 |
|
428 |
|
429 | tree.removeDependant('b', 'a');
|
430 |
|
431 | assert.isFalse(tree.hasDependant('b', 'a'));
|
432 | });
|
433 | });
|
434 |
|
435 | describe('#removeDependants(child)', function () {
|
436 | it('should remove the link between child and all parents', function () {
|
437 |
|
438 |
|
439 | let tree = new Tree();
|
440 | tree.addFile('a', true);
|
441 | tree.addFile('b', true);
|
442 | tree.addFile('c');
|
443 | tree.addDependant('c', 'a');
|
444 | tree.addDependant('c', 'b');
|
445 |
|
446 | tree.removeDependants('c');
|
447 |
|
448 | assert.isTrue(tree.hasFile('a'));
|
449 | assert.isTrue(tree.hasFile('b'));
|
450 | assert.isTrue(tree.hasFile('c'));
|
451 | assert.isFalse(tree.hasDependant('c', 'a'));
|
452 | assert.isFalse(tree.hasDependant('c', 'b'));
|
453 | });
|
454 | });
|
455 |
|
456 | describe('#dependantsOf(node, [options])', function () {
|
457 |
|
458 | let tree = new Tree();
|
459 | tree.addFile('a');
|
460 | tree.addFile('b');
|
461 | tree.addFile('c');
|
462 | tree.addFile('d');
|
463 | tree.addDependency('a', 'b');
|
464 | tree.addDependency('b', 'c');
|
465 | tree.addDependency('c', 'd');
|
466 |
|
467 | it('should return the direct dependencies of node', function () {
|
468 | assert.deepEqual(tree.dependantsOf('d'), [ 'c' ]);
|
469 | });
|
470 |
|
471 | context('with options', function () {
|
472 | context('.recursive', function () {
|
473 | it('should all the dependencies of node', function () {
|
474 | assert.deepEqual(tree.dependantsOf('d', { recursive: true }), [ 'c', 'b', 'a' ]);
|
475 | });
|
476 | });
|
477 |
|
478 | context('.objects', function () {
|
479 | it('should return the file objects', function () {
|
480 | tree.dependantsOf('d', { objects: true }).forEach(file => assert.instanceOf(file, File));
|
481 | });
|
482 | });
|
483 | });
|
484 | });
|
485 |
|
486 | describe('#size()', function () {
|
487 |
|
488 |
|
489 | let tree = new Tree();
|
490 | tree.addFile('a');
|
491 | tree.addFile('b');
|
492 | tree.addFile('c');
|
493 | tree.addDependency('a', 'b');
|
494 | tree.addDependency('a', 'c');
|
495 |
|
496 | it('should return the number of files in the tree', function () {
|
497 | assert.strictEqual(tree.size(), 3);
|
498 | });
|
499 | });
|
500 |
|
501 | describe('#clone()', function () {
|
502 |
|
503 |
|
504 | let tree = new Tree();
|
505 | tree.addFile('a');
|
506 | tree.addFile('b');
|
507 | tree.addFile('c');
|
508 | tree.addDependency('a', 'b');
|
509 | tree.addDependency('a', 'c');
|
510 |
|
511 | it('should make a clone of the original', function () {
|
512 | let clone = tree.clone();
|
513 |
|
514 | assert.notStrictEqual(tree, clone);
|
515 | assert.instanceOf(clone, Tree);
|
516 | assert.strictEqual(tree.size(), clone.size());
|
517 | assert.deepEqual(tree.getFiles({ topolical: true }), clone.getFiles({ topolical: true }));
|
518 | });
|
519 | });
|
520 |
|
521 | describe('#prune([entries])', function () {
|
522 | it('should only remove orphaned files', function () {
|
523 |
|
524 |
|
525 | let tree = new Tree();
|
526 | tree.addFile('a', true);
|
527 | tree.addFile('b');
|
528 | tree.addFile('c');
|
529 | tree.addDependency('a', 'b');
|
530 |
|
531 | tree.prune();
|
532 |
|
533 | assert.strictEqual(tree.size(), 2);
|
534 | assert.isFalse(tree.hasFile('c'));
|
535 | });
|
536 |
|
537 | it('should recursively remove orphaned trees', function () {
|
538 |
|
539 |
|
540 | let tree = new Tree();
|
541 | tree.addFile('a', true);
|
542 | tree.addFile('b');
|
543 | tree.addFile('c');
|
544 | tree.addFile('d');
|
545 | tree.addDependency('a', 'b');
|
546 | tree.addDependency('c', 'd');
|
547 |
|
548 | tree.prune();
|
549 |
|
550 | assert.strictEqual(tree.size(), 2);
|
551 | assert.isFalse(tree.hasFile('c'));
|
552 | assert.isFalse(tree.hasFile('d'));
|
553 | });
|
554 |
|
555 | it('should not remove dependencies that are still depended on elsewhere', function () {
|
556 |
|
557 |
|
558 | let tree = new Tree();
|
559 | tree.addFile('a', true);
|
560 | tree.addFile('b');
|
561 | tree.addFile('c');
|
562 | tree.addFile('d');
|
563 | tree.addDependency('a', 'b');
|
564 | tree.addDependency('b', 'c');
|
565 | tree.addDependency('d', 'b');
|
566 |
|
567 | tree.prune();
|
568 |
|
569 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'c', 'b', 'a' ]);
|
570 | });
|
571 |
|
572 | it('should properly handle a complex case', function () {
|
573 |
|
574 |
|
575 | let tree = new Tree();
|
576 | tree.addFile('a', true);
|
577 | tree.addFile('b');
|
578 | tree.addFile('c');
|
579 | tree.addFile('d');
|
580 | tree.addFile('e');
|
581 | tree.addFile('f');
|
582 | tree.addDependency('a', 'b');
|
583 | tree.addDependency('b', 'c');
|
584 | tree.addDependency('c', 'd');
|
585 | tree.addDependency('e', 'f');
|
586 | tree.addDependency('f', 'c');
|
587 |
|
588 | tree.prune();
|
589 |
|
590 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'd', 'c', 'b', 'a' ]);
|
591 | });
|
592 |
|
593 | context('with entries', function () {
|
594 | it('should prune anything that cannot reach the provided list of files', function () {
|
595 |
|
596 |
|
597 | let tree = new Tree();
|
598 | tree.addFile('a', true);
|
599 | tree.addFile('b');
|
600 | tree.addFile('c', true);
|
601 | tree.addFile('d');
|
602 | tree.addDependency('a', 'b');
|
603 | tree.addDependency('c', 'd');
|
604 |
|
605 | tree.prune([ 'c' ]);
|
606 |
|
607 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'd', 'c' ]);
|
608 | });
|
609 | });
|
610 | });
|
611 |
|
612 | describe('#removeCycles()', function () {
|
613 | it('should remove shallow cycles', function () {
|
614 |
|
615 |
|
616 | let tree = new Tree();
|
617 | tree.addFile('a', true);
|
618 | tree.addFile('b');
|
619 | tree.addFile('c');
|
620 | tree.addDependency('a', 'b');
|
621 | tree.addDependency('a', 'c');
|
622 | tree.addDependency('b', 'c');
|
623 | tree.addDependency('c', 'b');
|
624 |
|
625 | tree.removeCycles();
|
626 |
|
627 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'c', 'b', 'a' ]);
|
628 | });
|
629 |
|
630 | it('should remove cycles found deeper in the graph', function () {
|
631 |
|
632 |
|
633 | let tree = new Tree();
|
634 | tree.addFile('a', true);
|
635 | tree.addFile('b');
|
636 | tree.addFile('c');
|
637 | tree.addFile('d');
|
638 | tree.addDependency('a', 'b');
|
639 | tree.addDependency('b', 'c');
|
640 | tree.addDependency('b', 'd');
|
641 | tree.addDependency('c', 'd');
|
642 | tree.addDependency('d', 'c');
|
643 |
|
644 | tree.removeCycles();
|
645 |
|
646 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'd', 'c', 'b', 'a' ]);
|
647 | });
|
648 |
|
649 | it('should remove large cycles in the graph', function () {
|
650 |
|
651 | let tree = new Tree();
|
652 | tree.addFile('a', true);
|
653 | tree.addFile('b');
|
654 | tree.addFile('c');
|
655 | tree.addFile('d');
|
656 | tree.addDependency('a', 'b');
|
657 | tree.addDependency('b', 'c');
|
658 | tree.addDependency('c', 'd');
|
659 | tree.addDependency('d', 'b');
|
660 |
|
661 | tree.removeCycles();
|
662 |
|
663 | assert.deepEqual(tree.getFiles({ topological: true }), [ 'd', 'c', 'b', 'a' ]);
|
664 | });
|
665 | });
|
666 |
|
667 | describe('#toJSON()', function () {
|
668 | it('should return a list of vertices and edges for reconstructing the graph', function () {
|
669 |
|
670 | let tree = new Tree();
|
671 | let a = tree.addFile('a', true);
|
672 | let b = tree.addFile('b');
|
673 | tree.addDependency('a', 'b');
|
674 |
|
675 | assert.deepEqual(tree.toJSON(), {
|
676 | vertices: [
|
677 | [ 'a', a.toString() ],
|
678 | [ 'b', b.toString() ]
|
679 | ],
|
680 | edges: [
|
681 | [ 'b', 'a' ]
|
682 | ]
|
683 | });
|
684 | });
|
685 | });
|
686 |
|
687 | describe('#toString([space])', function () {
|
688 | it('should completely stringify to JSON', function () {
|
689 |
|
690 | let tree = new Tree();
|
691 | let a = tree.addFile('a', true);
|
692 | let b = tree.addFile('b');
|
693 | tree.addDependency('a', 'b');
|
694 |
|
695 | assert.strictEqual(tree.toString(), JSON.stringify({
|
696 | vertices: [
|
697 | [ 'a', a.toString() ],
|
698 | [ 'b', b.toString() ]
|
699 | ],
|
700 | edges: [
|
701 | [ 'b', 'a' ]
|
702 | ]
|
703 | }));
|
704 | });
|
705 | });
|
706 |
|
707 | describe('.fromString(input)', function () {
|
708 | it('should parse a JSON string into a tree instance', function () {
|
709 |
|
710 | let tree = new Tree();
|
711 | tree.addFile('a', true);
|
712 | tree.addFile('b');
|
713 | tree.addDependency('a', 'b');
|
714 |
|
715 | let actual = Tree.fromString(tree.toString());
|
716 | assert.instanceOf(actual, Tree);
|
717 | assert.isTrue(actual.graph.equals(tree.graph, eqV, () => true));
|
718 |
|
719 | function eqV(a, b) {
|
720 | return a.path === b.path;
|
721 | }
|
722 | });
|
723 | });
|
724 | });
|