Files
lodash/test/test-fp-doc.js
2016-02-09 19:36:37 -08:00

581 lines
17 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;(function() {
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
var undefined;
/** Used as a reference to the global object. */
var root = (typeof global == 'object' && global) || this;
var phantom = root.phantom,
amd = root.define && define.amd,
document = !phantom && root.document,
noop = function() {},
argv = root.process && process.argv;
/** Use a single "load" function. */
var load = (!amd && typeof require == 'function')
? require
: noop;
/** The unit testing framework. */
var QUnit = root.QUnit || (root.QUnit = (
QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit,
QUnit = QUnit.QUnit || QUnit
));
/** Load stable Lodash and QUnit Extras. */
var _ = root._ || load('../lodash.js');
if (_) {
_ = _.runInContext(root);
}
var QUnitExtras = load('../node_modules/qunit-extras/qunit-extras.js');
if (QUnitExtras) {
QUnitExtras.runInContext(root);
}
var mapping = root.mapping || load('../fp/_mapping.js'),
applyFPMapping = load('../lib/doc/apply-fp-mapping'),
Entry = load('docdown/lib/entry');
/*--------------------------------------------------------------------------*/
function toCommentLine(line) {
return ' * ' + line;
}
function toEntry(name, paramLines, exampleLines, attachedToPrototype) {
var start = [
'/**',
' * ',
' * Foo',
' * '
];
var end = [
' */',
'function ' + name + '(a, b, c) {',
'',
'}'
];
var staticLine = attachedToPrototype ? [] : [' * @static'];
var params = paramLines.map(function(line) {
return ' * @param ' + line;
});
var example = (exampleLines || []).map(toCommentLine);
return [].concat(start, staticLine, params, [' * @example'], example, end).join('\n');
}
var differenceBySource = toEntry('differenceBy', [
'{Array} array The array to inspect.',
'{...Array} [values] The values to exclude.',
'{Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.'
], [
'_.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);',
'// → [3.1, 1.3]',
'',
'// The `_.property` iteratee shorthand.',
"_.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');",
"// → [{ 'x': 2 }]"
]);
var setParams = [
'{Object} object The object to modify.',
'{Array|string} path The path of the property to set.',
'{*} value The value to set.'
];
/*--------------------------------------------------------------------------*/
if (argv) {
console.log('Running doc generation tests.');
}
mapping.aryMethod[2].push('customFun');
applyFPMapping(mapping);
/*--------------------------------------------------------------------------*/
QUnit.module('getExample');
(function() {
QUnit.test('should reorder parameters', function(assert) {
assert.expect(1);
var entry = new Entry(differenceBySource, differenceBySource);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'_.differenceBy(Math.floor, [4.4, 2.5], [3.1, 2.2, 1.3]);',
'// → [3.1, 1.3]',
'',
'// The `_.property` iteratee shorthand.',
"_.differenceBy('x', [{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }]);",
"// → [{ 'x': 2 }]",
'```'
].join('\n'));
});
QUnit.test('should reorder parameters that have a special order', function(assert) {
assert.expect(1);
var example = toEntry('set', setParams, [
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"_.set(object, 'a[0].b.c', 4);",
"_.set(object, 'x[0].y.z', 5);",
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"_.set('a[0].b.c', 4, object);",
"_.set('x[0].y.z', 5, object);",
'```'
].join('\n'));
});
QUnit.test('should preserve comments', function(assert) {
assert.expect(1);
var example = toEntry('set', setParams, [
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"_.set(object, 'a[0].b.c', 4);",
'// => 4',
"_.set(object, 'x[0].y.z', 5);",
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"_.set('a[0].b.c', 4, object);",
'// => 4',
"_.set('x[0].y.z', 5, object);",
'```'
].join('\n'));
});
QUnit.test('should remove console.logs from example', function(assert) {
assert.expect(1);
var example = toEntry('set', setParams, [
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
'',
"_.set(object, 'a[0].b.c', 4);",
'console.log(object.a[0].b.c);',
'// => 4',
'',
"_.set(object, 'x[0].y.z', 5);",
'console.log(object.x[0].y.z);',
'// => 5'
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
'',
"_.set('a[0].b.c', 4, object);",
'// => 4',
'',
"_.set('x[0].y.z', 5, object);",
'// => 5',
'```'
].join('\n'));
});
QUnit.test('should merge extra arguments into an array', function(assert) {
assert.expect(1);
var example = toEntry('pullAt', [
'{Array} array The array to modify.',
'{...(number|number[])} [indexes] The indexes of elements to remove,\n' +
' * specified individually or in arrays.'
], [
'var array = [5, 10, 15, 20];',
'var evens = _.pullAt(array, 1, 3);',
'',
'console.log(array);',
'// => [5, 15]',
'',
'console.log(evens);',
'// => [10, 20]'
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'var array = [5, 10, 15, 20];',
'var evens = _.pullAt([1, 3], array);',
'',
'// => [5, 15]',
'',
'// => [10, 20]',
'```'
].join('\n'));
});
QUnit.test('should inject default values into optional arguments that became compulsory', function(assert) {
assert.expect(1);
var example = toEntry('sampleSize', [
'{Array|Object} collection The collection to sample.',
'{number} [n=0] The number of elements to sample.'
], [
'_.sampleSize([1, 2, 3]);',
'// => [3, 1]',
'',
'_.sampleSize([1, 2, 3], 4);',
'// => [2, 3, 1]'
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'_.sampleSize(0, [1, 2, 3]);',
'// => [3, 1]',
'',
'_.sampleSize(4, [1, 2, 3]);',
'// => [2, 3, 1]',
'```'
].join('\n'));
});
QUnit.test('should inject referenced values into optional arguments that became compulsory, ' +
'if a parameter\'s default value references parameter (direct reference)',
function(assert) {
assert.expect(1);
var example = toEntry('customFun', [
'{Array} array Array',
'{number} [foo=array] Foo'
], [
'_.customFun([1, 2, 3]);',
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'_.customFun([1, 2, 3], [1, 2, 3]);',
'```'
].join('\n'));
});
QUnit.test('should inject referenced values into optional arguments that became compulsory, ' +
'if a parameter\'s default value references parameter (member expression)',
function(assert) {
assert.expect(1);
var example = toEntry('fill', [
'{Array} array The array to fill.',
'{*} value The value to fill `array` with.',
'{number} [start=0] The start position.',
'{number} [end=array.length] The end position.'
], [
'var array = [1, 2, 3];',
'',
"_.fill(array, 'a');",
'console.log(array);',
"// => ['a', 'a', 'a']",
'',
'_.fill(Array(3), 2, 1);',
'// => [undefined, 2, 2]',
'',
"_.fill([4, 6, 8, 10], '*');",
"// => [*, '*', '*', *]"
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'var array = [1, 2, 3];',
'',
"_.fill(0, array.length, 'a', array);",
"// => ['a', 'a', 'a']",
'',
'_.fill(1, 3, 2, Array(3));',
'// => [undefined, 2, 2]',
'',
"_.fill(0, 4, '*', [4, 6, 8, 10]);",
"// => [*, '*', '*', *]",
'```'
].join('\n'));
});
QUnit.test('should inject default values in the middle of the arguments', function(assert) {
assert.expect(1);
var example = toEntry('inRange', [
'{number} number The number to check.',
'{number} [start=0] The start of the range.',
'{number} end The end of the range.'
], [
'_.inRange(4, 8);',
'// => true'
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'_.inRange(8, 0, 4);',
'// => true',
'```'
].join('\n'));
});
QUnit.test('should not use ignored params as default values', function(assert) {
assert.expect(1);
var example = toEntry('drop', [
'{Array} array The array to query.',
'{number} [n=1] The number of elements to drop.',
'{Object} [guard] Enables use as an iteratee for functions like `_.map`.'
], [
'_.drop([1, 2, 3]);',
'// => [2, 3]'
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
'```js',
'_.drop(1, [1, 2, 3]);',
'// => [2, 3]',
'```'
].join('\n'));
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('getParams');
(function() {
QUnit.test('should reorder arguments and remove default values', function(assert) {
assert.expect(1);
var example = toEntry('differenceBy', [
'{Array} array The array to inspect.',
'{...Array} [values] The values to exclude.',
'{Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['Function|Object|string', 'iteratee', 'The iteratee invoked per element. '],
['Array|Array[]', 'values', 'The values to exclude. '],
['Array', 'array', 'The array to inspect. ']
]);
});
QUnit.test('should reorder arguments that have a special order', function(assert) {
assert.expect(1);
var example = toEntry('set', [
'{Object} object The object to modify.',
'{Array|string} path The path of the property to set.',
'{*} value The value to set.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['Array|string', 'path', 'The path of the property to set. '],
['*', 'value', 'The value to set. '],
['Object', 'object', 'The object to modify. '],
]);
});
QUnit.test('should transform rest arguments into an array', function(assert) {
assert.expect(1);
var example = toEntry('pullAt', [
'{Array} array The array to modify.',
'{...(number|number[])} [indexes] The indexes of elements to remove,\n' +
' * specified individually or in arrays.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
// TODO Remove this line in favor of the commented one.
// Is linked to a docdown issue (https://github.com/jdalton/docdown/pull/37)
// that does not handle parens in the arguments well
['((number|number)|((number|number)[]', 'indexes', 'The indexes of elements to remove, specified individually or in arrays. '],
// ['number|number[]', '[indexes]', 'The indexes of elements to remove, specified individually or in arrays. '],
['Array', 'array', 'The array to modify. '],
]);
});
QUnit.test('should duplicate and de-restify "rest" parameters if there are less parameters than cap', function(assert) {
assert.expect(1);
var example = toEntry('intersectionWith', [
'{...Array} [arrays] The arrays to inspect.',
'{Function} [comparator] The comparator invoked per element.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['Function', 'comparator', 'The comparator invoked per element. '],
['Array', 'arrays', 'The arrays to inspect. '],
['Array', 'arrays', 'The arrays to inspect. ']
]);
});
QUnit.test('should consider method to have an ary of `ary - 1` when capped and wrapped', function(assert) {
assert.expect(1);
var wrapped = true;
var example = toEntry('flatMap', [
'{Array} array The array to iterate over.',
'{Function|Object|string} [iteratee=_.identity] The function invoked per iteration.'
], [], wrapped);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['Function|Object|string', 'iteratee', 'The function invoked per iteration. ']
]);
});
QUnit.test('should remove arguments ignored because of capping (includes)', function(assert) {
assert.expect(1);
var example = toEntry('includes', [
'{Array|Object|string} collection The collection to search.',
'{*} value The value to search for.',
'{number} [fromIndex=0] The index to search from.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['*', 'value', 'The value to search for. '],
['Array|Object|string', 'collection', 'The collection to search. ']
]);
});
QUnit.test('should remove arguments ignored because of capping (trim)', function(assert) {
assert.expect(1);
var example = toEntry('trim', [
"{string} [string=''] The string to trim.",
'{string} [chars=whitespace] The characters to trim.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['string', 'string', 'The string to trim. ']
]);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('getDesc');
(function() {
function toSourceWithDescription(name, description) {
var start = [
'/**',
' * '
];
var end = [
' * @static',
' * ',
' */',
'function ' + name + '(a, b, c) {',
'',
'}'
];
var descriptionLines = description.map(toCommentLine);
return [].concat(start, descriptionLines, end).join('\n');
}
QUnit.test('should remove notes about mutators arguments and remove default values', function(assert) {
assert.expect(1);
var example = toSourceWithDescription('pullAt', [
'Removes elements from `array` corresponding to `indexes` and returns an',
'array of removed elements.',
'',
'**Note:** Unlike `_.at`, this method mutates `array`.',
''
]);
var entry = new Entry(example, example);
var actual = entry.getDesc();
assert.equal(actual, [
'Removes elements from `array` corresponding to `indexes` and returns an',
'array of removed elements.'
].join('\n'));
});
QUnit.test('should remove following related lines', function(assert) {
assert.expect(1);
var example = toSourceWithDescription('assign', [
'Assigns own enumerable properties of source objects to the destination',
'object. Source objects are applied from left to right. Subsequent sources',
'overwrite property assignments of previous sources.',
'',
'**Note:** This method mutates `object` and is loosely based on',
'[`Object.assign`](https://mdn.io/Object/assign).',
''
]);
var entry = new Entry(example, example);
var actual = entry.getDesc();
assert.equal(actual, [
'Assigns own enumerable properties of source objects to the destination',
'object. Source objects are applied from left to right. Subsequent sources',
'overwrite property assignments of previous sources.',
].join('\n'));
});
}());
QUnit.config.asyncRetries = 10;
QUnit.config.hidepassed = true;
if (!document) {
QUnit.config.noglobals = true;
QUnit.load();
}
}.call(this));