mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-29 06:27:49 +00:00
261 lines
9.6 KiB
JavaScript
261 lines
9.6 KiB
JavaScript
import lodashStable from 'lodash';
|
|
|
|
import {
|
|
_,
|
|
identity,
|
|
whitespace,
|
|
MAX_SAFE_INTEGER,
|
|
MAX_INTEGER,
|
|
MAX_ARRAY_LENGTH,
|
|
symbol,
|
|
falsey,
|
|
} from './utils';
|
|
|
|
describe('number coercion methods', () => {
|
|
lodashStable.each(['toFinite', 'toInteger', 'toNumber', 'toSafeInteger'], (methodName) => {
|
|
const func = _[methodName];
|
|
|
|
it(`\`_.${methodName}\` should preserve the sign of \`0\``, () => {
|
|
const values = [0, '0', -0, '-0'];
|
|
const expected = [
|
|
[0, Infinity],
|
|
[0, Infinity],
|
|
[-0, -Infinity],
|
|
[-0, -Infinity],
|
|
];
|
|
|
|
lodashStable.times(2, (index) => {
|
|
const others = lodashStable.map(values, index ? Object : identity);
|
|
|
|
const actual = lodashStable.map(others, (value) => {
|
|
const result = func(value);
|
|
return [result, 1 / result];
|
|
});
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
});
|
|
|
|
lodashStable.each(
|
|
['toFinite', 'toInteger', 'toLength', 'toNumber', 'toSafeInteger'],
|
|
(methodName) => {
|
|
const func = _[methodName];
|
|
const isToFinite = methodName === 'toFinite';
|
|
const isToLength = methodName === 'toLength';
|
|
const isToNumber = methodName === 'toNumber';
|
|
const isToSafeInteger = methodName === 'toSafeInteger';
|
|
|
|
function negative(string) {
|
|
return `-${string}`;
|
|
}
|
|
|
|
function pad(string) {
|
|
return whitespace + string + whitespace;
|
|
}
|
|
|
|
function positive(string) {
|
|
return `+${string}`;
|
|
}
|
|
|
|
it(`\`_.${methodName}\` should pass thru primitive number values`, () => {
|
|
const values = [0, 1, NaN];
|
|
|
|
const expected = lodashStable.map(values, (value) =>
|
|
!isToNumber && value !== value ? 0 : value,
|
|
);
|
|
|
|
const actual = lodashStable.map(values, func);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should convert number primitives and objects to numbers`, () => {
|
|
const values = [2, 1.2, MAX_SAFE_INTEGER, MAX_INTEGER, Infinity, NaN];
|
|
|
|
const expected = lodashStable.map(values, (value) => {
|
|
if (!isToNumber) {
|
|
if (!isToFinite && value === 1.2) {
|
|
value = 1;
|
|
} else if (value === Infinity) {
|
|
value = MAX_INTEGER;
|
|
} else if (value !== value) {
|
|
value = 0;
|
|
}
|
|
if (isToLength || isToSafeInteger) {
|
|
value = Math.min(
|
|
value,
|
|
isToLength ? MAX_ARRAY_LENGTH : MAX_SAFE_INTEGER,
|
|
);
|
|
}
|
|
}
|
|
const neg = isToLength ? 0 : -value;
|
|
return [value, value, neg, neg];
|
|
});
|
|
|
|
const actual = lodashStable.map(values, (value) => [
|
|
func(value),
|
|
func(Object(value)),
|
|
func(-value),
|
|
func(Object(-value)),
|
|
]);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should convert string primitives and objects to numbers`, () => {
|
|
const transforms = [identity, pad, positive, negative];
|
|
|
|
const values = [
|
|
'10',
|
|
'1.234567890',
|
|
`${MAX_SAFE_INTEGER}`,
|
|
'1e+308',
|
|
'1e308',
|
|
'1E+308',
|
|
'1E308',
|
|
'5e-324',
|
|
'5E-324',
|
|
'Infinity',
|
|
'NaN',
|
|
];
|
|
|
|
const expected = lodashStable.map(values, (value) => {
|
|
let n = +value;
|
|
if (!isToNumber) {
|
|
if (!isToFinite && n === 1.23456789) {
|
|
n = 1;
|
|
} else if (n === Infinity) {
|
|
n = MAX_INTEGER;
|
|
} else if ((!isToFinite && n === Number.MIN_VALUE) || n !== n) {
|
|
n = 0;
|
|
}
|
|
if (isToLength || isToSafeInteger) {
|
|
n = Math.min(n, isToLength ? MAX_ARRAY_LENGTH : MAX_SAFE_INTEGER);
|
|
}
|
|
}
|
|
const neg = isToLength ? 0 : -n;
|
|
return [n, n, n, n, n, n, neg, neg];
|
|
});
|
|
|
|
const actual = lodashStable.map(values, (value) =>
|
|
lodashStable.flatMap(transforms, (mod) => [
|
|
func(mod(value)),
|
|
func(Object(mod(value))),
|
|
]),
|
|
);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should convert binary/octal strings to numbers`, () => {
|
|
const numbers = [42, 5349, 1715004];
|
|
const transforms = [identity, pad];
|
|
const values = ['0b101010', '0o12345', '0x1a2b3c'];
|
|
|
|
const expected = lodashStable.map(numbers, (n) =>
|
|
lodashStable.times(8, lodashStable.constant(n)),
|
|
);
|
|
|
|
const actual = lodashStable.map(values, (value) => {
|
|
const upper = value.toUpperCase();
|
|
return lodashStable.flatMap(transforms, (mod) => [
|
|
func(mod(value)),
|
|
func(Object(mod(value))),
|
|
func(mod(upper)),
|
|
func(Object(mod(upper))),
|
|
]);
|
|
});
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should convert invalid binary/octal strings to \`${
|
|
isToNumber ? 'NaN' : '0'
|
|
}\``, () => {
|
|
const transforms = [identity, pad, positive, negative];
|
|
const values = ['0b', '0o', '0x', '0b1010102', '0o123458', '0x1a2b3x'];
|
|
|
|
const expected = lodashStable.map(values, (n) =>
|
|
lodashStable.times(8, lodashStable.constant(isToNumber ? NaN : 0)),
|
|
);
|
|
|
|
const actual = lodashStable.map(values, (value) =>
|
|
lodashStable.flatMap(transforms, (mod) => [
|
|
func(mod(value)),
|
|
func(Object(mod(value))),
|
|
]),
|
|
);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should convert symbols to \`${
|
|
isToNumber ? 'NaN' : '0'
|
|
}\``, () => {
|
|
if (Symbol) {
|
|
const object1 = Object(symbol);
|
|
const object2 = Object(symbol);
|
|
const values = [symbol, object1, object2];
|
|
const expected = lodashStable.map(
|
|
values,
|
|
lodashStable.constant(isToNumber ? NaN : 0),
|
|
);
|
|
|
|
object2.valueOf = undefined;
|
|
const actual = lodashStable.map(values, func);
|
|
|
|
expect(actual).toEqual(expected);
|
|
}
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should convert empty values to \`0\` or \`NaN\``, () => {
|
|
const values = falsey.concat(whitespace);
|
|
|
|
const expected = lodashStable.map(values, (value) =>
|
|
isToNumber && value !== whitespace ? Number(value) : 0,
|
|
);
|
|
|
|
const actual = lodashStable.map(values, (value, index) =>
|
|
index ? func(value) : func(),
|
|
);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it(`\`_.${methodName}\` should coerce objects to numbers`, () => {
|
|
const values = [
|
|
{},
|
|
[],
|
|
[1],
|
|
[1, 2],
|
|
{ valueOf: '1.1' },
|
|
{ valueOf: '1.1', toString: lodashStable.constant('2.2') },
|
|
{ valueOf: lodashStable.constant('1.1'), toString: '2.2' },
|
|
{
|
|
valueOf: lodashStable.constant('1.1'),
|
|
toString: lodashStable.constant('2.2'),
|
|
},
|
|
{ valueOf: lodashStable.constant('-0x1a2b3c') },
|
|
{ toString: lodashStable.constant('-0x1a2b3c') },
|
|
{ valueOf: lodashStable.constant('0o12345') },
|
|
{ toString: lodashStable.constant('0o12345') },
|
|
{ valueOf: lodashStable.constant('0b101010') },
|
|
{ toString: lodashStable.constant('0b101010') },
|
|
];
|
|
|
|
let expected = [NaN, 0, 1, NaN, NaN, 2.2, 1.1, 1.1, NaN, NaN, 5349, 5349, 42, 42];
|
|
|
|
if (isToFinite) {
|
|
expected = [0, 0, 1, 0, 0, 2.2, 1.1, 1.1, 0, 0, 5349, 5349, 42, 42];
|
|
} else if (!isToNumber) {
|
|
expected = [0, 0, 1, 0, 0, 2, 1, 1, 0, 0, 5349, 5349, 42, 42];
|
|
}
|
|
const actual = lodashStable.map(values, func);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
},
|
|
);
|
|
});
|