@elench/testkit 0.1.68 → 0.1.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,13 @@
1
1
  import crypto from "crypto";
2
2
  import fs from "fs";
3
+ import { createRequire } from "module";
3
4
  import path from "path";
4
5
  import { build } from "esbuild";
5
6
  import { execa, execaCommand } from "execa";
6
7
  import { fileURLToPath } from "url";
7
8
  import {
8
9
  collectConfiguredInputs,
10
+ isBareModuleSpecifier,
9
11
  parseModuleSpecifier,
10
12
  resolveConfiguredCwd,
11
13
  resolveConfiguredPath,
@@ -181,7 +183,7 @@ async function runConfiguredStep(config, step, env, resolvedToolchain, options =
181
183
 
182
184
  async function bundleConfiguredModule(productDir, step) {
183
185
  const { modulePath } = parseModuleSpecifier(step.specifier);
184
- const absoluteModulePath = resolveConfiguredPath(productDir, step.cwd, modulePath);
186
+ const absoluteModulePath = resolveConfiguredModuleEntry(productDir, step);
185
187
  const bundleDir = path.join(productDir, ".testkit", "_template-steps");
186
188
  fs.mkdirSync(bundleDir, { recursive: true });
187
189
 
@@ -210,6 +212,24 @@ async function bundleConfiguredModule(productDir, step) {
210
212
  };
211
213
  }
212
214
 
215
+ function resolveConfiguredModuleEntry(productDir, step) {
216
+ const { modulePath } = parseModuleSpecifier(step.specifier);
217
+ if (modulePath.startsWith("@elench/testkit")) {
218
+ return resolvePackageSubpath(modulePath);
219
+ }
220
+ const candidatePath = resolveConfiguredPath(productDir, step.cwd, modulePath);
221
+ if (fs.existsSync(candidatePath)) {
222
+ return candidatePath;
223
+ }
224
+ if (!isBareModuleSpecifier(modulePath)) {
225
+ return candidatePath;
226
+ }
227
+
228
+ const cwd = resolveConfiguredCwd(productDir, step.cwd);
229
+ const requireFromCwd = createRequire(path.join(cwd, "__testkit__.cjs"));
230
+ return requireFromCwd.resolve(modulePath);
231
+ }
232
+
213
233
  function buildModuleCacheKey(modulePath) {
214
234
  const content = fs.readFileSync(modulePath, "utf8");
215
235
  return crypto.createHash("sha256").update(modulePath).update("\0").update(content).digest("hex");
@@ -117,7 +117,7 @@ export function buildConfigToPrepare(build) {
117
117
  kind: "command",
118
118
  cmd: build.script,
119
119
  cwd: build.cwd || undefined,
120
- inputs: [...build.inputs],
120
+ inputs: [],
121
121
  },
122
122
  ],
123
123
  };
@@ -132,13 +132,13 @@ export function buildConfigToPrepare(build) {
132
132
  kind: "module",
133
133
  specifier: "@elench/testkit/setup/next-runtime-tsconfig#writeNextRuntimeTsconfig",
134
134
  cwd: build.cwd || undefined,
135
- inputs,
135
+ inputs: [],
136
136
  },
137
137
  {
138
138
  kind: "command",
139
139
  cmd: "./node_modules/.bin/next build",
140
140
  cwd: build.cwd || undefined,
141
- inputs,
141
+ inputs: [],
142
142
  },
143
143
  ],
144
144
  };
@@ -149,15 +149,15 @@ export function buildConfigToPrepare(build) {
149
149
  return {
150
150
  inputs,
151
151
  steps: [
152
- {
153
- kind: "command",
154
- cmd,
155
- cwd: build.cwd || undefined,
156
- inputs,
157
- },
158
- ],
159
- };
160
- }
152
+ {
153
+ kind: "command",
154
+ cmd,
155
+ cwd: build.cwd || undefined,
156
+ inputs: [],
157
+ },
158
+ ],
159
+ };
160
+ }
161
161
 
