浏览代码

feat(jest-config): added a binfile that sets some Node env variables to allow jest to work with ESM

benduran 5 天之前
父节点
当前提交
cd50c3afe8

+ 1 - 5
packages/component-library/jest.config.js

@@ -1,7 +1,3 @@
 import { defineJestConfigForNextJs } from "@pythnetwork/jest-config/define-next-config";
-("@pythnetwork/jest-config");
 
-export default defineJestConfigForNextJs({
-  testEnvironment: "jsdom",
-  setupFiles: ["./jest.setup.js"],
-});
+export default defineJestConfigForNextJs();

+ 0 - 3
packages/component-library/jest.setup.js

@@ -1,3 +0,0 @@
-import React from "react";
-
-globalThis.React = React;

+ 1 - 1
packages/component-library/package.json

@@ -324,7 +324,7 @@
     "test:lint:eslint": "eslint . --max-warnings 0",
     "test:lint:stylelint": "stylelint 'src/**/*.scss' --max-warnings 0",
     "test:types": "tsc",
-    "test:unit": "jest"
+    "test:unit": "test-unit"
   },
   "peerDependencies": {
     "next": "catalog:",

+ 26 - 1
packages/jest-config/package.json

@@ -12,15 +12,20 @@
     "@cprussin/eslint-config": "catalog:",
     "@cprussin/jest-config": "catalog:",
     "@cprussin/tsconfig": "catalog:",
-    "@types/jest": "^29"
+    "@types/jest": "^29",
+    "@types/react": "catalog:"
   },
   "dependencies": {
     "@swc/core": "^1.15.0",
     "@swc/jest": "^0.2.39",
     "jest-ts-webcompat-resolver": "^1.0.1",
     "jest": "^29",
+    "react": "catalog:",
     "ts-deepmerge": "^7.0.3"
   },
+  "bin": {
+    "test-unit": "./test-unit.mjs"
+  },
   "exports": {
     "./define-config": {
       "require": {
@@ -42,6 +47,26 @@
         "default": "./dist/esm/define-next-config.mjs"
       }
     },
+    "./define-react-config": {
+      "require": {
+        "types": "./dist/cjs/define-react-config.d.ts",
+        "default": "./dist/cjs/define-react-config.cjs"
+      },
+      "import": {
+        "types": "./dist/esm/define-react-config.d.ts",
+        "default": "./dist/esm/define-react-config.mjs"
+      }
+    },
+    "./setup-file-react": {
+      "require": {
+        "types": "./dist/cjs/setup-file-react.d.ts",
+        "default": "./dist/cjs/setup-file-react.cjs"
+      },
+      "import": {
+        "types": "./dist/esm/setup-file-react.d.ts",
+        "default": "./dist/esm/setup-file-react.mjs"
+      }
+    },
     "./package.json": "./package.json"
   },
   "module": "./dist/esm/index.mjs",

+ 4 - 1
packages/jest-config/src/define-next-config.ts

@@ -2,7 +2,10 @@ import type { Config } from "jest";
 import { nextjs } from "@cprussin/jest-config/next";
 import { defineJestConfig } from "./define-config.js";
 import { merge } from "ts-deepmerge";
+import { defineReactConfig } from "./define-react-config.js";
 
 export function defineJestConfigForNextJs(config?: Config): Config {
-  return defineJestConfig(merge(nextjs, config ?? {}) as Config);
+  return defineJestConfig(
+    merge(nextjs, defineReactConfig(), config ?? {}) as Config,
+  );
 }

+ 37 - 0
packages/jest-config/src/define-react-config.ts

@@ -0,0 +1,37 @@
+import type { Config } from "jest";
+import fs from "node:fs";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+import { defineJestConfig } from "./define-config.js";
+
+function getThisDirname(): string {
+  // Works in ESM
+  if (typeof import.meta.url === "string") {
+    return path.dirname(fileURLToPath(import.meta.url));
+  }
+  // Works in CJS
+  return __dirname;
+}
+
+/**
+ * sets up a jest test environment that works
+ * for testing react components
+ */
+export function defineReactConfig(config?: Config): Config {
+  const dirname = getThisDirname();
+  const allFiles = fs.readdirSync(dirname);
+
+  const setupFiles = allFiles
+    .filter(
+      (fp) =>
+        fp.endsWith("setup-file-react.mjs") ||
+        fp.endsWith("setup-file-react.cjs"),
+    )
+    .map((fp) => path.join(dirname, fp));
+
+  return defineJestConfig({
+    ...config,
+    setupFiles,
+    testEnvironment: "jsdom",
+  });
+}

+ 5 - 0
packages/jest-config/src/setup-file-react.ts

@@ -0,0 +1,5 @@
+// jest prefers CJS environments, so this is a bit of a hack
+// to properly assign React as a global for all tests
+import("react").then(({ default: React }) => {
+  globalThis.React = React;
+});

+ 21 - 0
packages/jest-config/test-unit.mjs

@@ -0,0 +1,21 @@
+import { execSync } from "node:child_process";
+import path from "node:path";
+
+const jestBinFilePath = path.join(
+  import.meta.dirname,
+  "node_modules",
+  ".bin",
+  "jest",
+);
+
+// necessary evil to allow all Jest users
+// to benefit from ESM imports and use
+// our shared configs (especially for React component tests)
+execSync(
+  `NODE_OPTIONS="--experimental-vm-modules" '${jestBinFilePath}' ${process.argv.slice(2).join(" ")}`.trim(),
+  {
+    cwd: process.cwd(),
+    shell: true,
+    stdio: "inherit",
+  },
+);

+ 6 - 0
pnpm-lock.yaml

@@ -2258,6 +2258,9 @@ importers:
       jest-ts-webcompat-resolver:
         specifier: ^1.0.1
         version: 1.0.1(jest-resolve@29.7.0)
+      react:
+        specifier: 'catalog:'
+        version: 19.1.0
       ts-deepmerge:
         specifier: ^7.0.3
         version: 7.0.3
@@ -2277,6 +2280,9 @@ importers:
       '@types/jest':
         specifier: ^29
         version: 29.5.14
+      '@types/react':
+        specifier: 'catalog:'
+        version: 19.1.0
 
   packages/known-publishers:
     devDependencies: