4a657bee2a53567ebd6bd2a3d719466d51d6e3ff
[yaffs-website] / node_modules / grunt-legacy-util / test / index.js
1 'use strict';
2
3 var util = require('../');
4
5 var fs = require('fs');
6 var path = require('path');
7
8 var Tempfile = require('temporary/lib/file');
9
10 exports['util.callbackify'] = {
11   'return': function(test) {
12     test.expect(1);
13     // This function returns a value.
14     function add(a, b) {
15       return a + b;
16     }
17     util.callbackify(add)(1, 2, function(result) {
18       test.equal(result, 3, 'should be the correct result.');
19       test.done();
20     });
21   },
22   'callback (sync)': function(test) {
23     test.expect(1);
24     // This function accepts a callback which it calls synchronously.
25     function add(a, b, done) {
26       done(a + b);
27     }
28     util.callbackify(add)(1, 2, function(result) {
29       test.equal(result, 3, 'should be the correct result.');
30       test.done();
31     });
32   },
33   'callback (async)': function(test) {
34     test.expect(1);
35     // This function accepts a callback which it calls asynchronously.
36     function add(a, b, done) {
37       setTimeout(done.bind(null, a + b), 0);
38     }
39     util.callbackify(add)(1, 2, function(result) {
40       test.equal(result, 3, 'should be the correct result.');
41       test.done();
42     });
43   }
44 };
45
46 exports['util'] = {
47   'error': function(test) {
48     test.expect(9);
49     var origError = new Error('Original error.');
50
51     var err = util.error('Test message.');
52     test.ok(err instanceof Error, 'Should be an Error.');
53     test.equal(err.name, 'Error', 'Should be an Error.');
54     test.equal(err.message, 'Test message.', 'Should have the correct message.');
55
56     err = util.error('Test message.', origError);
57     test.ok(err instanceof Error, 'Should be an Error.');
58     test.equal(err.name, 'Error', 'Should be an Error.');
59     test.equal(err.message, 'Test message.', 'Should have the correct message.');
60     test.equal(err.origError, origError, 'Should reflect the original error.');
61
62     var newError = new Error('Test message.');
63     err = util.error(newError, origError);
64     test.equal(err, newError, 'Should be the passed-in Error.');
65     test.equal(err.origError, origError, 'Should reflect the original error.');
66     test.done();
67   },
68   'linefeed': function(test) {
69     test.expect(1);
70     if (process.platform === 'win32') {
71       test.equal(util.linefeed, '\r\n', 'linefeed should be operating-system appropriate.');
72     } else {
73       test.equal(util.linefeed, '\n', 'linefeed should be operating-system appropriate.');
74     }
75     test.done();
76   },
77   'normalizelf': function(test) {
78     test.expect(1);
79     if (process.platform === 'win32') {
80       test.equal(util.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\r\nbar\r\nbaz\r\n\r\nqux\r\n\r\nquux', 'linefeeds should be normalized');
81     } else {
82       test.equal(util.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\nbar\nbaz\n\nqux\n\nquux', 'linefeeds should be normalized');
83     }
84     test.done();
85   }
86 };
87
88 exports['util.spawn'] = {
89   setUp: function(done) {
90     this.script = path.resolve('test/fixtures/spawn.js');
91     done();
92   },
93   'exit code 0': function(test) {
94     test.expect(6);
95     util.spawn({
96       cmd: process.execPath,
97       args: [ this.script, 0 ],
98     }, function(err, result, code) {
99       test.equals(err, null);
100       test.equals(code, 0);
101       test.equals(result.stdout, 'stdout');
102       test.equals(result.stderr, 'stderr');
103       test.equals(result.code, 0);
104       test.equals(String(result), 'stdout');
105       test.done();
106     });
107   },
108   'exit code 0, fallback': function(test) {
109     test.expect(6);
110     util.spawn({
111       cmd: process.execPath,
112       args: [ this.script, 0 ],
113       fallback: 'ignored if exit code is 0'
114     }, function(err, result, code) {
115       test.equals(err, null);
116       test.equals(code, 0);
117       test.equals(result.stdout, 'stdout');
118       test.equals(result.stderr, 'stderr');
119       test.equals(result.code, 0);
120       test.equals(String(result), 'stdout');
121       test.done();
122     });
123   },
124   'non-zero exit code': function(test) {
125     test.expect(7);
126     util.spawn({
127       cmd: process.execPath,
128       args: [ this.script, 123 ],
129     }, function(err, result, code) {
130       test.ok(err instanceof Error);
131       test.equals(err.message, 'stderr');
132       test.equals(code, 123);
133       test.equals(result.stdout, 'stdout');
134       test.equals(result.stderr, 'stderr');
135       test.equals(result.code, 123);
136       test.equals(String(result), 'stderr');
137       test.done();
138     });
139   },
140   'non-zero exit code, fallback': function(test) {
141     test.expect(6);
142     util.spawn({
143       cmd: process.execPath,
144       args: [ this.script, 123 ],
145       fallback: 'custom fallback'
146     }, function(err, result, code) {
147       test.equals(err, null);
148       test.equals(code, 123);
149       test.equals(result.stdout, 'stdout');
150       test.equals(result.stderr, 'stderr');
151       test.equals(result.code, 123);
152       test.equals(String(result), 'custom fallback');
153       test.done();
154     });
155   },
156   'cmd not found': function(test) {
157     test.expect(3);
158     util.spawn({
159       cmd: 'nodewtfmisspelled',
160     }, function(err, result, code) {
161       test.ok(err instanceof Error);
162       test.equals(code, 127);
163       test.equals(result.code, 127);
164       test.done();
165     });
166   },
167   'cmd not found, fallback': function(test) {
168     test.expect(4);
169     util.spawn({
170       cmd: 'nodewtfmisspelled',
171       fallback: 'use a fallback or good luck'
172     }, function(err, result, code) {
173       test.equals(err, null);
174       test.equals(code, 127);
175       test.equals(result.code, 127);
176       test.equals(String(result), 'use a fallback or good luck');
177       test.done();
178     });
179   },
180   'cmd not in path': function(test) {
181     test.expect(6);
182     var win32 = process.platform === 'win32';
183     util.spawn({
184       cmd: 'test\\fixtures\\exec' + (win32 ? '.cmd' : '.sh'),
185     }, function(err, result, code) {
186       test.equals(err, null);
187       test.equals(code, 0);
188       test.equals(result.stdout, 'done');
189       test.equals(result.stderr, '');
190       test.equals(result.code, 0);
191       test.equals(String(result), 'done');
192       test.done();
193     });
194   },
195   'cmd not in path (with cwd)': function(test) {
196     test.expect(6);
197     var win32 = process.platform === 'win32';
198     util.spawn({
199       cmd: './exec' + (win32 ? '.cmd' : '.sh'),
200       opts: {cwd: 'test/fixtures'},
201     }, function(err, result, code) {
202       test.equals(err, null);
203       test.equals(code, 0);
204       test.equals(result.stdout, 'done');
205       test.equals(result.stderr, '');
206       test.equals(result.code, 0);
207       test.equals(String(result), 'done');
208       test.done();
209     });
210   },
211   'grunt': function(test) {
212     test.expect(3);
213     util.spawn({
214       grunt: true,
215       args: [ '--gruntfile', 'test/fixtures/Gruntfile-print-text.js', 'print:foo' ],
216     }, function(err, result, code) {
217       test.equals(err, null);
218       test.equals(code, 0);
219       test.ok(/^OUTPUT: foo/m.test(result.stdout), 'stdout should contain output indicating the grunt task was run.');
220       test.done();
221     });
222   },
223   'grunt (with cwd)': function(test) {
224     test.expect(3);
225     util.spawn({
226       grunt: true,
227       args: [ '--gruntfile', 'Gruntfile-print-text.js', 'print:foo' ],
228       opts: {cwd: 'test/fixtures'},
229     }, function(err, result, code) {
230       test.equals(err, null);
231       test.equals(code, 0);
232       test.ok(/^OUTPUT: foo/m.test(result.stdout), 'stdout should contain output indicating the grunt task was run.');
233       test.done();
234     });
235   },
236   'grunt passes execArgv': function(test) {
237     test.expect(3);
238     util.spawn({
239       cmd: process.execPath,
240       args: [ '--harmony', process.argv[1], '--gruntfile', 'test/fixtures/Gruntfile-execArgv.js'],
241     }, function(err, result, code) {
242       test.equals(err, null);
243       test.equals(code, 0);
244       test.ok(/^OUTPUT: --harmony/m.test(result.stdout), 'stdout should contain passed-through process.execArgv.');
245       test.done();
246     });
247   },
248   'grunt result.toString() with error': function(test) {
249     // grunt.log.error uses standard out, to be fixed in 0.5.
250     test.expect(4);
251     util.spawn({
252       grunt: true,
253       args: [ 'nonexistentTask' ]
254     }, function(err, result, code) {
255       test.ok(err instanceof Error, 'Should be an Error.');
256       test.equal(err.name, 'Error', 'Should be an Error.');
257       test.equals(code, 3);
258       test.ok(/Warning: Task "nonexistentTask" not found./m.test(result.toString()), 'stdout should contain output indicating the grunt task was (attempted to be) run.');
259       test.done();
260     });
261   },
262   'custom stdio stream(s)': function(test) {
263     test.expect(6);
264     var stdoutFile = new Tempfile();
265     var stderrFile = new Tempfile();
266     var stdout = fs.openSync(stdoutFile.path, 'a');
267     var stderr = fs.openSync(stderrFile.path, 'a');
268     var child = util.spawn({
269       cmd: process.execPath,
270       args: [ this.script, 0 ],
271       opts: {stdio: [null, stdout, stderr]},
272     }, function(err, result, code) {
273       test.equals(code, 0);
274       test.equals(String(fs.readFileSync(stdoutFile.path)), 'stdout\n', 'Child process stdout should have been captured via custom stream.');
275       test.equals(String(fs.readFileSync(stderrFile.path)), 'stderr\n', 'Child process stderr should have been captured via custom stream.');
276       stdoutFile.unlinkSync();
277       stderrFile.unlinkSync();
278       test.equals(result.stdout, '', 'Nothing will be passed to the stdout string when spawn stdio is a custom stream.');
279       test.done();
280     });
281     test.ok(!child.stdout, 'child should not have a stdout property.');
282     test.ok(!child.stderr, 'child should not have a stderr property.');
283   },
284 };
285
286 exports['util.spawn.multibyte'] = {
287   setUp: function(done) {
288     this.script = path.resolve('test/fixtures/spawn-multibyte.js');
289     done();
290   },
291   'partial stdout': function(test) {
292     test.expect(4);
293     util.spawn({
294       cmd: process.execPath,
295       args: [ this.script ],
296     }, function(err, result, code) {
297       test.equals(err, null);
298       test.equals(code, 0);
299       test.equals(result.stdout, 'こんにちは');
300       test.equals(result.stderr, 'こんにちは');
301       test.done();
302     });
303   }
304 };
305
306 exports['util.underscore.string'] = function(test) {
307   test.expect(4);
308   test.equals(util._.trim('    foo     '), 'foo', 'Should have trimmed the string.');
309   test.equals(util._.capitalize('foo'), 'Foo', 'Should have capitalized the first letter.');
310   test.equals(util._.words('one two three').length, 3, 'Should have counted three words.');
311   test.ok(util._.isBlank(' '), 'Should be blank.');
312   test.done();
313 };
314
315 function getType(val) {
316   if (Buffer.isBuffer(val)) { return 'buffer'; }
317   return Object.prototype.toString.call(val).slice(8, -1).toLowerCase();
318 }
319
320 exports['util.recurse'] = {
321   setUp: function(done) {
322     this.typeValue = function(value) {
323       return {
324         value: value,
325         type: getType(value),
326       };
327     };
328     done();
329   },
330   'primitives': function(test) {
331     test.expect(1);
332     var actual = util.recurse({
333       bool: true,
334       num: 1,
335       str: 'foo',
336       nul: null,
337       undef: undefined,
338     }, this.typeValue);
339     var expected = {
340       bool: {type: 'boolean', value: true},
341       num: {type: 'number', value: 1},
342       str: {type: 'string', value: 'foo'},
343       nul: {type: 'null', value: null},
344       undef: {type: 'undefined', value: undefined},
345     };
346     test.deepEqual(actual, expected, 'Should process primitive values.');
347     test.done();
348   },
349   'array': function(test) {
350     test.expect(1);
351     var actual = util.recurse({
352       arr: [
353         true,
354         1,
355         'foo',
356         null,
357         undefined,
358         [
359           true,
360           1,
361           'foo',
362           null,
363           undefined,
364         ],
365       ],
366     }, this.typeValue);
367     var expected = {
368       arr: [
369         {type: 'boolean', value: true},
370         {type: 'number', value: 1},
371         {type: 'string', value: 'foo'},
372         {type: 'null', value: null},
373         {type: 'undefined', value: undefined},
374         [
375           {type: 'boolean', value: true},
376           {type: 'number', value: 1},
377           {type: 'string', value: 'foo'},
378           {type: 'null', value: null},
379           {type: 'undefined', value: undefined},
380         ],
381       ],
382     };
383     test.deepEqual(actual, expected, 'Should recurse over arrays.');
384     test.done();
385   },
386   'object': function(test) {
387     test.expect(1);
388     var actual = util.recurse({
389       obj: {
390         bool: true,
391         num: 1,
392         str: 'foo',
393         nul: null,
394         undef: undefined,
395         obj: {
396           bool: true,
397           num: 1,
398           str: 'foo',
399           nul: null,
400           undef: undefined,
401         },
402       },
403     }, this.typeValue);
404     var expected = {
405       obj: {
406         bool: {type: 'boolean', value: true},
407         num: {type: 'number', value: 1},
408         str: {type: 'string', value: 'foo'},
409         nul: {type: 'null', value: null},
410         undef: {type: 'undefined', value: undefined},
411         obj: {
412           bool: {type: 'boolean', value: true},
413           num: {type: 'number', value: 1},
414           str: {type: 'string', value: 'foo'},
415           nul: {type: 'null', value: null},
416           undef: {type: 'undefined', value: undefined},
417         },
418       },
419     };
420     test.deepEqual(actual, expected, 'Should recurse over objects.');
421     test.done();
422   },
423   'array in object': function(test) {
424     test.expect(1);
425     var actual = util.recurse({
426       obj: {
427         arr: [
428           true,
429           1,
430           'foo',
431           null,
432           undefined,
433         ],
434       },
435     }, this.typeValue);
436     var expected = {
437       obj: {
438         arr: [
439           {type: 'boolean', value: true},
440           {type: 'number', value: 1},
441           {type: 'string', value: 'foo'},
442           {type: 'null', value: null},
443           {type: 'undefined', value: undefined},
444         ],
445       },
446     };
447     test.deepEqual(actual, expected, 'Should recurse over arrays in objects.');
448     test.done();
449   },
450   'object in array': function(test) {
451     test.expect(1);
452     var actual = util.recurse({
453       arr: [
454         true,
455         {
456           num: 1,
457           str: 'foo',
458         },
459         null,
460         undefined,
461       ],
462     }, this.typeValue);
463     var expected = {
464       arr: [
465         {type: 'boolean', value: true},
466         {
467           num: {type: 'number', value: 1},
468           str: {type: 'string', value: 'foo'},
469         },
470         {type: 'null', value: null},
471         {type: 'undefined', value: undefined},
472       ],
473     };
474     test.deepEqual(actual, expected, 'Should recurse over objects in arrays.');
475     test.done();
476   },
477   'buffer': function(test) {
478     test.expect(1);
479     var actual = util.recurse({
480       buf: new Buffer('buf'),
481     }, this.typeValue);
482     var expected = {
483       buf: {type: 'buffer', value: new Buffer('buf')},
484     };
485     test.deepEqual(actual, expected, 'Should not mangle Buffer instances.');
486     test.done();
487   },
488   'inherited properties': function(test) {
489     test.expect(1);
490     var actual = util.recurse({
491       obj: Object.create({num: 1}, {
492         str: {value: 'foo', enumerable: true},
493         ignored: {value: 'ignored', enumerable: false},
494       }),
495     }, this.typeValue);
496     var expected = {
497       obj: {
498         num: {type: 'number', value: 1},
499         str: {type: 'string', value: 'foo'},
500       }
501     };
502     test.deepEqual(actual, expected, 'Should enumerate inherited object properties.');
503     test.done();
504   },
505   'circular references': function(test) {
506     test.expect(6);
507     function assertErrorWithPath(expectedPath) {
508       return function(actual) {
509         return actual.path === expectedPath &&
510           actual.message === 'Circular reference detected (' + expectedPath + ')';
511       };
512     }
513     test.doesNotThrow(function() {
514       var obj = {
515         // wat
516         a:[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
517         // does
518         b:[[[[],[[[],[[[[],[[[],[[[],[[[],[[[],[[[[],[[]]]]]]]]]]]]]]]]]]]]],
519         // it
520         c:{d:{e:{f:{g:{h:{i:{j:{k:{l:{m:{n:{o:{p:{q:{r:{s:{}}}}}}}}}}}}}}}}},
521         // mean
522         t:[{u:[{v:[[[[],[[[],[[[{w:[{x:[[[],[[[{y:[[1]]}]]]]]}]}]]]]]]]]}]}],
523       };
524       util.recurse(obj, function(v) { return v; });
525     }, 'Should not throw when no circular reference is detected.');
526     test.throws(function() {
527       var obj = {a: 1, b: 2};
528       obj.obj = obj;
529       util.recurse(obj, function(v) { return v; });
530     }, assertErrorWithPath('.obj'), 'Should throw when a circular reference is detected.');
531     test.throws(function() {
532       var obj = {a:{'b b':{'c-c':{d_d:{e:{f:{g:{h:{i:{j:{k:{l:{}}}}}}}}}}}}};
533       obj.a['b b']['c-c'].d_d.e.f.g.h.i.j.k.l.obj = obj;
534       util.recurse(obj, function(v) { return v; });
535     }, assertErrorWithPath('.a["b b"]["c-c"].d_d.e.f.g.h.i.j.k.l.obj'), 'Should throw when a circular reference is detected.');
536     test.throws(function() {
537       var obj = {a: 1, b: 2};
538       obj.arr = [1, 2, obj, 3, 4];
539       util.recurse(obj, function(v) { return v; });
540     }, assertErrorWithPath('.arr[2]'), 'Should throw when a circular reference is detected.');
541     test.throws(function() {
542       var obj = {a: 1, b: 2};
543       obj.arr = [{a:[1,{b:[2,{c:[3,obj,4]},5]},6]},7];
544       util.recurse(obj, function(v) { return v; });
545     }, assertErrorWithPath('.arr[0].a[1].b[1].c[1]'), 'Should throw when a circular reference is detected.');
546     test.throws(function() {
547       var obj = {a: 1, b: 2};
548       obj.arr = [];
549       obj.arr.push(0,{a:[1,{b:[2,{c:[3,obj.arr,4]},5]},6]},7);
550       util.recurse(obj, function(v) { return v; });
551     }, assertErrorWithPath('.arr[1].a[1].b[1].c[1]'), 'Should throw when a circular reference is detected.');
552     test.done();
553   },
554 };