Initial commit
[yaffs-website] / node_modules / globule / test / globule_test.js
1 'use strict';
2
3 var path = require('path');
4
5 var globule = require('../lib/globule.js');
6
7 /*
8   ======== A Handy Little Nodeunit Reference ========
9   https://github.com/caolan/nodeunit
10
11   Test methods:
12     test.expect(numAssertions)
13     test.done()
14   Test assertions:
15     test.ok(value, [message])
16     test.equal(actual, expected, [message])
17     test.notEqual(actual, expected, [message])
18     test.deepEqual(actual, expected, [message])
19     test.notDeepEqual(actual, expected, [message])
20     test.strictEqual(actual, expected, [message])
21     test.notStrictEqual(actual, expected, [message])
22     test.throws(block, [error], [message])
23     test.doesNotThrow(block, [error], [message])
24     test.ifError(value)
25 */
26
27 exports['match'] = {
28   'empty set': function(test) {
29     test.expect(6);
30     // Should return empty set if a required argument is missing or an empty set.
31     test.deepEqual(globule.match(null, 'foo.js'), [], 'should return empty set.');
32     test.deepEqual(globule.match('*.js', null), [], 'should return empty set.');
33     test.deepEqual(globule.match([], 'foo.js'), [], 'should return empty set.');
34     test.deepEqual(globule.match('*.js', []), [], 'should return empty set.');
35     test.deepEqual(globule.match(null, ['foo.js']), [], 'should return empty set.');
36     test.deepEqual(globule.match(['*.js'], null), [], 'should return empty set.');
37     test.done();
38   },
39   'basic matching': function(test) {
40     test.expect(6);
41     test.deepEqual(globule.match('*.js', 'foo.js'), ['foo.js'], 'should match correctly.');
42     test.deepEqual(globule.match('*.js', ['foo.js']), ['foo.js'], 'should match correctly.');
43     test.deepEqual(globule.match('*.js', ['foo.js', 'bar.css']), ['foo.js'], 'should match correctly.');
44     test.deepEqual(globule.match(['*.js', '*.css'], 'foo.js'), ['foo.js'], 'should match correctly.');
45     test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js']), ['foo.js'], 'should match correctly.');
46     test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js', 'bar.css']), ['foo.js', 'bar.css'], 'should match correctly.');
47     test.done();
48   },
49   'no matches': function(test) {
50     test.expect(2);
51     test.deepEqual(globule.match('*.js', 'foo.css'), [], 'should fail to match.');
52     test.deepEqual(globule.match('*.js', ['foo.css', 'bar.css']), [], 'should fail to match.');
53     test.done();
54   },
55   'unique': function(test) {
56     test.expect(2);
57     test.deepEqual(globule.match('*.js', ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.');
58     test.deepEqual(globule.match(['*.js', '*.*'], ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.');
59     test.done();
60   },
61   'flatten': function(test) {
62     test.expect(1);
63     test.deepEqual(globule.match([['*.js', '*.css'], ['*.*', '*.js']], ['foo.js', 'bar.css']),
64       ['foo.js', 'bar.css'],
65       'should process nested pattern arrays correctly.');
66     test.done();
67   },
68   'exclusion': function(test) {
69     test.expect(5);
70     test.deepEqual(globule.match(['!*.js'], ['foo.js', 'bar.js']), [], 'solitary exclusion should match nothing');
71     test.deepEqual(globule.match(['*.js', '!*.js'], ['foo.js', 'bar.js']), [], 'exclusion should cancel match');
72     test.deepEqual(globule.match(['*.js', '!f*.js'], ['foo.js', 'bar.js', 'baz.js']),
73       ['bar.js', 'baz.js'],
74       'partial exclusion should partially cancel match');
75     test.deepEqual(globule.match(['*.js', '!*.js', 'b*.js'], ['foo.js', 'bar.js', 'baz.js']),
76       ['bar.js', 'baz.js'],
77       'inclusion / exclusion order matters');
78     test.deepEqual(globule.match(['*.js', '!f*.js', '*.js'], ['foo.js', 'bar.js', 'baz.js']),
79       ['bar.js', 'baz.js', 'foo.js'],
80       'inclusion / exclusion order matters');
81     test.done();
82   },
83   'options.matchBase': function(test) {
84     test.expect(2);
85     test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js'], {matchBase: true}),
86       ['foo.js', 'baz/xyz.js'],
87       'should matchBase (minimatch) when specified.');
88     test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js']),
89       ['foo.js'],
90       'should not matchBase (minimatch) by default.');
91     test.done();
92   },
93 };
94
95 exports['isMatch'] = {
96   'basic matching': function(test) {
97     test.expect(6);
98     test.ok(globule.isMatch('*.js', 'foo.js'), 'should match correctly.');
99     test.ok(globule.isMatch('*.js', ['foo.js']), 'should match correctly.');
100     test.ok(globule.isMatch('*.js', ['foo.js', 'bar.css']), 'should match correctly.');
101     test.ok(globule.isMatch(['*.js', '*.css'], 'foo.js'), 'should match correctly.');
102     test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js']), 'should match correctly.');
103     test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js', 'bar.css']), 'should match correctly.');
104     test.done();
105   },
106   'no matches': function(test) {
107     test.expect(6);
108     test.ok(!globule.isMatch('*.js', 'foo.css'), 'should fail to match.');
109     test.ok(!globule.isMatch('*.js', ['foo.css', 'bar.css']), 'should fail to match.');
110     test.ok(!globule.isMatch(null, 'foo.css'), 'should fail to match.');
111     test.ok(!globule.isMatch('*.js', null), 'should fail to match.');
112     test.ok(!globule.isMatch([], 'foo.css'), 'should fail to match.');
113     test.ok(!globule.isMatch('*.js', []), 'should fail to match.');
114     test.done();
115   },
116   'options.matchBase': function(test) {
117     test.expect(2);
118     test.ok(globule.isMatch('*.js', ['baz/xyz.js'], {matchBase: true}), 'should matchBase (minimatch) when specified.');
119     test.ok(!globule.isMatch('*.js', ['baz/xyz.js']), 'should not matchBase (minimatch) by default.');
120     test.done();
121   },
122 };
123
124 exports['find'] = {
125   setUp: function(done) {
126     this.cwd = process.cwd();
127     process.chdir('test/fixtures/expand');
128     done();
129   },
130   tearDown: function(done) {
131     process.chdir(this.cwd);
132     done();
133   },
134   'basic matching': function(test) {
135     test.expect(5);
136     test.deepEqual(globule.find('**/*.js'), ['js/bar.js', 'js/foo.js'], 'single pattern argument should match.');
137     test.deepEqual(globule.find('**/*.js', '**/*.css'),
138       ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
139       'multiple pattern arguments should match.');
140     test.deepEqual(globule.find(['**/*.js', '**/*.css']),
141       ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
142       'array of patterns should match.');
143     test.deepEqual(globule.find([['**/*.js'], [['**/*.css', 'js/*.js']]]),
144       ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
145       'array of arrays of patterns should be flattened.');
146     test.deepEqual(globule.find('*.xyz'), [], 'bad pattern should fail to match.');
147     test.done();
148   },
149   'unique': function(test) {
150     test.expect(4);
151     test.deepEqual(globule.find('**/*.js', 'js/*.js'),
152       ['js/bar.js', 'js/foo.js'],
153       'file list should be uniqed.');
154     test.deepEqual(globule.find('**/*.js', '**/*.css', 'js/*.js'), ['js/bar.js', 'js/foo.js',
155       'css/baz.css', 'css/qux.css'],
156       'file list should be uniqed.');
157     test.deepEqual(globule.find('js', 'js/'),
158       ['js', 'js/'],
159       'mixed non-ending-/ and ending-/ dirs will not be uniqed by default.');
160     test.deepEqual(globule.find('js', 'js/', {mark: true}),
161       ['js/'],
162       'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.');
163     test.done();
164   },
165   'file order': function(test) {
166     test.expect(5);
167     var actual = globule.find('**/*.{js,css}');
168     var expected = ['css/baz.css', 'css/qux.css', 'js/bar.js', 'js/foo.js'];
169     test.deepEqual(actual, expected, 'should select 4 files in this order, by default.');
170
171     actual = globule.find('js/foo.js', 'js/bar.js', '**/*.{js,css}');
172     expected = ['js/foo.js', 'js/bar.js', 'css/baz.css', 'css/qux.css'];
173     test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
174
175     actual = globule.find('js/bar.js', 'js/foo.js', '**/*.{js,css}');
176     expected = ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'];
177     test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.');
178
179     actual = globule.find('**/*.{js,css}', '!css/qux.css', 'css/qux.css');
180     expected = ['css/baz.css', 'js/bar.js', 'js/foo.js', 'css/qux.css'];
181     test.deepEqual(actual, expected, 'if a file is excluded and then re-added, it should be added at the end.');
182
183     actual = globule.find('js/foo.js', '**/*.{js,css}', '!css/qux.css', 'css/qux.css');
184     expected = ['js/foo.js', 'css/baz.css', 'js/bar.js', 'css/qux.css'];
185     test.deepEqual(actual, expected, 'should be able to combine specified-up-front and excluded/added-at-end.');
186     test.done();
187   },
188   'exclusion': function(test) {
189     test.expect(8);
190     test.deepEqual(globule.find(['!js/*.js']), [], 'solitary exclusion should match nothing');
191     test.deepEqual(globule.find(['js/bar.js','!js/bar.js']), [], 'exclusion should negate match');
192     test.deepEqual(globule.find(['**/*.js', '!js/foo.js']),
193       ['js/bar.js'],
194       'should omit single file from matched set');
195     test.deepEqual(globule.find(['!js/foo.js', '**/*.js']),
196       ['js/bar.js', 'js/foo.js'],
197       'inclusion / exclusion order matters');
198     test.deepEqual(globule.find(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']),
199       ['js/foo.js','css/qux.css'],
200       'multiple exclusions should be removed from the set');
201     test.deepEqual(globule.find(['**/*.js', '**/*.css', '!**/*.css']),
202       ['js/bar.js', 'js/foo.js'],
203       'excluded wildcards should be removed from the matched set');
204     test.deepEqual(globule.find(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']),
205       ['js/foo.js', 'css/qux.css'],
206       'different pattern for exclusion should still work');
207     test.deepEqual(globule.find(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']),
208       ['js/foo.js', 'css/baz.css', 'css/qux.css'],
209       'inclusion / exclusion order matters');
210     test.done();
211   },
212   'options.mark': function(test) {
213     test.expect(4);
214     test.deepEqual(globule.find('**d*/**'), [
215       'deep',
216       'deep/deep.txt',
217       'deep/deeper',
218       'deep/deeper/deeper.txt',
219       'deep/deeper/deepest',
220       'deep/deeper/deepest/deepest.txt'], 'should match files and directories.');
221     test.deepEqual(globule.find('**d*/**/'), [
222       'deep/',
223       'deep/deeper/',
224       'deep/deeper/deepest/'], 'trailing / in pattern should match directories only, matches end in /.');
225     test.deepEqual(globule.find('**d*/**', {mark: true}), [
226       'deep/',
227       'deep/deep.txt',
228       'deep/deeper/',
229       'deep/deeper/deeper.txt',
230       'deep/deeper/deepest/',
231       'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.');
232     test.deepEqual(globule.find('**d*/**/', {mark: true}), [
233       'deep/',
234       'deep/deeper/',
235       'deep/deeper/deepest/'], 'the minimatch "mark" option should not remove trailing / from matched paths.');
236     test.done();
237   },
238   'options.filter': function(test) {
239     test.expect(5);
240     test.deepEqual(globule.find('**d*/**', {filter: 'isFile'}), [
241       'deep/deep.txt',
242       'deep/deeper/deeper.txt',
243       'deep/deeper/deepest/deepest.txt'
244     ], 'should match files only.');
245     test.deepEqual(globule.find('**d*/**', {filter: 'isDirectory'}), [
246       'deep',
247       'deep/deeper',
248       'deep/deeper/deepest'
249     ], 'should match directories only.');
250     test.deepEqual(globule.find('**', {
251       arbitraryProp: /deepest/,
252       filter: function(filepath, options) {
253         return options.arbitraryProp.test(filepath);
254       }
255     }), [
256       'deep/deeper/deepest',
257       'deep/deeper/deepest/deepest.txt',
258     ], 'should filter arbitrarily.');
259     test.deepEqual(globule.find('js', 'css', {filter: 'isFile'}), [], 'should fail to match.');
260     test.deepEqual(globule.find('**/*.js', {filter: 'isDirectory'}), [], 'should fail to match.');
261     test.done();
262   },
263   'options.matchBase': function(test) {
264     test.expect(3);
265     test.deepEqual(globule.find('*.js'), [], 'should not matchBase (minimatch) by default.');
266     test.deepEqual(globule.find('*.js', {matchBase: true}),
267       ['js/bar.js', 'js/foo.js'],
268       'matchBase option should be passed through to minimatch.');
269     test.deepEqual(globule.find('*.js', '*.css', {matchBase: true}),
270       ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'],
271       'matchBase option should be passed through to minimatch.');
272     test.done();
273   },
274   'options.srcBase': function(test) {
275     test.expect(5);
276     test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep'}),
277       ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
278       'should find paths matching pattern relative to srcBase.');
279     test.deepEqual(globule.find(['**/deep*.txt'], {cwd: 'deep'}),
280       ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
281       'cwd and srcBase should do the same thing.');
282     test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isFile'}),
283       ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
284       'srcBase should not prevent filtering.');
285     test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isDirectory'}),
286       ['deeper', 'deeper/deepest'],
287       'srcBase should not prevent filtering.');
288     test.deepEqual(globule.find(['**/deep*.txt', '!**/deeper**'], {srcBase: 'deep'}),
289       ['deep.txt', 'deeper/deepest/deepest.txt'],
290       'srcBase should not prevent exclusions.');
291     test.done();
292   },
293   'options.prefixBase': function(test) {
294     test.expect(2);
295     test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: false}),
296       ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'],
297       'should not prefix srcBase to returned paths.');
298     test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: true}),
299       ['deep/deep.txt', 'deep/deeper/deeper.txt', 'deep/deeper/deepest/deepest.txt'],
300       'should prefix srcBase to returned paths.');
301     test.done();
302   },
303   'options.nonull': function(test) {
304     test.expect(3);
305     test.deepEqual(globule.find(['*omg*'], {nonull: true}),
306       ['*omg*'],
307       'non-matching patterns should be returned in result set.');
308     test.deepEqual(globule.find(['js/a*', 'js/b*', 'js/c*'], {nonull: true}),
309       ['js/a*', 'js/bar.js', 'js/c*'],
310       'non-matching patterns should be returned in result set.');
311     test.deepEqual(globule.find(['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], {nonull: true}),
312       ['js/foo.js', 'js/bar.js', 'js/nonexistent.js'],
313       'non-matching filenames should be returned in result set.');
314     test.done();
315   },
316 };
317
318 exports['mapping'] = {
319   'basic mapping': function(test) {
320     test.expect(1);
321
322     var actual = globule.mapping(['a.txt', 'b.txt', 'c.txt']);
323     var expected = [
324       {dest: 'a.txt', src: ['a.txt']},
325       {dest: 'b.txt', src: ['b.txt']},
326       {dest: 'c.txt', src: ['c.txt']},
327     ];
328     test.deepEqual(actual, expected, 'default options should create same-to-same src-dest mappings.');
329
330     test.done();
331   },
332   'options.srcBase': function(test) {
333     test.expect(2);
334     var actual, expected;
335     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo'});
336     expected = [
337       {dest: 'a.txt', src: ['foo/a.txt']},
338       {dest: 'bar/b.txt', src: ['foo/bar/b.txt']},
339       {dest: 'bar/baz/c.txt', src: ['foo/bar/baz/c.txt']},
340     ];
341     test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (no trailing /).');
342
343     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo/'});
344     test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (trailing /).');
345
346     test.done();
347   },
348   'options.destBase': function(test) {
349     test.expect(2);
350     var actual, expected;
351
352     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest'});
353     expected = [
354       {dest: 'dest/a.txt', src: ['a.txt']},
355       {dest: 'dest/bar/b.txt', src: ['bar/b.txt']},
356       {dest: 'dest/bar/baz/c.txt', src: ['bar/baz/c.txt']},
357     ];
358     test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (no trailing /).');
359
360     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest/'});
361     test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (trailing /).');
362
363     test.done();
364   },
365   'options.flatten': function(test) {
366     test.expect(1);
367     var actual, expected;
368
369     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {flatten: true});
370     expected = [
371       {dest: 'a.txt', src: ['a.txt']},
372       {dest: 'b.txt', src: ['bar/b.txt']},
373       {dest: 'c.txt', src: ['bar/baz/c.txt']},
374     ];
375     test.deepEqual(actual, expected, 'flatten should remove all src path parts from dest.');
376
377     test.done();
378   },
379   'options.flatten + options.destBase': function(test) {
380     test.expect(1);
381     var actual, expected;
382
383     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest', flatten: true});
384     expected = [
385       {dest: 'dest/a.txt', src: ['a.txt']},
386       {dest: 'dest/b.txt', src: ['bar/b.txt']},
387       {dest: 'dest/c.txt', src: ['bar/baz/c.txt']},
388     ];
389     test.deepEqual(actual, expected, 'flatten and destBase should work together.');
390
391     test.done();
392   },
393   'options.ext': function(test) {
394     test.expect(1);
395     var actual, expected;
396
397     actual = globule.mapping(['x/a.js', 'x.y/b.min.js', 'x.y/z.z/c'], {ext: '.foo'});
398     expected = [
399       {dest: 'x/a.foo', src: ['x/a.js']},
400       {dest: 'x.y/b.foo', src: ['x.y/b.min.js']},
401       {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
402     ];
403     test.deepEqual(actual, expected, 'by default, ext should replace everything after the first dot in the filename.');
404
405     test.done();
406   },
407   'options.extDot': function(test) {
408     test.expect(2);
409     var actual, expected;
410
411     actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'first'});
412     expected = [
413       {dest: 'x/a.foo', src: ['x/a.js']},
414       {dest: 'x.y/b.foo', src: ['x.y/b.bbb.min.js']},
415       {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
416     ];
417     test.deepEqual(actual, expected, 'extDot of "first" should replace everything after the first dot in the filename.');
418
419     actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'last'});
420     expected = [
421       {dest: 'x/a.foo', src: ['x/a.js']},
422       {dest: 'x.y/b.bbb.min.foo', src: ['x.y/b.bbb.min.js']},
423       {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']},
424     ];
425     test.deepEqual(actual, expected, 'extDot of "last" should replace everything after the last dot in the filename.');
426
427     test.done();
428   },
429   'options.rename': function(test) {
430     test.expect(1);
431     var actual, expected;
432     actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {
433       arbitraryProp: 'FOO',
434       rename: function(dest, options) {
435         return path.join(options.arbitraryProp, dest.toUpperCase());
436       }
437     });
438     expected = [
439       {dest: 'FOO/A.TXT', src: ['a.txt']},
440       {dest: 'FOO/BAR/B.TXT', src: ['bar/b.txt']},
441       {dest: 'FOO/BAR/BAZ/C.TXT', src: ['bar/baz/c.txt']},
442     ];
443     test.deepEqual(actual, expected, 'allow arbitrary renaming of files.');
444
445     test.done();
446   },
447 };
448
449 exports['findMapping'] = {
450   setUp: function(done) {
451     this.cwd = process.cwd();
452     process.chdir('test/fixtures');
453     done();
454   },
455   tearDown: function(done) {
456     process.chdir(this.cwd);
457     done();
458   },
459   'basic matching': function(test) {
460     test.expect(2);
461
462     var actual = globule.findMapping(['expand/**/*.txt']);
463     var expected = [
464       {dest: 'expand/deep/deep.txt', src: ['expand/deep/deep.txt']},
465       {dest: 'expand/deep/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
466       {dest: 'expand/deep/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
467     ];
468     test.deepEqual(actual, expected, 'default options');
469
470     expected = globule.mapping(globule.find(['expand/**/*.txt']));
471     test.deepEqual(actual, expected, 'this is what it\'s doing under the hood, anwyays.');
472
473     test.done();
474   },
475   'options.srcBase': function(test) {
476     test.expect(1);
477     var actual = globule.findMapping(['**/*.txt'], {destBase: 'dest', srcBase: 'expand/deep'});
478     var expected = [
479       {dest: 'dest/deep.txt', src: ['expand/deep/deep.txt']},
480       {dest: 'dest/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']},
481       {dest: 'dest/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']},
482     ];
483     test.deepEqual(actual, expected, 'srcBase should be stripped from front of destPath, pre-destBase+destPath join');
484     test.done();
485   },
486 };