@elench/testkit 0.1.83 → 0.1.84
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.
- package/lib/cli/agents/providers/codex.mjs +1 -1
- package/lib/cli/tui/run-session-app.mjs +1 -1
- package/node_modules/@elench/next-analysis/package.json +1 -1
- package/node_modules/@elench/testkit-bridge/package.json +2 -2
- package/node_modules/@elench/testkit-protocol/package.json +1 -1
- package/node_modules/@elench/ts-analysis/package.json +1 -1
- package/package.json +7 -6
- package/lib/app/configs.test.mjs +0 -34
- package/lib/app/typecheck.test.mjs +0 -24
- package/lib/bundler/index.test.mjs +0 -164
- package/lib/cli/agents/investigation-context.test.mjs +0 -144
- package/lib/cli/agents/providers/claude.test.mjs +0 -95
- package/lib/cli/agents/providers/codex.test.mjs +0 -93
- package/lib/cli/args.test.mjs +0 -110
- package/lib/cli/command-helpers.test.mjs +0 -122
- package/lib/cli/commands/investigate.test.mjs +0 -83
- package/lib/cli/presentation/code-frames.test.mjs +0 -71
- package/lib/cli/presentation/events-reporter.test.mjs +0 -73
- package/lib/cli/presentation/run-reporter.test.mjs +0 -192
- package/lib/cli/presentation/summary-box.test.mjs +0 -60
- package/lib/cli/presentation/terminal-layout.test.mjs +0 -23
- package/lib/cli/presentation/tree-reporter.test.mjs +0 -166
- package/lib/cli/tui/run-session-app.test.mjs +0 -50
- package/lib/cli/tui/run-tree-state.test.mjs +0 -324
- package/lib/config/database.test.mjs +0 -29
- package/lib/config/discovery.test.mjs +0 -276
- package/lib/config/env.test.mjs +0 -40
- package/lib/config/index.test.mjs +0 -44
- package/lib/config/paths.test.mjs +0 -27
- package/lib/config/runtime.test.mjs +0 -82
- package/lib/config/skip-config.test.mjs +0 -63
- package/lib/config-api/index.test.mjs +0 -398
- package/lib/config-api/next-runtime-tsconfig.test.mjs +0 -58
- package/lib/coverage/backend-discovery.test.mjs +0 -61
- package/lib/coverage/evidence.test.mjs +0 -87
- package/lib/coverage/index.test.mjs +0 -715
- package/lib/coverage/routing.test.mjs +0 -36
- package/lib/coverage/shared.test.mjs +0 -72
- package/lib/database/fingerprint.test.mjs +0 -99
- package/lib/database/index.test.mjs +0 -95
- package/lib/database/naming.test.mjs +0 -39
- package/lib/database/state.test.mjs +0 -66
- package/lib/database/template-steps.test.mjs +0 -43
- package/lib/discovery/file-metadata.test.mjs +0 -51
- package/lib/discovery/index.test.mjs +0 -182
- package/lib/discovery/path-policy.test.mjs +0 -65
- package/lib/drizzle/index.test.mjs +0 -33
- package/lib/env/index.test.mjs +0 -82
- package/lib/history/index.test.mjs +0 -115
- package/lib/package.test.mjs +0 -59
- package/lib/playwright/index.test.mjs +0 -43
- package/lib/regressions/github.test.mjs +0 -324
- package/lib/regressions/index.test.mjs +0 -187
- package/lib/reporters/playwright.test.mjs +0 -167
- package/lib/runner/default-runtime-errors.test.mjs +0 -49
- package/lib/runner/execution-config.test.mjs +0 -67
- package/lib/runner/failure-details.test.mjs +0 -114
- package/lib/runner/formatting.test.mjs +0 -205
- package/lib/runner/metadata.test.mjs +0 -52
- package/lib/runner/planning.test.mjs +0 -371
- package/lib/runner/playwright-config.test.mjs +0 -78
- package/lib/runner/processes.test.mjs +0 -21
- package/lib/runner/regressions.test.mjs +0 -168
- package/lib/runner/reporting.test.mjs +0 -310
- package/lib/runner/results.test.mjs +0 -376
- package/lib/runner/runtime-manager.test.mjs +0 -252
- package/lib/runner/runtime-preparation.test.mjs +0 -141
- package/lib/runner/selection.test.mjs +0 -24
- package/lib/runner/setup-operations.test.mjs +0 -94
- package/lib/runner/state.test.mjs +0 -62
- package/lib/runner/suite-selection.test.mjs +0 -49
- package/lib/runner/template.test.mjs +0 -272
- package/lib/runtime-src/k6/http-checks.test.mjs +0 -120
- package/lib/runtime-src/k6/http.test.mjs +0 -205
- package/lib/runtime-src/shared/http-parsing.test.mjs +0 -69
- package/lib/shared/build-config.test.mjs +0 -132
- package/lib/shared/configured-steps.test.mjs +0 -102
- package/lib/shared/execution-schema.test.mjs +0 -26
- package/lib/shared/file-timeout.test.mjs +0 -64
- package/lib/shared/test-context.test.mjs +0 -43
- package/lib/timing/index.test.mjs +0 -64
- package/lib/toolchains/index.test.mjs +0 -168
- package/lib/vitest/index.test.mjs +0 -20
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
buildConfigToPrepare,
|
|
4
|
-
compiledEntryFromBuild,
|
|
5
|
-
normalizeBuildConfig,
|
|
6
|
-
} from "./build-config.mjs";
|
|
7
|
-
|
|
8
|
-
describe("shared build config helpers", () => {
|
|
9
|
-
it("normalizes tsc build config and derives prepare steps", () => {
|
|
10
|
-
const build = normalizeBuildConfig(
|
|
11
|
-
{
|
|
12
|
-
kind: "tsc",
|
|
13
|
-
entry: "src/server.ts",
|
|
14
|
-
outDir: "dist",
|
|
15
|
-
},
|
|
16
|
-
"runtime.build"
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
expect(build).toEqual({
|
|
20
|
-
kind: "tsc",
|
|
21
|
-
cwd: null,
|
|
22
|
-
entry: "src/server.ts",
|
|
23
|
-
tsconfig: "tsconfig.json",
|
|
24
|
-
outDir: "dist",
|
|
25
|
-
inputs: [],
|
|
26
|
-
});
|
|
27
|
-
expect(compiledEntryFromBuild(build)).toBe("dist/server.js");
|
|
28
|
-
expect(buildConfigToPrepare(build)).toEqual({
|
|
29
|
-
inputs: ["tsconfig.json", "package.json", "src"],
|
|
30
|
-
steps: [
|
|
31
|
-
{
|
|
32
|
-
kind: "command",
|
|
33
|
-
cmd: './node_modules/.bin/tsc -p tsconfig.json --outDir "{prepareDir}/dist"',
|
|
34
|
-
cwd: undefined,
|
|
35
|
-
inputs: [],
|
|
36
|
-
},
|
|
37
|
-
],
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("normalizes script and steps builds", () => {
|
|
42
|
-
expect(
|
|
43
|
-
normalizeBuildConfig(
|
|
44
|
-
{
|
|
45
|
-
kind: "script",
|
|
46
|
-
script: "npm run build",
|
|
47
|
-
cwd: "frontend",
|
|
48
|
-
inputs: ["frontend/package.json"],
|
|
49
|
-
},
|
|
50
|
-
"runtime.build"
|
|
51
|
-
)
|
|
52
|
-
).toEqual({
|
|
53
|
-
kind: "script",
|
|
54
|
-
script: "npm run build",
|
|
55
|
-
cwd: "frontend",
|
|
56
|
-
inputs: ["frontend/package.json"],
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(
|
|
60
|
-
normalizeBuildConfig(
|
|
61
|
-
{
|
|
62
|
-
kind: "next",
|
|
63
|
-
cwd: "frontend",
|
|
64
|
-
},
|
|
65
|
-
"runtime.build"
|
|
66
|
-
)
|
|
67
|
-
).toEqual({
|
|
68
|
-
kind: "next",
|
|
69
|
-
cwd: "frontend",
|
|
70
|
-
distDir: "dist",
|
|
71
|
-
tsconfig: "tsconfig.json",
|
|
72
|
-
inputs: [],
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
expect(
|
|
76
|
-
normalizeBuildConfig(
|
|
77
|
-
{
|
|
78
|
-
kind: "steps",
|
|
79
|
-
inputs: ["scripts/prepare.mjs"],
|
|
80
|
-
steps: [{ kind: "command", run: "node scripts/prepare.mjs" }],
|
|
81
|
-
},
|
|
82
|
-
"runtime.build"
|
|
83
|
-
)
|
|
84
|
-
).toEqual({
|
|
85
|
-
kind: "steps",
|
|
86
|
-
inputs: ["scripts/prepare.mjs"],
|
|
87
|
-
steps: [
|
|
88
|
-
{
|
|
89
|
-
kind: "command",
|
|
90
|
-
cmd: "node scripts/prepare.mjs",
|
|
91
|
-
cwd: null,
|
|
92
|
-
inputs: [],
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
expect(
|
|
98
|
-
buildConfigToPrepare({
|
|
99
|
-
kind: "next",
|
|
100
|
-
cwd: "frontend",
|
|
101
|
-
distDir: "dist",
|
|
102
|
-
tsconfig: "tsconfig.json",
|
|
103
|
-
inputs: [],
|
|
104
|
-
})
|
|
105
|
-
).toEqual({
|
|
106
|
-
inputs: [
|
|
107
|
-
"frontend/tsconfig.json",
|
|
108
|
-
"frontend/package.json",
|
|
109
|
-
"frontend/src",
|
|
110
|
-
"frontend/app",
|
|
111
|
-
"frontend/public",
|
|
112
|
-
"frontend/next.config.js",
|
|
113
|
-
"frontend/next.config.mjs",
|
|
114
|
-
"frontend/next.config.ts",
|
|
115
|
-
],
|
|
116
|
-
steps: [
|
|
117
|
-
{
|
|
118
|
-
kind: "module",
|
|
119
|
-
specifier: "@elench/testkit/config/next-runtime-tsconfig#writeNextRuntimeTsconfig",
|
|
120
|
-
cwd: "frontend",
|
|
121
|
-
inputs: [],
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
kind: "command",
|
|
125
|
-
cmd: "./node_modules/.bin/next build",
|
|
126
|
-
cwd: "frontend",
|
|
127
|
-
inputs: [],
|
|
128
|
-
},
|
|
129
|
-
],
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
});
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import os from "os";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
import {
|
|
6
|
-
collectConfiguredInputs,
|
|
7
|
-
finalizeConfiguredStep,
|
|
8
|
-
isBareModuleSpecifier,
|
|
9
|
-
normalizeConfiguredStep,
|
|
10
|
-
parseModuleSpecifier,
|
|
11
|
-
validateConfiguredCollection,
|
|
12
|
-
} from "./configured-steps.mjs";
|
|
13
|
-
|
|
14
|
-
const tempDirs = [];
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
for (const dir of tempDirs.splice(0)) {
|
|
18
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
describe("shared configured steps", () => {
|
|
23
|
-
it("normalizes and finalizes configured steps", () => {
|
|
24
|
-
const normalized = normalizeConfiguredStep(
|
|
25
|
-
{ kind: "module", target: "./seed.mjs#run", cwd: "db", inputs: ["schema.sql"] },
|
|
26
|
-
'Service "api" database.template.seed[0]'
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
expect(normalized).toEqual({
|
|
30
|
-
kind: "module",
|
|
31
|
-
specifier: "./seed.mjs#run",
|
|
32
|
-
cwd: "db",
|
|
33
|
-
inputs: ["schema.sql"],
|
|
34
|
-
});
|
|
35
|
-
expect(parseModuleSpecifier(normalized.specifier)).toEqual({
|
|
36
|
-
modulePath: "./seed.mjs",
|
|
37
|
-
exportName: "run",
|
|
38
|
-
});
|
|
39
|
-
expect(finalizeConfiguredStep(normalized, (value) => value.toUpperCase())).toEqual({
|
|
40
|
-
kind: "module",
|
|
41
|
-
specifier: "./SEED.MJS#RUN",
|
|
42
|
-
cwd: "DB",
|
|
43
|
-
inputs: ["SCHEMA.SQL"],
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("collects and validates configured input paths", () => {
|
|
48
|
-
const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-configured-steps-"));
|
|
49
|
-
tempDirs.push(productDir);
|
|
50
|
-
fs.mkdirSync(path.join(productDir, "db"), { recursive: true });
|
|
51
|
-
fs.writeFileSync(path.join(productDir, "db", "schema.sql"), "-- schema\n");
|
|
52
|
-
fs.writeFileSync(path.join(productDir, "db", "seed.mjs"), "export default async function run() {}\n");
|
|
53
|
-
|
|
54
|
-
const collection = {
|
|
55
|
-
inputs: ["db/schema.sql"],
|
|
56
|
-
steps: [
|
|
57
|
-
{ kind: "sql-file", path: "schema.sql", cwd: "db", inputs: [] },
|
|
58
|
-
{ kind: "module", target: "./seed.mjs#run", cwd: "db", inputs: [] },
|
|
59
|
-
],
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
expect(collectConfiguredInputs(productDir, collection)).toEqual([
|
|
63
|
-
path.join(productDir, "db", "schema.sql"),
|
|
64
|
-
path.join(productDir, "db", "seed.mjs"),
|
|
65
|
-
]);
|
|
66
|
-
expect(() =>
|
|
67
|
-
validateConfiguredCollection({
|
|
68
|
-
productDir,
|
|
69
|
-
label: 'Service "api" runtime.prepare',
|
|
70
|
-
...collection,
|
|
71
|
-
})
|
|
72
|
-
).not.toThrow();
|
|
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
|
-
target: "@elench/testkit/config/next-runtime-tsconfig#writeNextRuntimeTsconfig",
|
|
86
|
-
cwd: "frontend",
|
|
87
|
-
inputs: [],
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
expect(isBareModuleSpecifier("@elench/testkit/config/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
|
-
});
|
|
102
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
normalizeDatabaseBinding,
|
|
4
|
-
normalizeExecutionConfig,
|
|
5
|
-
normalizeRuntimeMaxConcurrentTasks,
|
|
6
|
-
resolveExecutionConfig,
|
|
7
|
-
} from "./execution-schema.mjs";
|
|
8
|
-
|
|
9
|
-
describe("shared execution schema", () => {
|
|
10
|
-
it("normalizes execution config and repo/cli overrides", () => {
|
|
11
|
-
expect(normalizeExecutionConfig({ workers: 2, fileTimeoutSeconds: 30 })).toEqual({
|
|
12
|
-
workers: 2,
|
|
13
|
-
fileTimeoutSeconds: 30,
|
|
14
|
-
});
|
|
15
|
-
expect(resolveExecutionConfig({ cli: { workers: 3 }, repo: { workers: 2, fileTimeoutSeconds: 45 } })).toEqual({
|
|
16
|
-
workers: 3,
|
|
17
|
-
fileTimeoutSeconds: 45,
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("validates runtime concurrency and database binding", () => {
|
|
22
|
-
expect(normalizeRuntimeMaxConcurrentTasks(undefined)).toBe(Number.POSITIVE_INFINITY);
|
|
23
|
-
expect(normalizeDatabaseBinding("shared")).toBe("shared");
|
|
24
|
-
expect(() => normalizeDatabaseBinding("legacy")).toThrow('Invalid database.binding value "legacy"');
|
|
25
|
-
});
|
|
26
|
-
});
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
buildFileTimeoutEnv,
|
|
4
|
-
DEFAULT_FILE_TIMEOUT_SECONDS,
|
|
5
|
-
formatFileTimeoutBudgetError,
|
|
6
|
-
formatWaitForTimeoutError,
|
|
7
|
-
normalizeFileTimeoutSeconds,
|
|
8
|
-
normalizeWaitIntervalSeconds,
|
|
9
|
-
parseFileTimeoutOption,
|
|
10
|
-
readFileTimeoutBudget,
|
|
11
|
-
remainingFileTimeoutMs,
|
|
12
|
-
remainingFileTimeoutSeconds,
|
|
13
|
-
} from "./file-timeout.mjs";
|
|
14
|
-
|
|
15
|
-
describe("file-timeout", () => {
|
|
16
|
-
it("normalizes positive file timeout values", () => {
|
|
17
|
-
expect(parseFileTimeoutOption("45")).toBe(45);
|
|
18
|
-
expect(normalizeFileTimeoutSeconds(DEFAULT_FILE_TIMEOUT_SECONDS)).toBe(60);
|
|
19
|
-
expect(() => parseFileTimeoutOption("0")).toThrow(
|
|
20
|
-
'Invalid --file-timeout-seconds value "0"'
|
|
21
|
-
);
|
|
22
|
-
expect(() => normalizeFileTimeoutSeconds(0)).toThrow(
|
|
23
|
-
"execution.fileTimeoutSeconds must be a positive integer."
|
|
24
|
-
);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("builds and reads runtime timeout budget env", () => {
|
|
28
|
-
const env = buildFileTimeoutEnv(45, 1_000);
|
|
29
|
-
expect(env).toEqual({
|
|
30
|
-
TESTKIT_INTERNAL_FILE_TIMEOUT_SECONDS: "45",
|
|
31
|
-
TESTKIT_INTERNAL_FILE_DEADLINE_MS: "46000",
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
expect(readFileTimeoutBudget(env)).toEqual({
|
|
35
|
-
fileTimeoutSeconds: 45,
|
|
36
|
-
deadlineMs: 46_000,
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("computes remaining file timeout budget", () => {
|
|
41
|
-
const budget = {
|
|
42
|
-
fileTimeoutSeconds: 45,
|
|
43
|
-
deadlineMs: 46_000,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
expect(remainingFileTimeoutMs(budget, 40_000)).toBe(6_000);
|
|
47
|
-
expect(remainingFileTimeoutMs(budget, 47_000)).toBe(0);
|
|
48
|
-
expect(remainingFileTimeoutSeconds(budget, 44_500)).toBe(1.5);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("normalizes wait intervals and timeout errors", () => {
|
|
52
|
-
expect(normalizeWaitIntervalSeconds()).toBe(0.25);
|
|
53
|
-
expect(normalizeWaitIntervalSeconds(0.5)).toBe(0.5);
|
|
54
|
-
expect(() => normalizeWaitIntervalSeconds(0)).toThrow(
|
|
55
|
-
"waitFor intervalSeconds must be a positive number."
|
|
56
|
-
);
|
|
57
|
-
expect(formatWaitForTimeoutError("cron worker pickup", 60)).toBe(
|
|
58
|
-
"Timed out waiting for cron worker pickup before the 60s test file timeout"
|
|
59
|
-
);
|
|
60
|
-
expect(formatFileTimeoutBudgetError(60)).toBe(
|
|
61
|
-
"Default runtime exceeded the 60s test file timeout"
|
|
62
|
-
);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
|
|
3
|
-
import { buildTestNamespace, readTestkitContext } from "./test-context.mjs";
|
|
4
|
-
|
|
5
|
-
describe("buildTestNamespace", () => {
|
|
6
|
-
it("prefers the lease id when present", () => {
|
|
7
|
-
expect(buildTestNamespace({ runtimeId: "runtime-2", leaseId: "lease-4" })).toBe("lease-4");
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it("falls back to the runtime id", () => {
|
|
11
|
-
expect(buildTestNamespace({ runtimeId: "runtime-2" })).toBe("runtime-2");
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("normalizes unsafe characters", () => {
|
|
15
|
-
expect(buildTestNamespace({ leaseId: " Lease 4 / Weird " })).toBe("lease-4-weird");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("falls back to standalone when no runtime identifiers exist", () => {
|
|
19
|
-
expect(buildTestNamespace({})).toBe("standalone");
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
describe("readTestkitContext", () => {
|
|
24
|
-
it("reads active state and normalized identifiers", () => {
|
|
25
|
-
expect(
|
|
26
|
-
readTestkitContext({
|
|
27
|
-
TESTKIT_ACTIVE: "1",
|
|
28
|
-
TESTKIT_RUNTIME_ID: "Runtime 2",
|
|
29
|
-
TESTKIT_LEASE_ID: "Lease 3",
|
|
30
|
-
})
|
|
31
|
-
).toEqual({
|
|
32
|
-
active: true,
|
|
33
|
-
runtimeId: "runtime-2",
|
|
34
|
-
leaseId: "lease-3",
|
|
35
|
-
namespace: "lease-3",
|
|
36
|
-
rawEnv: {
|
|
37
|
-
TESTKIT_ACTIVE: "1",
|
|
38
|
-
TESTKIT_RUNTIME_ID: "Runtime 2",
|
|
39
|
-
TESTKIT_LEASE_ID: "Lease 3",
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
});
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
applyTimingUpdates,
|
|
4
|
-
buildTimingKey,
|
|
5
|
-
createEmptyTimings,
|
|
6
|
-
estimateTaskDuration,
|
|
7
|
-
normalizeTimings,
|
|
8
|
-
} from "./index.mjs";
|
|
9
|
-
|
|
10
|
-
describe("timings", () => {
|
|
11
|
-
it("creates and normalizes empty timing structures", () => {
|
|
12
|
-
expect(createEmptyTimings()).toEqual({ version: 1, files: {} });
|
|
13
|
-
expect(normalizeTimings({})).toEqual({ version: 1, files: {} });
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("applies rolling timing updates", () => {
|
|
17
|
-
const next = applyTimingUpdates(
|
|
18
|
-
{
|
|
19
|
-
version: 1,
|
|
20
|
-
files: {
|
|
21
|
-
"api|k6|integration|a.js": {
|
|
22
|
-
durationMs: 1000,
|
|
23
|
-
runs: 1,
|
|
24
|
-
updatedAt: "2020-01-01T00:00:00.000Z",
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
[{ key: "api|k6|integration|a.js", durationMs: 3000 }],
|
|
29
|
-
"2020-01-02T00:00:00.000Z"
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
expect(next.files["api|k6|integration|a.js"]).toEqual({
|
|
33
|
-
durationMs: 2000,
|
|
34
|
-
runs: 2,
|
|
35
|
-
updatedAt: "2020-01-02T00:00:00.000Z",
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("estimates task durations and builds timing keys", () => {
|
|
40
|
-
expect(
|
|
41
|
-
estimateTaskDuration(
|
|
42
|
-
{ files: { key: { durationMs: 3210 } } },
|
|
43
|
-
"key",
|
|
44
|
-
{ framework: "k6", type: "integration", weight: 1, files: ["a.js"] }
|
|
45
|
-
)
|
|
46
|
-
).toBe(3210);
|
|
47
|
-
|
|
48
|
-
expect(
|
|
49
|
-
estimateTaskDuration(
|
|
50
|
-
{ files: {} },
|
|
51
|
-
"key",
|
|
52
|
-
{ framework: "playwright", type: "e2e", weight: 2, files: ["a.js", "b.js"] }
|
|
53
|
-
)
|
|
54
|
-
).toBe(20000);
|
|
55
|
-
|
|
56
|
-
expect(
|
|
57
|
-
buildTimingKey(
|
|
58
|
-
"api",
|
|
59
|
-
{ framework: "k6", type: "integration" },
|
|
60
|
-
"tests/health.js"
|
|
61
|
-
)
|
|
62
|
-
).toBe("api|k6|integration|tests/health.js");
|
|
63
|
-
});
|
|
64
|
-
});
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import os from "os";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { execa } from "execa";
|
|
5
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
6
|
-
import {
|
|
7
|
-
applyToolchainEnv,
|
|
8
|
-
normalizeRuntimeToolchain,
|
|
9
|
-
normalizeToolchainRegistry,
|
|
10
|
-
resolveConfiguredToolchain,
|
|
11
|
-
} from "./index.mjs";
|
|
12
|
-
|
|
13
|
-
const tempDirs = [];
|
|
14
|
-
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
while (tempDirs.length > 0) {
|
|
17
|
-
fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
function makeTempDir(prefix) {
|
|
22
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
23
|
-
tempDirs.push(dir);
|
|
24
|
-
return dir;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function writeJson(filePath, value) {
|
|
28
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
29
|
-
fs.writeFileSync(filePath, JSON.stringify(value, null, 2));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
describe("toolchains", () => {
|
|
33
|
-
it("normalizes named toolchain profiles and runtime references", () => {
|
|
34
|
-
const registry = normalizeToolchainRegistry({
|
|
35
|
-
frontend: {
|
|
36
|
-
cwd: "frontend",
|
|
37
|
-
install: "download",
|
|
38
|
-
node: "20.19.5",
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
expect(normalizeRuntimeToolchain("frontend", "Service \"web\" runtime.toolchain", registry)).toEqual(
|
|
43
|
-
expect.objectContaining({
|
|
44
|
-
kind: "node",
|
|
45
|
-
cwd: "frontend",
|
|
46
|
-
install: "download",
|
|
47
|
-
node: "20.19.5",
|
|
48
|
-
refName: "frontend",
|
|
49
|
-
})
|
|
50
|
-
);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("fails clearly when host versions do not satisfy a require-host toolchain", async () => {
|
|
54
|
-
const productDir = makeTempDir("testkit-toolchain-host-");
|
|
55
|
-
writeJson(path.join(productDir, "package.json"), {
|
|
56
|
-
name: "toolchain-host-product",
|
|
57
|
-
engines: {
|
|
58
|
-
node: ">=20.19.5 <21",
|
|
59
|
-
npm: ">=10.8.2 <11",
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const config = {
|
|
64
|
-
name: "frontend",
|
|
65
|
-
productDir,
|
|
66
|
-
testkit: {
|
|
67
|
-
runtime: {
|
|
68
|
-
toolchain: {
|
|
69
|
-
kind: "node",
|
|
70
|
-
cwd: ".",
|
|
71
|
-
detect: "auto",
|
|
72
|
-
install: "require-host",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
await expect(
|
|
79
|
-
resolveConfiguredToolchain(config, {
|
|
80
|
-
hostNodeVersion: "18.19.0",
|
|
81
|
-
hostNpmVersion: "10.8.2",
|
|
82
|
-
})
|
|
83
|
-
).rejects.toThrow("requires Node >=20.19.5 <21");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("provisions a downloaded Node toolchain from a deterministic range minimum", async () => {
|
|
87
|
-
const productDir = makeTempDir("testkit-toolchain-download-");
|
|
88
|
-
writeJson(path.join(productDir, "package.json"), {
|
|
89
|
-
name: "toolchain-download-product",
|
|
90
|
-
engines: {
|
|
91
|
-
node: ">=20.19.5 <21",
|
|
92
|
-
npm: ">=10.8.2 <11",
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const archiveBuffer = await buildFakeNodeArchive();
|
|
97
|
-
const config = {
|
|
98
|
-
name: "frontend",
|
|
99
|
-
productDir,
|
|
100
|
-
testkit: {
|
|
101
|
-
runtime: {
|
|
102
|
-
toolchain: {
|
|
103
|
-
kind: "node",
|
|
104
|
-
cwd: ".",
|
|
105
|
-
detect: "auto",
|
|
106
|
-
install: "download",
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const resolved = await resolveConfiguredToolchain(config, {
|
|
113
|
-
fetchImpl: async () => ({
|
|
114
|
-
ok: true,
|
|
115
|
-
status: 200,
|
|
116
|
-
arrayBuffer: async () => archiveBuffer,
|
|
117
|
-
}),
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
expect(resolved).toMatchObject({
|
|
121
|
-
kind: "node",
|
|
122
|
-
install: "download",
|
|
123
|
-
nodeVersion: "20.19.5",
|
|
124
|
-
npmVersion: "10.8.2",
|
|
125
|
-
nodeSource: "package.json#engines.node",
|
|
126
|
-
npmSource: "package.json#engines.npm",
|
|
127
|
-
});
|
|
128
|
-
expect(fs.existsSync(resolved.nodeExecutable)).toBe(true);
|
|
129
|
-
expect(applyToolchainEnv({ PATH: "/usr/bin" }, resolved).PATH).toContain(
|
|
130
|
-
path.dirname(resolved.nodeExecutable)
|
|
131
|
-
);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
async function buildFakeNodeArchive() {
|
|
136
|
-
const root = makeTempDir("testkit-node-archive-root-");
|
|
137
|
-
const platform = process.platform === "darwin" ? "darwin" : process.platform;
|
|
138
|
-
const arch = process.arch;
|
|
139
|
-
const bundleDir = path.join(root, `node-v20.19.5-${platform}-${arch}`);
|
|
140
|
-
const binDir = path.join(bundleDir, "bin");
|
|
141
|
-
fs.mkdirSync(binDir, { recursive: true });
|
|
142
|
-
|
|
143
|
-
fs.writeFileSync(
|
|
144
|
-
path.join(binDir, "node"),
|
|
145
|
-
[
|
|
146
|
-
"#!/usr/bin/env bash",
|
|
147
|
-
'if [[ \"$1\" == *\"template-step-module-runner.mjs\" ]]; then',
|
|
148
|
-
" shift",
|
|
149
|
-
" exec node \"$@\"",
|
|
150
|
-
"fi",
|
|
151
|
-
'if [[ \"$1\" == *\"npm-cli.js\" ]]; then',
|
|
152
|
-
" shift",
|
|
153
|
-
" exec node \"$@\"",
|
|
154
|
-
"fi",
|
|
155
|
-
"exec node \"$@\"",
|
|
156
|
-
].join("\n"),
|
|
157
|
-
{ mode: 0o755 }
|
|
158
|
-
);
|
|
159
|
-
fs.writeFileSync(
|
|
160
|
-
path.join(binDir, "npm"),
|
|
161
|
-
['#!/usr/bin/env bash', 'echo "10.8.2"'].join("\n"),
|
|
162
|
-
{ mode: 0o755 }
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
const archivePath = path.join(root, "node-v20.19.5-linux-x64.tar.gz");
|
|
166
|
-
await execa("tar", ["-czf", archivePath, "-C", root, path.basename(bundleDir)]);
|
|
167
|
-
return fs.readFileSync(archivePath);
|
|
168
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { defineConfig, testkitExcludes } from "./index.mjs";
|
|
3
|
-
|
|
4
|
-
describe("testkit vitest defineConfig", () => {
|
|
5
|
-
it("appends testkit suite excludes", () => {
|
|
6
|
-
const config = defineConfig({
|
|
7
|
-
test: {
|
|
8
|
-
exclude: ["dist"],
|
|
9
|
-
},
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
expect(config.test.exclude).toEqual(
|
|
13
|
-
expect.arrayContaining(["dist", "**/*.int.testkit.ts", "**/*.pw.testkit.ts"])
|
|
14
|
-
);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("exports the default testkit excludes", () => {
|
|
18
|
-
expect(testkitExcludes()).toContain("**/*.scenario.testkit.ts");
|
|
19
|
-
});
|
|
20
|
-
});
|