Skip to content

Commit 7fbc75e

Browse files
authored
Maintenance tasks (#1951)
* upgrade ava; update testlib for new api * remove some deps; bump minimum TS version in peerDeps to 4.2
1 parent e641088 commit 7fbc75e

File tree

6 files changed

+527
-1698
lines changed

6 files changed

+527
-1698
lines changed

ava.config.cjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ module.exports = {
1818
nodeArguments: ['--loader', './src/test/test-loader.mjs', '--no-warnings'],
1919
timeout: '300s',
2020
concurrency: 4,
21+
// We do chdir -- maybe other things -- that you can't do in worker_threads.
22+
workerThreads: false,
2123
};
2224

2325
{

package.json

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,31 +120,28 @@
120120
"@types/rimraf": "^3.0.0",
121121
"@types/semver": "^7.1.0",
122122
"@yarnpkg/fslib": "^2.4.0",
123-
"ava": "^3.15.0",
123+
"ava": "^5.1.1",
124124
"axios": "^0.21.1",
125125
"dprint": "^0.25.0",
126126
"expect": "27.0.2",
127127
"get-stream": "^6.0.0",
128128
"lodash": "^4.17.15",
129-
"ntypescript": "^1.201507091536.1",
130129
"nyc": "^15.0.1",
131130
"outdent": "^0.8.0",
132131
"proper-lockfile": "^4.1.2",
133132
"proxyquire": "^2.0.0",
134-
"react": "^16.14.0",
135133
"rimraf": "^3.0.0",
136134
"semver": "^7.1.3",
137135
"throat": "^6.0.1",
138136
"typedoc": "^0.22.10",
139137
"typescript": "4.7.4",
140-
"typescript-json-schema": "^0.53.0",
141-
"util.promisify": "^1.0.1"
138+
"typescript-json-schema": "^0.53.0"
142139
},
143140
"peerDependencies": {
144141
"@swc/core": ">=1.2.50",
145142
"@swc/wasm": ">=1.2.50",
146143
"@types/node": "*",
147-
"typescript": ">=2.7"
144+
"typescript": ">=4.2"
148145
},
149146
"peerDependenciesMeta": {
150147
"@swc/core": {
@@ -172,7 +169,7 @@
172169
"singleQuote": true
173170
},
174171
"volta": {
175-
"node": "18.1.0",
172+
"node": "18.14.0",
176173
"npm": "6.14.15"
177174
},
178175
"packageManager": "[email protected]"

src/externs.d.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/test/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NodeFS } from '@yarnpkg/fslib';
22
import { exec as childProcessExec } from 'child_process';
3-
import * as promisify from 'util.promisify';
3+
import { promisify } from 'util';
44
import { sync as rimrafSync } from 'rimraf';
55
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
66
import { join, resolve } from 'path';

src/test/testlib.ts

Lines changed: 93 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
import avaTest, {
88
ExecutionContext,
99
Implementation,
10-
OneOrMoreMacros,
10+
ImplementationFn,
11+
Macro,
12+
MacroDeclarationOptions,
13+
MacroFn,
14+
TestFn,
1115
} from 'ava';
1216
import * as assert from 'assert';
1317
import throat from 'throat';
@@ -58,59 +62,72 @@ export const test = createTestInterface({
5862
// In case someone wants to `const test = context()`
5963
export const context = test.context;
6064

65+
export type SimpleTitleFn = (providedTitle: string | undefined) => string;
66+
export type SimpleImplementationFn<Context = unknown> = (
67+
t: ExecutionContext<Context>
68+
) => PromiseLike<void>;
69+
export type SimpleContextFn<Context, T> = (
70+
t: ExecutionContext<Context>
71+
) => Promise<T>;
72+
6173
export interface TestInterface<
6274
Context
6375
> /*extends Omit<AvaTestInterface<Context>, 'before' | 'beforeEach' | 'after' | 'afterEach' | 'failing' | 'serial'>*/ {
6476
//#region copy-pasted from ava's .d.ts
6577
/** Declare a concurrent test. */
66-
(title: string, implementation: Implementation<Context>): void;
78+
(title: string, implementation: Implementation<unknown[], Context>): void;
6779
/** Declare a concurrent test that uses one or more macros. Additional arguments are passed to the macro. */
6880
<T extends any[]>(
6981
title: string,
70-
macros: OneOrMoreMacros<T, Context>,
82+
implementation: Implementation<T, Context>,
7183
...rest: T
7284
): void;
7385
/** Declare a concurrent test that uses one or more macros. The macro is responsible for generating a unique test title. */
74-
<T extends any[]>(macros: OneOrMoreMacros<T, Context>, ...rest: T): void;
86+
<T extends any[]>(macro: Implementation<T, Context>, ...rest: T): void;
7587
//#endregion
7688

77-
serial(title: string, implementation: Implementation<Context>): void;
89+
serial(
90+
title: string,
91+
implementation: Implementation<unknown[], Context>
92+
): void;
7893
/** Declare a concurrent test that uses one or more macros. Additional arguments are passed to the macro. */
7994
serial<T extends any[]>(
8095
title: string,
81-
macros: OneOrMoreMacros<T, Context>,
96+
implementation: Implementation<T, Context>,
8297
...rest: T
8398
): void;
8499
/** Declare a concurrent test that uses one or more macros. The macro is responsible for generating a unique test title. */
85100
serial<T extends any[]>(
86-
macros: OneOrMoreMacros<T, Context>,
101+
implementation: Implementation<T, Context>,
87102
...rest: T
88103
): void;
89-
skip(title: string, implementation: Implementation<Context>): void;
104+
skip(title: string, implementation: Implementation<unknown[], Context>): void;
90105
/** Declare a concurrent test that uses one or more macros. Additional arguments are passed to the macro. */
91106
skip<T extends any[]>(
92107
title: string,
93-
macros: OneOrMoreMacros<T, Context>,
108+
implementation: Implementation<T, Context>,
94109
...rest: T
95110
): void;
96111
/** Declare a concurrent test that uses one or more macros. The macro is responsible for generating a unique test title. */
97-
skip<T extends any[]>(macros: OneOrMoreMacros<T, Context>, ...rest: T): void;
112+
skip<T extends any[]>(
113+
implementation: Implementation<T, Context>,
114+
...rest: T
115+
): void;
98116

99117
macro<Args extends any[], Ctx = Context>(
100118
cb: (
101119
...args: Args
102120
) =>
103-
| [
104-
((title: string | undefined) => string | undefined) | string,
105-
(t: ExecutionContext<Ctx>) => Promise<void>
106-
]
107-
| ((t: ExecutionContext<Ctx>) => Promise<void>)
108-
): AvaMacro<Args, Ctx>;
121+
| [SimpleTitleFn | string, SimpleImplementationFn<Ctx>]
122+
| SimpleImplementationFn<Ctx>
123+
): Macro<Args, Ctx>;
124+
125+
avaMacro: MacroFn<Context>;
109126

110-
beforeAll(cb: (t: ExecutionContext<Context>) => Promise<void>): void;
111-
beforeEach(cb: (t: ExecutionContext<Context>) => Promise<void>): void;
127+
beforeAll(cb: SimpleImplementationFn<Context>): void;
128+
beforeEach(cb: SimpleImplementationFn<Context>): void;
112129
context<T extends object | void>(
113-
cb: (t: ExecutionContext<Context>) => Promise<T>
130+
cb: SimpleContextFn<Context, T>
114131
): TestInterface<Context & T>;
115132
suite(title: string, cb: (test: TestInterface<Context>) => void): void;
116133

@@ -125,10 +142,6 @@ export interface TestInterface<
125142

126143
// TODO add teardownEach
127144
}
128-
export interface AvaMacro<Args extends any[] = any[], Ctx = unknown> {
129-
(test: ExecutionContext<Ctx>, ...args: Args): Promise<void>;
130-
title?(givenTitle: string | undefined, ...args: Args): string;
131-
}
132145

133146
function createTestInterface<Context>(opts: {
134147
titlePrefix: string | undefined;
@@ -145,13 +158,11 @@ function createTestInterface<Context>(opts: {
145158
let suiteOrTestDeclared = false;
146159
function computeTitle<Args extends any[]>(
147160
title: string | undefined,
148-
macros?: AvaMacro<Args, any>[],
161+
impl?: Implementation<Args, any>,
149162
...args: Args
150163
) {
151-
for (const macro of macros ?? []) {
152-
if (macro.title) {
153-
title = macro.title(title, ...args);
154-
}
164+
if (isMacroWithTitle(impl)) {
165+
title = impl.title!(title, ...args);
155166
}
156167
assert(title);
157168
// return `${ titlePrefix }${ separator }${ title }`;
@@ -165,13 +176,8 @@ function createTestInterface<Context>(opts: {
165176
function parseArgs(args: any[]) {
166177
const title =
167178
typeof args[0] === 'string' ? (args.shift() as string) : undefined;
168-
const macros =
169-
typeof args[0] === 'function'
170-
? [args.shift() as AvaMacro]
171-
: Array.isArray(args[0])
172-
? (args.shift() as AvaMacro[])
173-
: [];
174-
return { title, macros, args };
179+
const impl = args.shift() as Implementation<any[], Context>;
180+
return { title, impl, args };
175181
}
176182
function assertOrderingForDeclaringTest() {
177183
suiteOrTestDeclared = true;
@@ -196,29 +202,32 @@ function createTestInterface<Context>(opts: {
196202
*/
197203
function declareTest(
198204
title: string | undefined,
199-
macros: AvaMacro<any[], Context>[],
205+
impl: Implementation<any[], Context>,
200206
avaDeclareFunction: Function & { skip: Function },
201207
args: any[],
202208
skip = false
203209
) {
204-
const wrappedMacros = macros.map((macro) => {
205-
return async function (t: ExecutionContext<Context>, ...args: any[]) {
206-
return concurrencyLimiter(
207-
errorPostprocessor(async () => {
208-
let i = 0;
209-
for (const func of beforeEachFunctions) {
210-
await func(t);
211-
i++;
212-
}
213-
return macro(t, ...args);
214-
})
215-
);
216-
};
217-
});
218-
const computedTitle = computeTitle(title, macros, ...args);
210+
const wrapped = async function (
211+
t: ExecutionContext<Context>,
212+
...args: any[]
213+
) {
214+
return concurrencyLimiter(
215+
errorPostprocessor(async () => {
216+
let i = 0;
217+
for (const func of beforeEachFunctions) {
218+
await func(t);
219+
i++;
220+
}
221+
return isMacro(impl)
222+
? impl.exec(t, ...args)
223+
: (impl as ImplementationFn<any[], Context>)(t, ...args);
224+
})
225+
);
226+
};
227+
const computedTitle = computeTitle(title, impl, ...args);
219228
(automaticallySkip || skip ? avaDeclareFunction.skip : avaDeclareFunction)(
220229
computedTitle,
221-
wrappedMacros,
230+
wrapped,
222231
...args
223232
);
224233
}
@@ -229,23 +238,23 @@ function createTestInterface<Context>(opts: {
229238
// start till it finishes.
230239
// HOWEVER if it returns a single shared state, can tests concurrently use this shared state?
231240
// if(!automaticallyDoSerial && mustDoSerial) throw new Error('Cannot declare non-serial tests because you have declared a beforeAll() hook for this test suite.');
232-
const { args, macros, title } = parseArgs(inputArgs);
241+
const { args, impl, title } = parseArgs(inputArgs);
233242
return declareTest(
234243
title,
235-
macros,
244+
impl,
236245
automaticallyDoSerial ? avaTest.serial : avaTest,
237246
args
238247
);
239248
}
240249
test.serial = function (...inputArgs: any[]) {
241250
assertOrderingForDeclaringTest();
242-
const { args, macros, title } = parseArgs(inputArgs);
243-
return declareTest(title, macros, avaTest.serial, args);
251+
const { args, impl, title } = parseArgs(inputArgs);
252+
return declareTest(title, impl, avaTest.serial, args);
244253
};
245254
test.skip = function (...inputArgs: any[]) {
246255
assertOrderingForDeclaringTest();
247-
const { args, macros, title } = parseArgs(inputArgs);
248-
return declareTest(title, macros, avaTest, args, true);
256+
const { args, impl, title } = parseArgs(inputArgs);
257+
return declareTest(title, impl, avaTest, args, true);
249258
};
250259
test.beforeEach = function (
251260
cb: (test: ExecutionContext<Context>) => Promise<void>
@@ -274,27 +283,29 @@ function createTestInterface<Context>(opts: {
274283
cb: (
275284
...args: Args
276285
) =>
277-
| [
278-
((title: string | undefined) => string | undefined) | string,
279-
(t: ExecutionContext<Context>) => Promise<void>
280-
]
281-
| ((t: ExecutionContext<Context>) => Promise<void>)
286+
| [SimpleTitleFn | string, SimpleImplementationFn<Context>]
287+
| SimpleImplementationFn<Context>
282288
) {
283-
function macro(testInterface: ExecutionContext<Context>, ...args: Args) {
284-
const ret = cb(...args);
285-
const macroFunction = Array.isArray(ret) ? ret[1] : ret;
286-
return macroFunction(testInterface);
287-
}
288-
macro.title = function (givenTitle: string | undefined, ...args: Args) {
289+
function title(givenTitle: string | undefined, ...args: Args) {
289290
const ret = cb(...args);
290291
return Array.isArray(ret)
291292
? typeof ret[0] === 'string'
292293
? ret[0]
293294
: ret[0](givenTitle)
294-
: givenTitle;
295+
: givenTitle ?? 'UNKNOWN';
296+
}
297+
function exec(testInterface: ExecutionContext<Context>, ...args: Args) {
298+
const ret = cb(...args);
299+
const impl = Array.isArray(ret) ? ret[1] : ret;
300+
return impl(testInterface);
301+
}
302+
const declaration: MacroDeclarationOptions<Args, Context> = {
303+
title,
304+
exec,
295305
};
296-
return macro;
306+
return (avaTest as TestFn<Context>).macro<Args>(declaration);
297307
};
308+
test.avaMacro = (avaTest as TestFn<Context>).macro;
298309
test.suite = function (
299310
title: string,
300311
cb: (test: TestInterface<Context>) => void
@@ -322,3 +333,14 @@ function createTestInterface<Context>(opts: {
322333
};
323334
return test as any;
324335
}
336+
337+
function isMacro(
338+
implementation?: Implementation<any, any>
339+
): implementation is Macro<any> {
340+
return implementation != null && typeof implementation !== 'function';
341+
}
342+
function isMacroWithTitle(
343+
implementation?: Implementation<any, any>
344+
): implementation is Macro<any> {
345+
return !!(implementation && (implementation as Macro<[]>)?.title);
346+
}

0 commit comments

Comments
 (0)