Skip to content

Commit

Permalink
✨(jest) Add new it.prop and related
Browse files Browse the repository at this point in the history
Related to #3303
  • Loading branch information
dubzzz committed Oct 20, 2022
1 parent 1474ef9 commit 4750409
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 152 deletions.
47 changes: 43 additions & 4 deletions packages/jest/src/jest-fast-check.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { it, test, jest } from '@jest/globals';
import { it as itJest, test as testJest, jest } from '@jest/globals';
import { type Global } from '@jest/types';
import * as fc from 'fast-check';

type It = typeof it;
type It = Global.ItConcurrent;

// Pre-requisite: https://github.com/Microsoft/TypeScript/pull/26063
// Require TypeScript 3.1
Expand Down Expand Up @@ -106,6 +107,44 @@ function internalTestProp(testFn: It) {
return Object.assign(base, extras);
}

export const testProp = internalTestProp(test);
export const itProp = internalTestProp(it);
type TestProp<Ts extends [any] | any[]> = (
arbitraries: ArbitraryTuple<Ts>,
params?: fc.Parameters<Ts>
) => (testName: string, prop: Prop<Ts>, timeout?: number | undefined) => void;

function buildTestProp<Ts extends [any] | any[]>(
testFn: It | It['only' | 'skip' | 'failing' | 'concurrent'] | It['concurrent']['only' | 'skip' | 'failing']
): TestProp<Ts> {
return (arbitraries: ArbitraryTuple<Ts>, params?: fc.Parameters<Ts>) =>
(testName: string, prop: Prop<Ts>, _timeout?: number | undefined) =>
internalTestPropExecute(testFn, testName, arbitraries, prop, params);
}

type FastCheckItBuilder<T> = T &
('each' extends keyof T ? T & { prop: TestProp<unknown[]> } : T) & {
[K in keyof Omit<T, 'each'>]: FastCheckItBuilder<T[K]>;
};

function enrichWithTestProp<T extends (...args: any[]) => any>(testFn: T): FastCheckItBuilder<T> {
if (typeof testFn !== 'function') {
throw new Error(`Unexpected entry encountered while build {it/test} for @fast-check/jest`);
}
if (Object.keys(testFn).length === 0) {
return testFn as FastCheckItBuilder<T>;
}
const enrichedTestFn = (...args: Parameters<T>): ReturnType<T> => testFn(...args);
const extraKeys: Partial<FastCheckItBuilder<T>> = {};
for (const key in testFn) {
extraKeys[key] = key === 'each' ? enrichWithTestProp(testFn[key] as any) : testFn[key];
}
if ('each' in testFn) {
extraKeys['prop' as keyof typeof extraKeys] = buildTestProp(testFn as any) as any;
}
return Object.assign(enrichedTestFn, extraKeys) as FastCheckItBuilder<T>;
}

export const test: FastCheckItBuilder<It> = enrichWithTestProp(testJest);
export const it: FastCheckItBuilder<It> = enrichWithTestProp(itJest);
export const testProp = internalTestProp(testJest);
export const itProp = internalTestProp(itJest);
export { fc };
Loading

0 comments on commit 4750409

Please sign in to comment.