UNPKG

react-klasha

Version:

This is an reactJS library for implementing klasha payment gateway

1,201 lines (1,023 loc) 222 kB
'use strict'; var tape = require('tape'); var forEach = require('foreach'); var debug = require('object-inspect'); var assign = require('object.assign'); var keys = require('object-keys'); var has = require('has'); var arrowFns = require('make-arrow-function').list(); var hasStrictMode = require('has-strict-mode')(); var functionsHaveNames = require('functions-have-names')(); var functionsHaveConfigurableNames = require('functions-have-names').functionsHaveConfigurableNames(); var hasBigInts = require('has-bigints')(); var $getProto = require('../helpers/getProto'); var $setProto = require('../helpers/setProto'); var defineProperty = require('./helpers/defineProperty'); var getInferredName = require('../helpers/getInferredName'); var getOwnPropertyDescriptor = require('../helpers/getOwnPropertyDescriptor'); var assertRecordTests = require('./helpers/assertRecord'); var v = require('es-value-fixtures'); var diffOps = require('./diffOps'); var $BigInt = hasBigInts ? BigInt : null; var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1; var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false // IE 9 does not throw in strict mode when writability/configurability/extensibility is violated var noThrowOnStrictViolation = (function () { try { delete [].length; return true; } catch (e) { } return false; }()); var makeTest = function makeTest(skips) { return function test(opName, maybeOpts, maybeCb) { var origOpts = arguments.length > 2 ? maybeOpts : {}; var opts = assign( {}, origOpts, { skip: (skips && skips[opName]) || origOpts.skip } ); var cb = arguments.length > 2 ? maybeCb : maybeOpts; return tape(opName, opts, cb); }; }; var leadingPoo = '\uD83D'; var trailingPoo = '\uDCA9'; var wholePoo = leadingPoo + trailingPoo; var getArraySubclassWithSpeciesConstructor = function getArraySubclass(speciesConstructor) { var Bar = function Bar() { var inst = []; Object.setPrototypeOf(inst, Bar.prototype); defineProperty(inst, 'constructor', { value: Bar }); return inst; }; Bar.prototype = Object.create(Array.prototype); Object.setPrototypeOf(Bar, Array); defineProperty(Bar, Symbol.species, { value: speciesConstructor }); return Bar; }; var testIterator = function (t, iterator, expected) { var resultCount = 0; var result; while (result = iterator.next(), !result.done) { // eslint-disable-line no-sequences t.deepEqual(result, { done: false, value: expected[resultCount] }, 'result ' + resultCount); resultCount += 1; } t.equal(resultCount, expected.length, 'expected ' + expected.length + ', got ' + resultCount); }; var hasSpecies = v.hasSymbols && Symbol.species; var hasLastIndex = 'lastIndex' in (/a/).exec('a'); // IE 8 var hasGroups = 'groups' in (/a/).exec('a'); // modern engines var kludgeMatch = function kludgeMatch(R, matchObject) { if (hasGroups) { assign(matchObject, { groups: matchObject.groups }); } if (hasLastIndex) { assign(matchObject, { lastIndex: R.lastIndex }); } return matchObject; }; var testEnumerableOwnNames = function (t, enumerableOwnNames) { forEach(v.primitives, function (nonObject) { t['throws']( function () { enumerableOwnNames(nonObject); }, debug(nonObject) + ' is not an Object' ); }); var Child = function Child() { this.own = {}; }; Child.prototype = { inherited: {} }; var obj = new Child(); t.equal('own' in obj, true, 'has "own"'); t.equal(has(obj, 'own'), true, 'has own "own"'); t.equal(Object.prototype.propertyIsEnumerable.call(obj, 'own'), true, 'has enumerable "own"'); t.equal('inherited' in obj, true, 'has "inherited"'); t.equal(has(obj, 'inherited'), false, 'has non-own "inherited"'); t.equal(has(Child.prototype, 'inherited'), true, 'Child.prototype has own "inherited"'); t.equal(Child.prototype.inherited, obj.inherited, 'Child.prototype.inherited === obj.inherited'); t.equal(Object.prototype.propertyIsEnumerable.call(Child.prototype, 'inherited'), true, 'has enumerable "inherited"'); t.equal('toString' in obj, true, 'has "toString"'); t.equal(has(obj, 'toString'), false, 'has non-own "toString"'); t.equal(has(Object.prototype, 'toString'), true, 'Object.prototype has own "toString"'); t.equal(Object.prototype.toString, obj.toString, 'Object.prototype.toString === obj.toString'); // eslint-disable-next-line no-useless-call t.equal(Object.prototype.propertyIsEnumerable.call(Object.prototype, 'toString'), false, 'has non-enumerable "toString"'); return obj; }; var testToNumber = function (t, ES, ToNumber) { t.equal(NaN, ToNumber(undefined), 'undefined coerces to NaN'); t.equal(ToNumber(null), 0, 'null coerces to +0'); t.equal(ToNumber(false), 0, 'false coerces to +0'); t.equal(1, ToNumber(true), 'true coerces to 1'); t.test('numbers', function (st) { st.equal(NaN, ToNumber(NaN), 'NaN returns itself'); forEach(v.zeroes.concat(v.infinities, 42), function (num) { st.equal(num, ToNumber(num), num + ' returns itself'); }); forEach(['foo', '0', '4a', '2.0', 'Infinity', '-Infinity'], function (numString) { st.equal(+numString, ToNumber(numString), '"' + numString + '" coerces to ' + Number(numString)); }); st.end(); }); t.test('objects', function (st) { forEach(v.objects, function (object) { st.equal(ToNumber(object), ToNumber(ES.ToPrimitive(object)), 'object ' + object + ' coerces to same as ToPrimitive of object does'); }); st['throws'](function () { return ToNumber(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); st.end(); }); // TODO: check if this applies to ES5 t.test('binary literals', function (st) { st.equal(ToNumber('0b10'), 2, '0b10 is 2'); st.equal(ToNumber({ toString: function () { return '0b11'; } }), 3, 'Object that toStrings to 0b11 is 3'); st.equal(ToNumber('0b12'), NaN, '0b12 is NaN'); st.equal(ToNumber({ toString: function () { return '0b112'; } }), NaN, 'Object that toStrings to 0b112 is NaN'); st.end(); }); // TODO: check if this applies to ES5 t.test('octal literals', function (st) { st.equal(ToNumber('0o10'), 8, '0o10 is 8'); st.equal(ToNumber({ toString: function () { return '0o11'; } }), 9, 'Object that toStrings to 0o11 is 9'); st.equal(ToNumber('0o18'), NaN, '0o18 is NaN'); st.equal(ToNumber({ toString: function () { return '0o118'; } }), NaN, 'Object that toStrings to 0o118 is NaN'); st.end(); }); // TODO: check if this applies to ES5 t.test('signed hex numbers', function (st) { st.equal(ToNumber('-0xF'), NaN, '-0xF is NaN'); st.equal(ToNumber(' -0xF '), NaN, 'space-padded -0xF is NaN'); st.equal(ToNumber('+0xF'), NaN, '+0xF is NaN'); st.equal(ToNumber(' +0xF '), NaN, 'space-padded +0xF is NaN'); st.end(); }); // TODO: check if this applies to ES5 t.test('trimming of whitespace and non-whitespace characters', function (st) { var whitespace = ' \t\x0b\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'; st.equal(0, ToNumber(whitespace + 0 + whitespace), 'whitespace is trimmed'); // Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace. var nonWhitespaces = { '\\u0085': '\u0085', '\\u200b': '\u200b', '\\ufffe': '\ufffe' }; forEach(nonWhitespaces, function (desc, nonWS) { st.equal(ToNumber(nonWS + 0 + nonWS), NaN, 'non-whitespace ' + desc + ' not trimmed'); }); st.end(); }); // TODO: skip for ES5 forEach(v.symbols, function (symbol) { t['throws']( function () { ToNumber(symbol); }, TypeError, 'Symbols can’t be converted to a Number: ' + debug(symbol) ); var boxed = Object(symbol); t['throws']( function () { ToNumber(boxed); }, TypeError, 'boxed Symbols can’t be converted to a Number: ' + debug(boxed) ); }); // TODO: check if this applies to ES5 t.test('dates', function (st) { var invalid = new Date(NaN); st.equal(ToNumber(invalid), NaN, 'invalid Date coerces to NaN'); var now = +new Date(); st.equal(ToNumber(new Date(now)), now, 'Date coerces to timestamp'); st.end(); }); }; var es5 = function ES5(ES, ops, expectedMissing, skips) { var test = makeTest(skips); test('has expected operations', function (t) { var diff = diffOps(ES, ops, expectedMissing); t.deepEqual(diff.extra, [], 'no extra ops'); t.deepEqual(diff.missing, [], 'no unexpected missing ops'); t.deepEqual(diff.extraMissing, [], 'no unexpected "expected missing" ops'); t.end(); }); test('ToPrimitive', function (t) { t.test('primitives', function (st) { var testPrimitive = function (primitive) { st.equal(ES.ToPrimitive(primitive), primitive, debug(primitive) + ' is returned correctly'); }; forEach(v.primitives, testPrimitive); st.end(); }); t.test('objects', function (st) { st.equal(ES.ToPrimitive(v.coercibleObject), 3, 'coercibleObject with no hint coerces to valueOf'); st.equal(ES.ToPrimitive({}), '[object Object]', '{} with no hint coerces to Object#toString'); st.equal(ES.ToPrimitive(v.coercibleObject, Number), 3, 'coercibleObject with hint Number coerces to valueOf'); st.equal(ES.ToPrimitive({}, Number), '[object Object]', '{} with hint Number coerces to NaN'); st.equal(ES.ToPrimitive(v.coercibleObject, String), 42, 'coercibleObject with hint String coerces to nonstringified toString'); st.equal(ES.ToPrimitive({}, String), '[object Object]', '{} with hint String coerces to Object#toString'); st.equal(ES.ToPrimitive(v.coercibleFnObject), v.coercibleFnObject.toString(), 'coercibleFnObject coerces to toString'); st.equal(ES.ToPrimitive(v.toStringOnlyObject), 7, 'toStringOnlyObject returns non-stringified toString'); st.equal(ES.ToPrimitive(v.valueOfOnlyObject), 4, 'valueOfOnlyObject returns valueOf'); st['throws'](function () { return ES.ToPrimitive(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws a TypeError'); st['throws'](function () { return ES.ToPrimitive(v.uncoercibleFnObject); }, TypeError, 'uncoercibleFnObject throws a TypeError'); st.end(); }); t.test('dates', function (st) { var invalid = new Date(NaN); st.equal(ES.ToPrimitive(invalid), Date.prototype.toString.call(invalid), 'invalid Date coerces to Date#toString'); var now = new Date(); st.equal(ES.ToPrimitive(now), Date.prototype.toString.call(now), 'Date coerces to Date#toString'); st.end(); }); t.end(); }); test('ToBoolean', function (t) { t.equal(false, ES.ToBoolean(undefined), 'undefined coerces to false'); t.equal(false, ES.ToBoolean(null), 'null coerces to false'); t.equal(false, ES.ToBoolean(false), 'false returns false'); t.equal(true, ES.ToBoolean(true), 'true returns true'); t.test('numbers', function (st) { forEach(v.zeroes.concat(NaN), function (falsyNumber) { st.equal(false, ES.ToBoolean(falsyNumber), 'falsy number ' + falsyNumber + ' coerces to false'); }); forEach(v.infinities.concat([42, 1]), function (truthyNumber) { st.equal(true, ES.ToBoolean(truthyNumber), 'truthy number ' + truthyNumber + ' coerces to true'); }); st.end(); }); t.equal(false, ES.ToBoolean(''), 'empty string coerces to false'); t.equal(true, ES.ToBoolean('foo'), 'nonempty string coerces to true'); t.test('objects', function (st) { forEach(v.objects, function (obj) { st.equal(true, ES.ToBoolean(obj), 'object coerces to true'); }); st.equal(true, ES.ToBoolean(v.uncoercibleObject), 'uncoercibleObject coerces to true'); st.end(); }); t.end(); }); test('ToNumber', function (t) { t.equal(NaN, ES.ToNumber(undefined), 'undefined coerces to NaN'); t.equal(ES.ToNumber(null), 0, 'null coerces to +0'); t.equal(ES.ToNumber(false), 0, 'false coerces to +0'); t.equal(1, ES.ToNumber(true), 'true coerces to 1'); t.test('numbers', function (st) { st.equal(NaN, ES.ToNumber(NaN), 'NaN returns itself'); forEach(v.zeroes.concat(v.infinities, 42), function (num) { st.equal(num, ES.ToNumber(num), num + ' returns itself'); }); forEach(['foo', '0', '4a', '2.0', 'Infinity', '-Infinity'], function (numString) { st.equal(+numString, ES.ToNumber(numString), '"' + numString + '" coerces to ' + Number(numString)); }); st.end(); }); t.test('objects', function (st) { forEach(v.objects, function (object) { st.equal(ES.ToNumber(object), ES.ToNumber(ES.ToPrimitive(object)), 'object ' + object + ' coerces to same as ToPrimitive of object does'); }); st['throws'](function () { return ES.ToNumber(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); st.end(); }); t.test('binary literals', function (st) { st.equal(ES.ToNumber('0b10'), NaN, '0b10 is NaN'); st.equal(ES.ToNumber({ toString: function () { return '0b11'; } }), NaN, 'Object that toStrings to 0b11 is NaN'); st.equal(ES.ToNumber('0b12'), NaN, '0b12 is NaN'); st.equal(ES.ToNumber({ toString: function () { return '0b112'; } }), NaN, 'Object that toStrings to 0b112 is NaN'); st.end(); }); t.test('octal literals', function (st) { st.equal(ES.ToNumber('0o10'), NaN, '0o10 is NaN'); st.equal(ES.ToNumber({ toString: function () { return '0o11'; } }), NaN, 'Object that toStrings to 0o11 is NaN'); st.equal(ES.ToNumber('0o18'), NaN, '0o18 is NaN'); st.equal(ES.ToNumber({ toString: function () { return '0o118'; } }), NaN, 'Object that toStrings to 0o118 is NaN'); st.end(); }); t.test('signed hex numbers', function (st) { st.equal(ES.ToNumber('-0xF'), NaN, '-0xF is NaN'); st.equal(ES.ToNumber(' -0xF '), NaN, 'space-padded -0xF is NaN'); st.equal(ES.ToNumber('+0xF'), NaN, '+0xF is NaN'); st.equal(ES.ToNumber(' +0xF '), NaN, 'space-padded +0xF is NaN'); st.end(); }); // TODO: check if this applies to ES5 t.test('trimming of whitespace and non-whitespace characters', function (st) { var whitespace = ' \t\x0b\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u0085'; st.equal(ES.ToNumber(whitespace + 0 + whitespace), 0, 'whitespace is trimmed'); // Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace. var nonWhitespaces = { '\\u200b': '\u200b', '\\ufffe': '\ufffe' }; forEach(nonWhitespaces, function (desc, nonWS) { st.equal(ES.ToNumber(nonWS + 0 + nonWS), NaN, 'non-whitespace ' + desc + ' not trimmed'); }); st.end(); }); t.test('dates', function (st) { var invalid = new Date(NaN); st.equal(ES.ToNumber(invalid), NaN, 'invalid Date coerces to NaN'); var now = +new Date(); st.equal(ES.ToNumber(new Date(now)), now, 'Date coerces to timestamp'); st.end(); }); t.end(); }); test('ToInteger', function (t) { forEach([NaN], function (num) { t.equal(0, ES.ToInteger(num), debug(num) + ' returns +0'); }); forEach(v.zeroes.concat(v.infinities, 42), function (num) { t.equal(num, ES.ToInteger(num), debug(num) + ' returns itself'); t.equal(-num, ES.ToInteger(-num), '-' + debug(num) + ' returns itself'); }); t.equal(3, ES.ToInteger(Math.PI), 'pi returns 3'); t['throws'](function () { return ES.ToInteger(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); t.end(); }); test('ToInt32', function (t) { t.equal(ES.ToInt32(NaN), 0, 'NaN coerces to +0'); forEach(v.zeroes.concat(v.infinities), function (num) { t.equal(ES.ToInt32(num), 0, num + ' returns +0'); t.equal(ES.ToInt32(-num), 0, '-' + num + ' returns +0'); }); t['throws'](function () { return ES.ToInt32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); t.equal(ES.ToInt32(0x100000000), 0, '2^32 returns +0'); t.equal(ES.ToInt32(0x100000000 - 1), -1, '2^32 - 1 returns -1'); t.equal(ES.ToInt32(0x80000000), -0x80000000, '2^31 returns -2^31'); t.equal(ES.ToInt32(0x80000000 - 1), 0x80000000 - 1, '2^31 - 1 returns 2^31 - 1'); forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) { t.equal(ES.ToInt32(num), ES.ToInt32(ES.ToUint32(num)), 'ToInt32(x) === ToInt32(ToUint32(x)) for 0x' + num.toString(16)); t.equal(ES.ToInt32(-num), ES.ToInt32(ES.ToUint32(-num)), 'ToInt32(x) === ToInt32(ToUint32(x)) for -0x' + num.toString(16)); }); t.end(); }); test('ToUint32', function (t) { t.equal(0, ES.ToUint32(NaN), 'NaN coerces to +0'); forEach([0, Infinity], function (num) { t.equal(0, ES.ToUint32(num), num + ' returns +0'); t.equal(0, ES.ToUint32(-num), '-' + num + ' returns +0'); }); t['throws'](function () { return ES.ToUint32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); t.equal(ES.ToUint32(0x100000000), 0, '2^32 returns +0'); t.equal(ES.ToUint32(0x100000000 - 1), 0x100000000 - 1, '2^32 - 1 returns 2^32 - 1'); t.equal(ES.ToUint32(0x80000000), 0x80000000, '2^31 returns 2^31'); t.equal(ES.ToUint32(0x80000000 - 1), 0x80000000 - 1, '2^31 - 1 returns 2^31 - 1'); forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) { t.equal(ES.ToUint32(num), ES.ToUint32(ES.ToInt32(num)), 'ToUint32(x) === ToUint32(ToInt32(x)) for 0x' + num.toString(16)); t.equal(ES.ToUint32(-num), ES.ToUint32(ES.ToInt32(-num)), 'ToUint32(x) === ToUint32(ToInt32(x)) for -0x' + num.toString(16)); }); t.end(); }); test('ToUint16', function (t) { t.equal(0, ES.ToUint16(NaN), 'NaN coerces to +0'); forEach([0, Infinity], function (num) { t.equal(0, ES.ToUint16(num), num + ' returns +0'); t.equal(0, ES.ToUint16(-num), '-' + num + ' returns +0'); }); t['throws'](function () { return ES.ToUint16(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); t.equal(ES.ToUint16(0x100000000), 0, '2^32 returns +0'); t.equal(ES.ToUint16(0x100000000 - 1), 0x10000 - 1, '2^32 - 1 returns 2^16 - 1'); t.equal(ES.ToUint16(0x80000000), 0, '2^31 returns +0'); t.equal(ES.ToUint16(0x80000000 - 1), 0x10000 - 1, '2^31 - 1 returns 2^16 - 1'); t.equal(ES.ToUint16(0x10000), 0, '2^16 returns +0'); t.equal(ES.ToUint16(0x10000 - 1), 0x10000 - 1, '2^16 - 1 returns 2^16 - 1'); t.end(); }); test('ToString', function (t) { forEach(v.objects.concat(v.nonSymbolPrimitives), function (item) { t.equal(ES.ToString(item), String(item), 'ES.ToString(' + debug(item) + ') ToStrings to String(' + debug(item) + ')'); }); t['throws'](function () { return ES.ToString(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws'); t.end(); }); test('ToObject', function (t) { t['throws'](function () { return ES.ToObject(undefined); }, TypeError, 'undefined throws'); t['throws'](function () { return ES.ToObject(null); }, TypeError, 'null throws'); forEach(v.numbers, function (number) { var obj = ES.ToObject(number); t.equal(typeof obj, 'object', 'number ' + number + ' coerces to object'); t.equal(true, obj instanceof Number, 'object of ' + number + ' is Number object'); t.equal(obj.valueOf(), number, 'object of ' + number + ' coerces to ' + number); }); t.end(); }); test('CheckObjectCoercible', function (t) { t['throws'](function () { return ES.CheckObjectCoercible(undefined); }, TypeError, 'undefined throws'); t['throws'](function () { return ES.CheckObjectCoercible(null); }, TypeError, 'null throws'); var checkCoercible = function (value) { t.doesNotThrow(function () { return ES.CheckObjectCoercible(value); }, debug(value) + ' does not throw'); }; forEach(v.objects.concat(v.nonNullPrimitives), checkCoercible); t.end(); }); test('IsCallable', function (t) { t.equal(true, ES.IsCallable(function () {}), 'function is callable'); var nonCallables = [/a/g, {}, Object.prototype, NaN].concat(v.nonFunctions); forEach(nonCallables, function (nonCallable) { t.equal(false, ES.IsCallable(nonCallable), debug(nonCallable) + ' is not callable'); }); t.end(); }); test('SameValue', function (t) { t.equal(true, ES.SameValue(NaN, NaN), 'NaN is SameValue as NaN'); t.equal(false, ES.SameValue(0, -0), '+0 is not SameValue as -0'); forEach(v.objects.concat(v.primitives), function (val) { t.equal(val === val, ES.SameValue(val, val), debug(val) + ' is SameValue to itself'); }); t.end(); }); test('Type', function (t) { t.equal(ES.Type(), 'Undefined', 'Type() is Undefined'); t.equal(ES.Type(undefined), 'Undefined', 'Type(undefined) is Undefined'); t.equal(ES.Type(null), 'Null', 'Type(null) is Null'); t.equal(ES.Type(true), 'Boolean', 'Type(true) is Boolean'); t.equal(ES.Type(false), 'Boolean', 'Type(false) is Boolean'); t.equal(ES.Type(0), 'Number', 'Type(0) is Number'); t.equal(ES.Type(NaN), 'Number', 'Type(NaN) is Number'); t.equal(ES.Type('abc'), 'String', 'Type("abc") is String'); t.equal(ES.Type(function () {}), 'Object', 'Type(function () {}) is Object'); t.equal(ES.Type({}), 'Object', 'Type({}) is Object'); t.end(); }); assertRecordTests(ES, test); test('IsAccessorDescriptor', function (t) { forEach(v.nonUndefinedPrimitives, function (primitive) { t['throws']( function () { ES.IsAccessorDescriptor(primitive); }, TypeError, debug(primitive) + ' is not a Property Descriptor' ); }); t.equal(ES.IsAccessorDescriptor(), false, 'no value is not an Accessor Descriptor'); t.equal(ES.IsAccessorDescriptor(undefined), false, 'undefined value is not an Accessor Descriptor'); t.equal(ES.IsAccessorDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is an Accessor Descriptor'); t.equal(ES.IsAccessorDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is an Accessor Descriptor'); t.equal(ES.IsAccessorDescriptor(v.dataDescriptor()), false, 'data descriptor is not an Accessor Descriptor'); t.equal(ES.IsAccessorDescriptor(v.genericDescriptor()), false, 'generic descriptor is not an Accessor Descriptor'); t.end(); }); test('IsDataDescriptor', function (t) { forEach(v.nonUndefinedPrimitives, function (primitive) { t['throws']( function () { ES.IsDataDescriptor(primitive); }, TypeError, debug(primitive) + ' is not a Property Descriptor' ); }); t.equal(ES.IsDataDescriptor(), false, 'no value is not a Data Descriptor'); t.equal(ES.IsDataDescriptor(undefined), false, 'undefined value is not a Data Descriptor'); t.equal(ES.IsDataDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a Data Descriptor'); t.equal(ES.IsDataDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a Data Descriptor'); t.equal(ES.IsDataDescriptor(v.dataDescriptor()), true, 'data descriptor is a Data Descriptor'); t.equal(ES.IsDataDescriptor(v.genericDescriptor()), false, 'generic descriptor is not a Data Descriptor'); t.end(); }); test('IsGenericDescriptor', function (t) { forEach(v.nonUndefinedPrimitives, function (primitive) { t['throws']( function () { ES.IsGenericDescriptor(primitive); }, TypeError, debug(primitive) + ' is not a Property Descriptor' ); }); t.equal(ES.IsGenericDescriptor(), false, 'no value is not a Data Descriptor'); t.equal(ES.IsGenericDescriptor(undefined), false, 'undefined value is not a Data Descriptor'); t.equal(ES.IsGenericDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a generic Descriptor'); t.equal(ES.IsGenericDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a generic Descriptor'); t.equal(ES.IsGenericDescriptor(v.dataDescriptor()), false, 'data descriptor is not a generic Descriptor'); t.equal(ES.IsGenericDescriptor(v.genericDescriptor()), true, 'generic descriptor is a generic Descriptor'); t.end(); }); test('FromPropertyDescriptor', function (t) { t.equal(ES.FromPropertyDescriptor(), undefined, 'no value begets undefined'); t.equal(ES.FromPropertyDescriptor(undefined), undefined, 'undefined value begets undefined'); forEach(v.nonNullPrimitives.concat(null), function (primitive) { t['throws']( function () { ES.FromPropertyDescriptor(primitive); }, TypeError, debug(primitive) + ' is not a Property Descriptor' ); }); var accessor = v.accessorDescriptor(); t.deepEqual(ES.FromPropertyDescriptor(accessor), { get: accessor['[[Get]]'], set: accessor['[[Set]]'], enumerable: !!accessor['[[Enumerable]]'], configurable: !!accessor['[[Configurable]]'] }); var mutator = v.mutatorDescriptor(); t.deepEqual(ES.FromPropertyDescriptor(mutator), { get: mutator['[[Get]]'], set: mutator['[[Set]]'], enumerable: !!mutator['[[Enumerable]]'], configurable: !!mutator['[[Configurable]]'] }); var data = v.dataDescriptor(); t.deepEqual(ES.FromPropertyDescriptor(data), { value: data['[[Value]]'], writable: data['[[Writable]]'], enumerable: !!data['[[Enumerable]]'], configurable: !!data['[[Configurable]]'] }); t['throws']( function () { ES.FromPropertyDescriptor(v.genericDescriptor()); }, TypeError, 'a complete Property Descriptor is required' ); t.end(); }); test('ToPropertyDescriptor', function (t) { forEach(v.nonUndefinedPrimitives, function (primitive) { t['throws']( function () { ES.ToPropertyDescriptor(primitive); }, TypeError, debug(primitive) + ' is not an Object' ); }); var accessor = v.accessorDescriptor(); t.deepEqual(ES.ToPropertyDescriptor({ get: accessor['[[Get]]'], enumerable: !!accessor['[[Enumerable]]'], configurable: !!accessor['[[Configurable]]'] }), accessor); var mutator = v.mutatorDescriptor(); t.deepEqual(ES.ToPropertyDescriptor({ set: mutator['[[Set]]'], enumerable: !!mutator['[[Enumerable]]'], configurable: !!mutator['[[Configurable]]'] }), mutator); var data = v.descriptors.nonConfigurable(v.dataDescriptor()); t.deepEqual(ES.ToPropertyDescriptor({ value: data['[[Value]]'], writable: data['[[Writable]]'], configurable: !!data['[[Configurable]]'] }), data); var both = v.bothDescriptor(); t['throws']( function () { ES.ToPropertyDescriptor({ get: both['[[Get]]'], value: both['[[Value]]'] }); }, TypeError, 'data and accessor descriptors are mutually exclusive' ); t['throws']( function () { ES.ToPropertyDescriptor({ get: 'not callable' }); }, TypeError, '"get" must be undefined or callable' ); t['throws']( function () { ES.ToPropertyDescriptor({ set: 'not callable' }); }, TypeError, '"set" must be undefined or callable' ); forEach(v.nonFunctions, function (nonFunction) { if (typeof nonFunction !== 'undefined') { t['throws']( function () { ES.ToPropertyDescriptor({ get: nonFunction }); }, TypeError, '`.get` has ' + debug(nonFunction) + ', which is not a Function' ); t['throws']( function () { ES.ToPropertyDescriptor({ set: nonFunction }); }, TypeError, '`.set` has ' + debug(nonFunction) + ', which is not a Function' ); } }); forEach(['get', 'set'], function (accessorName) { forEach(['value', 'writable'], function (dataName) { var o = {}; o[accessorName] = undefined; o[dataName] = undefined; t['throws']( function () { ES.ToPropertyDescriptor(o); }, TypeError, accessorName + ' + ' + dataName + ' is invalid' ); }); }); t.end(); }); test('Abstract Equality Comparison', function (t) { t.test('same types use ===', function (st) { forEach(v.primitives.concat(v.objects), function (value) { st.equal(ES['Abstract Equality Comparison'](value, value), value === value, debug(value) + ' is abstractly equal to itself'); }); st.end(); }); t.test('different types coerce', function (st) { var pairs = [ [null, undefined], [3, '3'], [true, '3'], [true, 3], [false, 0], [false, '0'], [3, [3]], ['3', [3]], [true, [1]], [false, [0]], [String(v.coercibleObject), v.coercibleObject], [Number(String(v.coercibleObject)), v.coercibleObject], [Number(v.coercibleObject), v.coercibleObject], [String(Number(v.coercibleObject)), v.coercibleObject] ]; forEach(pairs, function (pair) { var a = pair[0]; var b = pair[1]; // eslint-disable-next-line eqeqeq st.equal(ES['Abstract Equality Comparison'](a, b), a == b, debug(a) + ' == ' + debug(b)); // eslint-disable-next-line eqeqeq st.equal(ES['Abstract Equality Comparison'](b, a), b == a, debug(b) + ' == ' + debug(a)); }); st.end(); }); t.end(); }); test('Strict Equality Comparison', function (t) { t.test('same types use ===', function (st) { forEach(v.primitives.concat(v.objects), function (value) { st.equal(ES['Strict Equality Comparison'](value, value), value === value, debug(value) + ' is strictly equal to itself'); }); st.end(); }); t.test('different types are not ===', function (st) { var pairs = [ [null, undefined], [3, '3'], [true, '3'], [true, 3], [false, 0], [false, '0'], [3, [3]], ['3', [3]], [true, [1]], [false, [0]], [String(v.coercibleObject), v.coercibleObject], [Number(String(v.coercibleObject)), v.coercibleObject], [Number(v.coercibleObject), v.coercibleObject], [String(Number(v.coercibleObject)), v.coercibleObject] ]; forEach(pairs, function (pair) { var a = pair[0]; var b = pair[1]; st.equal(ES['Strict Equality Comparison'](a, b), a === b, debug(a) + ' === ' + debug(b)); st.equal(ES['Strict Equality Comparison'](b, a), b === a, debug(b) + ' === ' + debug(a)); }); st.end(); }); t.end(); }); test('Abstract Relational Comparison', function (t) { t.test('at least one operand is NaN', function (st) { st.equal(ES['Abstract Relational Comparison'](NaN, {}, true), undefined, 'LeftFirst: first is NaN, returns undefined'); st.equal(ES['Abstract Relational Comparison']({}, NaN, true), undefined, 'LeftFirst: second is NaN, returns undefined'); st.equal(ES['Abstract Relational Comparison'](NaN, {}, false), undefined, '!LeftFirst: first is NaN, returns undefined'); st.equal(ES['Abstract Relational Comparison']({}, NaN, false), undefined, '!LeftFirst: second is NaN, returns undefined'); st.end(); }); forEach(v.nonBooleans, function (nonBoolean) { t['throws']( function () { ES['Abstract Relational Comparison'](3, 4, nonBoolean); }, TypeError, debug(nonBoolean) + ' is not a Boolean' ); }); forEach(v.zeroes, function (zero) { t.equal(ES['Abstract Relational Comparison'](zero, 1, true), true, 'LeftFirst: ' + debug(zero) + ' is less than 1'); t.equal(ES['Abstract Relational Comparison'](zero, 1, false), true, '!LeftFirst: ' + debug(zero) + ' is less than 1'); t.equal(ES['Abstract Relational Comparison'](1, zero, true), false, 'LeftFirst: 1 is not less than ' + debug(zero)); t.equal(ES['Abstract Relational Comparison'](1, zero, false), false, '!LeftFirst: 1 is not less than ' + debug(zero)); t.equal(ES['Abstract Relational Comparison'](zero, zero, true), false, 'LeftFirst: ' + debug(zero) + ' is not less than ' + debug(zero)); t.equal(ES['Abstract Relational Comparison'](zero, zero, false), false, '!LeftFirst: ' + debug(zero) + ' is not less than ' + debug(zero)); }); t.equal(ES['Abstract Relational Comparison'](Infinity, -Infinity, true), false, 'LeftFirst: ∞ is not less than -∞'); t.equal(ES['Abstract Relational Comparison'](Infinity, -Infinity, false), false, '!LeftFirst: ∞ is not less than -∞'); t.equal(ES['Abstract Relational Comparison'](-Infinity, Infinity, true), true, 'LeftFirst: -∞ is less than ∞'); t.equal(ES['Abstract Relational Comparison'](-Infinity, Infinity, false), true, '!LeftFirst: -∞ is less than ∞'); t.equal(ES['Abstract Relational Comparison'](-Infinity, 0, true), true, 'LeftFirst: -∞ is less than +0'); t.equal(ES['Abstract Relational Comparison'](-Infinity, 0, false), true, '!LeftFirst: -∞ is less than +0'); t.equal(ES['Abstract Relational Comparison'](0, -Infinity, true), false, 'LeftFirst: +0 is not less than -∞'); t.equal(ES['Abstract Relational Comparison'](0, -Infinity, false), false, '!LeftFirst: +0 is not less than -∞'); t.equal(ES['Abstract Relational Comparison'](3, 4, true), true, 'LeftFirst: 3 is less than 4'); t.equal(ES['Abstract Relational Comparison'](4, 3, true), false, 'LeftFirst: 3 is not less than 4'); t.equal(ES['Abstract Relational Comparison'](3, 4, false), true, '!LeftFirst: 3 is less than 4'); t.equal(ES['Abstract Relational Comparison'](4, 3, false), false, '!LeftFirst: 3 is not less than 4'); t.equal(ES['Abstract Relational Comparison']('3', '4', true), true, 'LeftFirst: "3" is less than "4"'); t.equal(ES['Abstract Relational Comparison']('4', '3', true), false, 'LeftFirst: "3" is not less than "4"'); t.equal(ES['Abstract Relational Comparison']('3', '4', false), true, '!LeftFirst: "3" is less than "4"'); t.equal(ES['Abstract Relational Comparison']('4', '3', false), false, '!LeftFirst: "3" is not less than "4"'); t.equal(ES['Abstract Relational Comparison']('a', 'abc', true), true, 'LeftFirst: "a" is less than "abc"'); t.equal(ES['Abstract Relational Comparison']('abc', 'a', true), false, 'LeftFirst: "abc" is not less than "a"'); t.equal(ES['Abstract Relational Comparison']('a', 'abc', false), true, '!LeftFirst: "a" is less than "abc"'); t.equal(ES['Abstract Relational Comparison']('abc', 'a', false), false, '!LeftFirst: "abc" is not less than "a"'); t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, true), true, 'LeftFirst: coercible object is less than 42'); t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, true), false, 'LeftFirst: 42 is not less than coercible object'); t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, false), true, '!LeftFirst: coercible object is less than 42'); t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, false), false, '!LeftFirst: 42 is not less than coercible object'); t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', true), false, 'LeftFirst: coercible object is not less than "3"'); t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, true), false, 'LeftFirst: "3" is not less than coercible object'); t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', false), false, '!LeftFirst: coercible object is not less than "3"'); t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, false), false, '!LeftFirst: "3" is not less than coercible object'); t.end(); }); test('SecFromTime', function (t) { var now = new Date(); t.equal(ES.SecFromTime(now.getTime()), now.getUTCSeconds(), 'second from Date timestamp matches getUTCSeconds'); t.end(); }); test('MinFromTime', function (t) { var now = new Date(); t.equal(ES.MinFromTime(now.getTime()), now.getUTCMinutes(), 'minute from Date timestamp matches getUTCMinutes'); t.end(); }); test('HourFromTime', function (t) { var now = new Date(); t.equal(ES.HourFromTime(now.getTime()), now.getUTCHours(), 'hour from Date timestamp matches getUTCHours'); t.end(); }); test('msFromTime', function (t) { var now = new Date(); t.equal(ES.msFromTime(now.getTime()), now.getUTCMilliseconds(), 'ms from Date timestamp matches getUTCMilliseconds'); t.end(); }); var msPerSecond = 1e3; var msPerMinute = 60 * msPerSecond; var msPerHour = 60 * msPerMinute; var msPerDay = 24 * msPerHour; test('Day', function (t) { var time = Date.UTC(2019, 8, 10, 2, 3, 4, 5); var add = 2.5; var later = new Date(time + (add * msPerDay)); t.equal(ES.Day(later.getTime()), ES.Day(time) + Math.floor(add), 'adding 2.5 days worth of ms, gives a Day delta of 2'); t.end(); }); test('DayFromYear', function (t) { t.equal(ES.DayFromYear(2021) - ES.DayFromYear(2020), 366, '2021 is a leap year, has 366 days'); t.equal(ES.DayFromYear(2020) - ES.DayFromYear(2019), 365, '2020 is not a leap year, has 365 days'); t.equal(ES.DayFromYear(2019) - ES.DayFromYear(2018), 365, '2019 is not a leap year, has 365 days'); t.equal(ES.DayFromYear(2018) - ES.DayFromYear(2017), 365, '2018 is not a leap year, has 365 days'); t.equal(ES.DayFromYear(2017) - ES.DayFromYear(2016), 366, '2017 is a leap year, has 366 days'); t.end(); }); test('TimeWithinDay', function (t) { var time = Date.UTC(2019, 8, 10, 2, 3, 4, 5); var add = 2.5; var later = new Date(time + (add * msPerDay)); t.equal(ES.TimeWithinDay(later.getTime()), ES.TimeWithinDay(time) + (0.5 * msPerDay), 'adding 2.5 days worth of ms, gives a TimeWithinDay delta of +0.5'); t.end(); }); test('TimeFromYear', function (t) { for (var i = 1900; i < 2100; i += 1) { t.equal(ES.TimeFromYear(i), Date.UTC(i, 0, 1), 'TimeFromYear matches a Date object’s year: ' + i); } t.end(); }); test('YearFromTime', function (t) { for (var i = 1900; i < 2100; i += 1) { t.equal(ES.YearFromTime(Date.UTC(i, 0, 1)), i, 'YearFromTime matches a Date object’s year on 1/1: ' + i); t.equal(ES.YearFromTime(Date.UTC(i, 10, 1)), i, 'YearFromTime matches a Date object’s year on 10/1: ' + i); } t.end(); }); test('WeekDay', function (t) { var now = new Date(); var today = now.getUTCDay(); for (var i = 0; i < 7; i += 1) { var weekDay = ES.WeekDay(now.getTime() + (i * msPerDay)); t.equal(weekDay, (today + i) % 7, i + ' days after today (' + today + '), WeekDay is ' + weekDay); } t.end(); }); test('DaysInYear', function (t) { t.equal(ES.DaysInYear(2021), 365, '2021 is not a leap year'); t.equal(ES.DaysInYear(2020), 366, '2020 is a leap year'); t.equal(ES.DaysInYear(2019), 365, '2019 is not a leap year'); t.equal(ES.DaysInYear(2018), 365, '2018 is not a leap year'); t.equal(ES.DaysInYear(2017), 365, '2017 is not a leap year'); t.equal(ES.DaysInYear(2016), 366, '2016 is a leap year'); t.equal(ES.DaysInYear(2000), 366, '2000 is a leap year'); t.equal(ES.DaysInYear(1900), 365, '1900 is not a leap year'); t.end(); }); test('InLeapYear', function (t) { t.equal(ES.InLeapYear(Date.UTC(2021, 0, 1)), 0, '2021 is not a leap year'); t.equal(ES.InLeapYear(Date.UTC(2020, 0, 1)), 1, '2020 is a leap year'); t.equal(ES.InLeapYear(Date.UTC(2019, 0, 1)), 0, '2019 is not a leap year'); t.equal(ES.InLeapYear(Date.UTC(2018, 0, 1)), 0, '2018 is not a leap year'); t.equal(ES.InLeapYear(Date.UTC(2017, 0, 1)), 0, '2017 is not a leap year'); t.equal(ES.InLeapYear(Date.UTC(2016, 0, 1)), 1, '2016 is a leap year'); t.end(); }); test('DayWithinYear', function (t) { t.equal(ES.DayWithinYear(Date.UTC(2019, 0, 1)), 0, '1/1 is the 1st day'); t.equal(ES.DayWithinYear(Date.UTC(2019, 11, 31)), 364, '12/31 is the 365th day in a non leap year'); t.equal(ES.DayWithinYear(Date.UTC(2016, 11, 31)), 365, '12/31 is the 366th day in a leap year'); t.end(); }); test('MonthFromTime', function (t) { t.equal(ES.MonthFromTime(Date.UTC(2019, 0, 1)), 0, 'non-leap: 1/1 gives January'); t.equal(ES.MonthFromTime(Date.UTC(2019, 0, 31)), 0, 'non-leap: 1/31 gives January'); t.equal(ES.MonthFromTime(Date.UTC(2019, 1, 1)), 1, 'non-leap: 2/1 gives February'); t.equal(ES.MonthFromTime(Date.UTC(2019, 1, 28)), 1, 'non-leap: 2/28 gives February'); t.equal(ES.MonthFromTime(Date.UTC(2019, 1, 29)), 2, 'non-leap: 2/29 gives March'); t.equal(ES.MonthFromTime(Date.UTC(2019, 2, 1)), 2, 'non-leap: 3/1 gives March'); t.equal(ES.MonthFromTime(Date.UTC(2019, 2, 31)), 2, 'non-leap: 3/31 gives March'); t.equal(ES.MonthFromTime(Date.UTC(2019, 3, 1)), 3, 'non-leap: 4/1 gives April'); t.equal(ES.MonthFromTime(Date.UTC(2019, 3, 30)), 3, 'non-leap: 4/30 gives April'); t.equal(ES.MonthFromTime(Date.UTC(2019, 4, 1)), 4, 'non-leap: 5/1 gives May'); t.equal(ES.MonthFromTime(Date.UTC(2019, 4, 31)), 4, 'non-leap: 5/31 gives May'); t.equal(ES.MonthFromTime(Date.UTC(2019, 5, 1)), 5, 'non-leap: 6/1 gives June'); t.equal(ES.MonthFromTime(Date.UTC(2019, 5, 30)), 5, 'non-leap: 6/30 gives June'); t.equal(ES.MonthFromTime(Date.UTC(2019, 6, 1)), 6, 'non-leap: 7/1 gives July'); t.equal(ES.MonthFromTime(Date.UTC(2019, 6, 31)), 6, 'non-leap: 7/31 gives July'); t.equal(ES.MonthFromTime(Date.UTC(2019, 7, 1)), 7, 'non-leap: 8/1 gives August'); t.equal(ES.MonthFromTime(Date.UTC(2019, 7, 30)), 7, 'non-leap: 8/30 gives August'); t.equal(ES.MonthFromTime(Date.UTC(2019, 8, 1)), 8, 'non-leap: 9/1 gives September'); t.equal(ES.MonthFromTime(Date.UTC(2019, 8, 30)), 8, 'non-leap: 9/30 gives September'); t.equal(ES.MonthFromTime(Date.UTC(2019, 9, 1)), 9, 'non-leap: 10/1 gives October'); t.equal(ES.MonthFromTime(Date.UTC(2019, 9, 31)), 9, 'non-leap: 10/31 gives October'); t.equal(ES.MonthFromTime(Date.UTC(2019, 10, 1)), 10, 'non-leap: 11/1 gives November'); t.equal(ES.MonthFromTime(Date.UTC(2019, 10, 30)), 10, 'non-leap: 11/30 gives November'); t.equal(ES.MonthFromTime(Date.UTC(2019, 11, 1)), 11, 'non-leap: 12/1 gives December'); t.equal(ES.MonthFromTime(Date.UTC(2019, 11, 31)), 11, 'non-leap: 12/31 gives December'); t.equal(ES.MonthFromTime(Date.UTC(2016, 0, 1)), 0, 'leap: 1/1 gives January'); t.equal(ES.MonthFromTime(Date.UTC(2016, 0, 31)), 0, 'leap: 1/31 gives January'); t.equal(ES.MonthFromTime(Date.UTC(2016, 1, 1)), 1, 'leap: 2/1 gives February'); t.equal(ES.MonthFromTime(Date.UTC(2016, 1, 28)), 1, 'leap: 2/28 gives February'); t.equal(ES.MonthFromTime(Date.UTC(2016, 1, 29)), 1, 'leap: 2/29 gives February'); t.equal(ES.MonthFromTime(Date.UTC(2016, 2, 1)), 2, 'leap: 3/1 gives March'); t.equal(ES.MonthFromTime(Date.UTC(2016, 2, 31)), 2, 'leap: 3/31 gives March'); t.equal(ES.MonthFromTime(Date.UTC(2016, 3, 1)), 3, 'leap: 4/1 gives April'); t.equal(ES.MonthFromTime(Date.UTC(2016, 3, 30)), 3, 'leap: 4/30 gives April'); t.equal(ES.MonthFromTime(Date.UTC(2016, 4, 1)), 4, 'leap: 5/1 gives May'); t.equal(ES.MonthFromTime(Date.UTC(2016, 4, 31)), 4, 'leap: 5/31 gives May'); t.equal(ES.MonthFromTime(Date.UTC(2016, 5, 1)), 5, 'leap: 6/1 gives June'); t.equal(ES.MonthFromTime(Date.UTC(2016, 5, 30)), 5, 'leap: 6/30 gives June'); t.equal(ES.MonthFromTime(Date.UTC(2016, 6, 1)), 6, 'leap: 7/1 gives July'); t.equal(ES.MonthFromTime(Date.UTC(2016, 6, 31)), 6, 'leap: 7/31 gives July'); t.equal(ES.MonthFromTime(Date.UTC(2016, 7, 1)), 7, 'leap: 8/1 gives August'); t.equal(ES.MonthFromTime(Date.UTC(2016, 7, 30)), 7, 'leap: 8/30 gives August'); t.equal(ES.MonthFromTime(Date.UTC(2016, 8, 1)), 8, 'leap: 9/1 gives September'); t.equal(ES.MonthFromTime(Date.UTC(2016, 8, 30)), 8, 'leap: 9/30 gives September'); t.equal(ES.MonthFromTime(Date.UTC(2016, 9, 1)), 9, 'leap: 10/1 gives October'); t.equal(ES.MonthFromTime(Date.UTC(2016, 9, 31)), 9, 'leap: 10/31 gives October'); t.equal(ES.MonthFromTime(Date.UTC(2016, 10, 1)), 10, 'leap: 11/1 gives November'); t.equal(ES.MonthFromTime(Date.UTC(2016, 10, 30)), 10, 'leap: 11/30 gives November'); t.equal(ES.MonthFromTime(Date.UTC(2016, 11, 1)), 11, 'leap: 12/1 gives December'); t.equal(ES.MonthFromTime(Date.UTC(2016, 11, 31)), 11, 'leap: 12/31 gives December'); t.end(); }); test('DateFromTime', function (t) { var i; for (i = 1; i <= 28; i += 1) { t.equal(ES.DateFromTime(Date.UTC(2019, 1, i)), i, '2019.02.' + i + ' is date ' + i); } for (i = 1; i <= 29; i += 1) { t.equal(ES.DateFromTime(Date.UTC(2016, 1, i)), i, '2016.02.' + i + ' is date ' + i); } for (i = 1; i <= 30; i += 1) { t.equal(ES.DateFromTime(Date.UTC(2019, 2, i)), i, '2019.03.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 3, i)), i, '2019.04.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 5, i)), i, '2019.06.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 7, i)), i, '2019.08.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 8, i)), i, '2019.09.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 10, i)), i, '2019.11.' + i + ' is date ' + i); } for (i = 1; i <= 31; i += 1) { t.equal(ES.DateFromTime(Date.UTC(2019, 0, i)), i, '2019.01.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 4, i)), i, '2019.05.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 6, i)), i, '2019.07.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 9, i)), i, '2019.10.' + i + ' is date ' + i); t.equal(ES.DateFromTime(Date.UTC(2019, 11, i)), i, '2019.12.' + i + ' is date ' + i); } t.end(); }); test('MakeDay', function (t) { forEach([NaN, Infinity, -Infinity], function (nonFiniteNumber) { t.equal(ES.MakeDay(nonFiniteNumber, 0, 0), NaN, 'year: ' + debug(nonFiniteNumber) + ' is not finite'); t.equal(ES.MakeDay(0, nonFiniteNumber, 0), NaN, 'month: ' + debug(nonFiniteNumber) + ' is not finite'); t.equal(ES.MakeDay(0, 0, nonFiniteNumber), NaN, 'date: ' + debug(nonFiniteNumber) + ' is not finite'); }); var day2015 = 16687; t.equal(ES.MakeDay(2015, 8, 9), day2015, '2015.09.09 is day 16687'); var day2016 = day2015 + 366; // 2016 is a leap year t.equal(ES.MakeDay(2016, 8, 9), day2016, '2015.09.09 is day 17053'); var day2017 = day2016 + 365; t.equal(ES.MakeDay(2017, 8, 9), day2017, '2017.09.09 is day 17418'); var day2018 = day2017 + 365; t.equal(ES.MakeDay(2018, 8, 9), day2018, '2018.09.09 is day 17783'); var day2019 = day2018 + 365; t.equal(ES.MakeDay(2019, 8, 9), day2019, '2019.09.09 is day 18148'); t.end(); }); test('MakeDate', function (t) { forEach(v.infinities.concat(NaN), function (nonFiniteNumber) { t.equal(ES.MakeDate(nonFiniteNumber, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `day`'); t.equal(ES.MakeDate(0, nonFiniteNumber), NaN, debug(nonFiniteNumber) + ' is not a finite `time`'); }); t.equal(ES.MakeDate(0, 0), 0, 'zero day and zero time is zero date'); t.equal(ES.MakeDate(0, 123), 123, 'zero day and nonzero time is a date of the "time"'); t.equal(ES.MakeDate(1, 0), msPerDay, 'day of 1 and zero time is a date of "ms per day"'); t.equal(ES.MakeDate(3, 0), 3 * msPerDay, 'day of 3 and zero time is a date of thrice "ms per day"'); t.equal(ES.MakeDate(1, 123), msPerDay + 123, 'day of 1 and nonzero time is a date of "ms per day" plus the "time"'); t.equal(ES.MakeDate(3, 123), (3 * msPerDay) + 123, 'day of 3 and nonzero time is a date of thrice "ms per day" plus the "time"'); t.end(); }); test('MakeTime', function (t) { forEach(v.infinities.concat(NaN), function (nonFiniteNumber) { t.equal(ES.MakeTime(nonFiniteNumber, 0, 0, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `hour`'); t.equal(ES.MakeTime(0, nonFiniteNumber, 0, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `min`'); t.equal(ES.MakeTime(0, 0, nonFiniteNumber, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `sec`'); t.equal(ES.MakeTime(0, 0, 0, nonFiniteNumber), NaN, debug(nonFiniteNumber) + ' is not a finite `ms`'); }); t.equal( ES.MakeTime(1.2, 2.3, 3.4, 4.5), (1 * msPerHour) + (2 * msPerMinute) + (3 * msPerSecond) + 4, 'all numbers are converted to integer, multiplied by the right number of ms, and summed' ); t.end(); }); test('TimeClip', function (t) { forEach(v.infinities.concat(NaN), function (nonFiniteNumber) { t.equal(ES.TimeClip(nonFiniteNumber), NaN, debug(nonFiniteNumber) + ' is not a finite `time`'); }); t.equal(ES.TimeClip(8.64e15 + 1), NaN, '8.64e15 is the largest magnitude considered "finite"'); t.equal(ES.TimeClip(-8.64e15 - 1), NaN, '-8.64e15 is the largest magnitude considered "finite"'); forEach(v.zeroes.concat([-10, 10, +new Date()]), function (time) { t.looseEqual(ES.TimeClip(time), time, debug(time) + ' is a time of ' + debug(time)); }); t.end(); }); test('modulo', function (t) { t.equal(3 % 2, 1, '+3 % 2 is +1'); t.equal(ES.modulo(3, 2), 1, '+3 mod 2 is +1'); t.equal(-3 % 2, -1, '-3 % 2 is -1'); t.equal(ES.modulo(-3, 2), 1, '-3 mod 2 is +1'); t.end(); }); }; var es2015 = function ES2015(ES, ops, expectedMissing, skips) { es5(ES, ops, expectedMissing, assign(assign({}, skips), { CheckObjectCoercible: true, FromPropertyDescriptor: true, ToNumber: true, ToString: true, Type: true })); var test = makeTest(skips); var getNamelessFunction = function () { var f = Object(function () {}); try { delete f.name; } catch (e) { /**/ } return f; }; test('AdvanceStringIndex', function (t) { forEach(v.nonStrings, function (nonString) { t['throws']( function () { ES.AdvanceStringIndex(nonString); }, TypeError, '"S" argument must be a String; ' + debug(nonString) + ' is not' ); }); var notInts = v.nonNumbers.concat( v.nonIntegerNumbers, v.infinities, [NaN, [], new Date(), Math.pow(2, 53), -1] ); forEach(notInts, function (nonInt) { t['throws']( function () { ES.AdvanceStringIndex('abc', nonInt); }, TypeError, '"index" argument must be an integer, ' + debug(nonInt) + ' is not.' ); }); forEach(v.nonBooleans, function (nonBoolean) { t['throws']( function () { ES.AdvanceStringIndex('abc', 0, nonBoolean); }, TypeError, debug(nonBoolean) + ' is not a Boolean' ); }); var str = 'a' + wholePoo + 'c'; t.test('non-unicode mode', function (st) { for (var i = 0; i < str.length + 2; i += 1) { st.equal(ES.AdvanceStringIndex(str, i, false), i + 1, i + ' advances to ' + (i + 1)); } st.end(); }); t.test('unicode mode', function (st) { st.equal(ES.AdvanceStringIndex(str, 0, true), 1, '0 advances to 1'); st.equal(ES.AdvanceStringIndex(str, 1, true), 3, '1 advances to 3'); st.equal(ES.AdvanceStringIndex(str, 2, true), 3, '2 advances to 3'); st.equal(ES.AdvanceStringIndex(str, 3, true), 4, '3 advances to 4'); st.equal(ES.AdvanceStringIndex(str, 4, true), 5, '4 advances to 5'); st.end(); }); t.test('lone surrogates', function (st) { var halfPoo = 'a' + leadingPoo + 'c'; st.equal(ES.AdvanceStringIndex(halfPoo, 0, true), 1, '0 advances to 1'); st.equal(ES.AdvanceStringIndex(halfPoo, 1, true), 2, '1 advances to 2'); st.equal(ES.AdvanceStringInd