Skip to content

Instantly share code, notes, and snippets.

@thejoshwolfe
Created August 23, 2017 21:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thejoshwolfe/bb00255524eeca6396269e1221c96a4a to your computer and use it in GitHub Desktop.
Save thejoshwolfe/bb00255524eeca6396269e1221c96a4a to your computer and use it in GitHub Desktop.
Idea for generic parameter type coercion checking
function verifyParameterToIndex(testCases) {
// TODO: Something similar to verifyParameterToInteger, possibly begin by calling it first.
// TODO: Then also test that outside [0, 2**53-1] throws a RangeError.
}
function verifyParameterToInteger(testCases) {
function MyError() {}
var simpleValues = [
[
// these values coerce to 0
undefined,
null,
false,
"",
"foo",
"true",
"0",
0,
0.9,
-0,
-0.9,
NaN,
], [
// these values coerce to 1
1,
1.9,
true,
]
];
for (var i = 0; i < 2; i++) {
var testCase = testCases[i];
simpleValues[i].forEach(function(value) {
if (Object.prototype.hasOwnProperty.call(testCase, "skip")) {
// this value is specially handled, so don't test the normal coercion.
if (Array.prototype.indexOf.call(testCase.skip, value) !== -1) return;
}
if (Object.prototype.hasOwnProperty.call(testCase, "expectedValue")) {
// value will be accepted and produce a result.
assert.sameValue(testCase.f(value), testCase.expectedValue);
} else if (Object.prototype.hasOwnProperty.call(testCase, "expectedError")) {
// value with cause the function to throw.
assert.throws(testCase.expectedError, function() {
testCase.f(value);
});
} else {
assert(false, "must define one of 'expectedValue' or 'expectedError'");
}
});
}
var testCase = testCases[2];
assert(Object.prototype.hasOwnProperty.call(testCase, "value"));
assert(Number.isInteger(testCase.value));
assert(Object.prototype.hasOwnProperty.call(testCase, "expectedValue"));
// already an integer
assert.sameValue(testCase.f(testCase.value), testCase.expectedValue);
// string to integer
assert.sameValue(testCase.f(testCase.value.toString()), testCase.expectedValue);
// unbox wrapped integer
assert.sameValue(testCase.f(Object(testCase.value)), testCase.expectedValue);
// unbox and also string to integer
assert.sameValue(testCase.f(Object(testCase.value.toString())), testCase.expectedValue);
// valueOf method
assert.sameValue(testCase.f({valueOf:()=>testCase.value}), testCase.expectedValue);
// toString method
assert.sameValue(testCase.f({toString:()=>testCase.value.toString()}), testCase.expectedValue);
// valueOf precedence over toString
assert.sameValue(testCase.f({valueOf:()=>testCase.value, toString(){throw new MyError();}}), testCase.expectedValue);
// cannot coerce Symbol to Number
assert.throws(TypeError, () => testCase.f(Symbol(0)));
// cannot coerce BigInt to Number
assert.throws(TypeError, () => testCase.f(1n));
// propagate errors from valueOf
assert.throws(MyError, () => testCase.f({valueOf(){throw new MyError();}}));
// propagate errors from toString
assert.throws(MyError, () => testCase.f({toString(){throw new MyError();}}));
// propagate errors from valueOf without consulting toString
assert.throws(MyError, () => testCase.f({valueOf(){throw new MyError();}, toString:()=>testCase.value.toString()}));
}
verifyParameterToIndex([
{ f: (zero) => BigInt.asIntN(zero, 1n), expectedValue: 0n },
{ f: (one) => BigInt.asIntN(one, 1n), expectedValue: -1n },
{ f: (other) => BigInt.asIntN(other, 10n), value: 3, expectedValue: 2n },
]);
verifyParameterToInteger([
{ f: (zero) => 100n.toString(zero), expectedError: RangeError, skip: [undefined] },
{ f: (one) => 100n.toString(one), expectedError: RangeError },
{ f: (other) => 100n.toString(other), value: 16, expectedValue: "64" },
]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment