diff --git a/src/index.ts b/src/index.ts index 8053027..68dac8f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ -import { Arbitrary, check, Parameters, property, RunDetails } from 'fast-check'; +import { Arbitrary, asyncProperty, check, Parameters, property, RunDetails } from 'fast-check'; -export type Check = (this: Mocha.Context, val: T) => boolean | never | void; +export type CheckStatus = boolean | void; +export type Check = (this: Mocha.Context, val: T) => never | CheckStatus | Promise; export type WrappedIt = (name: string, check: Check) => void; export type Suite = (it: WrappedIt) => void; @@ -9,14 +10,14 @@ export interface ErrorParameters extends Parameters { errorReporter?: ErrorReporter; } -export function over(name: string, strategy: Arbitrary, suite: Suite, parameters?: ErrorParameters): void { +export function over(name: string, strategy: Arbitrary, suite: Suite, parameters: ErrorParameters = {}): void { describe(name, () => { suite((name, test) => { it(name, function (this: Mocha.Context): Promise { const ctx = this; // something about check's type signature requires examples to be tuples, // which leads to triple-wrapping examples for tuple properties. help remove one layer - const examples: Array<[T]> = parameters?.examples?.map((it) => [it]) || []; + const examples: Array<[T]> = parameters.examples?.map((it) => [it]) || []; const checkParameters: Parameters<[T]> = { ...parameters, // handle result formatting here @@ -24,15 +25,16 @@ export function over(name: string, strategy: Arbitrary, suite: Suite, p reporter: undefined, examples, }; - const reporter = (parameters?.errorReporter || briefReporter) as ErrorReporter<[T]>; + const reporter = (parameters.errorReporter || briefReporter) as ErrorReporter<[T]>; - return new Promise((res, rej) => { - // wrap the strategy arb in a one-shot property checking the test fn - const result = check(property(strategy, (val) => test.call(ctx, val)), checkParameters); + // wrap the strategy arb in a one-shot property checking the test fn + // TODO: switch between property and asyncProperty as needed + const property = asyncProperty(strategy, (val) => Promise.resolve(test.call(ctx, val))); + return Promise.resolve(check(property, checkParameters)).then((result) => { if (result.failed) { - rej(new Error(reporter(result))); + throw new Error(reporter(result)); } else { - res(); + return undefined; } }); }); diff --git a/test/TestOver.ts b/test/TestOver.ts index 08c5613..826b614 100644 --- a/test/TestOver.ts +++ b/test/TestOver.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; -import { array, defaultReportMessage, integer, lorem, oneof, tuple, uuid } from 'fast-check'; +import { array, defaultReportMessage, integer, lorem, tuple, uuid } from 'fast-check'; -import { over } from '../src/index'; +import { over } from '../src'; const LARGE_VALUE = Math.floor(Math.random() * 1_000_000_000); @@ -22,6 +22,10 @@ describe('example properties', () => { return true; }); + + it('should resolve async checks', async (n: number) => { + expect(n).to.be.lessThanOrEqual(90); + }); }); over('some IDs', uuid(), (it) => {