162
162
  export function compiledEntryFromBuild(build) {
163
163
  if (!build || build.kind !== "tsc") return null;
@@ -32,7 +32,7 @@ describe("shared build config helpers", () => {
32
32
  kind: "command",
33
33
  cmd: './node_modules/.bin/tsc -p tsconfig.json --outDir "{prepareDir}/dist"',
34
34
  cwd: undefined,
35
- inputs: ["tsconfig.json", "package.json", "src"],
35
+ inputs: [],
36
36
  },
37
37
  ],
38
38
  });
@@ -118,31 +118,13 @@ describe("shared build config helpers", () => {
118
118
  kind: "module",
119
119
  specifier: "@elench/testkit/setup/next-runtime-tsconfig#writeNextRuntimeTsconfig",
120
120
  cwd: "frontend",
121
- inputs: [
122
- "frontend/tsconfig.json",
123
- "frontend/package.json",
124
- "frontend/src",
125
- "frontend/app",
126
- "frontend/public",
127
- "frontend/next.config.js",
128
- "frontend/next.config.mjs",
129
- "frontend/next.config.ts",
130
- ],
121
+ inputs: [],
131
122
  },
132
123
  {
133
124
  kind: "command",
134
125
  cmd: "./node_modules/.bin/next build",
135
126
  cwd: "frontend",
136
- inputs: [
137
- "frontend/tsconfig.json",
138
- "frontend/package.json",
139
- "frontend/src",
140
- "frontend/app",
141
- "frontend/public",
142
- "frontend/next.config.js",
143
- "frontend/next.config.mjs",
144
- "frontend/next.config.ts",
145
- ],
127
+ inputs: [],
146
128
  },
147
129
  ],
148
130
  });
@@ -94,6 +94,12 @@ export function parseModuleSpecifier(specifier) {
94
94
  };
95
95
  }
96
96
 
97
+ export function isBareModuleSpecifier(modulePath) {
98
+ if (typeof modulePath !== "string" || modulePath.length === 0) return false;
99
+ if (modulePath.startsWith("./") || modulePath.startsWith("../")) return false;
100
+ return !path.isAbsolute(modulePath);
101
+ }
102
+
97
103
  export function resolveConfiguredCwd(productDir, stepCwd) {
98
104
  return path.resolve(productDir, stepCwd || ".");
99
105
  }
@@ -112,7 +118,15 @@ export function collectConfiguredInputs(productDir, { inputs = [], steps = [] }
112
118
  collected.add(resolveConfiguredPath(productDir, step.cwd, step.path));
113
119
  }
114
120
  if (step.kind === "module") {
115
- collected.add(resolveConfiguredPath(productDir, step.cwd, parseModuleSpecifier(step.specifier).modulePath));
121
+ const { modulePath } = parseModuleSpecifier(step.specifier);
122
+ const candidatePath = resolveConfiguredPath(productDir, step.cwd, modulePath);
123
+ if (modulePath.startsWith("@elench/testkit") || fs.existsSync(candidatePath)) {
124
+ if (!modulePath.startsWith("@elench/testkit")) {
125
+ collected.add(candidatePath);
126
+ }
127
+ } else if (!isBareModuleSpecifier(modulePath)) {
128
+ collected.add(candidatePath);
129
+ }
116
130
  }
