@jterrazz/test 17.0.0 → 18.0.0
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/dist/browser/index.js +1 -2
- package/dist/browser/services.js +1 -2
- package/dist/browser/stubs.js +1 -2
- package/dist/{shared-index.browser.js → browser-shared-index.browser.js} +82 -40
- package/dist/checker.js +15 -824
- package/dist/in-place.global-setup.d.ts +1 -0
- package/dist/in-place.global-setup.js +1 -1
- package/dist/index.d.ts +2 -14
- package/dist/index.js +83 -204
- package/dist/mobile-session.global-setup.d.ts +1 -0
- package/dist/oxlint.cjs +2 -2
- package/dist/oxlint.js +67 -2321
- package/dist/route-coverage.global-setup.d.ts +1 -0
- package/dist/route-coverage.global-setup.js +1 -2
- package/dist/services.global-setup.d.ts +1 -1
- package/dist/services.global-setup.js +1 -2
- package/dist/services.js +1 -1
- package/dist/shared-appium.adapter.js +14 -14
- package/dist/shared-artifacts.js +7 -5
- package/dist/shared-derived-projects.js +23 -8
- package/dist/shared-in-place.js +1 -1
- package/dist/shared-ledger.js +1 -1
- package/dist/shared-listened-port.js +19 -0
- package/dist/shared-literate-plugin.js +2 -1
- package/dist/shared-pause.js +12 -1
- package/dist/shared-playwright.adapter.js +17 -19
- package/dist/shared-process-alive.js +13 -0
- package/dist/shared-record-key.js +13 -0
- package/dist/shared-serve.js +107 -65
- package/dist/shared-services.global-setup.js +4 -9
- package/dist/shared-session-ledger.js +10 -6
- package/dist/shared-spec-document.js +2 -64
- package/dist/shared-spec-grammar.js +66 -0
- package/dist/shared-specs-modules.js +1033 -0
- package/dist/{shared-stream-body.js → shared-stub-reply.js} +40 -3
- package/dist/shared-stub-server.js +30 -78
- package/dist/shared-temp-root.global-setup.js +3 -10
- package/dist/shared-testcontainers.adapter.js +111 -8
- package/dist/temp-root.global-setup.js +1 -2
- package/dist/vitest.d.ts +17 -22
- package/dist/vitest.js +37 -53
- package/docs/concepts/architecture.md +20 -20
- package/docs/concepts/conventions.md +2 -2
- package/docs/guides/cli-specs.md +2 -0
- package/docs/guides/develop.md +20 -17
- package/docs/guides/mobile-specs.md +3 -3
- package/docs/guides/release.md +4 -3
- package/docs/guides/website-specs.md +1 -1
- package/docs/reference/linting.md +2 -2
- package/docs/reference/services.md +9 -9
- package/docs/reference/stubs.md +4 -2
- package/docs/start/set-up-a-project.md +31 -17
- package/package.json +10 -10
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { n as refusal } from "./shared-refusal.js";
|
|
2
|
-
import { a as field, i as RunContainers, o as serveContainers, r as TestcontainersAdapter, t as OWNER_LABEL } from "./shared-testcontainers.adapter.js";
|
|
2
|
+
import { a as field, i as RunContainers, o as serveContainers, r as TestcontainersAdapter, s as DOCKER_ABSENT, t as OWNER_LABEL } from "./shared-testcontainers.adapter.js";
|
|
3
3
|
import { t as loadPeer } from "./shared-peer.js";
|
|
4
4
|
import { t as SERVICE_IMAGES } from "./shared-service-images.js";
|
|
5
5
|
import { t as setupEntry } from "./shared-setup-entry.js";
|
|
6
|
+
import { t as processAlive } from "./shared-process-alive.js";
|
|
6
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
8
|
import { dirname, join } from "node:path";
|
|
8
9
|
import { hostname } from "node:os";
|
|
@@ -15,12 +16,7 @@ function ownerAlive(owner, host = hostname(), probe = (pid) => process.kill(pid,
|
|
|
15
16
|
const separator = owner.lastIndexOf(":");
|
|
16
17
|
const pid = Number(owner.slice(separator + 1));
|
|
17
18
|
if (separator === -1 || owner.slice(0, separator) !== host || !Number.isSafeInteger(pid) || pid <= 0) return true;
|
|
18
|
-
|
|
19
|
-
probe(pid);
|
|
20
|
-
return true;
|
|
21
|
-
} catch (error) {
|
|
22
|
-
return Reflect.get(new Object(error), "code") !== "ESRCH";
|
|
23
|
-
}
|
|
19
|
+
return processAlive(pid, probe);
|
|
24
20
|
}
|
|
25
21
|
function orphans(containers, alive) {
|
|
26
22
|
const reaped = new Set(containers.filter((container) => container.State === "running" && container.Labels[REAPER_LABEL] === "true").map((reaper) => reaper.Labels[SESSION_LABEL]));
|
|
@@ -50,7 +46,6 @@ async function sweepOrphans(runtime, alive = ownerAlive) {
|
|
|
50
46
|
//#endregion
|
|
51
47
|
//#region src/services/containers/services.global-setup.ts
|
|
52
48
|
/** Every project's setup joins the one run's containers. Default images are pulled in the background, so the first file waits on a pull at most once; a project declaring no service needs no Docker. */
|
|
53
|
-
const DOCKER_ABSENT = "no Docker daemon answered";
|
|
54
49
|
/** `connect` stands in for the runtime's own client lookup, so the refusal is reachable without a daemon to stop. */
|
|
55
50
|
async function prepareDocker(connect) {
|
|
56
51
|
const { getContainerRuntimeClient, ImageName } = await loadPeer("testcontainers", "a declared service", async () => await import("testcontainers"));
|
|
@@ -174,6 +169,6 @@ async function setup(project, seams = {}) {
|
|
|
174
169
|
return joined.leave;
|
|
175
170
|
}
|
|
176
171
|
//#endregion
|
|
177
|
-
export {
|
|
172
|
+
export { servicesSetup as n, setup as r, prepareDocker as t };
|
|
178
173
|
|
|
179
174
|
//# sourceMappingURL=shared-services.global-setup.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as ServedProcess } from "./shared-serve.js";
|
|
2
2
|
import { t as isRecord } from "./shared-json-shape.js";
|
|
3
3
|
import { n as refusal } from "./shared-refusal.js";
|
|
4
|
-
import {
|
|
4
|
+
import { u as VITEST_ARTIFACTS_DIR } from "./shared-artifacts.js";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { join, resolve } from "node:path";
|
|
7
7
|
import { execFile } from "node:child_process";
|
|
@@ -227,9 +227,13 @@ async function reachAppium({ appium: declared, device }, root, run) {
|
|
|
227
227
|
//#region src/specifications/mobile/session/session-ledger.ts
|
|
228
228
|
const SERVER_CALL_TIMEOUT_MS = 1e4;
|
|
229
229
|
const MOBILE_SESSIONS_DIR = `${VITEST_ARTIFACTS_DIR}/mobile-sessions`;
|
|
230
|
-
function keyOf(serverUrl, requested) {
|
|
230
|
+
function keyOf(serverUrl, requested, worker) {
|
|
231
231
|
const sorted = Object.entries(requested).toSorted(([a], [b]) => a.localeCompare(b));
|
|
232
|
-
return JSON.stringify([
|
|
232
|
+
return JSON.stringify([
|
|
233
|
+
serverUrl,
|
|
234
|
+
sorted,
|
|
235
|
+
worker
|
|
236
|
+
]);
|
|
233
237
|
}
|
|
234
238
|
function isEntry(value) {
|
|
235
239
|
return isRecord(value) && [
|
|
@@ -249,13 +253,13 @@ function entries(directory) {
|
|
|
249
253
|
const parsed = (name) => JSON.parse(readFileSync(join(directory, name), "utf8"));
|
|
250
254
|
return entryFiles(directory).map((name) => parsed(name)).filter((entry) => isEntry(entry));
|
|
251
255
|
}
|
|
252
|
-
function sessionLedger(directory) {
|
|
256
|
+
function sessionLedger(directory, worker = process.env.VITEST_POOL_ID ?? "") {
|
|
253
257
|
return {
|
|
254
258
|
forget: (sessionId) => {
|
|
255
259
|
rmSync(join(directory, `${sessionId}.json`), { force: true });
|
|
256
260
|
},
|
|
257
261
|
lookup: (serverUrl, requested) => {
|
|
258
|
-
const key = keyOf(serverUrl, requested);
|
|
262
|
+
const key = keyOf(serverUrl, requested, worker);
|
|
259
263
|
return entries(directory).filter((entry) => entry.key === key).map(({ capabilities, serverUrl: url, sessionId }) => ({
|
|
260
264
|
capabilities,
|
|
261
265
|
serverUrl: url,
|
|
@@ -265,7 +269,7 @@ function sessionLedger(directory) {
|
|
|
265
269
|
record: (requested, session) => {
|
|
266
270
|
const entry = {
|
|
267
271
|
...session,
|
|
268
|
-
key: keyOf(session.serverUrl, requested)
|
|
272
|
+
key: keyOf(session.serverUrl, requested, worker)
|
|
269
273
|
};
|
|
270
274
|
mkdirSync(directory, { recursive: true });
|
|
271
275
|
writeFileSync(join(directory, `${session.sessionId}.json`), `${JSON.stringify(entry)}\n`);
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
+
import { a as RUN_KEYS, c as isRelativePath, i as PRESENCE, n as FILE_CONTENT_KEYS, r as FILE_STATES, s as SpecSyntaxError, t as DOCUMENT_KEYS } from "./shared-spec-grammar.js";
|
|
1
2
|
import { a as isPair, c as nodeItems, f as yamlSyntaxErrors, i as isNode, l as nodePairs, o as isScalar, r as isMap, s as isSeq, u as parseYamlSource } from "./shared-yaml-document.js";
|
|
2
3
|
import { GROUND_FIXTURES, isGroundFolder } from "@jterrazz/typescript/rules";
|
|
3
|
-
//#region lint/kit/project/relative-path.ts
|
|
4
|
-
function isRelativePath(value) {
|
|
5
|
-
return value.startsWith("./") || value.startsWith("../");
|
|
6
|
-
}
|
|
7
|
-
//#endregion
|
|
8
4
|
//#region lint/kit/project/dedent.ts
|
|
9
5
|
function indentOf(line) {
|
|
10
6
|
return /^[\t ]*/u.exec(line)?.[0].length ?? 0;
|
|
@@ -19,64 +15,6 @@ function dedent(text) {
|
|
|
19
15
|
return lines.map((line) => line.slice(common)).join("\n");
|
|
20
16
|
}
|
|
21
17
|
//#endregion
|
|
22
|
-
//#region lint/kit/project/spec-grammar.ts
|
|
23
|
-
const SPEC_EXTENSION = ".spec.yaml";
|
|
24
|
-
const DOCUMENT_KEYS = [
|
|
25
|
-
"description",
|
|
26
|
-
"fixture",
|
|
27
|
-
"env",
|
|
28
|
-
"serve",
|
|
29
|
-
"runs"
|
|
30
|
-
];
|
|
31
|
-
const RUN_KEYS = [
|
|
32
|
-
"command",
|
|
33
|
-
"stdin",
|
|
34
|
-
"timeout",
|
|
35
|
-
"waitFor",
|
|
36
|
-
"exit",
|
|
37
|
-
"stdout",
|
|
38
|
-
"stderr",
|
|
39
|
-
"files"
|
|
40
|
-
];
|
|
41
|
-
const FILE_CONTENT_KEYS = ["contains", "equals"];
|
|
42
|
-
const FILE_STATES = ["absent", "exists"];
|
|
43
|
-
const PRESENCE = {
|
|
44
|
-
document: [{
|
|
45
|
-
keys: ["description"],
|
|
46
|
-
law: "each",
|
|
47
|
-
refusal: () => "missing \"description:\": every document is one test, and this is its title"
|
|
48
|
-
}, {
|
|
49
|
-
keys: ["runs"],
|
|
50
|
-
law: "each",
|
|
51
|
-
refusal: () => "missing \"runs:\": description and runs are mandatory"
|
|
52
|
-
}],
|
|
53
|
-
files: [{
|
|
54
|
-
keys: FILE_CONTENT_KEYS,
|
|
55
|
-
law: "some",
|
|
56
|
-
refusal: (path) => `files: ${path} asserts nothing: give it contains: or equals:`
|
|
57
|
-
}],
|
|
58
|
-
run: [{
|
|
59
|
-
keys: ["command", "exit"],
|
|
60
|
-
law: "each",
|
|
61
|
-
refusal: (_subject, key) => `a run is missing "${key}:": command and exit are mandatory`
|
|
62
|
-
}, {
|
|
63
|
-
keys: ["waitFor"],
|
|
64
|
-
law: "apart",
|
|
65
|
-
refusal: () => "waitFor: and stdin: cannot share a run: the pattern is watched on a process nobody closed the input of",
|
|
66
|
-
with: "stdin"
|
|
67
|
-
}]
|
|
68
|
-
};
|
|
69
|
-
var SpecSyntaxError = class extends Error {
|
|
70
|
-
line;
|
|
71
|
-
reason;
|
|
72
|
-
constructor(fileName, line, message) {
|
|
73
|
-
super(`${fileName}:${line}: ${message}`);
|
|
74
|
-
this.line = line;
|
|
75
|
-
this.reason = message;
|
|
76
|
-
this.name = "SpecSyntaxError";
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
//#endregion
|
|
80
18
|
//#region lint/kit/project/spec-node.ts
|
|
81
19
|
function fail(context, node, message) {
|
|
82
20
|
throw new SpecSyntaxError(context.fileName, lineOf(context, node), message);
|
|
@@ -360,6 +298,6 @@ function parseSpecDocument(content, fileName) {
|
|
|
360
298
|
return readSpecFile(content, fileName).document;
|
|
361
299
|
}
|
|
362
300
|
//#endregion
|
|
363
|
-
export { scalarString as a,
|
|
301
|
+
export { scalarString as a, readSpecFile as i, documentPaths as n, dedent as o, parseSpecDocument as r, assertedStreams as t };
|
|
364
302
|
|
|
365
303
|
//# sourceMappingURL=shared-spec-document.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//#region lint/kit/project/relative-path.ts
|
|
2
|
+
function isRelativePath(value) {
|
|
3
|
+
return value.startsWith("./") || value.startsWith("../");
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region lint/kit/project/spec-grammar.ts
|
|
7
|
+
const SPEC_EXTENSION = ".spec.yaml";
|
|
8
|
+
const DOCUMENT_KEYS = [
|
|
9
|
+
"description",
|
|
10
|
+
"fixture",
|
|
11
|
+
"env",
|
|
12
|
+
"serve",
|
|
13
|
+
"runs"
|
|
14
|
+
];
|
|
15
|
+
const RUN_KEYS = [
|
|
16
|
+
"command",
|
|
17
|
+
"stdin",
|
|
18
|
+
"timeout",
|
|
19
|
+
"waitFor",
|
|
20
|
+
"exit",
|
|
21
|
+
"stdout",
|
|
22
|
+
"stderr",
|
|
23
|
+
"files"
|
|
24
|
+
];
|
|
25
|
+
const FILE_CONTENT_KEYS = ["contains", "equals"];
|
|
26
|
+
const FILE_STATES = ["absent", "exists"];
|
|
27
|
+
const PRESENCE = {
|
|
28
|
+
document: [{
|
|
29
|
+
keys: ["description"],
|
|
30
|
+
law: "each",
|
|
31
|
+
refusal: () => "missing \"description:\": every document is one test, and this is its title"
|
|
32
|
+
}, {
|
|
33
|
+
keys: ["runs"],
|
|
34
|
+
law: "each",
|
|
35
|
+
refusal: () => "missing \"runs:\": description and runs are mandatory"
|
|
36
|
+
}],
|
|
37
|
+
files: [{
|
|
38
|
+
keys: FILE_CONTENT_KEYS,
|
|
39
|
+
law: "some",
|
|
40
|
+
refusal: (path) => `files: ${path} asserts nothing: give it contains: or equals:`
|
|
41
|
+
}],
|
|
42
|
+
run: [{
|
|
43
|
+
keys: ["command", "exit"],
|
|
44
|
+
law: "each",
|
|
45
|
+
refusal: (_subject, key) => `a run is missing "${key}:": command and exit are mandatory`
|
|
46
|
+
}, {
|
|
47
|
+
keys: ["waitFor"],
|
|
48
|
+
law: "apart",
|
|
49
|
+
refusal: () => "waitFor: and stdin: cannot share a run: the pattern is watched on a process nobody closed the input of",
|
|
50
|
+
with: "stdin"
|
|
51
|
+
}]
|
|
52
|
+
};
|
|
53
|
+
var SpecSyntaxError = class extends Error {
|
|
54
|
+
line;
|
|
55
|
+
reason;
|
|
56
|
+
constructor(fileName, line, message) {
|
|
57
|
+
super(`${fileName}:${line}: ${message}`);
|
|
58
|
+
this.line = line;
|
|
59
|
+
this.reason = message;
|
|
60
|
+
this.name = "SpecSyntaxError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { RUN_KEYS as a, isRelativePath as c, PRESENCE as i, FILE_CONTENT_KEYS as n, SPEC_EXTENSION as o, FILE_STATES as r, SpecSyntaxError as s, DOCUMENT_KEYS as t };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=shared-spec-grammar.js.map
|