@opice/harness 0.6.0 → 0.7.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/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/reporter.d.ts +21 -1
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +34 -6
- package/dist/reporter.js.map +1 -1
- package/dist/scenario.d.ts +36 -4
- package/dist/scenario.d.ts.map +1 -1
- package/dist/scenario.js +88 -5
- package/dist/scenario.js.map +1 -1
- package/dist/tier.d.ts +44 -0
- package/dist/tier.d.ts.map +1 -0
- package/dist/tier.js +38 -0
- package/dist/tier.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +12 -1
- package/src/reporter.ts +56 -6
- package/src/scenario.ts +123 -9
- package/src/tier.ts +67 -0
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,10 @@ export { back, currentPath, currentUrl, forward, open, reload } from './navigati
|
|
|
4
4
|
export { getPage, getContext } from './context.js';
|
|
5
5
|
export { browserTest, DEFAULT_WALKTHROUGH_TIMEOUT_MS, invariant, step } from './scenario.js';
|
|
6
6
|
export type { BrowserTestMeta, StepContract } from './scenario.js';
|
|
7
|
+
export { DEFAULT_SCENARIO_TIER, DEFAULT_SELECTED_TIER, isTierSkipped, normalizeTier, parseSelectedTier, resolveSelectedTier, TIER_ORDER, } from './tier.js';
|
|
8
|
+
export type { SelectedTier, Tier } from './tier.js';
|
|
7
9
|
export { getReporter, setReporter, configureFromEnv } from './reporter.js';
|
|
8
|
-
export type { Reporter, ReporterConfig, StepEvent, ScenarioStart, ScenarioFinish } from './reporter.js';
|
|
10
|
+
export type { Reporter, ReporterConfig, StepEvent, ScenarioStart, ScenarioSkip, ScenarioFinish } from './reporter.js';
|
|
9
11
|
export { parseOpiceDsn } from './dsn.js';
|
|
10
12
|
export type { OpiceDsn } from './dsn.js';
|
|
11
13
|
export { command, call, runCommand, makeCtx, loadUserCommands, findUserCommandsFile, z } from './command.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEzD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAC5F,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAElE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC1E,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEzD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAC5F,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAElE,OAAO,EACN,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,GACV,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC1E,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAErH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAC5G,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEvD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAI9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAGzC,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { byLabel, byRole, byText } from './accessible.js';
|
|
|
3
3
|
export { back, currentPath, currentUrl, forward, open, reload } from './navigation.js';
|
|
4
4
|
export { getPage, getContext } from './context.js';
|
|
5
5
|
export { browserTest, DEFAULT_WALKTHROUGH_TIMEOUT_MS, invariant, step } from './scenario.js';
|
|
6
|
+
export { DEFAULT_SCENARIO_TIER, DEFAULT_SELECTED_TIER, isTierSkipped, normalizeTier, parseSelectedTier, resolveSelectedTier, TIER_ORDER, } from './tier.js';
|
|
6
7
|
export { getReporter, setReporter, configureFromEnv } from './reporter.js';
|
|
7
8
|
export { parseOpiceDsn } from './dsn.js';
|
|
8
9
|
export { command, call, runCommand, makeCtx, loadUserCommands, findUserCommandsFile, z } from './command.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEzD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAG5F,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAG1E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAG5G,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAG7D,iFAAiF;AACjF,uEAAuE;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEzD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAG5F,OAAO,EACN,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,GACV,MAAM,WAAW,CAAA;AAGlB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAG1E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAG5G,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAG7D,iFAAiF;AACjF,uEAAuE;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/reporter.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* The CLI handles end-of-run finalization: the reporter writes a
|
|
9
9
|
* handoff file under $TMPDIR with the runId and credentials, the
|
|
10
10
|
* `opice test` wrapper picks it up after `bun test` exits and POSTs
|
|
11
|
-
* /api/v1
|
|
11
|
+
* /api/v1/<slug>/runs/<id>/finish so the dashboard sees the run as completed.
|
|
12
12
|
*
|
|
13
13
|
* When env vars aren't configured, the reporter falls back to a no-op so
|
|
14
14
|
* harness behavior matches the bindx prototype.
|
|
@@ -21,6 +21,12 @@ export interface ReporterConfig {
|
|
|
21
21
|
commit?: string;
|
|
22
22
|
/** 'ci' for runs from automation, 'local' for opted-in dev runs. */
|
|
23
23
|
source?: 'ci' | 'local';
|
|
24
|
+
/**
|
|
25
|
+
* The tier this run SELECTED (from `OPICE_TIER`) — recorded on the run so the
|
|
26
|
+
* dashboard can explain why scenarios were skipped. Omitted when no tier
|
|
27
|
+
* filter was set (the run ran everything).
|
|
28
|
+
*/
|
|
29
|
+
tier?: string;
|
|
24
30
|
}
|
|
25
31
|
export interface StepEvent {
|
|
26
32
|
scenarioId: string;
|
|
@@ -72,6 +78,16 @@ export interface ScenarioStart {
|
|
|
72
78
|
seeds?: string[];
|
|
73
79
|
/** Identities / roles the scenario acts as. */
|
|
74
80
|
roles?: string[];
|
|
81
|
+
/** Declared tier (critical | standard | extended) — when it runs. */
|
|
82
|
+
tier?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A scenario the tier filter excluded from this run — registered for the record
|
|
86
|
+
* but never executed. Reported `skipped`, carrying a `reason` (which tier it
|
|
87
|
+
* declared vs the selected one) so the dashboard can explain the absence.
|
|
88
|
+
*/
|
|
89
|
+
export interface ScenarioSkip extends ScenarioStart {
|
|
90
|
+
reason?: string;
|
|
75
91
|
}
|
|
76
92
|
export interface ScenarioFinish {
|
|
77
93
|
scenarioId: string;
|
|
@@ -85,6 +101,8 @@ export interface ScenarioFinish {
|
|
|
85
101
|
}
|
|
86
102
|
export interface Reporter {
|
|
87
103
|
startScenario(input: ScenarioStart): Promise<string>;
|
|
104
|
+
/** Record a scenario the tier filter skipped (created already-finished as `skipped`). */
|
|
105
|
+
skipScenario(input: ScenarioSkip): Promise<void>;
|
|
88
106
|
recordStep(event: StepEvent): Promise<void>;
|
|
89
107
|
finishScenario(input: ScenarioFinish): Promise<void>;
|
|
90
108
|
flush(): Promise<void>;
|
|
@@ -92,6 +110,8 @@ export interface Reporter {
|
|
|
92
110
|
export declare const HANDOFF_DIR: string;
|
|
93
111
|
export interface RunHandoff {
|
|
94
112
|
endpoint: string;
|
|
113
|
+
/** Project slug — the CLI builds /api/v1/<project>/runs/<id>/finish from it. */
|
|
114
|
+
project: string;
|
|
95
115
|
apiKey: string;
|
|
96
116
|
runId: string;
|
|
97
117
|
}
|
package/dist/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAcH,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,IAAI,GAAG,OAAO,CAAA;IACvB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;OAKG;IACH,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,CAAA;IAC/D,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAa,SAAQ,aAAa;IAClD,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACxB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACpD,yFAAyF;IACzF,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAYD,eAAO,MAAM,WAAW,QAAwC,CAAA;AAMhE,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACb;AA8LD,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAEpD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,QAAQ,CAiC/E"}
|
package/dist/reporter.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* The CLI handles end-of-run finalization: the reporter writes a
|
|
9
9
|
* handoff file under $TMPDIR with the runId and credentials, the
|
|
10
10
|
* `opice test` wrapper picks it up after `bun test` exits and POSTs
|
|
11
|
-
* /api/v1
|
|
11
|
+
* /api/v1/<slug>/runs/<id>/finish so the dashboard sees the run as completed.
|
|
12
12
|
*
|
|
13
13
|
* When env vars aren't configured, the reporter falls back to a no-op so
|
|
14
14
|
* harness behavior matches the bindx prototype.
|
|
@@ -18,6 +18,7 @@ import { mkdirSync, writeFileSync } from 'node:fs';
|
|
|
18
18
|
import { tmpdir } from 'node:os';
|
|
19
19
|
import path from 'node:path';
|
|
20
20
|
import { parseOpiceDsn } from './dsn.js';
|
|
21
|
+
import { resolveSelectedTier } from './tier.js';
|
|
21
22
|
/** Per-request cap, so a hung connection can't stall a scenario's afterAll. */
|
|
22
23
|
const REQUEST_TIMEOUT_MS = 10_000;
|
|
23
24
|
/** Total cap on `flush()` waiting for pending step uploads (afterAll-bounded). */
|
|
@@ -26,6 +27,7 @@ class NoopReporter {
|
|
|
26
27
|
async startScenario(input) {
|
|
27
28
|
return `noop-${input.name}-${Date.now()}`;
|
|
28
29
|
}
|
|
30
|
+
async skipScenario(_input) { }
|
|
29
31
|
async recordStep(_event) { }
|
|
30
32
|
async finishScenario(_input) { }
|
|
31
33
|
async flush() { }
|
|
@@ -49,17 +51,23 @@ class HttpReporter {
|
|
|
49
51
|
return this.runIdPromise;
|
|
50
52
|
}
|
|
51
53
|
async startRun() {
|
|
52
|
-
const response = await this.fetch('POST',
|
|
54
|
+
const response = await this.fetch('POST', `/api/v1/${this.config.projectId}/runs`, {
|
|
53
55
|
branch: this.config.branch,
|
|
54
56
|
commit: this.config.commit,
|
|
55
57
|
source: this.config.source,
|
|
58
|
+
tier: this.config.tier,
|
|
56
59
|
});
|
|
57
60
|
const runId = response['runId'];
|
|
58
61
|
// Synchronous write so the CLI can pick this up even if the test
|
|
59
62
|
// process exits abruptly (process.on('exit') runs sync).
|
|
60
63
|
try {
|
|
61
64
|
mkdirSync(HANDOFF_DIR, { recursive: true });
|
|
62
|
-
const handoff = {
|
|
65
|
+
const handoff = {
|
|
66
|
+
endpoint: this.config.endpoint,
|
|
67
|
+
project: this.config.projectId,
|
|
68
|
+
apiKey: this.config.apiKey,
|
|
69
|
+
runId,
|
|
70
|
+
};
|
|
63
71
|
writeFileSync(handoffPath(), JSON.stringify(handoff), 'utf-8');
|
|
64
72
|
}
|
|
65
73
|
catch {
|
|
@@ -69,16 +77,33 @@ class HttpReporter {
|
|
|
69
77
|
}
|
|
70
78
|
async startScenario(input) {
|
|
71
79
|
const runId = await this.ensureRun();
|
|
72
|
-
const response = await this.fetch('POST', `/api/v1/runs/${runId}/scenarios`, {
|
|
80
|
+
const response = await this.fetch('POST', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios`, {
|
|
73
81
|
name: input.name,
|
|
74
82
|
hash: input.hash,
|
|
75
83
|
testFile: input.testFile,
|
|
76
84
|
feature: input.feature,
|
|
77
85
|
seeds: input.seeds,
|
|
78
86
|
roles: input.roles,
|
|
87
|
+
tier: input.tier,
|
|
79
88
|
});
|
|
80
89
|
return response['scenarioId'];
|
|
81
90
|
}
|
|
91
|
+
async skipScenario(input) {
|
|
92
|
+
const runId = await this.ensureRun();
|
|
93
|
+
// A skipped scenario is created already-finished on the platform — no
|
|
94
|
+
// steps follow, so we don't keep the returned id.
|
|
95
|
+
await this.fetch('POST', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios`, {
|
|
96
|
+
name: input.name,
|
|
97
|
+
hash: input.hash,
|
|
98
|
+
testFile: input.testFile,
|
|
99
|
+
feature: input.feature,
|
|
100
|
+
seeds: input.seeds,
|
|
101
|
+
roles: input.roles,
|
|
102
|
+
tier: input.tier,
|
|
103
|
+
skipped: true,
|
|
104
|
+
reason: input.reason,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
82
107
|
recordStep(event) {
|
|
83
108
|
// Track synchronously so flush() awaits the entire pipeline (including
|
|
84
109
|
// encodeScreenshot's fs.readFile and the upload), not just whatever
|
|
@@ -92,7 +117,7 @@ class HttpReporter {
|
|
|
92
117
|
const screenshot = event.screenshotPath
|
|
93
118
|
? await this.encodeScreenshot(event.screenshotPath)
|
|
94
119
|
: undefined;
|
|
95
|
-
await this.fetch('POST', `/api/v1/runs/${runId}/scenarios/${event.scenarioId}/steps`, {
|
|
120
|
+
await this.fetch('POST', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios/${event.scenarioId}/steps`, {
|
|
96
121
|
attempt: event.attempt,
|
|
97
122
|
sequence: event.sequence,
|
|
98
123
|
kind: event.kind,
|
|
@@ -110,7 +135,7 @@ class HttpReporter {
|
|
|
110
135
|
const runId = await this.ensureRun();
|
|
111
136
|
// Awaited inline so the scenario status is committed before the
|
|
112
137
|
// bun:test afterAll returns.
|
|
113
|
-
await this.fetch('PATCH', `/api/v1/runs/${runId}/scenarios/${input.scenarioId}`, {
|
|
138
|
+
await this.fetch('PATCH', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios/${input.scenarioId}`, {
|
|
114
139
|
status: input.status,
|
|
115
140
|
durationMs: input.durationMs,
|
|
116
141
|
attempts: input.attempts,
|
|
@@ -222,6 +247,9 @@ export function configureFromEnv(env = process.env) {
|
|
|
222
247
|
branch: env['OPICE_BRANCH'] ?? env['GITHUB_REF_NAME'],
|
|
223
248
|
commit: env['OPICE_COMMIT'] ?? env['GITHUB_SHA'],
|
|
224
249
|
source: isCI ? 'ci' : 'local',
|
|
250
|
+
// Record the selected tier only when one was explicitly requested — a run
|
|
251
|
+
// with no OPICE_TIER ran everything and carries no tier filter.
|
|
252
|
+
tier: env['OPICE_TIER'] ? resolveSelectedTier(env) : undefined,
|
|
225
253
|
});
|
|
226
254
|
setReporter(reporter);
|
|
227
255
|
return reporter;
|
package/dist/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
package/dist/scenario.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Tier } from './tier.js';
|
|
1
2
|
/**
|
|
2
3
|
* Scenario metadata — the **first** argument to `browserTest`.
|
|
3
4
|
*
|
|
@@ -23,6 +24,18 @@ export interface BrowserTestMeta {
|
|
|
23
24
|
hash?: string;
|
|
24
25
|
/** Feature / requirement id this scenario covers (e.g. `'F-SML-03a'`). */
|
|
25
26
|
feature?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Test tier — *when* this scenario runs (critical < standard < extended).
|
|
29
|
+
* A run selects a tier via `OPICE_TIER` / `opice test --tier`; selection is a
|
|
30
|
+
* threshold (running `standard` runs critical + standard). A scenario above
|
|
31
|
+
* the selected tier is **skipped**: reported as `skipped` (so it still shows
|
|
32
|
+
* on the dashboard) but never opens a browser. Defaults to `standard`.
|
|
33
|
+
*
|
|
34
|
+
* critical — the must-pass core, every push
|
|
35
|
+
* standard — the normal suite (default), PRs / merges
|
|
36
|
+
* extended — slow / edge / expensive, nightly or on demand
|
|
37
|
+
*/
|
|
38
|
+
tier?: Tier;
|
|
26
39
|
/**
|
|
27
40
|
* Seeds that must be loaded for this scenario to run — machine-checkable
|
|
28
41
|
* preconditions, not prose. e.g. `['initial-data', 'crm-master-data']`.
|
|
@@ -129,7 +142,16 @@ interface StepFn {
|
|
|
129
142
|
(name: string, contract: StepContract, fn: StepBody): Promise<void>;
|
|
130
143
|
}
|
|
131
144
|
interface StepExtras {
|
|
132
|
-
fixme:
|
|
145
|
+
fixme: {
|
|
146
|
+
/** Tolerated failure with just a body. */
|
|
147
|
+
(name: string, reason: string, fn: StepBody): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* Tolerated failure that also keeps a durable contract — pass
|
|
150
|
+
* `{ intent, manual }` before the body so the spec rationale and the
|
|
151
|
+
* end-user manual line survive on a `.fixme` step too.
|
|
152
|
+
*/
|
|
153
|
+
(name: string, reason: string, contract: StepContract, fn: StepBody): Promise<void>;
|
|
154
|
+
};
|
|
133
155
|
/**
|
|
134
156
|
* A **blocked** pending stub: the step can't be authored yet because the app
|
|
135
157
|
* feature it covers isn't implemented. Reports as 'pending' with the reason
|
|
@@ -160,6 +182,8 @@ interface StepExtras {
|
|
|
160
182
|
* step unexpectedly *passes*, it's flagged too ('fixmepass') so a stale marker
|
|
161
183
|
* doesn't linger. Unlike Playwright's `test.fixme()`, which **skips** the test,
|
|
162
184
|
* `step.fixme` **runs** it — the mandatory reason is there to keep them apart.
|
|
185
|
+
* Pass a contract before the body — `step.fixme(name, reason, { intent, manual },
|
|
186
|
+
* fn)` — to keep the durable `intent` / end-user `manual` on a tolerated step.
|
|
163
187
|
*
|
|
164
188
|
* `step.blocked(name, reason, contract?)` is a pending stub that **can't be
|
|
165
189
|
* authored yet** because the app feature doesn't exist — distinct from a plain
|
|
@@ -177,7 +201,9 @@ export declare const step: StepFn & StepExtras;
|
|
|
177
201
|
* A failing `invariant` fails the scenario like any hard assertion — it's an
|
|
178
202
|
* acceptance, not a nicety.
|
|
179
203
|
*
|
|
180
|
-
* - `invariant(name, fn)` — enforced now.
|
|
204
|
+
* - `invariant(name, fn)` — enforced now. Pass a contract first —
|
|
205
|
+
* `invariant(name, { intent, manual }, fn)` — to attach the durable `intent`
|
|
206
|
+
* and the end-user `manual` line to the acceptance, exactly like a `step`.
|
|
181
207
|
* - `invariant.todo(name, hint?)` — phase-1 stub: states the acceptance but
|
|
182
208
|
* isn't wired yet (status: pending). `opice-author` promotes it to an
|
|
183
209
|
* enforced `invariant(...)` (or an `invariant.fixme(...)` if it can't hold
|
|
@@ -188,13 +214,19 @@ export declare const step: StepFn & StepExtras;
|
|
|
188
214
|
* - `invariant.fixme(name, reason, fn)` — a known-unenforceable acceptance,
|
|
189
215
|
* tolerated like `step.fixme` (e.g. a security property deferred to a
|
|
190
216
|
* ticket). The body runs and is expected to fail; the failure is reported as
|
|
191
|
-
* an amber warning and neither fails the scenario nor the run.
|
|
217
|
+
* an amber warning and neither fails the scenario nor the run. Also accepts a
|
|
218
|
+
* contract before the body: `invariant.fixme(name, reason, { intent, manual },
|
|
219
|
+
* fn)`.
|
|
192
220
|
*/
|
|
193
221
|
export declare const invariant: {
|
|
194
222
|
(name: string, fn: StepBody): Promise<void>;
|
|
223
|
+
(name: string, contract: StepContract, fn: StepBody): Promise<void>;
|
|
195
224
|
todo: (name: string, hint?: string) => Promise<void>;
|
|
196
225
|
blocked: (name: string, reason: string) => Promise<void>;
|
|
197
|
-
fixme:
|
|
226
|
+
fixme: {
|
|
227
|
+
(name: string, reason: string, fn: StepBody): Promise<void>;
|
|
228
|
+
(name: string, reason: string, contract: StepContract, fn: StepBody): Promise<void>;
|
|
229
|
+
};
|
|
198
230
|
};
|
|
199
231
|
export {};
|
|
200
232
|
//# sourceMappingURL=scenario.d.ts.map
|
package/dist/scenario.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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"}
|
package/dist/scenario.js
CHANGED
|
@@ -4,6 +4,7 @@ import { closePage, getContext, launchPage } from './context.js';
|
|
|
4
4
|
import { screenshot } from './element.js';
|
|
5
5
|
import { getReporter } from './reporter.js';
|
|
6
6
|
import { loadUserSetup } from './setup.js';
|
|
7
|
+
import { isTierSkipped, normalizeTier, parseSelectedTier, TIER_ORDER } from './tier.js';
|
|
7
8
|
/**
|
|
8
9
|
* `bun:test` is resolved lazily, at the moment `browserTest` registers a
|
|
9
10
|
* scenario — never at module load. That keeps `@opice/harness` importable
|
|
@@ -46,6 +47,36 @@ function captureTestFile() {
|
|
|
46
47
|
}
|
|
47
48
|
return undefined;
|
|
48
49
|
}
|
|
50
|
+
// The tier this run selected (OPICE_TIER), resolved + cached once. An
|
|
51
|
+
// unrecognized value warns once and falls back to running everything.
|
|
52
|
+
let cachedSelectedTier;
|
|
53
|
+
function getSelectedTier() {
|
|
54
|
+
if (cachedSelectedTier === undefined) {
|
|
55
|
+
const parsed = parseSelectedTier();
|
|
56
|
+
if (!parsed.recognized) {
|
|
57
|
+
console.warn(`[opice] unknown OPICE_TIER="${process.env['OPICE_TIER']}" — running all tiers `
|
|
58
|
+
+ `(use one of: ${TIER_ORDER.join(', ')}).`);
|
|
59
|
+
}
|
|
60
|
+
cachedSelectedTier = parsed.tier;
|
|
61
|
+
}
|
|
62
|
+
return cachedSelectedTier;
|
|
63
|
+
}
|
|
64
|
+
// Names of scenarios skipped by the tier filter, summarized once at process
|
|
65
|
+
// exit so a tiered run prints "N skipped" instead of a line per scenario.
|
|
66
|
+
const skippedScenarioNames = [];
|
|
67
|
+
let skipSummaryHooked = false;
|
|
68
|
+
function noteSkipped(name) {
|
|
69
|
+
skippedScenarioNames.push(name);
|
|
70
|
+
if (skipSummaryHooked)
|
|
71
|
+
return;
|
|
72
|
+
skipSummaryHooked = true;
|
|
73
|
+
process.on('exit', () => {
|
|
74
|
+
if (skippedScenarioNames.length === 0)
|
|
75
|
+
return;
|
|
76
|
+
console.warn(`[opice] ${skippedScenarioNames.length} scenario(s) skipped — above the selected `
|
|
77
|
+
+ `tier '${getSelectedTier()}' (OPICE_TIER).`);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
49
80
|
let currentScenarioId = null;
|
|
50
81
|
let currentScenarioStart = 0;
|
|
51
82
|
let currentScenarioFailures = 0;
|
|
@@ -100,6 +131,13 @@ export function browserTest(meta, fn) {
|
|
|
100
131
|
// An async fn is the walkthrough body (browserTest owns its test()); a sync
|
|
101
132
|
// fn is the legacy registrar (it registers its own test()/hooks).
|
|
102
133
|
const isBody = fn.constructor.name === 'AsyncFunction';
|
|
134
|
+
// Tier gate: a scenario above the selected tier is registered but not run —
|
|
135
|
+
// reported `skipped` so the dashboard shows the full inventory.
|
|
136
|
+
const scenarioTier = normalizeTier(meta.tier);
|
|
137
|
+
if (isTierSkipped(scenarioTier, getSelectedTier())) {
|
|
138
|
+
registerSkipped(meta, scenarioTier, testFile, reporter);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
103
141
|
describe(meta.name, () => {
|
|
104
142
|
beforeAll(async () => {
|
|
105
143
|
currentScenarioStart = Date.now();
|
|
@@ -115,6 +153,7 @@ export function browserTest(meta, fn) {
|
|
|
115
153
|
feature: meta.feature,
|
|
116
154
|
seeds: meta.seeds,
|
|
117
155
|
roles: meta.roles,
|
|
156
|
+
tier: scenarioTier,
|
|
118
157
|
});
|
|
119
158
|
}
|
|
120
159
|
catch {
|
|
@@ -225,6 +264,38 @@ export function browserTest(meta, fn) {
|
|
|
225
264
|
}
|
|
226
265
|
});
|
|
227
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Register a scenario the tier filter excluded. It's reported to the platform as
|
|
269
|
+
* `skipped` (so the dashboard shows it alongside what ran) but never opens a
|
|
270
|
+
* browser. The report runs in a real — instant, browser-free — `test`, not a
|
|
271
|
+
* `test.skip`: bun won't run a describe's hooks if every test in it is skipped,
|
|
272
|
+
* so a skip body is the only place left to POST from. With reporting off (local
|
|
273
|
+
* authoring), the body is a no-op against the NoopReporter.
|
|
274
|
+
*/
|
|
275
|
+
function registerSkipped(meta, tier, testFile, reporter) {
|
|
276
|
+
noteSkipped(meta.name);
|
|
277
|
+
const { describe, test } = bunTest();
|
|
278
|
+
const reason = `tier '${tier}' above the selected tier '${getSelectedTier()}'`;
|
|
279
|
+
describe(meta.name, () => {
|
|
280
|
+
test('skipped (tier)', async () => {
|
|
281
|
+
try {
|
|
282
|
+
await reporter.skipScenario({
|
|
283
|
+
name: meta.name,
|
|
284
|
+
hash: meta.hash,
|
|
285
|
+
testFile,
|
|
286
|
+
feature: meta.feature,
|
|
287
|
+
seeds: meta.seeds,
|
|
288
|
+
roles: meta.roles,
|
|
289
|
+
tier,
|
|
290
|
+
reason,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// Best-effort: reporting a skip must never fail the run.
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
228
299
|
/**
|
|
229
300
|
* Open a fresh isolated browser context + page for `meta` and navigate to its
|
|
230
301
|
* scenario URL. `launchPage()` closes any previous context first, so calling
|
|
@@ -376,6 +447,8 @@ async function runUnit(unit) {
|
|
|
376
447
|
* step unexpectedly *passes*, it's flagged too ('fixmepass') so a stale marker
|
|
377
448
|
* doesn't linger. Unlike Playwright's `test.fixme()`, which **skips** the test,
|
|
378
449
|
* `step.fixme` **runs** it — the mandatory reason is there to keep them apart.
|
|
450
|
+
* Pass a contract before the body — `step.fixme(name, reason, { intent, manual },
|
|
451
|
+
* fn)` — to keep the durable `intent` / end-user `manual` on a tolerated step.
|
|
379
452
|
*
|
|
380
453
|
* `step.blocked(name, reason, contract?)` is a pending stub that **can't be
|
|
381
454
|
* authored yet** because the app feature doesn't exist — distinct from a plain
|
|
@@ -388,7 +461,9 @@ export const step = Object.assign((name, arg2, arg3) => {
|
|
|
388
461
|
}
|
|
389
462
|
return runUnit({ kind: 'step', name, contract: arg2, fn: arg3 });
|
|
390
463
|
}, {
|
|
391
|
-
fixme: (name, reason,
|
|
464
|
+
fixme: (name, reason, arg3, arg4) => typeof arg3 === 'function'
|
|
465
|
+
? runUnit({ kind: 'step', name, reason, fn: arg3 })
|
|
466
|
+
: runUnit({ kind: 'step', name, reason, contract: arg3, fn: arg4 }),
|
|
392
467
|
blocked: (name, reason, contract) => runUnit({ kind: 'step', name, contract, reason }),
|
|
393
468
|
});
|
|
394
469
|
/**
|
|
@@ -401,7 +476,9 @@ export const step = Object.assign((name, arg2, arg3) => {
|
|
|
401
476
|
* A failing `invariant` fails the scenario like any hard assertion — it's an
|
|
402
477
|
* acceptance, not a nicety.
|
|
403
478
|
*
|
|
404
|
-
* - `invariant(name, fn)` — enforced now.
|
|
479
|
+
* - `invariant(name, fn)` — enforced now. Pass a contract first —
|
|
480
|
+
* `invariant(name, { intent, manual }, fn)` — to attach the durable `intent`
|
|
481
|
+
* and the end-user `manual` line to the acceptance, exactly like a `step`.
|
|
405
482
|
* - `invariant.todo(name, hint?)` — phase-1 stub: states the acceptance but
|
|
406
483
|
* isn't wired yet (status: pending). `opice-author` promotes it to an
|
|
407
484
|
* enforced `invariant(...)` (or an `invariant.fixme(...)` if it can't hold
|
|
@@ -412,11 +489,17 @@ export const step = Object.assign((name, arg2, arg3) => {
|
|
|
412
489
|
* - `invariant.fixme(name, reason, fn)` — a known-unenforceable acceptance,
|
|
413
490
|
* tolerated like `step.fixme` (e.g. a security property deferred to a
|
|
414
491
|
* ticket). The body runs and is expected to fail; the failure is reported as
|
|
415
|
-
* an amber warning and neither fails the scenario nor the run.
|
|
492
|
+
* an amber warning and neither fails the scenario nor the run. Also accepts a
|
|
493
|
+
* contract before the body: `invariant.fixme(name, reason, { intent, manual },
|
|
494
|
+
* fn)`.
|
|
416
495
|
*/
|
|
417
|
-
export const invariant = Object.assign((name,
|
|
496
|
+
export const invariant = Object.assign((name, arg2, arg3) => typeof arg2 === 'function'
|
|
497
|
+
? runUnit({ kind: 'invariant', name, fn: arg2 })
|
|
498
|
+
: runUnit({ kind: 'invariant', name, contract: arg2, fn: arg3 }), {
|
|
418
499
|
todo: (name, hint) => runUnit({ kind: 'invariant', name, contract: hint ? { hint } : undefined }),
|
|
419
500
|
blocked: (name, reason) => runUnit({ kind: 'invariant', name, reason }),
|
|
420
|
-
fixme: (name, reason,
|
|
501
|
+
fixme: (name, reason, arg3, arg4) => typeof arg3 === 'function'
|
|
502
|
+
? runUnit({ kind: 'invariant', name, reason, fn: arg3 })
|
|
503
|
+
: runUnit({ kind: 'invariant', name, reason, contract: arg3, fn: arg4 }),
|
|
421
504
|
});
|
|
422
505
|
//# sourceMappingURL=scenario.js.map
|
package/dist/scenario.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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"}
|
package/dist/tier.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test tiers — an ordered hierarchy for *when* a scenario runs.
|
|
3
|
+
*
|
|
4
|
+
* A scenario declares its tier in `browserTest` meta (default `standard`); a run
|
|
5
|
+
* selects a tier via `OPICE_TIER` (the `opice test --tier` flag). Selection is a
|
|
6
|
+
* THRESHOLD: running a tier runs every scenario AT OR BELOW it — the standard
|
|
7
|
+
* `smoke ⊂ regression ⊂ full` model. Scenarios above the selected tier are
|
|
8
|
+
* *skipped*: still registered and reported as `skipped` (so the dashboard shows
|
|
9
|
+
* the full inventory, not just what ran), but they never open a browser.
|
|
10
|
+
*
|
|
11
|
+
* critical — the must-pass core. Run on every push.
|
|
12
|
+
* standard — the normal suite (the default for an untagged scenario). PRs / merges.
|
|
13
|
+
* extended — slow / edge / expensive. Run nightly or on demand.
|
|
14
|
+
*
|
|
15
|
+
* OPICE_TIER=critical → critical only
|
|
16
|
+
* OPICE_TIER=standard → critical + standard
|
|
17
|
+
* OPICE_TIER=extended → everything (also the default when OPICE_TIER is unset)
|
|
18
|
+
*/
|
|
19
|
+
export type Tier = 'critical' | 'standard' | 'extended';
|
|
20
|
+
/** Tiers low → high. A scenario's index is its level; it runs when level <= selected level. */
|
|
21
|
+
export declare const TIER_ORDER: readonly Tier[];
|
|
22
|
+
/** A scenario with no declared tier sits in the middle `standard` tier. */
|
|
23
|
+
export declare const DEFAULT_SCENARIO_TIER: Tier;
|
|
24
|
+
/** With no `OPICE_TIER` set, run everything — select the widest tier. */
|
|
25
|
+
export declare const DEFAULT_SELECTED_TIER: Tier;
|
|
26
|
+
/** Normalize a scenario's declared tier, defaulting (and tolerating junk) to `standard`. */
|
|
27
|
+
export declare function normalizeTier(tier: string | undefined): Tier;
|
|
28
|
+
export interface SelectedTier {
|
|
29
|
+
tier: Tier;
|
|
30
|
+
/** false when `OPICE_TIER` held an unrecognized value (the caller may warn). */
|
|
31
|
+
recognized: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The tier selected for this run, parsed from `OPICE_TIER`. Unset → run
|
|
35
|
+
* everything. `all`/`full` are friendly aliases for the widest tier. An
|
|
36
|
+
* unrecognized value resolves to "run everything" (`recognized: false`) rather
|
|
37
|
+
* than silently dropping tests — better to over-run than to skip on a typo.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseSelectedTier(env?: NodeJS.ProcessEnv): SelectedTier;
|
|
40
|
+
/** Convenience: the resolved selected tier, ignoring whether the value was recognized. */
|
|
41
|
+
export declare function resolveSelectedTier(env?: NodeJS.ProcessEnv): Tier;
|
|
42
|
+
/** A scenario is skipped when its tier sits ABOVE the selected one. */
|
|
43
|
+
export declare function isTierSkipped(scenarioTier: Tier, selectedTier: Tier): boolean;
|
|
44
|
+
//# sourceMappingURL=tier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.d.ts","sourceRoot":"","sources":["../src/tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAEvD,+FAA+F;AAC/F,eAAO,MAAM,UAAU,EAAE,SAAS,IAAI,EAAyC,CAAA;AAE/E,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,EAAE,IAAiB,CAAA;AAErD,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,EAAE,IAAiB,CAAA;AAMrD,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE5D;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,IAAI,CAAA;IACV,gFAAgF;IAChF,UAAU,EAAE,OAAO,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,CAMpF;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI,CAE9E;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,GAAG,OAAO,CAE7E"}
|
package/dist/tier.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Tiers low → high. A scenario's index is its level; it runs when level <= selected level. */
|
|
2
|
+
export const TIER_ORDER = ['critical', 'standard', 'extended'];
|
|
3
|
+
/** A scenario with no declared tier sits in the middle `standard` tier. */
|
|
4
|
+
export const DEFAULT_SCENARIO_TIER = 'standard';
|
|
5
|
+
/** With no `OPICE_TIER` set, run everything — select the widest tier. */
|
|
6
|
+
export const DEFAULT_SELECTED_TIER = 'extended';
|
|
7
|
+
function isTier(value) {
|
|
8
|
+
return value === 'critical' || value === 'standard' || value === 'extended';
|
|
9
|
+
}
|
|
10
|
+
/** Normalize a scenario's declared tier, defaulting (and tolerating junk) to `standard`. */
|
|
11
|
+
export function normalizeTier(tier) {
|
|
12
|
+
return isTier(tier) ? tier : DEFAULT_SCENARIO_TIER;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The tier selected for this run, parsed from `OPICE_TIER`. Unset → run
|
|
16
|
+
* everything. `all`/`full` are friendly aliases for the widest tier. An
|
|
17
|
+
* unrecognized value resolves to "run everything" (`recognized: false`) rather
|
|
18
|
+
* than silently dropping tests — better to over-run than to skip on a typo.
|
|
19
|
+
*/
|
|
20
|
+
export function parseSelectedTier(env = process.env) {
|
|
21
|
+
const raw = env['OPICE_TIER']?.trim().toLowerCase();
|
|
22
|
+
if (!raw)
|
|
23
|
+
return { tier: DEFAULT_SELECTED_TIER, recognized: true };
|
|
24
|
+
if (isTier(raw))
|
|
25
|
+
return { tier: raw, recognized: true };
|
|
26
|
+
if (raw === 'all' || raw === 'full')
|
|
27
|
+
return { tier: 'extended', recognized: true };
|
|
28
|
+
return { tier: DEFAULT_SELECTED_TIER, recognized: false };
|
|
29
|
+
}
|
|
30
|
+
/** Convenience: the resolved selected tier, ignoring whether the value was recognized. */
|
|
31
|
+
export function resolveSelectedTier(env = process.env) {
|
|
32
|
+
return parseSelectedTier(env).tier;
|
|
33
|
+
}
|
|
34
|
+
/** A scenario is skipped when its tier sits ABOVE the selected one. */
|
|
35
|
+
export function isTierSkipped(scenarioTier, selectedTier) {
|
|
36
|
+
return TIER_ORDER.indexOf(scenarioTier) > TIER_ORDER.indexOf(selectedTier);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=tier.js.map
|
package/dist/tier.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.js","sourceRoot":"","sources":["../src/tier.ts"],"names":[],"mappings":"AAoBA,+FAA+F;AAC/F,MAAM,CAAC,MAAM,UAAU,GAAoB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,CAAA;AAE/E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,qBAAqB,GAAS,UAAU,CAAA;AAErD,yEAAyE;AACzE,MAAM,CAAC,MAAM,qBAAqB,GAAS,UAAU,CAAA;AAErD,SAAS,MAAM,CAAC,KAAyB;IACxC,OAAO,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,CAAA;AAC5E,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,aAAa,CAAC,IAAwB;IACrD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAA;AACnD,CAAC;AAQD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrE,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACnD,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;IAClE,IAAI,MAAM,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;IACvD,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;IAClF,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;AAC1D,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACvE,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAI,CAAA;AACnC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAC,YAAkB,EAAE,YAAkB;IACnE,OAAO,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;AAC3E,CAAC"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -9,8 +9,19 @@ export { getPage, getContext } from './context.js'
|
|
|
9
9
|
export { browserTest, DEFAULT_WALKTHROUGH_TIMEOUT_MS, invariant, step } from './scenario.js'
|
|
10
10
|
export type { BrowserTestMeta, StepContract } from './scenario.js'
|
|
11
11
|
|
|
12
|
+
export {
|
|
13
|
+
DEFAULT_SCENARIO_TIER,
|
|
14
|
+
DEFAULT_SELECTED_TIER,
|
|
15
|
+
isTierSkipped,
|
|
16
|
+
normalizeTier,
|
|
17
|
+
parseSelectedTier,
|
|
18
|
+
resolveSelectedTier,
|
|
19
|
+
TIER_ORDER,
|
|
20
|
+
} from './tier.js'
|
|
21
|
+
export type { SelectedTier, Tier } from './tier.js'
|
|
22
|
+
|
|
12
23
|
export { getReporter, setReporter, configureFromEnv } from './reporter.js'
|
|
13
|
-
export type { Reporter, ReporterConfig, StepEvent, ScenarioStart, ScenarioFinish } from './reporter.js'
|
|
24
|
+
export type { Reporter, ReporterConfig, StepEvent, ScenarioStart, ScenarioSkip, ScenarioFinish } from './reporter.js'
|
|
14
25
|
|
|
15
26
|
export { parseOpiceDsn } from './dsn.js'
|
|
16
27
|
export type { OpiceDsn } from './dsn.js'
|
package/src/reporter.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* The CLI handles end-of-run finalization: the reporter writes a
|
|
9
9
|
* handoff file under $TMPDIR with the runId and credentials, the
|
|
10
10
|
* `opice test` wrapper picks it up after `bun test` exits and POSTs
|
|
11
|
-
* /api/v1
|
|
11
|
+
* /api/v1/<slug>/runs/<id>/finish so the dashboard sees the run as completed.
|
|
12
12
|
*
|
|
13
13
|
* When env vars aren't configured, the reporter falls back to a no-op so
|
|
14
14
|
* harness behavior matches the bindx prototype.
|
|
@@ -19,6 +19,7 @@ import { mkdirSync, writeFileSync } from 'node:fs'
|
|
|
19
19
|
import { tmpdir } from 'node:os'
|
|
20
20
|
import path from 'node:path'
|
|
21
21
|
import { parseOpiceDsn } from './dsn.js'
|
|
22
|
+
import { resolveSelectedTier } from './tier.js'
|
|
22
23
|
|
|
23
24
|
/** Per-request cap, so a hung connection can't stall a scenario's afterAll. */
|
|
24
25
|
const REQUEST_TIMEOUT_MS = 10_000
|
|
@@ -33,6 +34,12 @@ export interface ReporterConfig {
|
|
|
33
34
|
commit?: string
|
|
34
35
|
/** 'ci' for runs from automation, 'local' for opted-in dev runs. */
|
|
35
36
|
source?: 'ci' | 'local'
|
|
37
|
+
/**
|
|
38
|
+
* The tier this run SELECTED (from `OPICE_TIER`) — recorded on the run so the
|
|
39
|
+
* dashboard can explain why scenarios were skipped. Omitted when no tier
|
|
40
|
+
* filter was set (the run ran everything).
|
|
41
|
+
*/
|
|
42
|
+
tier?: string
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
export interface StepEvent {
|
|
@@ -86,6 +93,17 @@ export interface ScenarioStart {
|
|
|
86
93
|
seeds?: string[]
|
|
87
94
|
/** Identities / roles the scenario acts as. */
|
|
88
95
|
roles?: string[]
|
|
96
|
+
/** Declared tier (critical | standard | extended) — when it runs. */
|
|
97
|
+
tier?: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A scenario the tier filter excluded from this run — registered for the record
|
|
102
|
+
* but never executed. Reported `skipped`, carrying a `reason` (which tier it
|
|
103
|
+
* declared vs the selected one) so the dashboard can explain the absence.
|
|
104
|
+
*/
|
|
105
|
+
export interface ScenarioSkip extends ScenarioStart {
|
|
106
|
+
reason?: string
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
export interface ScenarioFinish {
|
|
@@ -101,6 +119,8 @@ export interface ScenarioFinish {
|
|
|
101
119
|
|
|
102
120
|
export interface Reporter {
|
|
103
121
|
startScenario(input: ScenarioStart): Promise<string>
|
|
122
|
+
/** Record a scenario the tier filter skipped (created already-finished as `skipped`). */
|
|
123
|
+
skipScenario(input: ScenarioSkip): Promise<void>
|
|
104
124
|
recordStep(event: StepEvent): Promise<void>
|
|
105
125
|
finishScenario(input: ScenarioFinish): Promise<void>
|
|
106
126
|
flush(): Promise<void>
|
|
@@ -110,6 +130,7 @@ class NoopReporter implements Reporter {
|
|
|
110
130
|
async startScenario(input: ScenarioStart): Promise<string> {
|
|
111
131
|
return `noop-${input.name}-${Date.now()}`
|
|
112
132
|
}
|
|
133
|
+
async skipScenario(_input: ScenarioSkip): Promise<void> {}
|
|
113
134
|
async recordStep(_event: StepEvent): Promise<void> {}
|
|
114
135
|
async finishScenario(_input: ScenarioFinish): Promise<void> {}
|
|
115
136
|
async flush(): Promise<void> {}
|
|
@@ -123,6 +144,8 @@ function handoffPath(pid = process.pid): string {
|
|
|
123
144
|
|
|
124
145
|
export interface RunHandoff {
|
|
125
146
|
endpoint: string
|
|
147
|
+
/** Project slug — the CLI builds /api/v1/<project>/runs/<id>/finish from it. */
|
|
148
|
+
project: string
|
|
126
149
|
apiKey: string
|
|
127
150
|
runId: string
|
|
128
151
|
}
|
|
@@ -142,17 +165,23 @@ class HttpReporter implements Reporter {
|
|
|
142
165
|
}
|
|
143
166
|
|
|
144
167
|
private async startRun(): Promise<string> {
|
|
145
|
-
const response = await this.fetch('POST',
|
|
168
|
+
const response = await this.fetch('POST', `/api/v1/${this.config.projectId}/runs`, {
|
|
146
169
|
branch: this.config.branch,
|
|
147
170
|
commit: this.config.commit,
|
|
148
171
|
source: this.config.source,
|
|
172
|
+
tier: this.config.tier,
|
|
149
173
|
})
|
|
150
174
|
const runId = response['runId'] as string
|
|
151
175
|
// Synchronous write so the CLI can pick this up even if the test
|
|
152
176
|
// process exits abruptly (process.on('exit') runs sync).
|
|
153
177
|
try {
|
|
154
178
|
mkdirSync(HANDOFF_DIR, { recursive: true })
|
|
155
|
-
const handoff: RunHandoff = {
|
|
179
|
+
const handoff: RunHandoff = {
|
|
180
|
+
endpoint: this.config.endpoint,
|
|
181
|
+
project: this.config.projectId,
|
|
182
|
+
apiKey: this.config.apiKey,
|
|
183
|
+
runId,
|
|
184
|
+
}
|
|
156
185
|
writeFileSync(handoffPath(), JSON.stringify(handoff), 'utf-8')
|
|
157
186
|
} catch {
|
|
158
187
|
// best-effort
|
|
@@ -162,17 +191,35 @@ class HttpReporter implements Reporter {
|
|
|
162
191
|
|
|
163
192
|
async startScenario(input: ScenarioStart): Promise<string> {
|
|
164
193
|
const runId = await this.ensureRun()
|
|
165
|
-
const response = await this.fetch('POST', `/api/v1/runs/${runId}/scenarios`, {
|
|
194
|
+
const response = await this.fetch('POST', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios`, {
|
|
166
195
|
name: input.name,
|
|
167
196
|
hash: input.hash,
|
|
168
197
|
testFile: input.testFile,
|
|
169
198
|
feature: input.feature,
|
|
170
199
|
seeds: input.seeds,
|
|
171
200
|
roles: input.roles,
|
|
201
|
+
tier: input.tier,
|
|
172
202
|
})
|
|
173
203
|
return response['scenarioId'] as string
|
|
174
204
|
}
|
|
175
205
|
|
|
206
|
+
async skipScenario(input: ScenarioSkip): Promise<void> {
|
|
207
|
+
const runId = await this.ensureRun()
|
|
208
|
+
// A skipped scenario is created already-finished on the platform — no
|
|
209
|
+
// steps follow, so we don't keep the returned id.
|
|
210
|
+
await this.fetch('POST', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios`, {
|
|
211
|
+
name: input.name,
|
|
212
|
+
hash: input.hash,
|
|
213
|
+
testFile: input.testFile,
|
|
214
|
+
feature: input.feature,
|
|
215
|
+
seeds: input.seeds,
|
|
216
|
+
roles: input.roles,
|
|
217
|
+
tier: input.tier,
|
|
218
|
+
skipped: true,
|
|
219
|
+
reason: input.reason,
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
176
223
|
recordStep(event: StepEvent): Promise<void> {
|
|
177
224
|
// Track synchronously so flush() awaits the entire pipeline (including
|
|
178
225
|
// encodeScreenshot's fs.readFile and the upload), not just whatever
|
|
@@ -187,7 +234,7 @@ class HttpReporter implements Reporter {
|
|
|
187
234
|
const screenshot = event.screenshotPath
|
|
188
235
|
? await this.encodeScreenshot(event.screenshotPath)
|
|
189
236
|
: undefined
|
|
190
|
-
await this.fetch('POST', `/api/v1/runs/${runId}/scenarios/${event.scenarioId}/steps`, {
|
|
237
|
+
await this.fetch('POST', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios/${event.scenarioId}/steps`, {
|
|
191
238
|
attempt: event.attempt,
|
|
192
239
|
sequence: event.sequence,
|
|
193
240
|
kind: event.kind,
|
|
@@ -206,7 +253,7 @@ class HttpReporter implements Reporter {
|
|
|
206
253
|
const runId = await this.ensureRun()
|
|
207
254
|
// Awaited inline so the scenario status is committed before the
|
|
208
255
|
// bun:test afterAll returns.
|
|
209
|
-
await this.fetch('PATCH', `/api/v1/runs/${runId}/scenarios/${input.scenarioId}`, {
|
|
256
|
+
await this.fetch('PATCH', `/api/v1/${this.config.projectId}/runs/${runId}/scenarios/${input.scenarioId}`, {
|
|
210
257
|
status: input.status,
|
|
211
258
|
durationMs: input.durationMs,
|
|
212
259
|
attempts: input.attempts,
|
|
@@ -326,6 +373,9 @@ export function configureFromEnv(env: NodeJS.ProcessEnv = process.env): Reporter
|
|
|
326
373
|
branch: env['OPICE_BRANCH'] ?? env['GITHUB_REF_NAME'],
|
|
327
374
|
commit: env['OPICE_COMMIT'] ?? env['GITHUB_SHA'],
|
|
328
375
|
source: isCI ? 'ci' : 'local',
|
|
376
|
+
// Record the selected tier only when one was explicitly requested — a run
|
|
377
|
+
// with no OPICE_TIER ran everything and carries no tier filter.
|
|
378
|
+
tier: env['OPICE_TIER'] ? resolveSelectedTier(env) : undefined,
|
|
329
379
|
})
|
|
330
380
|
setReporter(reporter)
|
|
331
381
|
return reporter
|
package/src/scenario.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { closePage, getContext, launchPage } from './context.js'
|
|
|
4
4
|
import { screenshot } from './element.js'
|
|
5
5
|
import { getReporter, type Reporter } from './reporter.js'
|
|
6
6
|
import { loadUserSetup } from './setup.js'
|
|
7
|
+
import { isTierSkipped, normalizeTier, parseSelectedTier, type Tier, TIER_ORDER } from './tier.js'
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* `bun:test` is resolved lazily, at the moment `browserTest` registers a
|
|
@@ -44,6 +45,18 @@ export interface BrowserTestMeta {
|
|
|
44
45
|
hash?: string
|
|
45
46
|
/** Feature / requirement id this scenario covers (e.g. `'F-SML-03a'`). */
|
|
46
47
|
feature?: string
|
|
48
|
+
/**
|
|
49
|
+
* Test tier — *when* this scenario runs (critical < standard < extended).
|
|
50
|
+
* A run selects a tier via `OPICE_TIER` / `opice test --tier`; selection is a
|
|
51
|
+
* threshold (running `standard` runs critical + standard). A scenario above
|
|
52
|
+
* the selected tier is **skipped**: reported as `skipped` (so it still shows
|
|
53
|
+
* on the dashboard) but never opens a browser. Defaults to `standard`.
|
|
54
|
+
*
|
|
55
|
+
* critical — the must-pass core, every push
|
|
56
|
+
* standard — the normal suite (default), PRs / merges
|
|
57
|
+
* extended — slow / edge / expensive, nightly or on demand
|
|
58
|
+
*/
|
|
59
|
+
tier?: Tier
|
|
47
60
|
/**
|
|
48
61
|
* Seeds that must be loaded for this scenario to run — machine-checkable
|
|
49
62
|
* preconditions, not prose. e.g. `['initial-data', 'crm-master-data']`.
|
|
@@ -107,6 +120,40 @@ function captureTestFile(): string | undefined {
|
|
|
107
120
|
return undefined
|
|
108
121
|
}
|
|
109
122
|
|
|
123
|
+
// The tier this run selected (OPICE_TIER), resolved + cached once. An
|
|
124
|
+
// unrecognized value warns once and falls back to running everything.
|
|
125
|
+
let cachedSelectedTier: Tier | undefined
|
|
126
|
+
function getSelectedTier(): Tier {
|
|
127
|
+
if (cachedSelectedTier === undefined) {
|
|
128
|
+
const parsed = parseSelectedTier()
|
|
129
|
+
if (!parsed.recognized) {
|
|
130
|
+
console.warn(
|
|
131
|
+
`[opice] unknown OPICE_TIER="${process.env['OPICE_TIER']}" — running all tiers `
|
|
132
|
+
+ `(use one of: ${TIER_ORDER.join(', ')}).`,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
cachedSelectedTier = parsed.tier
|
|
136
|
+
}
|
|
137
|
+
return cachedSelectedTier
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Names of scenarios skipped by the tier filter, summarized once at process
|
|
141
|
+
// exit so a tiered run prints "N skipped" instead of a line per scenario.
|
|
142
|
+
const skippedScenarioNames: string[] = []
|
|
143
|
+
let skipSummaryHooked = false
|
|
144
|
+
function noteSkipped(name: string): void {
|
|
145
|
+
skippedScenarioNames.push(name)
|
|
146
|
+
if (skipSummaryHooked) return
|
|
147
|
+
skipSummaryHooked = true
|
|
148
|
+
process.on('exit', () => {
|
|
149
|
+
if (skippedScenarioNames.length === 0) return
|
|
150
|
+
console.warn(
|
|
151
|
+
`[opice] ${skippedScenarioNames.length} scenario(s) skipped — above the selected `
|
|
152
|
+
+ `tier '${getSelectedTier()}' (OPICE_TIER).`,
|
|
153
|
+
)
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
110
157
|
let currentScenarioId: string | null = null
|
|
111
158
|
let currentScenarioStart: number = 0
|
|
112
159
|
let currentScenarioFailures = 0
|
|
@@ -165,6 +212,14 @@ export function browserTest(meta: BrowserTestMeta, fn: () => void | Promise<void
|
|
|
165
212
|
// fn is the legacy registrar (it registers its own test()/hooks).
|
|
166
213
|
const isBody = fn.constructor.name === 'AsyncFunction'
|
|
167
214
|
|
|
215
|
+
// Tier gate: a scenario above the selected tier is registered but not run —
|
|
216
|
+
// reported `skipped` so the dashboard shows the full inventory.
|
|
217
|
+
const scenarioTier = normalizeTier(meta.tier)
|
|
218
|
+
if (isTierSkipped(scenarioTier, getSelectedTier())) {
|
|
219
|
+
registerSkipped(meta, scenarioTier, testFile, reporter)
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
|
|
168
223
|
describe(meta.name, () => {
|
|
169
224
|
beforeAll(async () => {
|
|
170
225
|
currentScenarioStart = Date.now()
|
|
@@ -180,6 +235,7 @@ export function browserTest(meta: BrowserTestMeta, fn: () => void | Promise<void
|
|
|
180
235
|
feature: meta.feature,
|
|
181
236
|
seeds: meta.seeds,
|
|
182
237
|
roles: meta.roles,
|
|
238
|
+
tier: scenarioTier,
|
|
183
239
|
})
|
|
184
240
|
} catch {
|
|
185
241
|
currentScenarioId = null
|
|
@@ -285,6 +341,38 @@ export function browserTest(meta: BrowserTestMeta, fn: () => void | Promise<void
|
|
|
285
341
|
})
|
|
286
342
|
}
|
|
287
343
|
|
|
344
|
+
/**
|
|
345
|
+
* Register a scenario the tier filter excluded. It's reported to the platform as
|
|
346
|
+
* `skipped` (so the dashboard shows it alongside what ran) but never opens a
|
|
347
|
+
* browser. The report runs in a real — instant, browser-free — `test`, not a
|
|
348
|
+
* `test.skip`: bun won't run a describe's hooks if every test in it is skipped,
|
|
349
|
+
* so a skip body is the only place left to POST from. With reporting off (local
|
|
350
|
+
* authoring), the body is a no-op against the NoopReporter.
|
|
351
|
+
*/
|
|
352
|
+
function registerSkipped(meta: BrowserTestMeta, tier: Tier, testFile: string | undefined, reporter: Reporter): void {
|
|
353
|
+
noteSkipped(meta.name)
|
|
354
|
+
const { describe, test } = bunTest()
|
|
355
|
+
const reason = `tier '${tier}' above the selected tier '${getSelectedTier()}'`
|
|
356
|
+
describe(meta.name, () => {
|
|
357
|
+
test('skipped (tier)', async () => {
|
|
358
|
+
try {
|
|
359
|
+
await reporter.skipScenario({
|
|
360
|
+
name: meta.name,
|
|
361
|
+
hash: meta.hash,
|
|
362
|
+
testFile,
|
|
363
|
+
feature: meta.feature,
|
|
364
|
+
seeds: meta.seeds,
|
|
365
|
+
roles: meta.roles,
|
|
366
|
+
tier,
|
|
367
|
+
reason,
|
|
368
|
+
})
|
|
369
|
+
} catch {
|
|
370
|
+
// Best-effort: reporting a skip must never fail the run.
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
|
|
288
376
|
/**
|
|
289
377
|
* Open a fresh isolated browser context + page for `meta` and navigate to its
|
|
290
378
|
* scenario URL. `launchPage()` closes any previous context first, so calling
|
|
@@ -473,7 +561,16 @@ interface StepFn {
|
|
|
473
561
|
}
|
|
474
562
|
|
|
475
563
|
interface StepExtras {
|
|
476
|
-
fixme:
|
|
564
|
+
fixme: {
|
|
565
|
+
/** Tolerated failure with just a body. */
|
|
566
|
+
(name: string, reason: string, fn: StepBody): Promise<void>
|
|
567
|
+
/**
|
|
568
|
+
* Tolerated failure that also keeps a durable contract — pass
|
|
569
|
+
* `{ intent, manual }` before the body so the spec rationale and the
|
|
570
|
+
* end-user manual line survive on a `.fixme` step too.
|
|
571
|
+
*/
|
|
572
|
+
(name: string, reason: string, contract: StepContract, fn: StepBody): Promise<void>
|
|
573
|
+
}
|
|
477
574
|
/**
|
|
478
575
|
* A **blocked** pending stub: the step can't be authored yet because the app
|
|
479
576
|
* feature it covers isn't implemented. Reports as 'pending' with the reason
|
|
@@ -505,6 +602,8 @@ interface StepExtras {
|
|
|
505
602
|
* step unexpectedly *passes*, it's flagged too ('fixmepass') so a stale marker
|
|
506
603
|
* doesn't linger. Unlike Playwright's `test.fixme()`, which **skips** the test,
|
|
507
604
|
* `step.fixme` **runs** it — the mandatory reason is there to keep them apart.
|
|
605
|
+
* Pass a contract before the body — `step.fixme(name, reason, { intent, manual },
|
|
606
|
+
* fn)` — to keep the durable `intent` / end-user `manual` on a tolerated step.
|
|
508
607
|
*
|
|
509
608
|
* `step.blocked(name, reason, contract?)` is a pending stub that **can't be
|
|
510
609
|
* authored yet** because the app feature doesn't exist — distinct from a plain
|
|
@@ -519,8 +618,10 @@ export const step: StepFn & StepExtras = Object.assign(
|
|
|
519
618
|
return runUnit({ kind: 'step', name, contract: arg2, fn: arg3 })
|
|
520
619
|
},
|
|
521
620
|
{
|
|
522
|
-
fixme: (name: string, reason: string,
|
|
523
|
-
|
|
621
|
+
fixme: (name: string, reason: string, arg3: StepBody | StepContract, arg4?: StepBody): Promise<void> =>
|
|
622
|
+
typeof arg3 === 'function'
|
|
623
|
+
? runUnit({ kind: 'step', name, reason, fn: arg3 })
|
|
624
|
+
: runUnit({ kind: 'step', name, reason, contract: arg3, fn: arg4 }),
|
|
524
625
|
blocked: (name: string, reason: string, contract?: StepContract): Promise<void> =>
|
|
525
626
|
runUnit({ kind: 'step', name, contract, reason }),
|
|
526
627
|
},
|
|
@@ -536,7 +637,9 @@ export const step: StepFn & StepExtras = Object.assign(
|
|
|
536
637
|
* A failing `invariant` fails the scenario like any hard assertion — it's an
|
|
537
638
|
* acceptance, not a nicety.
|
|
538
639
|
*
|
|
539
|
-
* - `invariant(name, fn)` — enforced now.
|
|
640
|
+
* - `invariant(name, fn)` — enforced now. Pass a contract first —
|
|
641
|
+
* `invariant(name, { intent, manual }, fn)` — to attach the durable `intent`
|
|
642
|
+
* and the end-user `manual` line to the acceptance, exactly like a `step`.
|
|
540
643
|
* - `invariant.todo(name, hint?)` — phase-1 stub: states the acceptance but
|
|
541
644
|
* isn't wired yet (status: pending). `opice-author` promotes it to an
|
|
542
645
|
* enforced `invariant(...)` (or an `invariant.fixme(...)` if it can't hold
|
|
@@ -547,21 +650,32 @@ export const step: StepFn & StepExtras = Object.assign(
|
|
|
547
650
|
* - `invariant.fixme(name, reason, fn)` — a known-unenforceable acceptance,
|
|
548
651
|
* tolerated like `step.fixme` (e.g. a security property deferred to a
|
|
549
652
|
* ticket). The body runs and is expected to fail; the failure is reported as
|
|
550
|
-
* an amber warning and neither fails the scenario nor the run.
|
|
653
|
+
* an amber warning and neither fails the scenario nor the run. Also accepts a
|
|
654
|
+
* contract before the body: `invariant.fixme(name, reason, { intent, manual },
|
|
655
|
+
* fn)`.
|
|
551
656
|
*/
|
|
552
657
|
export const invariant: {
|
|
553
658
|
(name: string, fn: StepBody): Promise<void>
|
|
659
|
+
(name: string, contract: StepContract, fn: StepBody): Promise<void>
|
|
554
660
|
todo: (name: string, hint?: string) => Promise<void>
|
|
555
661
|
blocked: (name: string, reason: string) => Promise<void>
|
|
556
|
-
fixme:
|
|
662
|
+
fixme: {
|
|
663
|
+
(name: string, reason: string, fn: StepBody): Promise<void>
|
|
664
|
+
(name: string, reason: string, contract: StepContract, fn: StepBody): Promise<void>
|
|
665
|
+
}
|
|
557
666
|
} = Object.assign(
|
|
558
|
-
(name: string,
|
|
667
|
+
(name: string, arg2: StepBody | StepContract, arg3?: StepBody): Promise<void> =>
|
|
668
|
+
typeof arg2 === 'function'
|
|
669
|
+
? runUnit({ kind: 'invariant', name, fn: arg2 })
|
|
670
|
+
: runUnit({ kind: 'invariant', name, contract: arg2, fn: arg3 }),
|
|
559
671
|
{
|
|
560
672
|
todo: (name: string, hint?: string): Promise<void> =>
|
|
561
673
|
runUnit({ kind: 'invariant', name, contract: hint ? { hint } : undefined }),
|
|
562
674
|
blocked: (name: string, reason: string): Promise<void> =>
|
|
563
675
|
runUnit({ kind: 'invariant', name, reason }),
|
|
564
|
-
fixme: (name: string, reason: string,
|
|
565
|
-
|
|
676
|
+
fixme: (name: string, reason: string, arg3: StepBody | StepContract, arg4?: StepBody): Promise<void> =>
|
|
677
|
+
typeof arg3 === 'function'
|
|
678
|
+
? runUnit({ kind: 'invariant', name, reason, fn: arg3 })
|
|
679
|
+
: runUnit({ kind: 'invariant', name, reason, contract: arg3, fn: arg4 }),
|
|
566
680
|
},
|
|
567
681
|
)
|
package/src/tier.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test tiers — an ordered hierarchy for *when* a scenario runs.
|
|
3
|
+
*
|
|
4
|
+
* A scenario declares its tier in `browserTest` meta (default `standard`); a run
|
|
5
|
+
* selects a tier via `OPICE_TIER` (the `opice test --tier` flag). Selection is a
|
|
6
|
+
* THRESHOLD: running a tier runs every scenario AT OR BELOW it — the standard
|
|
7
|
+
* `smoke ⊂ regression ⊂ full` model. Scenarios above the selected tier are
|
|
8
|
+
* *skipped*: still registered and reported as `skipped` (so the dashboard shows
|
|
9
|
+
* the full inventory, not just what ran), but they never open a browser.
|
|
10
|
+
*
|
|
11
|
+
* critical — the must-pass core. Run on every push.
|
|
12
|
+
* standard — the normal suite (the default for an untagged scenario). PRs / merges.
|
|
13
|
+
* extended — slow / edge / expensive. Run nightly or on demand.
|
|
14
|
+
*
|
|
15
|
+
* OPICE_TIER=critical → critical only
|
|
16
|
+
* OPICE_TIER=standard → critical + standard
|
|
17
|
+
* OPICE_TIER=extended → everything (also the default when OPICE_TIER is unset)
|
|
18
|
+
*/
|
|
19
|
+
export type Tier = 'critical' | 'standard' | 'extended'
|
|
20
|
+
|
|
21
|
+
/** Tiers low → high. A scenario's index is its level; it runs when level <= selected level. */
|
|
22
|
+
export const TIER_ORDER: readonly Tier[] = ['critical', 'standard', 'extended']
|
|
23
|
+
|
|
24
|
+
/** A scenario with no declared tier sits in the middle `standard` tier. */
|
|
25
|
+
export const DEFAULT_SCENARIO_TIER: Tier = 'standard'
|
|
26
|
+
|
|
27
|
+
/** With no `OPICE_TIER` set, run everything — select the widest tier. */
|
|
28
|
+
export const DEFAULT_SELECTED_TIER: Tier = 'extended'
|
|
29
|
+
|
|
30
|
+
function isTier(value: string | undefined): value is Tier {
|
|
31
|
+
return value === 'critical' || value === 'standard' || value === 'extended'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Normalize a scenario's declared tier, defaulting (and tolerating junk) to `standard`. */
|
|
35
|
+
export function normalizeTier(tier: string | undefined): Tier {
|
|
36
|
+
return isTier(tier) ? tier : DEFAULT_SCENARIO_TIER
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface SelectedTier {
|
|
40
|
+
tier: Tier
|
|
41
|
+
/** false when `OPICE_TIER` held an unrecognized value (the caller may warn). */
|
|
42
|
+
recognized: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The tier selected for this run, parsed from `OPICE_TIER`. Unset → run
|
|
47
|
+
* everything. `all`/`full` are friendly aliases for the widest tier. An
|
|
48
|
+
* unrecognized value resolves to "run everything" (`recognized: false`) rather
|
|
49
|
+
* than silently dropping tests — better to over-run than to skip on a typo.
|
|
50
|
+
*/
|
|
51
|
+
export function parseSelectedTier(env: NodeJS.ProcessEnv = process.env): SelectedTier {
|
|
52
|
+
const raw = env['OPICE_TIER']?.trim().toLowerCase()
|
|
53
|
+
if (!raw) return { tier: DEFAULT_SELECTED_TIER, recognized: true }
|
|
54
|
+
if (isTier(raw)) return { tier: raw, recognized: true }
|
|
55
|
+
if (raw === 'all' || raw === 'full') return { tier: 'extended', recognized: true }
|
|
56
|
+
return { tier: DEFAULT_SELECTED_TIER, recognized: false }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Convenience: the resolved selected tier, ignoring whether the value was recognized. */
|
|
60
|
+
export function resolveSelectedTier(env: NodeJS.ProcessEnv = process.env): Tier {
|
|
61
|
+
return parseSelectedTier(env).tier
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** A scenario is skipped when its tier sits ABOVE the selected one. */
|
|
65
|
+
export function isTierSkipped(scenarioTier: Tier, selectedTier: Tier): boolean {
|
|
66
|
+
return TIER_ORDER.indexOf(scenarioTier) > TIER_ORDER.indexOf(selectedTier)
|
|
67
|
+
}
|