117
131
  for (const input of step.inputs || []) {
118
132
  collected.add(resolveConfiguredPath(productDir, step.cwd, input));
@@ -160,10 +174,15 @@ export function validateConfiguredCollection({ productDir, label, inputs = [], s
160
174
  ensureExistingPath(resolveConfiguredPath(productDir, step.cwd, step.path), `${label} sql file`);
161
175
  }
162
176
  if (step.kind === "module") {
163
- ensureExistingPath(
164
- resolveConfiguredPath(productDir, step.cwd, parseModuleSpecifier(step.specifier).modulePath),
165
- `${label} module`
166
- );
177
+ const { modulePath } = parseModuleSpecifier(step.specifier);
178
+ const candidatePath = resolveConfiguredPath(productDir, step.cwd, modulePath);
179
+ if (modulePath.startsWith("@elench/testkit")) {
180
+ // Internal testkit module steps are resolved by the runtime alias map.
181
+ } else if (fs.existsSync(candidatePath)) {
182
+ ensureExistingPath(candidatePath, `${label} module`);
183
+ } else if (!isBareModuleSpecifier(modulePath)) {
184
+ ensureExistingPath(candidatePath, `${label} module`);
185
+ }
167
186
  }
168
187
  for (const input of step.inputs || []) {
169
188
  ensureExistingPath(resolveConfiguredPath(productDir, step.cwd, input), `${label} step input`);
@@ -5,6 +5,7 @@ import { afterEach, describe, expect, it } from "vitest";
5
5
  import {
6
6
  collectConfiguredInputs,
7
7
  finalizeConfiguredStep,
8
+ isBareModuleSpecifier,
8
9
  normalizeConfiguredStep,
9
10
  parseModuleSpecifier,
10
11
  validateConfiguredCollection,
@@ -70,4 +71,32 @@ describe("shared configured steps", () => {
70
71
  })
71
72
  ).not.toThrow();
72
73
  });
74
+
75
+ it("treats bare module specifiers as modules, not product-relative file paths", () => {
76
+ const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-configured-steps-"));
77
+ tempDirs.push(productDir);
78
+ fs.mkdirSync(path.join(productDir, "frontend"), { recursive: true });
79
+
80
+ const collection = {
81
+ inputs: [],
82
+ steps: [
83
+ {
84
+ kind: "module",
85
+ specifier: "@elench/testkit/setup/next-runtime-tsconfig#writeNextRuntimeTsconfig",
86
+ cwd: "frontend",
87
+ inputs: [],
88
+ },
89
+ ],
90
+ };
91
+
92
+ expect(isBareModuleSpecifier("@elench/testkit/setup/next-runtime-tsconfig")).toBe(true);
93
+ expect(collectConfiguredInputs(productDir, collection)).toEqual([]);
94
+ expect(() =>
95
+ validateConfiguredCollection({
96
+ productDir,
97
+ label: 'Service "frontend" runtime.prepare',
98
+ ...collection,
99
+ })
100
+ ).not.toThrow();
101
+ });
73
102
  });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/next-analysis",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "SWC-backed Next.js source analysis primitives for Erench tools",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit-bridge",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "Browser bridge helpers for testkit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "typecheck": "tsc -p tsconfig.json --noEmit"
23
23
  },
24
24
  "dependencies": {
25
- "@elench/testkit-protocol": "0.1.68"
25
+ "@elench/testkit-protocol": "0.1.69"
26
26
  },
27
27
  "private": false
28
28
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit-protocol",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "Shared browser protocol for testkit bridge and extension consumers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/ts-analysis",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "TypeScript compiler-backed source analysis primitives for Erench tools",
5
5
  "type": "module",
6
6
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "CLI for discovering and running local HTTP, DAL, and Playwright test suites",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -64,10 +64,10 @@
64
64
  "vitest": "^3.2.4"
65
65
  },
66
66
  "dependencies": {
67
- "@elench/next-analysis": "0.1.68",
68
- "@elench/ts-analysis": "0.1.68",
69
- "@elench/testkit-bridge": "0.1.68",
70
- "@elench/testkit-protocol": "0.1.68",
67
+ "@elench/next-analysis": "0.1.69",
68
+ "@elench/ts-analysis": "0.1.69",
69
+ "@elench/testkit-bridge": "0.1.69",
70
+ "@elench/testkit-protocol": "0.1.69",
71
71
  "@babel/code-frame": "^7.29.0",
72
72
  "@oclif/core": "^4.10.6",
73
73
  "esbuild": "^0.25.11",