@elench/testkit 0.1.66 → 0.1.67
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/README.md +37 -62
- package/lib/app/doctor.mjs +139 -0
- package/lib/app/typecheck.mjs +203 -0
- package/lib/cli/commands/doctor.mjs +39 -0
- package/lib/cli/commands/typecheck.mjs +28 -0
- package/lib/cli/entrypoint.mjs +2 -0
- package/lib/config/index.mjs +11 -0
- package/lib/config/runtime.mjs +11 -1
- package/lib/config/runtime.test.mjs +26 -0
- package/lib/coverage/index.test.mjs +4 -2
- package/lib/discovery/file-metadata.mjs +122 -0
- package/lib/discovery/file-metadata.test.mjs +51 -0
- package/lib/discovery/index.mjs +10 -2
- package/lib/discovery/index.test.mjs +19 -19
- package/lib/runner/planning.mjs +10 -3
- package/lib/runner/planning.test.mjs +26 -0
- package/lib/setup/index.d.ts +88 -21
- package/lib/setup/index.mjs +177 -50
- package/lib/setup/index.test.mjs +194 -64
- package/lib/shared/build-config.mjs +144 -0
- package/lib/shared/build-config.test.mjs +81 -0
- 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 +5 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
import {
|
|
3
3
|
normalizeBrowserServiceConfig,
|
|
4
|
+
normalizeRuntimeConfig,
|
|
4
5
|
normalizeRuntimePrepareConfig,
|
|
5
6
|
normalizeTemplateLifecycleStep,
|
|
6
7
|
normalizeTemplateStepInputs,
|
|
@@ -45,6 +46,31 @@ describe("config runtime helpers", () => {
|
|
|
45
46
|
});
|
|
46
47
|
});
|
|
47
48
|
|
|
49
|
+
it("folds declarative runtime.build into runtime.prepare", () => {
|
|
50
|
+
expect(
|
|
51
|
+
normalizeRuntimeConfig(
|
|
52
|
+
{
|
|
53
|
+
build: {
|
|
54
|
+
kind: "tsc",
|
|
55
|
+
entry: "src/server.ts",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
"api",
|
|
59
|
+
{}
|
|
60
|
+
)
|
|
61
|
+
).toMatchObject({
|
|
62
|
+
build: {
|
|
63
|
+
kind: "tsc",
|
|
64
|
+
entry: "src/server.ts",
|
|
65
|
+
tsconfig: "tsconfig.json",
|
|
66
|
+
outDir: "dist",
|
|
67
|
+
},
|
|
68
|
+
prepare: {
|
|
69
|
+
inputs: ["tsconfig.json", "package.json", "src"],
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
48
74
|
it("rejects malformed lifecycle steps and empty step inputs", () => {
|
|
49
75
|
expect(() => normalizeTemplateLifecycleStep({ kind: "module" }, "runtime.prepare.steps[0]")).toThrow(
|
|
50
76
|
/specifier must be a non-empty string/
|
|
@@ -19,13 +19,15 @@ describe("coverage graph builder", () => {
|
|
|
19
19
|
productDir,
|
|
20
20
|
"testkit.setup.ts",
|
|
21
21
|
`
|
|
22
|
-
import { defineTestkitSetup,
|
|
22
|
+
import { defineTestkitSetup, nextApp } from "@elench/testkit/setup";
|
|
23
23
|
|
|
24
24
|
export default defineTestkitSetup({
|
|
25
25
|
services: {
|
|
26
|
-
web:
|
|
26
|
+
web: nextApp({
|
|
27
27
|
cwd: ".",
|
|
28
28
|
start: "node server.js",
|
|
29
|
+
mode: "start",
|
|
30
|
+
build: null,
|
|
29
31
|
baseUrl: "http://127.0.0.1:3000",
|
|
30
32
|
readyUrl: "http://127.0.0.1:3000"
|
|
31
33
|
})
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
|
|
5
|
+
export function loadTestFileMetadataMap(productDir, suitesByService = {}) {
|
|
6
|
+
const metadataByPath = new Map();
|
|
7
|
+
|
|
8
|
+
for (const suites of Object.values(suitesByService || {})) {
|
|
9
|
+
for (const suiteList of Object.values(suites || {})) {
|
|
10
|
+
for (const suite of suiteList || []) {
|
|
11
|
+
for (const filePath of suite.files || []) {
|
|
12
|
+
if (metadataByPath.has(filePath)) continue;
|
|
13
|
+
metadataByPath.set(filePath, readTestFileMetadata(productDir, filePath));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return metadataByPath;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function readTestFileMetadata(productDir, filePath) {
|
|
23
|
+
const absolutePath = path.join(productDir, filePath);
|
|
24
|
+
if (!fs.existsSync(absolutePath)) {
|
|
25
|
+
return emptyMetadata();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const sourceText = fs.readFileSync(absolutePath, "utf8");
|
|
29
|
+
const sourceFile = ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
30
|
+
|
|
31
|
+
for (const statement of sourceFile.statements) {
|
|
32
|
+
if (!ts.isVariableStatement(statement) || !hasExportModifier(statement)) continue;
|
|
33
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
34
|
+
if (!ts.isIdentifier(declaration.name) || declaration.name.text !== "testkit") continue;
|
|
35
|
+
const config = parseMetadataInitializer(declaration.initializer);
|
|
36
|
+
if (config) return config;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return emptyMetadata();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function parseMetadataInitializer(initializer) {
|
|
44
|
+
if (!initializer) return null;
|
|
45
|
+
if (ts.isCallExpression(initializer)) {
|
|
46
|
+
const callee = getCallIdentifier(initializer.expression);
|
|
47
|
+
if (callee === "defineTestkitFile" && initializer.arguments[0] && ts.isObjectLiteralExpression(initializer.arguments[0])) {
|
|
48
|
+
return parseMetadataObject(initializer.arguments[0]);
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
if (ts.isObjectLiteralExpression(initializer)) {
|
|
53
|
+
return parseMetadataObject(initializer);
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseMetadataObject(node) {
|
|
59
|
+
const metadata = emptyMetadata();
|
|
60
|
+
|
|
61
|
+
for (const property of node.properties) {
|
|
62
|
+
if (!ts.isPropertyAssignment(property)) continue;
|
|
63
|
+
const key = getPropertyName(property.name);
|
|
64
|
+
if (key === "locks") {
|
|
65
|
+
metadata.locks = parseLocks(property.initializer);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (key === "skip") {
|
|
69
|
+
metadata.skipReason = parseSkipReason(property.initializer);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return metadata;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function parseLocks(node) {
|
|
77
|
+
if (!ts.isArrayLiteralExpression(node)) return [];
|
|
78
|
+
const values = [];
|
|
79
|
+
for (const entry of node.elements) {
|
|
80
|
+
const value = readStringLiteral(entry);
|
|
81
|
+
if (value) values.push(value);
|
|
82
|
+
}
|
|
83
|
+
return [...new Set(values)].sort();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function parseSkipReason(node) {
|
|
87
|
+
const literal = readStringLiteral(node);
|
|
88
|
+
if (literal) return literal;
|
|
89
|
+
if (!ts.isObjectLiteralExpression(node)) return null;
|
|
90
|
+
for (const property of node.properties) {
|
|
91
|
+
if (!ts.isPropertyAssignment(property)) continue;
|
|
92
|
+
if (getPropertyName(property.name) !== "reason") continue;
|
|
93
|
+
return readStringLiteral(property.initializer) || null;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getCallIdentifier(node) {
|
|
99
|
+
if (ts.isIdentifier(node)) return node.text;
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function getPropertyName(node) {
|
|
104
|
+
if (ts.isIdentifier(node) || ts.isStringLiteral(node)) return node.text;
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function readStringLiteral(node) {
|
|
109
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function hasExportModifier(node) {
|
|
114
|
+
return (node.modifiers || []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function emptyMetadata() {
|
|
118
|
+
return {
|
|
119
|
+
locks: [],
|
|
120
|
+
skipReason: null,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
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 { readTestFileMetadata } from "./file-metadata.mjs";
|
|
6
|
+
|
|
7
|
+
const tempDirs = [];
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
for (const dir of tempDirs.splice(0)) {
|
|
11
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("test file metadata", () => {
|
|
16
|
+
it("reads exported testkit metadata from object literals and helper calls", () => {
|
|
17
|
+
const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-file-meta-"));
|
|
18
|
+
tempDirs.push(productDir);
|
|
19
|
+
fs.mkdirSync(path.join(productDir, "__testkit__"), { recursive: true });
|
|
20
|
+
fs.writeFileSync(
|
|
21
|
+
path.join(productDir, "__testkit__", "billing.int.testkit.ts"),
|
|
22
|
+
[
|
|
23
|
+
'import { defineTestkitFile } from "@elench/testkit/setup";',
|
|
24
|
+
'export const testkit = defineTestkitFile({',
|
|
25
|
+
' skip: "Billing is stubbed locally",',
|
|
26
|
+
' locks: ["background-workers", "background-workers"],',
|
|
27
|
+
"});",
|
|
28
|
+
].join("\n")
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
expect(readTestFileMetadata(productDir, "__testkit__/billing.int.testkit.ts")).toEqual({
|
|
32
|
+
skipReason: "Billing is stubbed locally",
|
|
33
|
+
locks: ["background-workers"],
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("returns empty metadata when no export is present", () => {
|
|
38
|
+
const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-file-meta-"));
|
|
39
|
+
tempDirs.push(productDir);
|
|
40
|
+
fs.mkdirSync(path.join(productDir, "__testkit__"), { recursive: true });
|
|
41
|
+
fs.writeFileSync(
|
|
42
|
+
path.join(productDir, "__testkit__", "health.int.testkit.ts"),
|
|
43
|
+
"export default {};\n"
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
expect(readTestFileMetadata(productDir, "__testkit__/health.int.testkit.ts")).toEqual({
|
|
47
|
+
skipReason: null,
|
|
48
|
+
locks: [],
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
package/lib/discovery/index.mjs
CHANGED
|
@@ -207,8 +207,16 @@ function buildResolvedSuiteEntries(config, suite, internalType, filters) {
|
|
|
207
207
|
|
|
208
208
|
for (const filePath of suite.files || []) {
|
|
209
209
|
if (filters.fileNameSet.size > 0 && !filters.fileNameSet.has(filePath)) continue;
|
|
210
|
-
const
|
|
211
|
-
const
|
|
210
|
+
const fileMetadata = config.testkit.fileMetadataByPath?.get(filePath) || { locks: [], skipReason: null };
|
|
211
|
+
const fileLocks = [
|
|
212
|
+
...(config.testkit.requirements?.fileLocksByPath?.get(filePath) || []),
|
|
213
|
+
...(fileMetadata.locks || []),
|
|
214
|
+
];
|
|
215
|
+
const skipReason =
|
|
216
|
+
fileMetadata.skipReason ||
|
|
217
|
+
config.testkit.skip?.fileReasonByPath?.get(filePath) ||
|
|
218
|
+
suiteSkipReason ||
|
|
219
|
+
null;
|
|
212
220
|
const skipped = Boolean(skipReason);
|
|
213
221
|
if (filters.runnableOnly && skipped) continue;
|
|
214
222
|
visibleFiles.push({
|
|
@@ -30,14 +30,6 @@ describe("public discovery", () => {
|
|
|
30
30
|
start: "node server.js",
|
|
31
31
|
baseUrl: "http://127.0.0.1:3000",
|
|
32
32
|
readyUrl: "http://127.0.0.1:3000"
|
|
33
|
-
},
|
|
34
|
-
requirements: {
|
|
35
|
-
files: [
|
|
36
|
-
{
|
|
37
|
-
path: "src/api/routes/__testkit__/agent-configs-auth-gate.int.testkit.ts",
|
|
38
|
-
locks: ["route-lock"]
|
|
39
|
-
}
|
|
40
|
-
]
|
|
41
33
|
}
|
|
42
34
|
},
|
|
43
35
|
frontend: {
|
|
@@ -47,22 +39,30 @@ describe("public discovery", () => {
|
|
|
47
39
|
baseUrl: "http://127.0.0.1:3001",
|
|
48
40
|
readyUrl: "http://127.0.0.1:3001"
|
|
49
41
|
},
|
|
50
|
-
dependsOn: ["api"]
|
|
51
|
-
skip: {
|
|
52
|
-
files: [
|
|
53
|
-
{
|
|
54
|
-
path: "frontend/src/app/login/__testkit__/auth.pw.testkit.ts",
|
|
55
|
-
reason: "Auth is stubbed locally"
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
}
|
|
42
|
+
dependsOn: ["api"]
|
|
59
43
|
}
|
|
60
44
|
}
|
|
61
45
|
});
|
|
62
46
|
`
|
|
63
47
|
);
|
|
64
|
-
writeFile(
|
|
65
|
-
|
|
48
|
+
writeFile(
|
|
49
|
+
productDir,
|
|
50
|
+
"src/api/routes/__testkit__/agent-configs-auth-gate.int.testkit.ts",
|
|
51
|
+
[
|
|
52
|
+
'import { defineTestkitFile } from "@elench/testkit/setup";',
|
|
53
|
+
'export const testkit = defineTestkitFile({ locks: ["route-lock"] });',
|
|
54
|
+
"export {};",
|
|
55
|
+
].join("\n")
|
|
56
|
+
);
|
|
57
|
+
writeFile(
|
|
58
|
+
productDir,
|
|
59
|
+
"frontend/src/app/login/__testkit__/auth.pw.testkit.ts",
|
|
60
|
+
[
|
|
61
|
+
'import { defineTestkitFile } from "@elench/testkit/setup";',
|
|
62
|
+
'export const testkit = defineTestkitFile({ skip: "Auth is stubbed locally" });',
|
|
63
|
+
"export {};",
|
|
64
|
+
].join("\n")
|
|
65
|
+
);
|
|
66
66
|
|
|
67
67
|
saveHistory(productDir, {
|
|
68
68
|
version: 1,
|
package/lib/runner/planning.mjs
CHANGED
|
@@ -223,14 +223,15 @@ function applySkipRules(config, displayType, suiteName, files, opts = {}) {
|
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
225
|
const skip = config.testkit?.skip;
|
|
226
|
-
|
|
226
|
+
const metadataByPath = config.testkit?.fileMetadataByPath || null;
|
|
227
|
+
if (!skip && !metadataByPath) {
|
|
227
228
|
return {
|
|
228
229
|
files,
|
|
229
230
|
skippedFiles: [],
|
|
230
231
|
};
|
|
231
232
|
}
|
|
232
233
|
|
|
233
|
-
const matchingSuiteRules = skip
|
|
234
|
+
const matchingSuiteRules = (skip?.suites || []).filter((rule) =>
|
|
234
235
|
matchesSuiteSelectors(displayType, suiteName, [rule.selector])
|
|
235
236
|
);
|
|
236
237
|
const suiteReason = matchingSuiteRules[0]?.reason || null;
|
|
@@ -239,7 +240,9 @@ function applySkipRules(config, displayType, suiteName, files, opts = {}) {
|
|
|
239
240
|
|
|
240
241
|
for (const file of files) {
|
|
241
242
|
const normalizedFile = normalizePathSeparators(file);
|
|
242
|
-
const
|
|
243
|
+
const fileMetadata = config.testkit.fileMetadataByPath?.get(normalizedFile) || null;
|
|
244
|
+
const reason =
|
|
245
|
+
fileMetadata?.skipReason || skip?.fileReasonByPath?.get(normalizedFile) || suiteReason;
|
|
243
246
|
if (reason) {
|
|
244
247
|
skippedFiles.push({
|
|
245
248
|
path: normalizedFile,
|
|
@@ -268,9 +271,13 @@ function resolveTaskLocks(config, suite, file) {
|
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
const normalizedFile = normalizePathSeparators(file);
|
|
274
|
+
const fileMetadata = config.testkit.fileMetadataByPath?.get(normalizedFile) || null;
|
|
271
275
|
for (const lockName of config.testkit.requirements?.fileLocksByPath?.get(normalizedFile) || []) {
|
|
272
276
|
locks.add(lockName);
|
|
273
277
|
}
|
|
278
|
+
for (const lockName of fileMetadata?.locks || []) {
|
|
279
|
+
locks.add(lockName);
|
|
280
|
+
}
|
|
274
281
|
|
|
275
282
|
return [...locks].sort();
|
|
276
283
|
}
|
|
@@ -138,6 +138,32 @@ describe("runner-planning", () => {
|
|
|
138
138
|
]);
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
+
it("does not require repo-level skip config when file metadata is present", () => {
|
|
142
|
+
const config = makeConfig("api", {
|
|
143
|
+
suites: {
|
|
144
|
+
integration: [
|
|
145
|
+
{
|
|
146
|
+
name: "health",
|
|
147
|
+
files: ["__testkit__/health/health.int.testkit.ts"],
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
testkit: {
|
|
152
|
+
fileMetadataByPath: new Map([
|
|
153
|
+
["__testkit__/health/health.int.testkit.ts", { skipReason: null, locks: [] }],
|
|
154
|
+
]),
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(collectSuites(config, ["int"], [], [])).toEqual([
|
|
159
|
+
expect.objectContaining({
|
|
160
|
+
name: "health",
|
|
161
|
+
files: ["__testkit__/health/health.int.testkit.ts"],
|
|
162
|
+
skippedFiles: [],
|
|
163
|
+
}),
|
|
164
|
+
]);
|
|
165
|
+
});
|
|
166
|
+
|
|
141
167
|
it("applies lock requirements to matching suites and files", () => {
|
|
142
168
|
const api = makeConfig("api", {
|
|
143
169
|
suites: {
|
package/lib/setup/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface DatabaseTemplateConfig {
|
|
|
7
7
|
verify?: TemplateLifecycleStepConfig[];
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export interface
|
|
10
|
+
export interface DatabaseTemplateOptions {
|
|
11
11
|
inputs?: string[];
|
|
12
12
|
schema?: string | TemplateSqlFileStepConfig;
|
|
13
13
|
migrate?: TemplateLifecycleStepConfig | TemplateLifecycleStepConfig[];
|
|
@@ -40,6 +40,30 @@ export type TemplateLifecycleStepConfig =
|
|
|
40
40
|
| TemplateSqlFileStepConfig
|
|
41
41
|
| TemplateModuleStepConfig;
|
|
42
42
|
|
|
43
|
+
export interface TscBuildConfig {
|
|
44
|
+
kind: "tsc";
|
|
45
|
+
cwd?: string;
|
|
46
|
+
entry?: string;
|
|
47
|
+
inputs?: string[];
|
|
48
|
+
outDir?: string;
|
|
49
|
+
tsconfig?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ScriptBuildConfig {
|
|
53
|
+
kind: "script";
|
|
54
|
+
cwd?: string;
|
|
55
|
+
inputs?: string[];
|
|
56
|
+
script: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface StepsBuildConfig {
|
|
60
|
+
kind: "steps";
|
|
61
|
+
inputs?: string[];
|
|
62
|
+
steps?: TemplateLifecycleStepConfig[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type BuildConfig = TscBuildConfig | ScriptBuildConfig | StepsBuildConfig;
|
|
66
|
+
|
|
43
67
|
export interface LocalDatabaseConfig {
|
|
44
68
|
provider: "local";
|
|
45
69
|
binding?: "shared" | "per-runtime";
|
|
@@ -66,6 +90,7 @@ export interface SkipConfig {
|
|
|
66
90
|
}
|
|
67
91
|
|
|
68
92
|
export interface RuntimeConfig {
|
|
93
|
+
build?: BuildConfig | null;
|
|
69
94
|
instances?: number;
|
|
70
95
|
maxConcurrentTasks?: number;
|
|
71
96
|
prepare?: {
|
|
@@ -126,7 +151,6 @@ export interface ServiceConfig {
|
|
|
126
151
|
databaseFrom?: string;
|
|
127
152
|
dependsOn?: string[];
|
|
128
153
|
discovery?: DiscoveryConfig;
|
|
129
|
-
env?: Record<string, string>;
|
|
130
154
|
envFile?: string;
|
|
131
155
|
envFiles?: string[];
|
|
132
156
|
browser?: BrowserServiceConfig;
|
|
@@ -144,6 +168,44 @@ export interface ServiceConfig {
|
|
|
144
168
|
skip?: SkipConfig;
|
|
145
169
|
}
|
|
146
170
|
|
|
171
|
+
export interface TestkitFileMetadata {
|
|
172
|
+
locks?: string[];
|
|
173
|
+
skip?: string | { reason: string };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface NodeAppOptions extends Omit<ServiceConfig, "local" | "runtime"> {
|
|
177
|
+
baseUrl?: string;
|
|
178
|
+
build?: BuildConfig | null;
|
|
179
|
+
buildInputs?: string[];
|
|
180
|
+
cwd?: string;
|
|
181
|
+
entry?: string;
|
|
182
|
+
env?: Record<string, string>;
|
|
183
|
+
outDir?: string;
|
|
184
|
+
port: number;
|
|
185
|
+
readyPath?: string;
|
|
186
|
+
readyTimeoutMs?: number;
|
|
187
|
+
readyUrl?: string;
|
|
188
|
+
runtime?: Omit<RuntimeConfig, "build">;
|
|
189
|
+
start?: string;
|
|
190
|
+
toolchain?: string | NodeToolchainConfig;
|
|
191
|
+
tsconfig?: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface NextAppOptions extends Omit<ServiceConfig, "local" | "runtime"> {
|
|
195
|
+
baseUrl?: string;
|
|
196
|
+
build?: BuildConfig | null;
|
|
197
|
+
buildInputs?: string[];
|
|
198
|
+
cwd?: string;
|
|
199
|
+
env?: Record<string, string>;
|
|
200
|
+
mode?: "dev" | "start";
|
|
201
|
+
port: number;
|
|
202
|
+
readyTimeoutMs?: number;
|
|
203
|
+
readyUrl?: string;
|
|
204
|
+
runtime?: Omit<RuntimeConfig, "build">;
|
|
205
|
+
start?: string;
|
|
206
|
+
toolchain?: string | NodeToolchainConfig;
|
|
207
|
+
}
|
|
208
|
+
|
|
147
209
|
export interface TestkitSetup {
|
|
148
210
|
discovery?: DiscoveryConfig;
|
|
149
211
|
execution?: TestkitExecutionConfig;
|
|
@@ -166,8 +228,8 @@ export interface TestkitSetup {
|
|
|
166
228
|
|
|
167
229
|
export declare function defineTestkitSetup<T extends TestkitSetup>(setup: T): T;
|
|
168
230
|
export declare function defineHttpProfile<T extends HttpSuiteConfig>(profile: T): T;
|
|
169
|
-
export declare function
|
|
170
|
-
export declare function
|
|
231
|
+
export declare function defineTestkitFile<T extends TestkitFileMetadata>(metadata: T): T;
|
|
232
|
+
export declare function postgresDatabase(options?: Omit<LocalDatabaseConfig, "provider">): LocalDatabaseConfig;
|
|
171
233
|
export declare function commandStep(
|
|
172
234
|
cmd: string,
|
|
173
235
|
options?: Omit<TemplateCommandStepConfig, "kind" | "cmd">
|
|
@@ -200,24 +262,29 @@ export declare function verifyModule(
|
|
|
200
262
|
specifier: string,
|
|
201
263
|
options?: Omit<TemplateModuleStepConfig, "kind" | "specifier">
|
|
202
264
|
): TemplateModuleStepConfig;
|
|
203
|
-
export declare function
|
|
204
|
-
options?:
|
|
205
|
-
):
|
|
265
|
+
export declare function templateDatabase(
|
|
266
|
+
options?: DatabaseTemplateOptions & Omit<LocalDatabaseConfig, "provider" | "template">
|
|
267
|
+
): LocalDatabaseConfig;
|
|
268
|
+
export declare function postgresFixture(
|
|
269
|
+
options?: Omit<LocalDatabaseConfig, "provider"> & {
|
|
270
|
+
discovery?: DiscoveryConfig;
|
|
271
|
+
envFiles?: string[];
|
|
272
|
+
}
|
|
273
|
+
): ServiceConfig;
|
|
274
|
+
export declare function databaseServiceEnv(
|
|
275
|
+
prefix: string,
|
|
276
|
+
serviceName: string
|
|
277
|
+
): Record<string, string>;
|
|
206
278
|
export declare function nodeToolchain(options?: NodeToolchainConfig): NodeToolchainConfig;
|
|
207
|
-
export declare function
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
export declare function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
export declare function tsxService(options: ServiceConfig["local"] & {
|
|
217
|
-
entry?: string;
|
|
218
|
-
envFiles?: string[];
|
|
219
|
-
readyPath?: string;
|
|
220
|
-
}): ServiceConfig;
|
|
279
|
+
export declare function tscBuild(options?: Omit<TscBuildConfig, "kind">): TscBuildConfig;
|
|
280
|
+
export declare function scriptBuild(
|
|
281
|
+
script: string,
|
|
282
|
+
options?: Omit<ScriptBuildConfig, "kind" | "script">
|
|
283
|
+
): ScriptBuildConfig;
|
|
284
|
+
export declare function stepsBuild(options?: Omit<StepsBuildConfig, "kind">): StepsBuildConfig;
|
|
285
|
+
export declare function nextBuild(options?: Omit<ScriptBuildConfig, "kind" | "script">): ScriptBuildConfig;
|
|
286
|
+
export declare function nodeApp(options: NodeAppOptions): ServiceConfig;
|
|
287
|
+
export declare function nextApp(options: NextAppOptions): ServiceConfig;
|
|
221
288
|
export declare function clerkSessionProfile(options?: {
|
|
222
289
|
apiBase?: string;
|
|
223
290
|
needsAuth?: boolean;
|