Skip to content

Commit 4b4b2f6

Browse files
committedJul 10, 2021
Refactor type definition
* Split across multiple files. * Rename types, most noticeably `TestInterface` is now `TestFn`, but really anything that had the Interface suffix has been changed. * Update some documentation.
1 parent fe12bd4 commit 4b4b2f6

10 files changed

+656
-646
lines changed
 

‎.xo-config.json

+5-6
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@
2323
},
2424
"overrides": [
2525
{
26-
"files": "index.d.ts",
26+
"files": [
27+
"index.d.ts",
28+
"types/*.d.ts"
29+
],
2730
"rules": {
28-
"@typescript-eslint/member-ordering": "off",
29-
"@typescript-eslint/method-signature-style": "off",
30-
"@typescript-eslint/prefer-readonly-parameter-types": "off",
31-
"@typescript-eslint/prefer-function-type": "off",
32-
"@typescript-eslint/unified-signatures": "off"
31+
"import/extensions": "off"
3332
}
3433
},
3534
{

‎docs/recipes/typescript.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,11 @@ test('providedTitle', macro, '3 * 3', 9);
186186

187187
## Typing [`t.context`](../01-writing-tests.md#test-context)
188188

189-
By default, the type of `t.context` will be the empty object (`{}`). AVA exposes an interface `TestInterface<Context>` which you can use to apply your own type to `t.context`. This can help you catch errors at compile-time:
189+
By default, the type of `t.context` will be the empty object (`{}`). AVA exposes an interface `TestInterface<Context>` (in AVA 4 this is `TestFn<Context>`) which you can use to apply your own type to `t.context`. This can help you catch errors at compile-time:
190190

191191
```ts
192-
import anyTest, {TestInterface} from 'ava';
192+
import anyTest, {TestInterface} from 'ava'; // AVA 3
193+
// import anyTest, {TestFn as TestInterface} from 'ava'; // AVA 4, usage is the same
193194

194195
const test = anyTest as TestInterface<{foo: string}>;
195196

@@ -213,7 +214,7 @@ test('an actual test', t => {
213214
You can also type the context when creating macros:
214215

215216
```ts
216-
import anyTest, {Macro, TestInterface} from 'ava';
217+
import anyTest, {Macro, TestInterface} from 'ava'; // AVA 3
217218

218219
interface Context {
219220
foo: string

‎index.d.ts

+6-632
Large diffs are not rendered by default.

‎package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
"files": [
3131
"entrypoints",
3232
"lib",
33-
"*.d.ts"
33+
"types",
34+
"index.d.ts",
35+
"plugin.d.ts"
3436
],
3537
"keywords": [
3638
"🦄",

‎test-d/context.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import {expectError, expectType} from 'tsd';
22

3-
import anyTest, {ExecutionContext, TestInterface} from '..';
3+
import anyTest, {ExecutionContext, TestFn} from '..';
44

55
interface Context {
66
foo: string;
77
}
88

9-
const test = anyTest as TestInterface<Context>; // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
9+
const test = anyTest as TestFn<Context>; // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
1010

1111
const macro = test.macro((t, expected: number) => {
1212
expectType<string>(t.context.foo);
@@ -27,6 +27,6 @@ interface Covariant extends Context {
2727
bar: number;
2828
}
2929

30-
const test2 = anyTest as TestInterface<Covariant>; // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
30+
const test2 = anyTest as TestFn<Covariant>; // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
3131
const hook = (t: ExecutionContext<Context>) => {};
3232
test2.beforeEach(hook);

‎test-d/implementation-result.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test('return a subscribable', t => {
1616
};
1717
});
1818

19-
test('return anything else', t => {
19+
test.after('return anything else', t => {
2020
return {
2121
foo: 'bar',
2222
subscribe() {},

‎types/assertions.d.ts

+338
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
export type ErrorConstructor = new (...args: any[]) => Error;
2+
3+
/** Specify one or more expectations the thrown error must satisfy. */
4+
export type ThrowsExpectation = {
5+
/** The thrown error must have a code that equals the given string or number. */
6+
code?: string | number;
7+
8+
/** The thrown error must be an instance of this constructor. */
9+
instanceOf?: ErrorConstructor;
10+
11+
/** The thrown error must be strictly equal to this value. */
12+
is?: Error;
13+
14+
/** The thrown error must have a message that equals the given string, or matches the regular expression. */
15+
message?: string | RegExp;
16+
17+
/** The thrown error must have a name that equals the given string. */
18+
name?: string;
19+
};
20+
21+
export interface Assertions {
22+
/**
23+
* Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
24+
* indicating whether the assertion passed. Comes with power-assert.
25+
*/
26+
assert: AssertAssertion;
27+
28+
/**
29+
* Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
30+
* `expected`, returning a boolean indicating whether the assertion passed.
31+
*/
32+
deepEqual: DeepEqualAssertion;
33+
34+
/**
35+
* Assert that `value` is like `selector`, returning a boolean indicating whether the assertion passed.
36+
*/
37+
like: LikeAssertion;
38+
39+
/** Fail the test, always returning `false`. */
40+
fail: FailAssertion;
41+
42+
/**
43+
* Assert that `actual` is strictly false, returning a boolean indicating whether the assertion passed.
44+
*/
45+
false: FalseAssertion;
46+
47+
/**
48+
* Assert that `actual` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), returning a boolean
49+
* indicating whether the assertion passed.
50+
*/
51+
falsy: FalsyAssertion;
52+
53+
/**
54+
* Assert that `actual` is [the same
55+
* value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
56+
* returning a boolean indicating whether the assertion passed.
57+
*/
58+
is: IsAssertion;
59+
60+
/**
61+
* Assert that `actual` is not [the same
62+
* value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
63+
* returning a boolean indicating whether the assertion passed.
64+
*/
65+
not: NotAssertion;
66+
67+
/**
68+
* Assert that `actual` is not [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
69+
* `expected`, returning a boolean indicating whether the assertion passed.
70+
*/
71+
notDeepEqual: NotDeepEqualAssertion;
72+
73+
/**
74+
* Assert that `string` does not match the regular expression, returning a boolean indicating whether the assertion
75+
* passed.
76+
*/
77+
notRegex: NotRegexAssertion;
78+
79+
/** Assert that the function does not throw. */
80+
notThrows: NotThrowsAssertion;
81+
82+
/** Assert that the async function does not throw, or that the promise does not reject. Must be awaited. */
83+
notThrowsAsync: NotThrowsAsyncAssertion;
84+
85+
/** Count a passing assertion, always returning `true`. */
86+
pass: PassAssertion;
87+
88+
/**
89+
* Assert that `string` matches the regular expression, returning a boolean indicating whether the assertion passed.
90+
*/
91+
regex: RegexAssertion;
92+
93+
/**
94+
* Assert that `expected` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to a
95+
* previously recorded [snapshot](https://github.com/concordancejs/concordance#serialization-details), or if
96+
* necessary record a new snapshot.
97+
*/
98+
snapshot: SnapshotAssertion;
99+
100+
/**
101+
* Assert that the function throws [an error](https://www.npmjs.com/package/is-error). If so, returns the error value.
102+
*/
103+
throws: ThrowsAssertion;
104+
105+
/**
106+
* Assert that the async function throws [an error](https://www.npmjs.com/package/is-error), or the promise rejects
107+
* with one. If so, returns a promise for the error value, which must be awaited.
108+
*/
109+
throwsAsync: ThrowsAsyncAssertion;
110+
111+
/**
112+
* Assert that `actual` is strictly true, returning a boolean indicating whether the assertion passed.
113+
*/
114+
true: TrueAssertion;
115+
116+
/**
117+
* Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
118+
* indicating whether the assertion passed.
119+
*/
120+
truthy: TruthyAssertion;
121+
}
122+
123+
export interface AssertAssertion {
124+
/**
125+
* Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
126+
* indicating whether the assertion passed. Comes with power-assert.
127+
*/
128+
(actual: any, message?: string): boolean;
129+
130+
/** Skip this assertion. */
131+
skip(actual: any, message?: string): void;
132+
}
133+
134+
export interface DeepEqualAssertion {
135+
/**
136+
* Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
137+
* `expected`, returning a boolean indicating whether the assertion passed.
138+
*/
139+
<Actual, Expected extends Actual>(actual: Actual, expected: Expected, message?: string): actual is Expected;
140+
141+
/** Skip this assertion. */
142+
skip(actual: any, expected: any, message?: string): void;
143+
}
144+
145+
export interface LikeAssertion {
146+
/**
147+
* Assert that `value` is like `selector`, returning a boolean indicating whether the assertion passed.
148+
*/
149+
<Expected extends Record<string, any>>(value: any, selector: Expected, message?: string): value is Expected;
150+
151+
/** Skip this assertion. */
152+
skip(value: any, selector: any, message?: string): void;
153+
}
154+
155+
export interface FailAssertion {
156+
/** Fail the test, always returning `false`. */
157+
(message?: string): boolean;
158+
159+
/** Skip this assertion. */
160+
skip(message?: string): void;
161+
}
162+
163+
export interface FalseAssertion {
164+
/**
165+
* Assert that `actual` is strictly false, returning a boolean indicating whether the assertion passed.
166+
*/
167+
(actual: any, message?: string): actual is false;
168+
169+
/** Skip this assertion. */
170+
skip(actual: any, message?: string): void;
171+
}
172+
173+
export interface FalsyAssertion {
174+
/**
175+
* Assert that `actual` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), returning a boolean
176+
* indicating whether the assertion passed.
177+
*/
178+
(actual: any, message?: string): boolean;
179+
180+
/** Skip this assertion. */
181+
skip(actual: any, message?: string): void;
182+
}
183+
184+
export interface IsAssertion {
185+
/**
186+
* Assert that `actual` is [the same
187+
* value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
188+
* returning a boolean indicating whether the assertion passed.
189+
*/
190+
<Actual, Expected extends Actual>(actual: Actual, expected: Expected, message?: string): actual is Expected;
191+
192+
/** Skip this assertion. */
193+
skip(actual: any, expected: any, message?: string): void;
194+
}
195+
196+
export interface NotAssertion {
197+
/**
198+
* Assert that `actual` is not [the same
199+
* value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
200+
* returning a boolean indicating whether the assertion passed.
201+
*/
202+
<Actual, Expected>(actual: Actual, expected: Expected, message?: string): boolean;
203+
204+
/** Skip this assertion. */
205+
skip(actual: any, expected: any, message?: string): void;
206+
}
207+
208+
export interface NotDeepEqualAssertion {
209+
/**
210+
* Assert that `actual` is not [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
211+
* `expected`, returning a boolean indicating whether the assertion passed.
212+
*/
213+
<Actual, Expected>(actual: Actual, expected: Expected, message?: string): boolean;
214+
215+
/** Skip this assertion. */
216+
skip(actual: any, expected: any, message?: string): void;
217+
}
218+
219+
export interface NotRegexAssertion {
220+
/**
221+
* Assert that `string` does not match the regular expression, returning a boolean indicating whether the assertion
222+
* passed.
223+
*/
224+
(string: string, regex: RegExp, message?: string): boolean;
225+
226+
/** Skip this assertion. */
227+
skip(string: string, regex: RegExp, message?: string): void;
228+
}
229+
230+
export interface NotThrowsAssertion {
231+
/** Assert that the function does not throw. */
232+
(fn: () => any, message?: string): void;
233+
234+
/** Skip this assertion. */
235+
skip(fn: () => any, message?: string): void;
236+
}
237+
238+
export interface NotThrowsAsyncAssertion {
239+
/** Assert that the async function does not throw. You must await the result. */
240+
(fn: () => PromiseLike<any>, message?: string): Promise<void>;
241+
242+
/** Assert that the promise does not reject. You must await the result. */
243+
(promise: PromiseLike<any>, message?: string): Promise<void>; // eslint-disable-line @typescript-eslint/unified-signatures
244+
245+
/** Skip this assertion. */
246+
skip(nonThrower: any, message?: string): void;
247+
}
248+
249+
export interface PassAssertion {
250+
/** Count a passing assertion, always returning `true`. */
251+
(message?: string): boolean;
252+
253+
/** Skip this assertion. */
254+
skip(message?: string): void;
255+
}
256+
257+
export interface RegexAssertion {
258+
/**
259+
* Assert that `string` matches the regular expression, returning a boolean indicating whether the assertion passed.
260+
*/
261+
(string: string, regex: RegExp, message?: string): boolean;
262+
263+
/** Skip this assertion. */
264+
skip(string: string, regex: RegExp, message?: string): void;
265+
}
266+
267+
export interface SnapshotAssertion {
268+
/**
269+
* Assert that `expected` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to a
270+
* previously recorded [snapshot](https://github.com/concordancejs/concordance#serialization-details), or if
271+
* necessary record a new snapshot.
272+
*/
273+
(expected: any, message?: string): void;
274+
275+
/** Skip this assertion. */
276+
skip(expected: any, message?: string): void;
277+
}
278+
279+
export interface ThrowsAssertion {
280+
/**
281+
* Assert that the function throws [an error](https://www.npmjs.com/package/is-error). If so, returns the error value.
282+
* The error must satisfy all expectations.
283+
*/
284+
<ThrownError extends Error>(fn: () => any, expectations?: ThrowsExpectation | null, message?: string): ThrownError;
285+
286+
/** Skip this assertion. */
287+
skip(fn: () => any, expectations?: any, message?: string): void;
288+
}
289+
290+
export interface ThrowsAsyncAssertion {
291+
/**
292+
* Assert that the async function throws [an error](https://www.npmjs.com/package/is-error). If so, returns the error
293+
* value. You must await the result.
294+
*/
295+
<ThrownError extends Error>(fn: () => PromiseLike<any>, expectations?: null, message?: string): Promise<ThrownError>;
296+
297+
/**
298+
* Assert that the async function throws [an error](https://www.npmjs.com/package/is-error). If so, returns the error
299+
* value. You must await the result. The error must satisfy all expectations.
300+
*/
301+
<ThrownError extends Error>(fn: () => PromiseLike<any>, expectations: ThrowsExpectation, message?: string): Promise<ThrownError>;
302+
303+
/**
304+
* Assert that the promise rejects with [an error](https://www.npmjs.com/package/is-error). If so, returns the
305+
* rejection reason. You must await the result.
306+
*/
307+
<ThrownError extends Error>(promise: PromiseLike<any>, expectations?: null, message?: string): Promise<ThrownError>; // eslint-disable-line @typescript-eslint/unified-signatures
308+
309+
/**
310+
* Assert that the promise rejects with [an error](https://www.npmjs.com/package/is-error). If so, returns the
311+
* rejection reason. You must await the result. The error must satisfy all expectations.
312+
*/
313+
<ThrownError extends Error>(promise: PromiseLike<any>, expectations: ThrowsExpectation, message?: string): Promise<ThrownError>; // eslint-disable-line @typescript-eslint/unified-signatures
314+
315+
/** Skip this assertion. */
316+
skip(thrower: any, expectations?: any, message?: string): void;
317+
}
318+
319+
export interface TrueAssertion {
320+
/**
321+
* Assert that `actual` is strictly true, returning a boolean indicating whether the assertion passed.
322+
*/
323+
(actual: any, message?: string): actual is true;
324+
325+
/** Skip this assertion. */
326+
skip(actual: any, message?: string): void;
327+
}
328+
329+
export interface TruthyAssertion {
330+
/**
331+
* Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
332+
* indicating whether the assertion passed.
333+
*/
334+
(actual: any, message?: string): boolean;
335+
336+
/** Skip this assertion. */
337+
skip(actual: any, message?: string): void;
338+
}

‎types/subscribable.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface Subscribable {
2+
subscribe(observer: {
3+
error(error: any): void;
4+
complete(): void;
5+
}): void;
6+
}

‎types/test-fn.d.ts

+232
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import type {Assertions} from './assertions';
2+
import type {Subscribable} from './subscribable';
3+
import type {TryFn} from './try-fn';
4+
5+
/** The `t` value passed to test & hook implementations. */
6+
export interface ExecutionContext<Context = unknown> extends Assertions {
7+
/** Test context, shared with hooks. */
8+
context: Context;
9+
10+
/** Title of the test or hook. */
11+
readonly title: string;
12+
13+
/** Whether the test has passed. Only accurate in afterEach hooks. */
14+
readonly passed: boolean;
15+
16+
readonly log: LogFn;
17+
readonly plan: PlanFn;
18+
readonly teardown: TeardownFn;
19+
readonly timeout: TimeoutFn;
20+
readonly try: TryFn<Context>;
21+
}
22+
23+
export interface LogFn {
24+
/** Log one or more values. */
25+
(...values: any[]): void;
26+
27+
/** Skip logging. */
28+
skip(...values: any[]): void;
29+
}
30+
31+
export interface PlanFn {
32+
/**
33+
* Plan how many assertion there are in the test. The test will fail if the actual assertion count doesn't match the
34+
* number of planned assertions. See [assertion planning](https://github.com/avajs/ava#assertion-planning).
35+
*/
36+
(count: number): void;
37+
38+
/** Don't plan assertions. */
39+
skip(count: number): void;
40+
}
41+
42+
/**
43+
* Set a timeout for the test, in milliseconds. The test will fail if the timeout is exceeded.
44+
* The timeout is reset each time an assertion is made.
45+
*/
46+
export type TimeoutFn = (ms: number, message?: string) => void;
47+
48+
/** Declare a function to be run after the test has ended. */
49+
export type TeardownFn = (fn: () => void) => void;
50+
51+
export type ImplementationFn<Args extends unknown[], Context = unknown> =
52+
((t: ExecutionContext<Context>, ...args: Args) => PromiseLike<void>) |
53+
((t: ExecutionContext<Context>, ...args: Args) => Subscribable) |
54+
((t: ExecutionContext<Context>, ...args: Args) => void);
55+
56+
export type TitleFn<Args extends unknown[]> = (providedTitle: string | undefined, ...args: Args) => string;
57+
58+
/** A reusable test or hook implementation. */
59+
export type Macro<Args extends unknown[], Context = unknown> = {
60+
/** The function that is executed when the macro is used. */
61+
readonly exec: ImplementationFn<Args, Context>;
62+
63+
/** Generates a test title when this macro is used. */
64+
readonly title?: TitleFn<Args>;
65+
};
66+
67+
/** A test or hook implementation. */
68+
export type Implementation<Args extends unknown[], Context = unknown> = ImplementationFn<Args, Context> | Macro<Args, Context>;
69+
70+
export interface TestFn<Context = unknown> {
71+
after: AfterFn<Context>;
72+
afterEach: AfterFn<Context>;
73+
before: BeforeFn<Context>;
74+
beforeEach: BeforeFn<Context>;
75+
failing: FailingFn<Context>;
76+
macro: MacroFn<Context>;
77+
meta: Meta;
78+
only: OnlyFn<Context>;
79+
serial: SerialFn<Context>;
80+
skip: SkipFn<Context>;
81+
todo: TodoFn;
82+
83+
/** Declare a concurrent test. Additional arguments are passed to the implementation or macro. */
84+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
85+
86+
/**
87+
* Declare a concurrent test that uses a macro. Additional arguments are passed to the macro.
88+
* The macro is responsible for generating a unique test title.
89+
*/
90+
<Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
91+
}
92+
93+
export interface AfterFn<Context = unknown> {
94+
always: AlwaysInterface<Context>;
95+
skip: HookSkipFn<Context>;
96+
97+
/**
98+
* Declare a hook that is run once, after all tests have passed.
99+
* Additional arguments are passed to the implementation or macro.
100+
*/
101+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
102+
103+
/**
104+
* Declare a hook that is run once, after all tests have passed.
105+
* Additional arguments are passed to the implementation or macro.
106+
*/
107+
<Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
108+
109+
}
110+
111+
export interface AlwaysInterface<Context = unknown> {
112+
skip: HookSkipFn<Context>;
113+
114+
/**
115+
* Declare a hook that is run once, after all tests are done.
116+
* Additional arguments are passed to the implementation or macro.
117+
*/
118+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
119+
120+
/**
121+
* Declare a hook that is run once, after all tests are done.
122+
* Additional arguments are passed to the implementation or macro.
123+
*/
124+
<Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
125+
}
126+
127+
export interface BeforeFn<Context = unknown> {
128+
skip: HookSkipFn<Context>;
129+
130+
/**
131+
* Declare a hook that is run once, before all tests.
132+
* Additional arguments are passed to the implementation or macro.
133+
*/
134+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
135+
136+
/**
137+
* Declare a hook that is run once, before all tests.
138+
* Additional arguments are passed to the implementation or macro.
139+
*/
140+
<Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
141+
}
142+
143+
export interface FailingFn<Context = unknown> {
144+
only: OnlyFn<Context>;
145+
skip: SkipFn<Context>;
146+
147+
/**
148+
* Declare a concurrent test that is expected to fail.
149+
* Additional arguments are passed to the implementation or macro.
150+
*/
151+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
152+
153+
/**
154+
* Declare a concurrent test, using a macro, that is expected to fail.
155+
* Additional arguments are passed to the macro. The macro is responsible for generating a unique test title.
156+
*/
157+
<Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
158+
}
159+
160+
export interface HookSkipFn<Context = unknown> {
161+
/** Skip this hook. */
162+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
163+
164+
/** Skip this hook. */
165+
<Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
166+
}
167+
168+
export interface OnlyFn<Context = unknown> {
169+
/**
170+
* Declare a test. Only this test and others declared with `.only()` are run.
171+
* Additional arguments are passed to the implementation or macro.
172+
*/
173+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
174+
175+
/**
176+
* Declare a test that uses a macro. Only this test and others declared with `.only()` are run.
177+
* Additional arguments are passed to the macro. The macro is responsible for generating a unique test title.
178+
*/
179+
<Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
180+
}
181+
182+
export interface SerialFn<Context = unknown> {
183+
after: AfterFn<Context>;
184+
afterEach: AfterFn<Context>;
185+
before: BeforeFn<Context>;
186+
beforeEach: BeforeFn<Context>;
187+
failing: FailingFn<Context>;
188+
only: OnlyFn<Context>;
189+
skip: SkipFn<Context>;
190+
todo: TodoFn;
191+
192+
/** Declare a serial test. Additional arguments are passed to the implementation or macro. */
193+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
194+
195+
/**
196+
* Declare a serial test that uses a macro. The macro is responsible for generating a unique test title.
197+
*/
198+
<Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
199+
}
200+
201+
export interface SkipFn<Context = unknown> {
202+
/** Skip this test. */
203+
<Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
204+
205+
/** Skip this test. */
206+
<Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
207+
}
208+
209+
/** Declare a test that should be implemented later. */
210+
export type TodoFn = (title: string) => void;
211+
212+
export type MacroDeclarationOptions<Args extends unknown[], Context = unknown> = {
213+
/** The function that is executed when the macro is used. */
214+
exec: ImplementationFn<Args, Context>;
215+
216+
/** The function responsible for generating a unique title when the macro is used. */
217+
title: TitleFn<Args>;
218+
};
219+
220+
export interface MacroFn<Context = unknown> {
221+
/** Declare a reusable test implementation. */
222+
<Args extends unknown[]>(/** The function that is executed when the macro is used. */ exec: ImplementationFn<Args, Context>): Macro<Args, Context>;
223+
<Args extends unknown[]>(declaration: MacroDeclarationOptions<Args, Context>): Macro<Args, Context>; // eslint-disable-line @typescript-eslint/unified-signatures
224+
}
225+
226+
export interface Meta {
227+
/** Path to the test file being executed. */
228+
file: string;
229+
230+
/** Directory where snapshots are stored. */
231+
snapshotDirectory: string;
232+
}

‎types/try-fn.d.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type {Implementation} from './test-fn';
2+
3+
export type CommitDiscardOptions = {
4+
/**
5+
* Whether the logs should be included in those of the parent test.
6+
*/
7+
retainLogs?: boolean;
8+
};
9+
10+
export interface AssertionError extends Error {}
11+
12+
export interface TryResult {
13+
/**
14+
* Title of the attempt, helping you tell attempts aparts.
15+
*/
16+
title: string;
17+
18+
/**
19+
* Indicates whether all assertions passed, or at least one failed.
20+
*/
21+
passed: boolean;
22+
23+
/**
24+
* Errors raised for each failed assertion.
25+
*/
26+
errors: AssertionError[];
27+
28+
/**
29+
* Logs created during the attempt using `t.log()`. Contains formatted values.
30+
*/
31+
logs: string[];
32+
33+
/**
34+
* Commit the attempt. Counts as one assertion for the plan count. If the
35+
* attempt failed, calling this will also cause your test to fail.
36+
*/
37+
commit(options?: CommitDiscardOptions): void;
38+
39+
/**
40+
* Discard the attempt.
41+
*/
42+
discard(options?: CommitDiscardOptions): void;
43+
}
44+
45+
export interface TryFn<Context = unknown> {
46+
/**
47+
* Attempt to run some assertions. The result must be explicitly committed or discarded or else
48+
* the test will fail. The title may help distinguish attempts from one another.
49+
*/
50+
<Args extends unknown[]>(title: string, fn: Implementation<Args, Context>, ...args: Args): Promise<TryResult>;
51+
52+
/**
53+
* Attempt to run some assertions. The result must be explicitly committed or discarded or else
54+
* the test will fail.
55+
*/
56+
<Args extends unknown[]>(fn: Implementation<Args, Context>, ...args: Args): Promise<TryResult>;
57+
}
58+

0 commit comments

Comments
 (0)
Please sign in to comment.