Test coverage for is(value) (#86)

This commit is contained in:
Adam Babcock 2019-04-28 03:15:11 -05:00 committed by Sindre Sorhus
parent 120f74ab63
commit 373605e40d
2 changed files with 116 additions and 56 deletions

View file

@ -16,6 +16,7 @@ export const enum TypeName {
number = 'number', number = 'number',
symbol = 'symbol', symbol = 'symbol',
Function = 'Function', Function = 'Function',
Generator = 'Generator',
GeneratorFunction = 'GeneratorFunction', GeneratorFunction = 'GeneratorFunction',
AsyncFunction = 'AsyncFunction', AsyncFunction = 'AsyncFunction',
Observable = 'Observable', Observable = 'Observable',

View file

@ -8,7 +8,7 @@ import test, {ExecutionContext} from 'ava';
import {JSDOM} from 'jsdom'; import {JSDOM} from 'jsdom';
import {Subject, Observable} from 'rxjs'; import {Subject, Observable} from 'rxjs';
import ZenObservable from 'zen-observable'; import ZenObservable from 'zen-observable';
import is from '../source'; import is, {TypeName} from '../source';
const isNode10orHigher = Number(process.versions.node.split('.')[0]) >= 10; const isNode10orHigher = Number(process.versions.node.split('.')[0]) >= 10;
@ -21,6 +21,7 @@ const createDomElement = (element: string) => document.createElement(element);
interface Test { interface Test {
fixtures: unknown[]; fixtures: unknown[];
typename?: TypeName;
is(value: unknown): boolean; is(value: unknown): boolean;
} }
@ -29,13 +30,15 @@ const types = new Map<string, Test>([
is: is.undefined, is: is.undefined,
fixtures: [ fixtures: [
undefined undefined
] ],
typename: TypeName.undefined
}], }],
['null', { ['null', {
is: is.null_, is: is.null_,
fixtures: [ fixtures: [
null null
] ],
typename: TypeName.null
}], }],
['string', { ['string', {
is: is.string, is: is.string,
@ -43,14 +46,16 @@ const types = new Map<string, Test>([
'🦄', '🦄',
'hello world', 'hello world',
'' ''
] ],
typename: TypeName.string
}], }],
['emptyString', { ['emptyString', {
is: is.emptyString, is: is.emptyString,
fixtures: [ fixtures: [
'', '',
String() String()
] ],
typename: TypeName.string
}], }],
['number', { ['number', {
is: is.number, is: is.number,
@ -61,19 +66,22 @@ const types = new Map<string, Test>([
-0, -0,
Infinity, Infinity,
-Infinity -Infinity
] ],
typename: TypeName.number
}], }],
['boolean', { ['boolean', {
is: is.boolean, is: is.boolean,
fixtures: [ fixtures: [
true, false true, false
] ],
typename: TypeName.boolean
}], }],
['symbol', { ['symbol', {
is: is.symbol, is: is.symbol,
fixtures: [ fixtures: [
Symbol('🦄') Symbol('🦄')
] ],
typename: TypeName.symbol
}], }],
['numericString', { ['numericString', {
is: is.numericString, is: is.numericString,
@ -81,21 +89,24 @@ const types = new Map<string, Test>([
'5', '5',
'-3.2', '-3.2',
'Infinity' 'Infinity'
] ],
typename: TypeName.string
}], }],
['array', { ['array', {
is: is.array, is: is.array,
fixtures: [ fixtures: [
[1, 2], [1, 2],
new Array(2) new Array(2)
] ],
typename: TypeName.Array
}], }],
['emptyArray', { ['emptyArray', {
is: is.emptyArray, is: is.emptyArray,
fixtures: [ fixtures: [
[], [],
new Array() // eslint-disable-line @typescript-eslint/no-array-constructor new Array() // eslint-disable-line @typescript-eslint/no-array-constructor
] ],
typename: TypeName.Array
}], }],
['function', { ['function', {
is: is.function_, is: is.function_,
@ -105,53 +116,61 @@ const types = new Map<string, Test>([
() => {}, () => {},
async function () {}, async function () {},
function * (): unknown {} function * (): unknown {}
] ],
typename: TypeName.Function
}], }],
['buffer', { ['buffer', {
is: is.buffer, is: is.buffer,
fixtures: [ fixtures: [
Buffer.from('🦄') Buffer.from('🦄')
] ],
typename: TypeName.Buffer
}], }],
['object', { ['object', {
is: is.object, is: is.object,
fixtures: [ fixtures: [
{x: 1}, {x: 1},
Object.create({x: 1}) Object.create({x: 1})
] ],
typename: TypeName.Object
}], }],
['regExp', { ['regExp', {
is: is.regExp, is: is.regExp,
fixtures: [ fixtures: [
/\w/, /\w/,
new RegExp('\\w') new RegExp('\\w')
] ],
typename: TypeName.RegExp
}], }],
['date', { ['date', {
is: is.date, is: is.date,
fixtures: [ fixtures: [
new Date() new Date()
] ],
typename: TypeName.Date
}], }],
['error', { ['error', {
is: is.error, is: is.error,
fixtures: [ fixtures: [
new Error('🦄'), new Error('🦄'),
new ErrorSubclassFixture() new ErrorSubclassFixture()
] ],
typename: TypeName.Error
}], }],
['nativePromise', { ['nativePromise', {
is: is.nativePromise, is: is.nativePromise,
fixtures: [ fixtures: [
Promise.resolve(), Promise.resolve(),
PromiseSubclassFixture.resolve() PromiseSubclassFixture.resolve()
] ],
typename: TypeName.Promise
}], }],
['promise', { ['promise', {
is: is.promise, is: is.promise,
fixtures: [ fixtures: [
{then() {}, catch() {}} {then() {}, catch() {}}
] ],
typename: TypeName.Object
}], }],
['generator', { ['generator', {
is: is.generator, is: is.generator,
@ -159,7 +178,8 @@ const types = new Map<string, Test>([
(function * () { (function * () {
yield 4; yield 4;
})() })()
] ],
typename: TypeName.Generator
}], }],
['generatorFunction', { ['generatorFunction', {
is: is.generatorFunction, is: is.generatorFunction,
@ -167,130 +187,151 @@ const types = new Map<string, Test>([
function * () { function * () {
yield 4; yield 4;
} }
] ],
typename: TypeName.Function
}], }],
['asyncFunction', { ['asyncFunction', {
is: is.asyncFunction, is: is.asyncFunction,
fixtures: [ fixtures: [
async function () {}, async function () {},
async () => {} async () => {}
] ],
typename: TypeName.Function
}], }],
['boundFunction', { ['boundFunction', {
is: is.boundFunction, is: is.boundFunction,
fixtures: [ fixtures: [
() => {}, () => {},
function () {}.bind(null) // eslint-disable-line no-extra-bind function () {}.bind(null) // eslint-disable-line no-extra-bind
] ],
typename: TypeName.Function
}], }],
['map', { ['map', {
is: is.map, is: is.map,
fixtures: [ fixtures: [
new Map([['one', '1']]) new Map([['one', '1']])
] ],
typename: TypeName.Map
}], }],
['emptyMap', { ['emptyMap', {
is: is.emptyMap, is: is.emptyMap,
fixtures: [ fixtures: [
new Map() new Map()
] ],
typename: TypeName.Map
}], }],
['set', { ['set', {
is: is.set, is: is.set,
fixtures: [ fixtures: [
new Set(['one']) new Set(['one'])
] ],
typename: TypeName.Set
}], }],
['emptySet', { ['emptySet', {
is: is.emptySet, is: is.emptySet,
fixtures: [ fixtures: [
new Set() new Set()
] ],
typename: TypeName.Set
}], }],
['weakSet', { ['weakSet', {
is: is.weakSet, is: is.weakSet,
fixtures: [ fixtures: [
new WeakSet() new WeakSet()
] ],
typename: TypeName.WeakSet
}], }],
['weakMap', { ['weakMap', {
is: is.weakMap, is: is.weakMap,
fixtures: [ fixtures: [
new WeakMap() new WeakMap()
] ],
typename: TypeName.WeakMap
}], }],
['int8Array', { ['int8Array', {
is: is.int8Array, is: is.int8Array,
fixtures: [ fixtures: [
new Int8Array() new Int8Array()
] ],
typename: TypeName.Int8Array
}], }],
['uint8Array', { ['uint8Array', {
is: is.uint8Array, is: is.uint8Array,
fixtures: [ fixtures: [
new Uint8Array() new Uint8Array()
] ],
typename: TypeName.Uint8Array
}], }],
['uint8ClampedArray', { ['uint8ClampedArray', {
is: is.uint8ClampedArray, is: is.uint8ClampedArray,
fixtures: [ fixtures: [
new Uint8ClampedArray() new Uint8ClampedArray()
] ],
typename: TypeName.Uint8ClampedArray
}], }],
['int16Array', { ['int16Array', {
is: is.int16Array, is: is.int16Array,
fixtures: [ fixtures: [
new Int16Array() new Int16Array()
] ],
typename: TypeName.Int16Array
}], }],
['uint16Array', { ['uint16Array', {
is: is.uint16Array, is: is.uint16Array,
fixtures: [ fixtures: [
new Uint16Array() new Uint16Array()
] ],
typename: TypeName.Uint16Array
}], }],
['int32Array', { ['int32Array', {
is: is.int32Array, is: is.int32Array,
fixtures: [ fixtures: [
new Int32Array() new Int32Array()
] ],
typename: TypeName.Int32Array
}], }],
['uint32Array', { ['uint32Array', {
is: is.uint32Array, is: is.uint32Array,
fixtures: [ fixtures: [
new Uint32Array() new Uint32Array()
] ],
typename: TypeName.Uint32Array
}], }],
['float32Array', { ['float32Array', {
is: is.float32Array, is: is.float32Array,
fixtures: [ fixtures: [
new Float32Array() new Float32Array()
] ],
typename: TypeName.Float32Array
}], }],
['float64Array', { ['float64Array', {
is: is.float64Array, is: is.float64Array,
fixtures: [ fixtures: [
new Float64Array() new Float64Array()
] ],
typename: TypeName.Float64Array
}], }],
['arrayBuffer', { ['arrayBuffer', {
is: is.arrayBuffer, is: is.arrayBuffer,
fixtures: [ fixtures: [
new ArrayBuffer(10) new ArrayBuffer(10)
] ],
typename: TypeName.ArrayBuffer
}], }],
['dataView', { ['dataView', {
is: is.dataView, is: is.dataView,
fixtures: [ fixtures: [
new DataView(new ArrayBuffer(10)) new DataView(new ArrayBuffer(10))
] ],
typename: TypeName.DataView
}], }],
['nan', { ['nan', {
is: is.nan, is: is.nan,
fixtures: [ fixtures: [
NaN, NaN,
Number.NaN Number.NaN
] ],
typename: TypeName.number
}], }],
['nullOrUndefined', { ['nullOrUndefined', {
is: is.nullOrUndefined, is: is.nullOrUndefined,
@ -305,20 +346,23 @@ const types = new Map<string, Test>([
{x: 1}, {x: 1},
Object.create(null), Object.create(null),
new Object() // eslint-disable-line no-new-object new Object() // eslint-disable-line no-new-object
] ],
typename: TypeName.Object
}], }],
['integer', { ['integer', {
is: is.integer, is: is.integer,
fixtures: [ fixtures: [
6 6
] ],
typename: TypeName.number
}], }],
['safeInteger', { ['safeInteger', {
is: is.safeInteger, is: is.safeInteger,
fixtures: [ fixtures: [
(2 ** 53) - 1, (2 ** 53) - 1,
-(2 ** 53) + 1 -(2 ** 53) + 1
] ],
typename: TypeName.number
}], }],
['domElement', { ['domElement', {
is: is.domElement, is: is.domElement,
@ -348,7 +392,8 @@ const types = new Map<string, Test>([
new Observable(), new Observable(),
new Subject(), new Subject(),
new ZenObservable(() => {}) new ZenObservable(() => {})
] ],
typename: TypeName.Observable
}], }],
['nodeStream', { ['nodeStream', {
is: is.nodeStream, is: is.nodeStream,
@ -362,14 +407,16 @@ const types = new Map<string, Test>([
new Stream.Transform(), new Stream.Transform(),
new Stream.Stream(), new Stream.Stream(),
new Stream.Writable() new Stream.Writable()
] ],
typename: TypeName.Object
}], }],
['infinite', { ['infinite', {
is: is.infinite, is: is.infinite,
fixtures: [ fixtures: [
Infinity, Infinity,
-Infinity -Infinity
] ],
typename: TypeName.number
}] }]
]); ]);
@ -383,7 +430,7 @@ const testType = (t: ExecutionContext, type: string, exclude?: string[]) => {
return; return;
} }
const {is: testIs} = testData; const {is: testIs, typename} = testData;
for (const [key, {fixtures}] of types) { for (const [key, {fixtures}] of types) {
// TODO: Automatically exclude value types in other tests that we have in the current one. // TODO: Automatically exclude value types in other tests that we have in the current one.
@ -392,21 +439,19 @@ const testType = (t: ExecutionContext, type: string, exclude?: string[]) => {
continue; continue;
} }
const assert = key === type ? t.true.bind(t) : t.false.bind(t); const isTypeUnderTest = key === type;
const assert = isTypeUnderTest ? t.true.bind(t) : t.false.bind(t);
for (const fixture of fixtures) { for (const fixture of fixtures) {
assert(testIs(fixture), `Value: ${util.inspect(fixture)}`); assert(testIs(fixture), `Value: ${util.inspect(fixture)}`);
if (isTypeUnderTest && typename) {
t.is(is(fixture), typename);
}
} }
} }
}; };
test('is', t => {
t.is(is(null), 'null');
t.is(is(undefined), 'undefined');
// TODO: Expand this to all the supported types. Maybe reuse `testType()` somehow.
});
test('is.undefined', t => { test('is.undefined', t => {
testType(t, 'undefined', ['nullOrUndefined']); testType(t, 'undefined', ['nullOrUndefined']);
}); });
@ -753,6 +798,20 @@ test('is.inRange', t => {
test('is.domElement', t => { test('is.domElement', t => {
testType(t, 'domElement'); testType(t, 'domElement');
t.false(is.domElement({nodeType: 1, nodeName: 'div'})); t.false(is.domElement({nodeType: 1, nodeName: 'div'}));
const htmlTagNameToTypeName = {
div: 'HTMLDivElement',
input: 'HTMLInputElement',
span: 'HTMLSpanElement',
img: 'HTMLImageElement',
canvas: 'HTMLCanvasElement',
script: 'HTMLScriptElement'
};
for (const [tagName, typeName] of Object.entries(htmlTagNameToTypeName)) {
const domElement = createDomElement(tagName);
t.is(is(domElement), typeName);
}
}); });
test('is.observable', t => { test('is.observable', t => {