Skip to content

Commit

Permalink
Upgrade vitest-environment-miniflare for recent Vitest versions
Browse files Browse the repository at this point in the history
- Mark `vitest-environment-miniflare` as `"type": "module"`
- Use Vitest's own `createChainable()`
- Delay importing `vitest` until needed

Closes #645
Closes #661
  • Loading branch information
mrbbot committed Aug 25, 2023
1 parent 7e4d906 commit 9f64855
Show file tree
Hide file tree
Showing 8 changed files with 1,728 additions and 318 deletions.
1,897 changes: 1,679 additions & 218 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"lint:fix": "npm run lint -- --fix",
"prepublishOnly": "npm run lint && npm run clean && npm run build && npm run types:bundle && npm run test",
"helpers:scaffold": "node scripts/scaffold.mjs",
"helpers:version": "node scripts/version.mjs"
"helpers:version": "node scripts/version.mjs",
"postinstall": "patch-package"
},
"devDependencies": {
"@ava/typescript": "^2.0.0",
Expand All @@ -47,6 +48,7 @@
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-prettier": "^3.4.1",
"esm": "^3.2.25",
"patch-package": "^8.0.0",
"prettier": "^2.3.2",
"rimraf": "^3.0.2",
"sinon": "^14.0.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/vitest-environment-miniflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
],
"author": "MrBBot <me@mrbbot.dev>",
"license": "MIT",
"type": "module",
"main": "./dist/src/index.js",
"module": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"files": [
"dist/src",
Expand Down Expand Up @@ -50,6 +50,6 @@
"@miniflare/shared-test": "2.14.0",
"miniflare": "2.14.0",
"react-dom": "^18.1.0",
"vitest": "^0.23.1"
"vitest": "^0.34.3"
}
}
73 changes: 0 additions & 73 deletions packages/vitest-environment-miniflare/src/chain.ts

This file was deleted.

43 changes: 21 additions & 22 deletions packages/vitest-environment-miniflare/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable es/no-dynamic-import */
// noinspection ES6ConvertVarToLetConst

import stream from "stream/web";
Expand All @@ -8,51 +9,45 @@ import {
StackedMemoryStorageFactory,
createMiniflareEnvironment,
} from "@miniflare/shared-test-environment";
import {
Environment,
SuiteAPI,
SuiteFactory,
afterAll,
afterEach,
beforeAll,
beforeEach,
describe,
} from "vitest";
import { createChainable } from "./chain";
import { createChainable } from "@vitest/runner/utils";
import type { Environment, SuiteAPI, SuiteFactory, describe } from "vitest";

const scriptRunner = new VMScriptRunner();
const queueBroker = new QueueBroker();

