feat: each support (#13)
* feat: add each support for test, describe * docs: document test * feat: label templating basic support * refactor: group test exports together * refactor: leverage each in repetitive tests * chore: pinned node -> alias * test: coverage for it, test
This commit is contained in:
parent
711d0097ce
commit
2bc6d94507
10 changed files with 145 additions and 88 deletions
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
||||||
18.15.0
|
lts/hydrogen
|
||||||
|
|
3
src/index.ts
Normal file
3
src/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export { default as test, it } from './testComponents/test'
|
||||||
|
export { default as describe } from './testComponents/describe'
|
||||||
|
export { default as expect } from './testComponents/expect'
|
|
@ -1,36 +0,0 @@
|
||||||
import { promises as fs } from 'fs'
|
|
||||||
|
|
||||||
import expect from './expect'
|
|
||||||
import { greenText, redText } from './utils'
|
|
||||||
import { type TestCaseLabel, type TestCaseFunction, type TestCaseGroup } from './types'
|
|
||||||
|
|
||||||
function describe(label: TestCaseLabel, testGroup: TestCaseGroup) {
|
|
||||||
if (process.env.COLLECT) {
|
|
||||||
testGroup()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.group(greenText(label))
|
|
||||||
testGroup()
|
|
||||||
console.groupEnd()
|
|
||||||
}
|
|
||||||
|
|
||||||
function test(label: TestCaseLabel, testCase: TestCaseFunction): void {
|
|
||||||
if (process.env.COLLECT) {
|
|
||||||
console.log(label)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
testCase()
|
|
||||||
console.log(greenText(`[PASSED] ${label}`))
|
|
||||||
} catch (e) {
|
|
||||||
console.group(redText(`[FAILED] ${label}`))
|
|
||||||
console.log(redText(String(e)))
|
|
||||||
console.groupEnd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const it = test
|
|
||||||
|
|
||||||
export { it, test, expect, describe }
|
|
43
src/testComponents/describe.ts
Normal file
43
src/testComponents/describe.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { promises as fs } from 'fs'
|
||||||
|
|
||||||
|
import { greenText, redText } from '../utils'
|
||||||
|
import { type TestCaseLabel, type TestCaseFunction, type TestCaseGroup } from '../types'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `describe` facilitates grouping tests together.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* describe('My test group', () => {
|
||||||
|
* test('My first test', ...)
|
||||||
|
*
|
||||||
|
* test('My second test', ...)
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
function describe(label: TestCaseLabel, testGroup: TestCaseGroup) {
|
||||||
|
if (process.env.COLLECT) {
|
||||||
|
testGroup()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.group(greenText(label))
|
||||||
|
testGroup()
|
||||||
|
console.groupEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(describe, 'each', {
|
||||||
|
value: function (values: Array<unknown>) {
|
||||||
|
return (label: TestCaseLabel, testGroup: TestCaseGroup) => {
|
||||||
|
values.forEach((value: unknown, index: number) => {
|
||||||
|
describe(label.replace(/%s/g, String(value)), () => testGroup(value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
type extendedDescribe = typeof describe & { [key: string]: (...args: Array<unknown>) => extendedDescribe }
|
||||||
|
|
||||||
|
const extDescribe = describe as extendedDescribe
|
||||||
|
|
||||||
|
export default extDescribe
|
|
@ -9,7 +9,7 @@ import {
|
||||||
type RawComparisonMatcher,
|
type RawComparisonMatcher,
|
||||||
type RawMatchersMap,
|
type RawMatchersMap,
|
||||||
type MatcherName,
|
type MatcherName,
|
||||||
} from './types'
|
} from '../types'
|
||||||
|
|
||||||
import matchers from './matchers'
|
import matchers from './matchers'
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
|
|
||||||
import { type MatcherReport } from './types'
|
import { type MatcherReport } from '../types'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Asserts whether value and other are strictly equal.
|
* Asserts whether value and other are strictly equal.
|
53
src/testComponents/test.ts
Normal file
53
src/testComponents/test.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import { promises as fs } from 'fs'
|
||||||
|
|
||||||
|
import { greenText, redText } from '../utils'
|
||||||
|
import { type TestCaseLabel, type TestCaseFunction, type TestCaseGroup } from '../types'
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `test` defines a single test case.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* test('My test', () => {
|
||||||
|
* // Assert things.
|
||||||
|
* })
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
function test(label: TestCaseLabel, testCase: TestCaseFunction): void {
|
||||||
|
if (process.env.COLLECT) {
|
||||||
|
console.log(label)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
testCase()
|
||||||
|
console.log(greenText(`[PASSED] ${label}`))
|
||||||
|
} catch (e) {
|
||||||
|
console.group(redText(`[FAILED] ${label}`))
|
||||||
|
console.log(redText(String(e)))
|
||||||
|
console.groupEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(test, 'each', {
|
||||||
|
value: function (values: Array<unknown>) {
|
||||||
|
return (label: TestCaseLabel, testCase: TestCaseFunction) => {
|
||||||
|
values.forEach((value: unknown, index: number) => {
|
||||||
|
test(label.replace(/%s/g, String(value)), () => testCase(value))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
type extendedTest = typeof test & { [key: string]: (...args: Array<unknown>) => extendedTest }
|
||||||
|
|
||||||
|
const extTest = test as extendedTest
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `it` is an alias of `test`.
|
||||||
|
*/
|
||||||
|
const it = extTest
|
||||||
|
|
||||||
|
export { it }
|
||||||
|
|
||||||
|
export default extTest
|
|
@ -2,8 +2,8 @@ import { type Server } from 'net'
|
||||||
|
|
||||||
export type TestCaseLabel = string
|
export type TestCaseLabel = string
|
||||||
export type TestFilePath = string
|
export type TestFilePath = string
|
||||||
export type TestCaseFunction = () => void
|
export type TestCaseFunction = (...args: Array<unknown>) => void
|
||||||
export type TestCaseGroup = () => void
|
export type TestCaseGroup = (...args: Array<unknown>) => void
|
||||||
|
|
||||||
export interface TestServer extends Server {
|
export interface TestServer extends Server {
|
||||||
failure?: boolean
|
failure?: boolean
|
||||||
|
|
|
@ -1,55 +1,17 @@
|
||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
import { describe, test, expect } from '../src/testCaseUtils'
|
import { describe, test, expect } from '../src'
|
||||||
|
|
||||||
describe('Equality', () => {
|
describe('Equality', () => {
|
||||||
test('Equality (number)', () => {
|
test.each([1, 'expectations', true])('Equality (value=%s)', (value: unknown) => {
|
||||||
assert.doesNotThrow(() => expect(1).toEqual(1))
|
assert.doesNotThrow(() => expect(value).toEqual(value))
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Equality (string)', () => {
|
test.each([
|
||||||
assert.doesNotThrow(() => expect('expectations').toEqual('expectations'))
|
[1, 2],
|
||||||
})
|
['expectation', 'something else'],
|
||||||
|
[true, false],
|
||||||
test('Equality (boolean)', () => {
|
])('Equality (failed - values=%s)', (...pair: Array<unknown>) => {
|
||||||
assert.doesNotThrow(() => expect(true).toEqual(true))
|
assert.throws(() => expect(pair[0]).toEqual(pair[1]))
|
||||||
})
|
|
||||||
|
|
||||||
test('Equality (failed - number)', () => {
|
|
||||||
assert.throws(() => expect(1).toEqual(2))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Equality (failed - string)', () => {
|
|
||||||
assert.throws(() => expect('expectation').toEqual('something else'))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Equality (failed - boolean)', () => {
|
|
||||||
assert.throws(() => expect(true).toEqual(false))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('Identity', () => {
|
|
||||||
test('Identity comparison (number)', () => {
|
|
||||||
assert.doesNotThrow(() => expect(1).toBe(1))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Identity comparison (boolean)', () => {
|
|
||||||
assert.doesNotThrow(() => expect(true).toBe(true))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Identity comparison (string)', () => {
|
|
||||||
assert.doesNotThrow(() => expect('identity').toBe('identity'))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Identity comparison (failed - number)', () => {
|
|
||||||
assert.throws(() => expect(1).toEqual(2))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Identity comparison (failed - boolean)', () => {
|
|
||||||
assert.throws(() => expect(false).toBe(true))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Identity comparison (failed - string)', () => {
|
|
||||||
assert.throws(() => expect('yes').toBe('no'))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Equality negation', () => {
|
test('Equality negation', () => {
|
||||||
|
@ -57,6 +19,24 @@ describe('Identity', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Identity', () => {
|
||||||
|
test.each([1, true, 'identity'])('Identity comparison (value=%s)', (value: unknown) => {
|
||||||
|
assert.doesNotThrow(() => expect(value).toBe(value))
|
||||||
|
})
|
||||||
|
|
||||||
|
test.each([
|
||||||
|
[1, 2],
|
||||||
|
[false, true],
|
||||||
|
['yes', 'no'],
|
||||||
|
])('Identity comparison (failed - value=%s)', (...pair: Array<unknown>) => {
|
||||||
|
assert.throws(() => expect(pair[0]).toBe(pair[1]))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Identity negation', () => {
|
||||||
|
assert.doesNotThrow(() => expect('yes').not.toBe('no'))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('Exception expectation', () => {
|
describe('Exception expectation', () => {
|
||||||
test('Expects error', () => {
|
test('Expects error', () => {
|
||||||
const err = new Error('err')
|
const err = new Error('err')
|
||||||
|
|
14
tests/it.test.ts
Normal file
14
tests/it.test.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
import { it, test, expect, describe } from '../src'
|
||||||
|
|
||||||
|
describe.each([it, test])('Runs tests', (fn: unknown) => {
|
||||||
|
const testFn = fn as typeof test
|
||||||
|
testFn('Runs a test', () => {
|
||||||
|
assert.doesNotThrow(() => expect(1).toEqual(1))
|
||||||
|
})
|
||||||
|
|
||||||
|
testFn.each([1, 2, 3])('Supports parametrization (value=%s)', (value: unknown) => {
|
||||||
|
assert.doesNotThrow(() => expect(value).toEqual(value))
|
||||||
|
})
|
||||||
|
})
|
Reference in a new issue