Skip to content

Commit 437acc8

Browse files
authored
Add tests for awaiting a delayed goodbye (#11)
1 parent 1c75e93 commit 437acc8

File tree

11 files changed

+132
-13
lines changed

11 files changed

+132
-13
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ jobs:
4444
run: yarn run lint:js
4545
- name: Check format
4646
run: yarn run lint:format
47-
- name: Check types
48-
run: yarn run lint:types
4947
- name: Build package
5048
run: yarn run build
51-
#- name: Run Tests
52-
#run: yarn run test
49+
- name: Run Tests
50+
run: yarn run test

eslint.config.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const rootDir = dirname(fileURLToPath(import.meta.url));
1414
const compat = new FlatCompat({ baseDirectory: rootDir });
1515

1616
export default [
17-
{ ignores: [".yarn/", ".pnp.*", "dist/"] },
17+
{ ignores: [".yarn/", ".pnp.*", "**/dist/"] },
1818
{ files: [allFiles], ...eslintJS.configs.recommended },
1919
...compat
2020
.extends(
@@ -35,9 +35,9 @@ export default [
3535
// Options specific to @typescript-eslint/parser
3636
parser: typescriptParser,
3737
parserOptions: {
38+
allowAutomaticSingleRunInference: true,
3839
ecmaVersion: "latest",
39-
project: "tsconfig.json",
40-
tsconfigRootDir: rootDir,
40+
EXPERIMENTAL_useProjectService: true,
4141
},
4242
},
4343
linterOptions: {
@@ -54,5 +54,8 @@ export default [
5454
{
5555
files: ["test/**/*.spec.?(c|m)ts"],
5656
languageOptions: { globals: globals.mocha },
57+
rules: {
58+
"@typescript-eslint/require-await": "off",
59+
},
5760
},
5861
];

mocha.config.cjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module.exports = {
22
require: "ts-node/register",
33
loader: ["ts-node/esm", "./.pnp.loader.mjs"],
4+
asyncOnly: true,
5+
forbidOnly: true,
46
spec: ["test/**/*.spec.*"],
57
watchFiles: ["src"],
68
};

package.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,14 @@
3838
"types": "./dist/index.d.cts",
3939
"sideEffects": false,
4040
"scripts": {
41-
"lint:js": "eslint --cache --cache-strategy=content --cache-location=node_modules/.cache/eslint/.eslintcache .",
41+
"lint:js": "eslint --cache-location=node_modules/.cache/eslint/.eslintcache .",
42+
"lint:format": "prettier --cache --check .",
43+
"lint": "yarn dedupe --check && yarn run lint:js && yarn run lint:format",
4244
"fix": "yarn run lint:js --fix",
4345
"format": "prettier --cache --write .",
44-
"lint:format": "prettier --cache --check .",
45-
"lint:types": "tsc",
46-
"lint": "yarn dedupe --check && yarn run lint:js && yarn run lint:format && yarn run lint:types",
47-
"build": "tsc --build src",
46+
"build": "tsc --build --verbose",
4847
"test": "mocha --config mocha.config.cjs",
49-
"clean": "tsc --build --clean",
48+
"clean": "tsc --build --clean && rm -rf test/dist",
5049
"prepublish": "yarn run lint",
5150
"prepack": "yarn run build",
5251
"postpack": "yarn run clean"

src/tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{
22
"extends": "../tsconfig.json",
3+
"include": ["./"],
34
"compilerOptions": {
5+
// Modules
6+
"rootDir": ".",
47
// Emit
58
"noEmit": false,
69
"declaration": true,

test/goodbye.spec.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { expect } from "chai";
2+
import { readFile } from "node:fs/promises";
3+
import { join } from "node:path";
4+
import { fileURLToPath } from "node:url";
5+
import { TransformAsyncModulesPlugin } from "transform-async-modules-webpack-plugin";
6+
import webpack from "webpack";
7+
8+
type GoodbyeEntry = typeof import("./src/simple.js");
9+
10+
const context = fileURLToPath(new URL(".", import.meta.url));
11+
const ENTRY_NAMES = ["simple", "chained"] as const;
12+
const CHECK_CHUNKS = ["goodbye", "parent"] as const;
13+
14+
for (const nodeVersion of [8, 6, 0.12]) {
15+
describe(`Goodbye delay with node ${nodeVersion} target`, function () {
16+
const outDir = join(context, "dist", `v${nodeVersion}`);
17+
let compileProblems = "";
18+
19+
before("Run Webpack", function (done) {
20+
this.timeout("5s");
21+
webpack(
22+
{
23+
name: `goodbye-node${nodeVersion}`,
24+
context,
25+
entry: Object.fromEntries(
26+
ENTRY_NAMES.map((name) => [name, `./src/${name}.js`]),
27+
),
28+
output: {
29+
clean: true,
30+
path: outDir,
31+
filename: "[name].cjs",
32+
library: { type: "commonjs-static" },
33+
},
34+
target: `async-node${nodeVersion}`,
35+
plugins: [
36+
new TransformAsyncModulesPlugin({
37+
browserslistConfigFile: false,
38+
targets: `node ${nodeVersion}`,
39+
}),
40+
],
41+
devtool: "source-map",
42+
mode: "development",
43+
node: false,
44+
},
45+
(err, stats) => {
46+
if (stats?.hasErrors()) {
47+
compileProblems = stats.toString("errors-only");
48+
}
49+
done(err);
50+
},
51+
);
52+
});
53+
54+
it("Compiles without errors", async function () {
55+
expect(compileProblems, compileProblems).to.be.empty;
56+
});
57+
58+
for (const name of CHECK_CHUNKS) {
59+
const outChunk = join(outDir, `src_${name}_js.cjs`);
60+
if (nodeVersion < 7.6) {
61+
it(`Transpiles the async function to a generator in the ${name} chunk`, async function () {
62+
const code = await readFile(outChunk, "utf-8");
63+
expect(code).to.have.string("function _asyncToGenerator(fn) {");
64+
});
65+
} else {
66+
it(`Contains async arrow function in the ${name} chunk`, async function () {
67+
const code = await readFile(outChunk, "utf-8");
68+
expect(code).to.have.string(
69+
" async (__webpack_handle_async_dependencies__, __webpack_async_result__) => {",
70+
);
71+
});
72+
}
73+
if (nodeVersion < 4) {
74+
it(`Uses the regenerator runtime in the ${name} chunk`, async function () {
75+
const code = await readFile(outChunk, "utf-8");
76+
expect(code).to.have.string(" function _regeneratorRuntime() {");
77+
});
78+
}
79+
}
80+
81+
for (const name of ENTRY_NAMES) {
82+
const outEntry = join(outDir, `${name}.cjs`);
83+
it(`Awaits with correct phrase and delay for ${name} entry`, async function () {
84+
const { goodbye } = (await import(outEntry)) as GoodbyeEntry;
85+
const { PHRASE, DELAY, awaitedPhrase, awaitedDelay } = await goodbye;
86+
expect(awaitedPhrase).to.be.a("string").which.equals(PHRASE);
87+
expect(awaitedDelay)
88+
.to.be.a("number")
89+
.which.is.at.least(0.99 * DELAY);
90+
});
91+
}
92+
});
93+
}

test/src/chained.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Chained entrypoint where both the TLA module and its parent are async.
2+
export const goodbye = import("./parent.js").then(({ pg }) => pg);

test/src/goodbye.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// This module contains a simple TLA to await a string after a short delay.
2+
// It will be wrapped in an async function by Webpack.
3+
import { setTimeout } from "node:timers/promises";
4+
5+
export const PHRASE = "Goodby async!";
6+
export const DELAY = 250;
7+
8+
const startTime = performance.now();
9+
export const awaitedPhrase = await setTimeout(DELAY, PHRASE);
10+
export const awaitedDelay = performance.now() - startTime;

test/src/parent.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Webpack will also async wrap this module because it imports the TLA module.
2+
import * as pg from "./goodbye.js";
3+
export { pg };

test/src/simple.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Simple entrypoint where only the TLA module is async.
2+
export const goodbye = import("./goodbye.js");

0 commit comments

Comments
 (0)