function setupIsolatedStorage(storageFactory: StackedMemoryStorageFactory) {
function setupIsolatedStorage(
vitestImpl: typeof import("vitest"),
storageFactory: StackedMemoryStorageFactory
) {
// `push()`/`pop()` at the start/end of each test
beforeEach(() => storageFactory.push());
afterEach(() => storageFactory.pop());
vitestImpl.beforeEach(() => storageFactory.push());
vitestImpl.afterEach(() => storageFactory.pop());

// `push()`/`pop()` at the start/end of each `describe` block
// (users must use the returned `describe` function instead of the default
// `describe`/`suite` from the `vitest` module)
const wrappedDescribeFn: typeof describe.fn = function (name, factory) {
if (typeof factory !== "function") {
return describe.fn.call(this, name, factory);
return vitestImpl.describe.fn.call(this, name, factory);
}
const newFactory: SuiteFactory = (test) => {
beforeAll(() => storageFactory.push());
afterAll(() => storageFactory.pop());
vitestImpl.beforeAll(() => storageFactory.push());
vitestImpl.afterAll(() => storageFactory.pop());
return factory(test);
};
return describe.fn.call(this, name, newFactory);
return vitestImpl.describe.fn.call(this, name, newFactory);
};

// https://github.com/vitest-dev/vitest/blob/69d55bc19c8ca6e1dfb28724eb55a45aefc37562/packages/vitest/src/runtime/suite.ts#L204-L215
const wrappedDescribe = wrappedDescribeFn as typeof describe;
wrappedDescribe.each = describe.each;
wrappedDescribe.each = vitestImpl.describe.each;
wrappedDescribe.skipIf = (condition) =>
(condition ? wrappedChainable.skip : wrappedChainable) as SuiteAPI;
wrappedDescribe.runIf = (condition) =>
(condition ? wrappedChainable : wrappedChainable.skip) as SuiteAPI;

// https://github.com/vitest-dev/vitest/blob/e691a9ca229dd84765a4b40192761ffc1827069c/packages/runner/src/suite.ts#L228
const wrappedChainable = createChainable(
// https://github.com/vitest-dev/vitest/blob/69d55bc19c8ca6e1dfb28724eb55a45aefc37562/packages/vitest/src/runtime/suite.ts#L217-L220
["concurrent", "shuffle", "skip", "only", "todo"],
wrappedDescribe
);
Expand All @@ -70,7 +65,10 @@ declare global {

export default <Environment>{
name: "miniflare",
transformMode: "ssr",
async setup(global, options) {
const vitestImpl = await import("vitest");

// Since `undici@5.14.0`, stream classes are loaded from the global scope
// if available (https://github.com/nodejs/undici/pull/1793). Make sure
// `undici` sets module variables for stream classes before we assign
Expand All @@ -79,7 +77,8 @@ export default <Environment>{
globalThis.ReadableStream = stream.ReadableStream;
globalThis.WritableStream = stream.WritableStream;
globalThis.TransformStream = stream.TransformStream;
require("undici/lib/fetch");
// @ts-expect-error `undici` doesn't provide type definitions for internals
await import("undici/lib/fetch/index.js");

// Create a Miniflare instance
const storageFactory = new StackedMemoryStorageFactory();
Expand All @@ -91,7 +90,7 @@ export default <Environment>{

// Attach isolated storage setup function
mfGlobalScope.setupMiniflareIsolatedStorage = () =>
setupIsolatedStorage(storageFactory);
setupIsolatedStorage(vitestImpl, storageFactory);

// `crypto` is defined as a getter on the global scope in Node 19+,
// so attempting to set it with `Object.assign()` would fail. Instead,
Expand Down
14 changes: 14 additions & 0 deletions patches/@ava+typescript+2.0.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diff --git a/node_modules/@ava/typescript/index.js b/node_modules/@ava/typescript/index.js
index 8fc5369..f71c919 100644
--- a/node_modules/@ava/typescript/index.js
+++ b/node_modules/@ava/typescript/index.js
@@ -167,7 +167,8 @@ module.exports = ({negotiateProtocol}) => {

const [from, to] = rewritePaths.find(([from]) => ref.startsWith(from));
// TODO: Support JSX preserve mode — https://www.typescriptlang.org/docs/handbook/jsx.html
- const rewritten = `${to}${ref.slice(from.length)}`.replace(testFileExtension, '.js');
+ const jsExtension = from.includes("vitest-environment-miniflare") ? ".cjs" : ".js";
+ const rewritten = `${to}${ref.slice(from.length)}`.replace(testFileExtension, jsExtension);
return requireFn(rewritten);
}
};
9 changes: 7 additions & 2 deletions scripts/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ async function buildPackage(name) {
);
}
// `vitest` requires custom environments to be ES modules with default exports
if (name === "vitest-environment-miniflare") {
const isVitestEnvironment = name === "vitest-environment-miniflare";
if (isVitestEnvironment) {
esmEntryPoints.unshift(indexPath);
} else {
cjsEntryPoints.unshift(indexPath);
Expand All @@ -120,7 +121,11 @@ async function buildPackage(name) {
outdir: outPath,
outbase: pkgRoot,
};
await esbuild.build({ ...pkgBuildOptions, entryPoints: cjsEntryPoints });
await esbuild.build({
...pkgBuildOptions,
entryPoints: cjsEntryPoints,
outExtension: isVitestEnvironment ? { ".js": ".cjs" } : undefined,
});
if (esmEntryPoints.length) {
await esbuild.build({
...pkgBuildOptions,
Expand Down
2 changes: 2 additions & 0 deletions types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ declare global {
var CryptoKey: typeof import("crypto").webcrypto.CryptoKey;
// eslint-disable-next-line no-var
var MessagePort: typeof import("worker_threads").MessagePort;
// eslint-disable-next-line no-var
type WebSocket = unknown;
}

export {};

0 comments on commit 9f64855

Please sign in to comment.