@nsxbet/playwright-orchestrator 0.6.1 → 0.6.2
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 +49 -21
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/test-discovery.d.ts.map +1 -1
- package/dist/core/test-discovery.js +11 -7
- package/dist/core/test-discovery.js.map +1 -1
- package/dist/core/test-id.d.ts +78 -0
- package/dist/core/test-id.d.ts.map +1 -0
- package/dist/core/test-id.js +95 -0
- package/dist/core/test-id.js.map +1 -0
- package/dist/fixture.d.ts +1 -0
- package/dist/fixture.d.ts.map +1 -1
- package/dist/fixture.js +31 -24
- package/dist/fixture.js.map +1 -1
- package/dist/reporter.d.ts +42 -22
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +171 -48
- package/dist/reporter.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,12 +6,12 @@ Intelligent Playwright test distribution across CI shards using historical timin
|
|
|
6
6
|
|
|
7
7
|
Default Playwright sharding (`--shard=N/M`) distributes tests by **file count**, not by duration. This creates significant imbalance:
|
|
8
8
|
|
|
9
|
-
| Shard
|
|
10
|
-
|
|
11
|
-
| Shard 1 | ~31 min
|
|
12
|
-
| Shard 2 | ~15 min
|
|
13
|
-
| Shard 3 | ~22 min
|
|
14
|
-
| Shard 4 | ~11 min
|
|
9
|
+
| Shard | Duration | vs Fastest |
|
|
10
|
+
| ------- | -------- | ---------- |
|
|
11
|
+
| Shard 1 | ~31 min | +182% |
|
|
12
|
+
| Shard 2 | ~15 min | +36% |
|
|
13
|
+
| Shard 3 | ~22 min | +100% |
|
|
14
|
+
| Shard 4 | ~11 min | baseline |
|
|
15
15
|
|
|
16
16
|
Your CI is bottlenecked by the slowest shard, wasting runner time.
|
|
17
17
|
|
|
@@ -75,13 +75,10 @@ playwright-orchestrator merge-timing \
|
|
|
75
75
|
Add the reporter to your `playwright.config.ts`:
|
|
76
76
|
|
|
77
77
|
```typescript
|
|
78
|
-
import { defineConfig } from
|
|
78
|
+
import { defineConfig } from "@playwright/test";
|
|
79
79
|
|
|
80
80
|
export default defineConfig({
|
|
81
|
-
reporter: [
|
|
82
|
-
['@nsxbet/playwright-orchestrator/reporter'],
|
|
83
|
-
['html'],
|
|
84
|
-
],
|
|
81
|
+
reporter: [["@nsxbet/playwright-orchestrator/reporter"], ["html"]],
|
|
85
82
|
});
|
|
86
83
|
```
|
|
87
84
|
|
|
@@ -110,6 +107,8 @@ Use the orchestrator in your own repository. The recommended pattern runs orches
|
|
|
110
107
|
|
|
111
108
|
**Important**: Use `npx playwright test --list --reporter=json` to generate the test list. This ensures accurate discovery of parameterized tests (`test.each`) and avoids mismatches between discovered and actual tests.
|
|
112
109
|
|
|
110
|
+
**Monorepo Note**: In monorepos, generate the test list from the same directory where tests run (where `playwright.config.ts` lives). See [Monorepo Usage](./docs/external-integration.md#monorepo-usage) for details.
|
|
111
|
+
|
|
113
112
|
```yaml
|
|
114
113
|
jobs:
|
|
115
114
|
# Phase 1: Orchestrate (runs once)
|
|
@@ -119,12 +118,12 @@ jobs:
|
|
|
119
118
|
shard-files: ${{ steps.orchestrate.outputs.shard-files }}
|
|
120
119
|
steps:
|
|
121
120
|
- uses: actions/checkout@v4
|
|
122
|
-
|
|
121
|
+
|
|
123
122
|
- uses: actions/setup-node@v4
|
|
124
123
|
with:
|
|
125
124
|
node-version: 20
|
|
126
125
|
cache: npm
|
|
127
|
-
|
|
126
|
+
|
|
128
127
|
- run: npm ci
|
|
129
128
|
|
|
130
129
|
- uses: NSXBet/playwright-orchestrator/.github/actions/setup-orchestrator@v0
|
|
@@ -136,14 +135,15 @@ jobs:
|
|
|
136
135
|
key: playwright-timing-${{ github.ref_name }}
|
|
137
136
|
restore-keys: playwright-timing-
|
|
138
137
|
|
|
139
|
-
# IMPORTANT: Generate test list
|
|
138
|
+
# IMPORTANT: Generate test list from the directory where tests run
|
|
139
|
+
# In monorepos, use working-directory to match where playwright.config.ts lives
|
|
140
140
|
- run: npx playwright test --list --reporter=json > test-list.json
|
|
141
141
|
|
|
142
142
|
# Action handles all orchestration logic
|
|
143
143
|
- uses: NSXBet/playwright-orchestrator/.github/actions/orchestrate@v0
|
|
144
144
|
id: orchestrate
|
|
145
145
|
with:
|
|
146
|
-
test-list: test-list.json
|
|
146
|
+
test-list: test-list.json # Use pre-generated list (recommended)
|
|
147
147
|
shards: 4
|
|
148
148
|
timing-file: timing-data.json
|
|
149
149
|
|
|
@@ -176,12 +176,12 @@ See [docs/external-integration.md](./docs/external-integration.md) for complete
|
|
|
176
176
|
|
|
177
177
|
## CLI Commands
|
|
178
178
|
|
|
179
|
-
| Command
|
|
180
|
-
|
|
181
|
-
| `list-tests`
|
|
182
|
-
| `assign`
|
|
183
|
-
| `extract-timing` | Extract timing from Playwright report
|
|
184
|
-
| `merge-timing`
|
|
179
|
+
| Command | Description |
|
|
180
|
+
| ---------------- | -------------------------------------------------------------------------------- |
|
|
181
|
+
| `list-tests` | Discover tests in a project (uses Playwright `--list`) |
|
|
182
|
+
| `assign` | Distribute tests across shards (uses Playwright `--list` for accurate discovery) |
|
|
183
|
+
| `extract-timing` | Extract timing from Playwright report |
|
|
184
|
+
| `merge-timing` | Merge timing data with EMA smoothing |
|
|
185
185
|
|
|
186
186
|
Run `playwright-orchestrator <command> --help` for details.
|
|
187
187
|
|
|
@@ -205,6 +205,34 @@ make build
|
|
|
205
205
|
make act-test
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
## E2E Testing
|
|
209
|
+
|
|
210
|
+
The repository includes comprehensive E2E tests that simulate real-world monorepo usage:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Run E2E monorepo workflow with Act
|
|
214
|
+
make act-e2e-monorepo
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The E2E workflow (`e2e-monorepo.yml`) tests the complete orchestration cycle:
|
|
218
|
+
|
|
219
|
+
1. **setup**: Build package, create tarball artifact
|
|
220
|
+
2. **orchestrate**: Use real `orchestrate` action to assign tests
|
|
221
|
+
3. **e2e-tests** (matrix): Use `get-shard` and `extract-timing` actions
|
|
222
|
+
4. **merge**: Use `merge-timing` action to combine timing data
|
|
223
|
+
|
|
224
|
+
**Note**: Publish validation is handled separately in CI via the `test-publish` job (Verdaccio).
|
|
225
|
+
|
|
226
|
+
Test scenarios covered in `examples/monorepo/`:
|
|
227
|
+
|
|
228
|
+
- Path normalization (orchestrate from root, run from subdirectory)
|
|
229
|
+
- Parameterized tests (`test.each` patterns)
|
|
230
|
+
- Nested describe blocks (4+ levels deep)
|
|
231
|
+
- Special characters in test names (Unicode, brackets)
|
|
232
|
+
- `::` separator conflicts in test titles
|
|
233
|
+
- Skip patterns (`skip`, `fixme`, `slow`, tags)
|
|
234
|
+
- Deep subdirectory paths
|
|
235
|
+
|
|
208
236
|
See [AGENTS.md](./AGENTS.md) for AI assistant instructions.
|
|
209
237
|
|
|
210
238
|
## License
|
package/dist/core/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './estimate.js';
|
|
|
3
3
|
export * from './lpt-algorithm.js';
|
|
4
4
|
export * from './slugify.js';
|
|
5
5
|
export * from './test-discovery.js';
|
|
6
|
+
export * from './test-id.js';
|
|
6
7
|
export * from './timing-store.js';
|
|
7
8
|
export * from './types.js';
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from './estimate.js';
|
|
|
3
3
|
export * from './lpt-algorithm.js';
|
|
4
4
|
export * from './slugify.js';
|
|
5
5
|
export * from './test-discovery.js';
|
|
6
|
+
export * from './test-id.js';
|
|
6
7
|
export * from './timing-store.js';
|
|
7
8
|
export * from './types.js';
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-discovery.d.ts","sourceRoot":"","sources":["../../src/core/test-discovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,YAAY,CAAC;AAGpB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAGvE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,EAAE,CAyBlB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,GACjB,cAAc,EAAE,CA2BlB;
|
|
1
|
+
{"version":3,"file":"test-discovery.d.ts","sourceRoot":"","sources":["../../src/core/test-discovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,YAAY,CAAC;AAGpB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAGvE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,EAAE,CAyBlB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,GACjB,cAAc,EAAE,CA2BlB;AA0ED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAuB,GACnC,cAAc,EAAE,CAgBlB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,cAAc,EAAE,CAkElB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EAAE,GACtB,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAU/B"}
|
|
@@ -113,22 +113,26 @@ function extractTestsFromSuite(suite, parentTitles, tests, rootDir, isRootSuite
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
|
-
* Resolve file path to be relative to
|
|
116
|
+
* Resolve file path to be relative to rootDir (Playwright's testDir/config dir)
|
|
117
117
|
*
|
|
118
118
|
* Playwright JSON output may contain:
|
|
119
119
|
* - Just filename (relative to rootDir): "account.spec.ts"
|
|
120
120
|
* - Full absolute path: "/Users/.../src/test/e2e/account.spec.ts"
|
|
121
121
|
*
|
|
122
|
-
* We
|
|
122
|
+
* We return paths relative to rootDir for consistency.
|
|
123
|
+
* This ensures test IDs match between:
|
|
124
|
+
* - Orchestrator (running from repo root, reading test-list.json)
|
|
125
|
+
* - Fixture (running from subdirectory where tests live)
|
|
126
|
+
*
|
|
127
|
+
* Both will generate paths like "src/test/e2e/login.spec.ts" regardless of CWD.
|
|
123
128
|
*/
|
|
124
129
|
function resolveFilePath(filePath, rootDir) {
|
|
125
|
-
// If it's already an absolute path, make it relative to
|
|
130
|
+
// If it's already an absolute path, make it relative to rootDir
|
|
126
131
|
if (path.isAbsolute(filePath)) {
|
|
127
|
-
return path.relative(
|
|
132
|
+
return path.relative(rootDir, filePath).replace(/\\/g, '/');
|
|
128
133
|
}
|
|
129
|
-
// If it's
|
|
130
|
-
|
|
131
|
-
return path.relative(process.cwd(), absolutePath).replace(/\\/g, '/');
|
|
134
|
+
// If it's a relative path already (relative to rootDir), just normalize it
|
|
135
|
+
return filePath.replace(/\\/g, '/');
|
|
132
136
|
}
|
|
133
137
|
/**
|
|
134
138
|
* Discover tests by scanning test files directly (fallback method)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-discovery.js","sourceRoot":"","sources":["../../src/core/test-discovery.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"test-discovery.js","sourceRoot":"","sources":["../../src/core/test-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test ID Generation Module
|
|
3
|
+
*
|
|
4
|
+
* This module provides shared functions for generating consistent test IDs
|
|
5
|
+
* across all orchestrator components (fixture, reporter).
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL: All components MUST use these shared functions to ensure
|
|
8
|
+
* test IDs match between shard assignment and runtime filtering.
|
|
9
|
+
*
|
|
10
|
+
* There are two contexts for test ID generation:
|
|
11
|
+
* 1. Discovery context: Uses buildTestId from types.ts (data from Playwright JSON)
|
|
12
|
+
* 2. Runtime context: Uses buildTestIdFromRuntime (data from testInfo.titlePath)
|
|
13
|
+
*
|
|
14
|
+
* @module @nsxbet/playwright-orchestrator/core/test-id
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Options for filtering runtime titlePath
|
|
18
|
+
*/
|
|
19
|
+
export interface FilterTitlePathOptions {
|
|
20
|
+
/** Playwright project name to exclude from titlePath */
|
|
21
|
+
projectName?: string;
|
|
22
|
+
/** File name (basename) to exclude from titlePath */
|
|
23
|
+
fileName?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Filter titlePath from Playwright runtime (testInfo.titlePath) to get only
|
|
27
|
+
* describe blocks and test title.
|
|
28
|
+
*
|
|
29
|
+
* Playwright's runtime titlePath includes:
|
|
30
|
+
* - Project name (e.g., "chromium")
|
|
31
|
+
* - File path or filename
|
|
32
|
+
* - Describe block titles
|
|
33
|
+
* - Test title
|
|
34
|
+
*
|
|
35
|
+
* This function removes non-meaningful elements to produce a clean titlePath
|
|
36
|
+
* that matches what test-discovery produces from Playwright's JSON output.
|
|
37
|
+
*
|
|
38
|
+
* @param titlePath - Raw titlePath from testInfo.titlePath or test.titlePath()
|
|
39
|
+
* @param options - Options for filtering
|
|
40
|
+
* @returns Filtered titlePath containing only describe blocks and test title
|
|
41
|
+
*/
|
|
42
|
+
export declare function filterRuntimeTitlePath(titlePath: string[], options?: FilterTitlePathOptions): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Options for building a test ID from runtime data
|
|
45
|
+
*/
|
|
46
|
+
export interface BuildTestIdFromRuntimeOptions {
|
|
47
|
+
/** Playwright project name to exclude from titlePath */
|
|
48
|
+
projectName?: string;
|
|
49
|
+
/** Base directory for relative path resolution (testDir or rootDir) */
|
|
50
|
+
baseDir?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Build a test ID from Playwright runtime data (fixture or reporter context).
|
|
54
|
+
*
|
|
55
|
+
* This function:
|
|
56
|
+
* 1. Converts the absolute file path to relative (using baseDir or cwd)
|
|
57
|
+
* 2. Filters the titlePath to remove project name, filename, and file paths
|
|
58
|
+
* 3. Joins file and filtered titles with "::"
|
|
59
|
+
*
|
|
60
|
+
* The resulting test ID format: {relative-file}::{describe1}::{describe2}::{testTitle}
|
|
61
|
+
*
|
|
62
|
+
* @param filePath - Absolute path to the test file (testInfo.file or test.location.file)
|
|
63
|
+
* @param titlePath - Raw titlePath from testInfo.titlePath or test.titlePath()
|
|
64
|
+
* @param options - Options for path resolution and filtering
|
|
65
|
+
* @returns Test ID string
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const testId = buildTestIdFromRuntime(
|
|
70
|
+
* '/project/e2e/login.spec.ts',
|
|
71
|
+
* ['chromium', 'login.spec.ts', 'Login', 'should work'],
|
|
72
|
+
* { projectName: 'chromium', baseDir: '/project' }
|
|
73
|
+
* );
|
|
74
|
+
* // Result: 'e2e/login.spec.ts::Login::should work'
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function buildTestIdFromRuntime(filePath: string, titlePath: string[], options?: BuildTestIdFromRuntimeOptions): string;
|
|
78
|
+
//# sourceMappingURL=test-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-id.d.ts","sourceRoot":"","sources":["../../src/core/test-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE,sBAA2B,GACnC,MAAM,EAAE,CAsBV;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,GAAE,6BAAkC,GAC1C,MAAM,CAgBR"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test ID Generation Module
|
|
3
|
+
*
|
|
4
|
+
* This module provides shared functions for generating consistent test IDs
|
|
5
|
+
* across all orchestrator components (fixture, reporter).
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL: All components MUST use these shared functions to ensure
|
|
8
|
+
* test IDs match between shard assignment and runtime filtering.
|
|
9
|
+
*
|
|
10
|
+
* There are two contexts for test ID generation:
|
|
11
|
+
* 1. Discovery context: Uses buildTestId from types.ts (data from Playwright JSON)
|
|
12
|
+
* 2. Runtime context: Uses buildTestIdFromRuntime (data from testInfo.titlePath)
|
|
13
|
+
*
|
|
14
|
+
* @module @nsxbet/playwright-orchestrator/core/test-id
|
|
15
|
+
*/
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
/**
|
|
18
|
+
* Filter titlePath from Playwright runtime (testInfo.titlePath) to get only
|
|
19
|
+
* describe blocks and test title.
|
|
20
|
+
*
|
|
21
|
+
* Playwright's runtime titlePath includes:
|
|
22
|
+
* - Project name (e.g., "chromium")
|
|
23
|
+
* - File path or filename
|
|
24
|
+
* - Describe block titles
|
|
25
|
+
* - Test title
|
|
26
|
+
*
|
|
27
|
+
* This function removes non-meaningful elements to produce a clean titlePath
|
|
28
|
+
* that matches what test-discovery produces from Playwright's JSON output.
|
|
29
|
+
*
|
|
30
|
+
* @param titlePath - Raw titlePath from testInfo.titlePath or test.titlePath()
|
|
31
|
+
* @param options - Options for filtering
|
|
32
|
+
* @returns Filtered titlePath containing only describe blocks and test title
|
|
33
|
+
*/
|
|
34
|
+
export function filterRuntimeTitlePath(titlePath, options = {}) {
|
|
35
|
+
const { projectName, fileName } = options;
|
|
36
|
+
return titlePath.filter((title) => {
|
|
37
|
+
// Filter empty strings
|
|
38
|
+
if (!title || title === '')
|
|
39
|
+
return false;
|
|
40
|
+
// Filter project name
|
|
41
|
+
if (projectName && title === projectName)
|
|
42
|
+
return false;
|
|
43
|
+
// Filter filename
|
|
44
|
+
if (fileName && title === fileName)
|
|
45
|
+
return false;
|
|
46
|
+
// Filter out file paths (contain / or \)
|
|
47
|
+
if (title.includes('/') || title.includes('\\'))
|
|
48
|
+
return false;
|
|
49
|
+
// Filter out spec/test file extensions
|
|
50
|
+
if (title.endsWith('.spec.ts') || title.endsWith('.test.ts'))
|
|
51
|
+
return false;
|
|
52
|
+
if (title.endsWith('.spec.js') || title.endsWith('.test.js'))
|
|
53
|
+
return false;
|
|
54
|
+
return true;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build a test ID from Playwright runtime data (fixture or reporter context).
|
|
59
|
+
*
|
|
60
|
+
* This function:
|
|
61
|
+
* 1. Converts the absolute file path to relative (using baseDir or cwd)
|
|
62
|
+
* 2. Filters the titlePath to remove project name, filename, and file paths
|
|
63
|
+
* 3. Joins file and filtered titles with "::"
|
|
64
|
+
*
|
|
65
|
+
* The resulting test ID format: {relative-file}::{describe1}::{describe2}::{testTitle}
|
|
66
|
+
*
|
|
67
|
+
* @param filePath - Absolute path to the test file (testInfo.file or test.location.file)
|
|
68
|
+
* @param titlePath - Raw titlePath from testInfo.titlePath or test.titlePath()
|
|
69
|
+
* @param options - Options for path resolution and filtering
|
|
70
|
+
* @returns Test ID string
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const testId = buildTestIdFromRuntime(
|
|
75
|
+
* '/project/e2e/login.spec.ts',
|
|
76
|
+
* ['chromium', 'login.spec.ts', 'Login', 'should work'],
|
|
77
|
+
* { projectName: 'chromium', baseDir: '/project' }
|
|
78
|
+
* );
|
|
79
|
+
* // Result: 'e2e/login.spec.ts::Login::should work'
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function buildTestIdFromRuntime(filePath, titlePath, options = {}) {
|
|
83
|
+
const { projectName, baseDir = process.cwd() } = options;
|
|
84
|
+
// Convert absolute path to relative
|
|
85
|
+
const file = path.relative(baseDir, filePath).replace(/\\/g, '/');
|
|
86
|
+
// Get filename for filtering
|
|
87
|
+
const fileName = path.basename(filePath);
|
|
88
|
+
// Filter titlePath
|
|
89
|
+
const filteredTitles = filterRuntimeTitlePath(titlePath, {
|
|
90
|
+
projectName,
|
|
91
|
+
fileName,
|
|
92
|
+
});
|
|
93
|
+
return [file, ...filteredTitles].join('::');
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=test-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-id.js","sourceRoot":"","sources":["../../src/core/test-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAYlC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAmB,EACnB,UAAkC,EAAE;IAEpC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE1C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAChC,uBAAuB;QACvB,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;QAEzC,sBAAsB;QACtB,IAAI,WAAW,IAAI,KAAK,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAEvD,kBAAkB;QAClB,IAAI,QAAQ,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAEjD,yCAAyC;QACzC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAE9D,uCAAuC;QACvC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3E,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QAE3E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAYD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,SAAmB,EACnB,UAAyC,EAAE;IAE3C,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAEzD,oCAAoC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAElE,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEzC,mBAAmB;IACnB,MAAM,cAAc,GAAG,sBAAsB,CAAC,SAAS,EAAE;QACvD,WAAW;QACX,QAAQ;KACT,CAAC,CAAC;IAEH,OAAO,CAAC,IAAI,EAAE,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|
package/dist/fixture.d.ts
CHANGED
package/dist/fixture.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAuDjD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EACxE,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GACnB,IAAI,CA0BN;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,GAAG,OAAO,CAUV"}
|
package/dist/fixture.js
CHANGED
|
@@ -19,7 +19,11 @@
|
|
|
19
19
|
* @module @nsxbet/playwright-orchestrator/fixture
|
|
20
20
|
*/
|
|
21
21
|
import * as fs from 'node:fs';
|
|
22
|
-
import
|
|
22
|
+
import { buildTestIdFromRuntime } from './core/test-id.js';
|
|
23
|
+
// Module initialization debug - only in debug mode
|
|
24
|
+
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
25
|
+
process.stderr.write('[Fixture Module] Loading orchestrator fixture\n');
|
|
26
|
+
}
|
|
23
27
|
// Cache the shard file to avoid re-reading on every test
|
|
24
28
|
let cachedAllowedTestIds = null;
|
|
25
29
|
let cacheInitialized = false;
|
|
@@ -35,9 +39,18 @@ function loadShardFile() {
|
|
|
35
39
|
return null;
|
|
36
40
|
}
|
|
37
41
|
try {
|
|
38
|
-
const
|
|
42
|
+
const parsed = JSON.parse(fs.readFileSync(shardFile, 'utf-8'));
|
|
43
|
+
// Validate shard file format
|
|
44
|
+
if (!Array.isArray(parsed) ||
|
|
45
|
+
!parsed.every((id) => typeof id === 'string')) {
|
|
46
|
+
throw new Error('[Orchestrator] Shard file must be a JSON array of strings');
|
|
47
|
+
}
|
|
48
|
+
const testIds = parsed;
|
|
39
49
|
cachedAllowedTestIds = new Set(testIds);
|
|
40
|
-
|
|
50
|
+
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
51
|
+
process.stderr.write(`[Orchestrator] Loaded ${testIds.length} tests for this shard\n`);
|
|
52
|
+
process.stderr.write(`[Orchestrator] Sample IDs: ${testIds.slice(0, 3).join(' | ')}\n`);
|
|
53
|
+
}
|
|
41
54
|
return cachedAllowedTestIds;
|
|
42
55
|
}
|
|
43
56
|
catch (error) {
|
|
@@ -45,21 +58,6 @@ function loadShardFile() {
|
|
|
45
58
|
throw error;
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
|
-
function buildTestId(filePath, titlePath, projectName) {
|
|
49
|
-
const file = path.relative(process.cwd(), filePath).replace(/\\/g, '/');
|
|
50
|
-
const fileName = path.basename(filePath);
|
|
51
|
-
// Filter titlePath to exclude project name, filename, and empty strings
|
|
52
|
-
const filteredTitles = titlePath.filter((title) => {
|
|
53
|
-
if (!title || title === '')
|
|
54
|
-
return false;
|
|
55
|
-
if (title === projectName)
|
|
56
|
-
return false;
|
|
57
|
-
if (title === fileName)
|
|
58
|
-
return false;
|
|
59
|
-
return true;
|
|
60
|
-
});
|
|
61
|
-
return [file, ...filteredTitles].join('::');
|
|
62
|
-
}
|
|
63
61
|
/**
|
|
64
62
|
* Sets up the orchestrator filter as a beforeEach hook.
|
|
65
63
|
* This will skip tests that are not in the current shard.
|
|
@@ -71,11 +69,17 @@ export function setupOrchestratorFilter(test) {
|
|
|
71
69
|
test.beforeEach(async ({}, testInfo) => {
|
|
72
70
|
const allowedTestIds = loadShardFile();
|
|
73
71
|
if (allowedTestIds) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
// Use project.testDir for consistent path resolution with test-discovery
|
|
73
|
+
const testId = buildTestIdFromRuntime(testInfo.file, testInfo.titlePath, {
|
|
74
|
+
projectName: testInfo.project.name,
|
|
75
|
+
baseDir: testInfo.project.testDir,
|
|
76
|
+
});
|
|
77
|
+
const isAllowed = allowedTestIds.has(testId);
|
|
78
|
+
// Debug: Write to stderr for visibility in CI logs
|
|
79
|
+
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
80
|
+
process.stderr.write(`[Fixture] testDir=${testInfo.project.testDir} | testId=${testId} | allowed=${isAllowed}\n`);
|
|
81
|
+
}
|
|
82
|
+
if (!isAllowed) {
|
|
79
83
|
test.skip(true, 'Not in shard');
|
|
80
84
|
}
|
|
81
85
|
}
|
|
@@ -92,7 +96,10 @@ export function shouldRunTest(testInfo) {
|
|
|
92
96
|
const allowedTestIds = loadShardFile();
|
|
93
97
|
if (!allowedTestIds)
|
|
94
98
|
return true;
|
|
95
|
-
const testId =
|
|
99
|
+
const testId = buildTestIdFromRuntime(testInfo.file, testInfo.titlePath, {
|
|
100
|
+
projectName: testInfo.project.name,
|
|
101
|
+
baseDir: testInfo.project.testDir,
|
|
102
|
+
});
|
|
96
103
|
return allowedTestIds.has(testId);
|
|
97
104
|
}
|
|
98
105
|
//# sourceMappingURL=fixture.js.map
|
package/dist/fixture.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"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"}
|
package/dist/reporter.d.ts
CHANGED
|
@@ -1,43 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Playwright Orchestrator Reporter
|
|
3
3
|
*
|
|
4
|
-
* A custom Playwright reporter that
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* A custom Playwright reporter that provides clean output for sharded tests.
|
|
5
|
+
* Shows only tests assigned to the current shard, with proper counts and summaries.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Correct "Running X tests" count (only shard tests, not total)
|
|
9
|
+
* - Clean output showing only shard tests (no skipped noise)
|
|
10
|
+
* - Debug mode to see filtered tests
|
|
11
|
+
* - Compatible with other reporters (json, html)
|
|
7
12
|
*
|
|
8
13
|
* Usage:
|
|
9
14
|
* 1. Add to playwright.config.ts:
|
|
10
|
-
* reporter: [['@nsxbet/playwright-orchestrator/reporter'], ['
|
|
15
|
+
* reporter: [['@nsxbet/playwright-orchestrator/reporter'], ['json', {...}]]
|
|
11
16
|
* 2. Set ORCHESTRATOR_SHARD_FILE env var to path of JSON file with test IDs
|
|
12
17
|
*
|
|
13
18
|
* Environment variables:
|
|
14
19
|
* - ORCHESTRATOR_SHARD_FILE: Path to JSON file with array of test IDs
|
|
15
|
-
* - ORCHESTRATOR_DEBUG: Set to "1" to
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* // shard.json
|
|
19
|
-
* ["e2e/login.spec.ts::Login::should login", "e2e/home.spec.ts::Home::should render"]
|
|
20
|
-
*
|
|
21
|
-
* // Run with filtering
|
|
22
|
-
* ORCHESTRATOR_SHARD_FILE=shard.json npx playwright test
|
|
20
|
+
* - ORCHESTRATOR_DEBUG: Set to "1" to show filtered tests
|
|
23
21
|
*
|
|
24
22
|
* @module @nsxbet/playwright-orchestrator/reporter
|
|
25
23
|
*/
|
|
26
|
-
import type { FullConfig, Reporter, Suite, TestCase } from '@playwright/test/reporter';
|
|
24
|
+
import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
|
|
27
25
|
export default class OrchestratorReporter implements Reporter {
|
|
28
26
|
private allowedTestIds;
|
|
29
27
|
private debug;
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
private startTime;
|
|
29
|
+
private rootDir;
|
|
30
|
+
private passed;
|
|
31
|
+
private failed;
|
|
32
|
+
private skipped;
|
|
33
|
+
private filtered;
|
|
34
|
+
onBegin(config: FullConfig, suite: Suite): void;
|
|
35
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
36
|
+
onEnd(_result: FullResult): void;
|
|
37
|
+
/**
|
|
38
|
+
* Print a test result line
|
|
39
|
+
*/
|
|
40
|
+
private printTestResult;
|
|
41
|
+
/**
|
|
42
|
+
* Print a filtered test (debug mode only)
|
|
43
|
+
*/
|
|
44
|
+
private printFiltered;
|
|
45
|
+
/**
|
|
46
|
+
* Get display title for a test (file > describe > test)
|
|
47
|
+
*/
|
|
48
|
+
private getDisplayTitle;
|
|
49
|
+
/**
|
|
50
|
+
* Filter titlePath to get only describe blocks and test title.
|
|
51
|
+
* Uses shared filterRuntimeTitlePath function for consistency.
|
|
52
|
+
*/
|
|
53
|
+
private getFilteredTitles;
|
|
54
|
+
/**
|
|
55
|
+
* Format duration in human readable format
|
|
56
|
+
*/
|
|
57
|
+
private formatDuration;
|
|
32
58
|
/**
|
|
33
59
|
* Build test ID from TestCase.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* This must match the format generated by the orchestrator.
|
|
37
|
-
*
|
|
38
|
-
* Note: titlePath() returns [projectName?, fileName, ...describes, testTitle]
|
|
39
|
-
* We need to filter out projectName and fileName since we already have
|
|
40
|
-
* the full relative file path.
|
|
60
|
+
* Uses shared buildTestIdFromRuntime function for consistency with fixture.
|
|
41
61
|
*/
|
|
42
62
|
private buildTestId;
|
|
43
63
|
}
|
package/dist/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;AA0BnC,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,QAAQ;IAC3D,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAAM;IAGrB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAK;IAErB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK;IAsCxC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU;IAsB5C,KAAK,CAAC,OAAO,EAAE,UAAU;IA0BzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAsCvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;;OAGG;IACH,OAAO,CAAC,WAAW;CASpB"}
|
package/dist/reporter.js
CHANGED
|
@@ -1,94 +1,217 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Playwright Orchestrator Reporter
|
|
3
3
|
*
|
|
4
|
-
* A custom Playwright reporter that
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* A custom Playwright reporter that provides clean output for sharded tests.
|
|
5
|
+
* Shows only tests assigned to the current shard, with proper counts and summaries.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Correct "Running X tests" count (only shard tests, not total)
|
|
9
|
+
* - Clean output showing only shard tests (no skipped noise)
|
|
10
|
+
* - Debug mode to see filtered tests
|
|
11
|
+
* - Compatible with other reporters (json, html)
|
|
7
12
|
*
|
|
8
13
|
* Usage:
|
|
9
14
|
* 1. Add to playwright.config.ts:
|
|
10
|
-
* reporter: [['@nsxbet/playwright-orchestrator/reporter'], ['
|
|
15
|
+
* reporter: [['@nsxbet/playwright-orchestrator/reporter'], ['json', {...}]]
|
|
11
16
|
* 2. Set ORCHESTRATOR_SHARD_FILE env var to path of JSON file with test IDs
|
|
12
17
|
*
|
|
13
18
|
* Environment variables:
|
|
14
19
|
* - ORCHESTRATOR_SHARD_FILE: Path to JSON file with array of test IDs
|
|
15
|
-
* - ORCHESTRATOR_DEBUG: Set to "1" to
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* // shard.json
|
|
19
|
-
* ["e2e/login.spec.ts::Login::should login", "e2e/home.spec.ts::Home::should render"]
|
|
20
|
-
*
|
|
21
|
-
* // Run with filtering
|
|
22
|
-
* ORCHESTRATOR_SHARD_FILE=shard.json npx playwright test
|
|
20
|
+
* - ORCHESTRATOR_DEBUG: Set to "1" to show filtered tests
|
|
23
21
|
*
|
|
24
22
|
* @module @nsxbet/playwright-orchestrator/reporter
|
|
25
23
|
*/
|
|
26
24
|
import * as fs from 'node:fs';
|
|
27
25
|
import * as path from 'node:path';
|
|
26
|
+
import { buildTestIdFromRuntime, filterRuntimeTitlePath, } from './core/test-id.js';
|
|
27
|
+
// ANSI color codes
|
|
28
|
+
const colors = {
|
|
29
|
+
green: '\x1b[32m',
|
|
30
|
+
red: '\x1b[31m',
|
|
31
|
+
yellow: '\x1b[33m',
|
|
32
|
+
gray: '\x1b[90m',
|
|
33
|
+
reset: '\x1b[0m',
|
|
34
|
+
bold: '\x1b[1m',
|
|
35
|
+
};
|
|
36
|
+
// Check if colors should be used
|
|
37
|
+
const useColors = process.env.FORCE_COLOR !== '0' &&
|
|
38
|
+
process.env.NO_COLOR === undefined &&
|
|
39
|
+
process.stdout.isTTY;
|
|
40
|
+
function color(code, text) {
|
|
41
|
+
return useColors ? `${colors[code]}${text}${colors.reset}` : text;
|
|
42
|
+
}
|
|
28
43
|
export default class OrchestratorReporter {
|
|
29
44
|
allowedTestIds = null;
|
|
30
45
|
debug = process.env.ORCHESTRATOR_DEBUG === '1';
|
|
31
|
-
|
|
46
|
+
startTime = 0;
|
|
47
|
+
rootDir = '';
|
|
48
|
+
// Counters for summary
|
|
49
|
+
passed = 0;
|
|
50
|
+
failed = 0;
|
|
51
|
+
skipped = 0;
|
|
52
|
+
filtered = 0;
|
|
53
|
+
onBegin(config, suite) {
|
|
54
|
+
this.startTime = Date.now();
|
|
55
|
+
this.rootDir = config.rootDir;
|
|
32
56
|
const shardFile = process.env.ORCHESTRATOR_SHARD_FILE;
|
|
33
57
|
if (!shardFile || !fs.existsSync(shardFile)) {
|
|
58
|
+
// No shard file - let other reporters handle output
|
|
34
59
|
if (this.debug) {
|
|
35
|
-
console.log('[Orchestrator] No shard file, running all tests');
|
|
60
|
+
console.log(color('gray', '[Orchestrator] No shard file, running all tests'));
|
|
36
61
|
}
|
|
37
62
|
return;
|
|
38
63
|
}
|
|
39
64
|
try {
|
|
40
65
|
const testIds = JSON.parse(fs.readFileSync(shardFile, 'utf-8'));
|
|
41
66
|
this.allowedTestIds = new Set(testIds);
|
|
42
|
-
|
|
67
|
+
// Count tests
|
|
68
|
+
const allTests = suite.allTests();
|
|
69
|
+
const shardTestCount = this.allowedTestIds.size;
|
|
70
|
+
this.filtered = allTests.length - shardTestCount;
|
|
71
|
+
// Print header
|
|
72
|
+
const workers = config.workers;
|
|
73
|
+
let header = `\nRunning ${color('bold', String(shardTestCount))} tests using ${workers} workers`;
|
|
74
|
+
if (this.debug && this.filtered > 0) {
|
|
75
|
+
header += color('gray', ` (${this.filtered} filtered by orchestrator)`);
|
|
76
|
+
}
|
|
77
|
+
console.log(header);
|
|
78
|
+
console.log('');
|
|
43
79
|
}
|
|
44
80
|
catch (error) {
|
|
45
81
|
console.error('[Orchestrator] Failed to load shard file:', error);
|
|
46
82
|
throw error;
|
|
47
83
|
}
|
|
48
84
|
}
|
|
49
|
-
|
|
85
|
+
onTestEnd(test, result) {
|
|
86
|
+
const testId = this.buildTestId(test);
|
|
87
|
+
const isInShard = !this.allowedTestIds || this.allowedTestIds.has(testId);
|
|
88
|
+
if (isInShard) {
|
|
89
|
+
// Track stats for shard tests
|
|
90
|
+
if (result.status === 'passed') {
|
|
91
|
+
this.passed++;
|
|
92
|
+
}
|
|
93
|
+
else if (result.status === 'failed' || result.status === 'timedOut') {
|
|
94
|
+
this.failed++;
|
|
95
|
+
}
|
|
96
|
+
else if (result.status === 'skipped') {
|
|
97
|
+
this.skipped++;
|
|
98
|
+
}
|
|
99
|
+
// Print test result
|
|
100
|
+
this.printTestResult(test, result);
|
|
101
|
+
}
|
|
102
|
+
else if (this.debug) {
|
|
103
|
+
// Show filtered tests only in debug mode
|
|
104
|
+
this.printFiltered(test);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
onEnd(_result) {
|
|
108
|
+
// Only print summary if we have a shard file
|
|
50
109
|
if (!this.allowedTestIds)
|
|
51
110
|
return;
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
111
|
+
const duration = Date.now() - this.startTime;
|
|
112
|
+
const durationStr = this.formatDuration(duration);
|
|
113
|
+
console.log('');
|
|
114
|
+
// Build summary parts
|
|
115
|
+
const parts = [];
|
|
116
|
+
if (this.passed > 0) {
|
|
117
|
+
parts.push(color('green', `${this.passed} passed`));
|
|
118
|
+
}
|
|
119
|
+
if (this.failed > 0) {
|
|
120
|
+
parts.push(color('red', `${this.failed} failed`));
|
|
121
|
+
}
|
|
122
|
+
if (this.skipped > 0) {
|
|
123
|
+
parts.push(color('yellow', `${this.skipped} skipped`));
|
|
124
|
+
}
|
|
125
|
+
if (parts.length > 0) {
|
|
126
|
+
console.log(` ${parts.join(', ')} ${color('gray', `(${durationStr})`)}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Print a test result line
|
|
131
|
+
*/
|
|
132
|
+
printTestResult(test, result) {
|
|
133
|
+
const duration = result.duration;
|
|
134
|
+
const durationStr = duration > 0 ? color('gray', ` (${this.formatDuration(duration)})`) : '';
|
|
135
|
+
const titlePath = this.getDisplayTitle(test);
|
|
136
|
+
let status;
|
|
137
|
+
switch (result.status) {
|
|
138
|
+
case 'passed':
|
|
139
|
+
status = color('green', '✓');
|
|
140
|
+
break;
|
|
141
|
+
case 'failed':
|
|
142
|
+
case 'timedOut':
|
|
143
|
+
status = color('red', '✗');
|
|
144
|
+
break;
|
|
145
|
+
case 'skipped':
|
|
146
|
+
status = color('yellow', '-');
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
status = '?';
|
|
150
|
+
}
|
|
151
|
+
console.log(` ${status} ${titlePath}${durationStr}`);
|
|
152
|
+
// Print error for failed tests
|
|
153
|
+
if (result.status === 'failed' || result.status === 'timedOut') {
|
|
154
|
+
for (const error of result.errors) {
|
|
155
|
+
if (error.message) {
|
|
156
|
+
const lines = error.message.split('\n').slice(0, 3);
|
|
157
|
+
for (const line of lines) {
|
|
158
|
+
console.log(color('red', ` ${line}`));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
57
161
|
}
|
|
58
162
|
}
|
|
59
163
|
}
|
|
60
164
|
/**
|
|
61
|
-
*
|
|
62
|
-
* Format: {relative-file}::{describe}::{test-title}
|
|
63
|
-
*
|
|
64
|
-
* This must match the format generated by the orchestrator.
|
|
65
|
-
*
|
|
66
|
-
* Note: titlePath() returns [projectName?, fileName, ...describes, testTitle]
|
|
67
|
-
* We need to filter out projectName and fileName since we already have
|
|
68
|
-
* the full relative file path.
|
|
165
|
+
* Print a filtered test (debug mode only)
|
|
69
166
|
*/
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
167
|
+
printFiltered(test) {
|
|
168
|
+
const titlePath = this.getDisplayTitle(test);
|
|
169
|
+
console.log(` ${color('gray', '○')} ${color('gray', titlePath)}`);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get display title for a test (file > describe > test)
|
|
173
|
+
*/
|
|
174
|
+
getDisplayTitle(test) {
|
|
175
|
+
const file = path.basename(test.location.file);
|
|
176
|
+
const filteredTitles = this.getFilteredTitles(test);
|
|
177
|
+
return `${file} > ${filteredTitles.join(' > ')}`;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Filter titlePath to get only describe blocks and test title.
|
|
181
|
+
* Uses shared filterRuntimeTitlePath function for consistency.
|
|
182
|
+
*/
|
|
183
|
+
getFilteredTitles(test) {
|
|
77
184
|
const titlePath = test.titlePath();
|
|
78
185
|
const projectName = test.parent?.project()?.name;
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
186
|
+
const fileName = path.basename(test.location.file);
|
|
187
|
+
return filterRuntimeTitlePath(titlePath, { projectName, fileName });
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Format duration in human readable format
|
|
191
|
+
*/
|
|
192
|
+
formatDuration(ms) {
|
|
193
|
+
if (ms < 1000) {
|
|
194
|
+
return `${ms}ms`;
|
|
195
|
+
}
|
|
196
|
+
const seconds = ms / 1000;
|
|
197
|
+
if (seconds < 60) {
|
|
198
|
+
return `${seconds.toFixed(1)}s`;
|
|
199
|
+
}
|
|
200
|
+
const minutes = Math.floor(seconds / 60);
|
|
201
|
+
const remainingSeconds = Math.round(seconds % 60);
|
|
202
|
+
return `${minutes}m ${remainingSeconds}s`;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Build test ID from TestCase.
|
|
206
|
+
* Uses shared buildTestIdFromRuntime function for consistency with fixture.
|
|
207
|
+
*/
|
|
208
|
+
buildTestId(test) {
|
|
209
|
+
const testDir = test.parent?.project()?.testDir;
|
|
210
|
+
const baseDir = testDir || this.rootDir || process.cwd();
|
|
211
|
+
return buildTestIdFromRuntime(test.location.file, test.titlePath(), {
|
|
212
|
+
projectName: test.parent?.project()?.name,
|
|
213
|
+
baseDir,
|
|
90
214
|
});
|
|
91
|
-
return [file, ...filteredTitles].join('::');
|
|
92
215
|
}
|
|
93
216
|
}
|
|
94
217
|
//# sourceMappingURL=reporter.js.map
|
package/dist/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED