UNPKG

hathora-et-labora-game

Version:

Game logic reducer for Uwe Rosenberg's Ora et Labora

145 lines (138 loc) 5.29 kB
import { describe, it, test, beforeEach, afterEach, before, after, mock } from 'node:test' import assert from 'node:assert/strict' export { describe, it, test, beforeEach, afterEach, before, after, mock } const deepEquals = (a: unknown, b: unknown): boolean => { try { assert.deepStrictEqual(a, b) return true } catch { return false } } const partiallyMatches = (actual: unknown, expected: unknown): boolean => { try { assert.partialDeepStrictEqual(actual, expected) return true } catch { return false } } type Matchers = { toBe(expected: unknown): void toStrictEqual(expected: unknown): void toMatchObject(expected: unknown): void toContain(expected: unknown): void toBeUndefined(): void toBeDefined(): void toBeTruthy(): void toBeFalsy(): void toHaveLength(n: number): void toThrow(expected?: unknown): void toBeInstanceOf(C: abstract new (...args: never[]) => unknown): void toBeCloseTo(n: number, d?: number): void toBeLessThan(n: number): void toBeGreaterThanOrEqual(n: number): void toHaveBeenCalled(): void toHaveBeenCalledWith(...args: unknown[]): void not: Matchers } export const expect = (actual: unknown): Matchers => { const make = (negated: boolean): Matchers => ({ toBe(expected) { negated ? assert.notStrictEqual(actual, expected) : assert.strictEqual(actual, expected) }, toStrictEqual(expected) { negated ? assert.notDeepStrictEqual(actual, expected) : assert.deepStrictEqual(actual, expected) }, toMatchObject(expected) { negated ? assert.ok(!partiallyMatches(actual, expected), `Expected value NOT to match object`) : assert.partialDeepStrictEqual(actual, expected) }, toContain(expected) { let contains: boolean if (typeof actual === 'string') { contains = actual.includes(expected as string) } else if (Array.isArray(actual)) { contains = actual.includes(expected) } else { contains = [...(actual as Iterable<unknown>)].includes(expected) } negated ? assert.ok(!contains, `Expected value NOT to contain ${JSON.stringify(expected)}`) : assert.ok(contains, `Expected ${JSON.stringify(actual)} to contain ${JSON.stringify(expected)}`) }, toBeUndefined() { negated ? assert.notStrictEqual(actual, undefined) : assert.strictEqual(actual, undefined) }, toBeDefined() { negated ? assert.strictEqual(actual, undefined) : assert.notStrictEqual(actual, undefined) }, toBeTruthy() { negated ? assert.ok(!actual) : assert.ok(actual) }, toBeFalsy() { negated ? assert.ok(actual) : assert.ok(!actual) }, toHaveLength(n) { const len = (actual as { length: number }).length negated ? assert.notStrictEqual(len, n) : assert.strictEqual(len, n) }, toThrow(expected) { if (negated) { assert.doesNotThrow(actual as () => void) } else if (typeof expected === 'string') { assert.throws(actual as () => void, { message: expected }) } else if (expected !== undefined) { assert.throws(actual as () => void, expected as Error) } else { assert.throws(actual as () => void) } }, toBeInstanceOf(C) { negated ? assert.ok(!(actual instanceof C), `Expected value NOT to be instance of ${C.name}`) : assert.ok(actual instanceof C, `Expected value to be instance of ${C.name}`) }, toBeCloseTo(n, d = 2) { const delta = Math.pow(10, -d) / 2 const diff = Math.abs((actual as number) - n) negated ? assert.ok(diff >= delta, `Expected ${String(actual)} NOT to be close to ${n}`) : assert.ok(diff < delta, `Expected ${String(actual)} to be close to ${n}${delta})`) }, toBeLessThan(n) { negated ? assert.ok((actual as number) >= n, `Expected ${String(actual)} NOT to be less than ${n}`) : assert.ok((actual as number) < n, `Expected ${String(actual)} to be less than ${n}`) }, toBeGreaterThanOrEqual(n) { negated ? assert.ok((actual as number) < n, `Expected ${String(actual)} NOT to be >= ${n}`) : assert.ok((actual as number) >= n, `Expected ${String(actual)} to be >= ${n}`) }, toHaveBeenCalled() { const calls = (actual as { mock: { calls: unknown[] } }).mock.calls.length negated ? assert.strictEqual(calls, 0, `Expected mock NOT to have been called`) : assert.ok(calls > 0, `Expected mock to have been called`) }, toHaveBeenCalledWith(...args) { const mockCalls = (actual as { mock: { calls: { arguments: unknown[] }[] } }).mock.calls const found = mockCalls.some((call) => deepEquals(call.arguments, args)) negated ? assert.ok(!found, `Expected mock NOT to have been called with ${JSON.stringify(args)}`) : assert.ok( found, `Expected mock to have been called with ${JSON.stringify(args)}, got: ${JSON.stringify(mockCalls.map((c) => c.arguments))}` ) }, get not() { return make(!negated) }, }) return make(false) } // no-op: node:test has no equivalent for asserting a specific number of assertions expect.assertions = (_n: number) => {} expect.hasAssertions = () => {}