@nsxbet/playwright-orchestrator 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -136
- package/dist/commands/assign.d.ts.map +1 -1
- package/dist/commands/assign.js +26 -2
- package/dist/commands/assign.js.map +1 -1
- package/dist/commands/extract-timing.d.ts +0 -1
- package/dist/commands/extract-timing.d.ts.map +1 -1
- package/dist/commands/extract-timing.js +2 -32
- package/dist/commands/extract-timing.js.map +1 -1
- package/dist/core/test-discovery.d.ts +17 -3
- package/dist/core/test-discovery.d.ts.map +1 -1
- package/dist/core/test-discovery.js +39 -19
- package/dist/core/test-discovery.js.map +1 -1
- package/dist/core/test-id.d.ts +23 -67
- package/dist/core/test-id.d.ts.map +1 -1
- package/dist/core/test-id.js +29 -86
- package/dist/core/test-id.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/package.json +1 -26
- package/dist/commands/filter-report.d.ts +0 -24
- package/dist/commands/filter-report.d.ts.map +0 -1
- package/dist/commands/filter-report.js +0 -123
- package/dist/commands/filter-report.js.map +0 -1
- package/dist/fixture.d.ts +0 -75
- package/dist/fixture.d.ts.map +0 -1
- package/dist/fixture.js +0 -148
- package/dist/fixture.js.map +0 -1
- package/dist/reporter.d.ts +0 -93
- package/dist/reporter.d.ts.map +0 -1
- package/dist/reporter.js +0 -343
- package/dist/reporter.js.map +0 -1
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { Command, Flags } from '@oclif/core';
|
|
4
|
-
export default class FilterReport extends Command {
|
|
5
|
-
static description = 'Remove orchestrator-skipped tests from a Playwright JSON report';
|
|
6
|
-
static examples = [
|
|
7
|
-
'<%= config.bin %> filter-report --report-file ./results.json',
|
|
8
|
-
'<%= config.bin %> filter-report --report-file ./merged.json --output-file ./filtered.json',
|
|
9
|
-
];
|
|
10
|
-
static flags = {
|
|
11
|
-
'report-file': Flags.string({
|
|
12
|
-
char: 'r',
|
|
13
|
-
description: 'Path to Playwright JSON report file',
|
|
14
|
-
required: true,
|
|
15
|
-
}),
|
|
16
|
-
'output-file': Flags.string({
|
|
17
|
-
char: 'o',
|
|
18
|
-
description: 'Path to write filtered report (defaults to overwriting input)',
|
|
19
|
-
}),
|
|
20
|
-
verbose: Flags.boolean({
|
|
21
|
-
char: 'v',
|
|
22
|
-
description: 'Show verbose output',
|
|
23
|
-
default: false,
|
|
24
|
-
}),
|
|
25
|
-
};
|
|
26
|
-
async run() {
|
|
27
|
-
const { flags } = await this.parse(FilterReport);
|
|
28
|
-
const reportPath = path.resolve(flags['report-file']);
|
|
29
|
-
if (!fs.existsSync(reportPath)) {
|
|
30
|
-
this.warn(`Report file not found: ${reportPath}`);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
let report;
|
|
34
|
-
try {
|
|
35
|
-
report = JSON.parse(fs.readFileSync(reportPath, 'utf-8'));
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
this.error(`Failed to parse report: ${reportPath}`);
|
|
39
|
-
}
|
|
40
|
-
if (!report.suites) {
|
|
41
|
-
this.warn('Report has no suites, nothing to filter');
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const suites = report.suites;
|
|
45
|
-
const beforeCount = this.countSpecs(suites);
|
|
46
|
-
this.filterSuites(suites);
|
|
47
|
-
const afterCount = this.countSpecs(suites);
|
|
48
|
-
const removed = beforeCount - afterCount;
|
|
49
|
-
const outputPath = flags['output-file']
|
|
50
|
-
? path.resolve(flags['output-file'])
|
|
51
|
-
: reportPath;
|
|
52
|
-
fs.writeFileSync(outputPath, JSON.stringify(report));
|
|
53
|
-
if (flags.verbose || removed > 0) {
|
|
54
|
-
this.log(`Filtered report: ${beforeCount} → ${afterCount} specs (removed ${removed} orchestrator-skipped)`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Check if a test has an orchestrator-skip annotation ("Not in shard").
|
|
59
|
-
*/
|
|
60
|
-
isOrchestratorSkipped(test) {
|
|
61
|
-
const annotations = test.annotations;
|
|
62
|
-
return (annotations?.some((a) => a.type === 'skip' && a.description === 'Not in shard') ?? false);
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Remove orchestrator-skipped entries at three levels:
|
|
66
|
-
* 1. Results: strip skipped results from tests with "Not in shard" annotation
|
|
67
|
-
* 2. Tests: remove tests with no remaining results
|
|
68
|
-
* 3. Specs/Suites: remove empty specs and prune empty suites
|
|
69
|
-
*/
|
|
70
|
-
filterSuites(suites) {
|
|
71
|
-
for (let i = suites.length - 1; i >= 0; i--) {
|
|
72
|
-
const suite = suites[i];
|
|
73
|
-
if (!suite)
|
|
74
|
-
continue;
|
|
75
|
-
if (Array.isArray(suite.specs)) {
|
|
76
|
-
const specs = suite.specs;
|
|
77
|
-
for (const spec of specs) {
|
|
78
|
-
const tests = spec.tests;
|
|
79
|
-
if (!tests)
|
|
80
|
-
continue;
|
|
81
|
-
// Result-level: strip skipped results from orchestrator-skipped tests
|
|
82
|
-
for (const test of tests) {
|
|
83
|
-
if (!this.isOrchestratorSkipped(test))
|
|
84
|
-
continue;
|
|
85
|
-
const results = test.results;
|
|
86
|
-
if (!results)
|
|
87
|
-
continue;
|
|
88
|
-
test.results = results.filter((r) => r.status !== 'skipped');
|
|
89
|
-
}
|
|
90
|
-
// Test-level: remove tests with no remaining results
|
|
91
|
-
spec.tests = tests.filter((test) => {
|
|
92
|
-
const results = test.results;
|
|
93
|
-
return results && results.length > 0;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
// Spec-level: remove specs with no remaining tests
|
|
97
|
-
suite.specs = specs.filter((spec) => {
|
|
98
|
-
const tests = spec.tests;
|
|
99
|
-
return tests && tests.length > 0;
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
if (Array.isArray(suite.suites)) {
|
|
103
|
-
this.filterSuites(suite.suites);
|
|
104
|
-
}
|
|
105
|
-
const hasSpecs = Array.isArray(suite.specs) && suite.specs.length > 0;
|
|
106
|
-
const hasSubSuites = Array.isArray(suite.suites) && suite.suites.length > 0;
|
|
107
|
-
if (!hasSpecs && !hasSubSuites) {
|
|
108
|
-
suites.splice(i, 1);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
countSpecs(suites) {
|
|
113
|
-
let count = 0;
|
|
114
|
-
for (const suite of suites) {
|
|
115
|
-
if (Array.isArray(suite.specs))
|
|
116
|
-
count += suite.specs.length;
|
|
117
|
-
if (Array.isArray(suite.suites))
|
|
118
|
-
count += this.countSpecs(suite.suites);
|
|
119
|
-
}
|
|
120
|
-
return count;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
//# sourceMappingURL=filter-report.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"filter-report.js","sourceRoot":"","sources":["../../src/commands/filter-report.ts"],"names":[],"mappings":"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"}
|
package/dist/fixture.d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Playwright Orchestrator Fixture
|
|
3
|
-
*
|
|
4
|
-
* A Playwright fixture that filters tests based on a JSON shard file.
|
|
5
|
-
* This provides actual test skipping (unlike the reporter which only adds metadata).
|
|
6
|
-
*
|
|
7
|
-
* Usage in your test setup file (e.g., tests/setup.ts):
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { test as base } from '@playwright/test';
|
|
10
|
-
* import { withOrchestratorFilter } from '@nsxbet/playwright-orchestrator/fixture';
|
|
11
|
-
*
|
|
12
|
-
* // Create extended test with orchestrator filtering
|
|
13
|
-
* export const test = withOrchestratorFilter(base);
|
|
14
|
-
* export { expect } from '@playwright/test';
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* Then in your test files:
|
|
18
|
-
* ```typescript
|
|
19
|
-
* import { test, expect } from './setup';
|
|
20
|
-
*
|
|
21
|
-
* test('my test', async ({ page }) => {
|
|
22
|
-
* // ...
|
|
23
|
-
* });
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Environment variables:
|
|
27
|
-
* - ORCHESTRATOR_SHARD_FILE: Path to JSON file with array of test IDs
|
|
28
|
-
* - ORCHESTRATOR_DEBUG: Set to "1" to enable debug logging
|
|
29
|
-
*
|
|
30
|
-
* @module @nsxbet/playwright-orchestrator/fixture
|
|
31
|
-
*/
|
|
32
|
-
import type { TestType } from '@playwright/test';
|
|
33
|
-
/**
|
|
34
|
-
* Creates an extended test with orchestrator filtering as an auto-fixture.
|
|
35
|
-
* This ensures tests not in the current shard are skipped.
|
|
36
|
-
*
|
|
37
|
-
* IMPORTANT: Use this function to create your test object, then export it.
|
|
38
|
-
* All test files should import the extended test, not the base test.
|
|
39
|
-
*
|
|
40
|
-
* @param test - The base test object from @playwright/test
|
|
41
|
-
* @returns Extended test with orchestrator filtering
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```typescript
|
|
45
|
-
* // In setup.ts
|
|
46
|
-
* import { test as base } from '@playwright/test';
|
|
47
|
-
* import { withOrchestratorFilter } from '@nsxbet/playwright-orchestrator/fixture';
|
|
48
|
-
*
|
|
49
|
-
* export const test = withOrchestratorFilter(base);
|
|
50
|
-
*
|
|
51
|
-
* // In your.spec.ts
|
|
52
|
-
* import { test } from './setup';
|
|
53
|
-
* test('example', async ({ page }) => { ... });
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
export declare function withOrchestratorFilter<T extends object, W extends object>(test: TestType<T, W>): TestType<T & {
|
|
57
|
-
_orchestratorFilter: undefined;
|
|
58
|
-
}, W>;
|
|
59
|
-
/**
|
|
60
|
-
* Check if a test should run based on the shard file.
|
|
61
|
-
* Can be called manually in individual tests.
|
|
62
|
-
*
|
|
63
|
-
* @param testInfo - The testInfo object from Playwright
|
|
64
|
-
* @returns true if the test should run, false if it should be skipped
|
|
65
|
-
* @throws Error if project testDir is not configured
|
|
66
|
-
*/
|
|
67
|
-
export declare function shouldRunTest(testInfo: {
|
|
68
|
-
file: string;
|
|
69
|
-
titlePath: string[];
|
|
70
|
-
project: {
|
|
71
|
-
name: string;
|
|
72
|
-
testDir: string;
|
|
73
|
-
};
|
|
74
|
-
}): boolean;
|
|
75
|
-
//# sourceMappingURL=fixture.d.ts.map
|
package/dist/fixture.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAuDjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EACvE,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GACnB,QAAQ,CAAC,CAAC,GAAG;IAAE,mBAAmB,EAAE,SAAS,CAAA;CAAE,EAAE,CAAC,CAAC,CAwDrD;AAED;;;;;;;GAOG;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,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C,GAAG,OAAO,CAUV"}
|
package/dist/fixture.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Playwright Orchestrator Fixture
|
|
3
|
-
*
|
|
4
|
-
* A Playwright fixture that filters tests based on a JSON shard file.
|
|
5
|
-
* This provides actual test skipping (unlike the reporter which only adds metadata).
|
|
6
|
-
*
|
|
7
|
-
* Usage in your test setup file (e.g., tests/setup.ts):
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { test as base } from '@playwright/test';
|
|
10
|
-
* import { withOrchestratorFilter } from '@nsxbet/playwright-orchestrator/fixture';
|
|
11
|
-
*
|
|
12
|
-
* // Create extended test with orchestrator filtering
|
|
13
|
-
* export const test = withOrchestratorFilter(base);
|
|
14
|
-
* export { expect } from '@playwright/test';
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* Then in your test files:
|
|
18
|
-
* ```typescript
|
|
19
|
-
* import { test, expect } from './setup';
|
|
20
|
-
*
|
|
21
|
-
* test('my test', async ({ page }) => {
|
|
22
|
-
* // ...
|
|
23
|
-
* });
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Environment variables:
|
|
27
|
-
* - ORCHESTRATOR_SHARD_FILE: Path to JSON file with array of test IDs
|
|
28
|
-
* - ORCHESTRATOR_DEBUG: Set to "1" to enable debug logging
|
|
29
|
-
*
|
|
30
|
-
* @module @nsxbet/playwright-orchestrator/fixture
|
|
31
|
-
*/
|
|
32
|
-
import * as fs from 'node:fs';
|
|
33
|
-
import { buildTestIdFromRuntime } from './core/test-id.js';
|
|
34
|
-
// Module initialization debug - only in debug mode
|
|
35
|
-
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
36
|
-
process.stderr.write('[Fixture Module] Loading orchestrator fixture\n');
|
|
37
|
-
}
|
|
38
|
-
// Cache the shard file to avoid re-reading on every test
|
|
39
|
-
let cachedAllowedTestIds = null;
|
|
40
|
-
let cacheInitialized = false;
|
|
41
|
-
function loadShardFile() {
|
|
42
|
-
if (cacheInitialized)
|
|
43
|
-
return cachedAllowedTestIds;
|
|
44
|
-
cacheInitialized = true;
|
|
45
|
-
const shardFile = process.env.ORCHESTRATOR_SHARD_FILE;
|
|
46
|
-
if (!shardFile || !fs.existsSync(shardFile)) {
|
|
47
|
-
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
48
|
-
console.log('[Orchestrator] No shard file, running all tests');
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
const parsed = JSON.parse(fs.readFileSync(shardFile, 'utf-8'));
|
|
54
|
-
// Validate shard file format
|
|
55
|
-
if (!Array.isArray(parsed) ||
|
|
56
|
-
!parsed.every((id) => typeof id === 'string')) {
|
|
57
|
-
throw new Error('[Orchestrator] Shard file must be a JSON array of strings');
|
|
58
|
-
}
|
|
59
|
-
const testIds = parsed;
|
|
60
|
-
cachedAllowedTestIds = new Set(testIds);
|
|
61
|
-
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
62
|
-
process.stderr.write(`[Orchestrator] Loaded ${testIds.length} tests for this shard\n`);
|
|
63
|
-
process.stderr.write(`[Orchestrator] Sample IDs: ${testIds.slice(0, 3).join(' | ')}\n`);
|
|
64
|
-
}
|
|
65
|
-
return cachedAllowedTestIds;
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
console.error('[Orchestrator] Failed to load shard file:', error);
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Creates an extended test with orchestrator filtering as an auto-fixture.
|
|
74
|
-
* This ensures tests not in the current shard are skipped.
|
|
75
|
-
*
|
|
76
|
-
* IMPORTANT: Use this function to create your test object, then export it.
|
|
77
|
-
* All test files should import the extended test, not the base test.
|
|
78
|
-
*
|
|
79
|
-
* @param test - The base test object from @playwright/test
|
|
80
|
-
* @returns Extended test with orchestrator filtering
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```typescript
|
|
84
|
-
* // In setup.ts
|
|
85
|
-
* import { test as base } from '@playwright/test';
|
|
86
|
-
* import { withOrchestratorFilter } from '@nsxbet/playwright-orchestrator/fixture';
|
|
87
|
-
*
|
|
88
|
-
* export const test = withOrchestratorFilter(base);
|
|
89
|
-
*
|
|
90
|
-
* // In your.spec.ts
|
|
91
|
-
* import { test } from './setup';
|
|
92
|
-
* test('example', async ({ page }) => { ... });
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
export function withOrchestratorFilter(test) {
|
|
96
|
-
return test.extend({
|
|
97
|
-
// @ts-expect-error - Playwright's auto fixture typing is complex
|
|
98
|
-
_orchestratorFilter: [
|
|
99
|
-
async (
|
|
100
|
-
// biome-ignore lint/correctness/noEmptyPattern: Playwright requires empty destructuring
|
|
101
|
-
{}, use, testInfo) => {
|
|
102
|
-
const allowedTestIds = loadShardFile();
|
|
103
|
-
if (allowedTestIds) {
|
|
104
|
-
// CRITICAL: Use project.testDir for consistent path resolution with test-discovery
|
|
105
|
-
// No fallback to process.cwd() - this causes path mismatch bugs
|
|
106
|
-
const testDir = testInfo.project.testDir;
|
|
107
|
-
if (!testDir) {
|
|
108
|
-
throw new Error('[Orchestrator Fixture] Could not determine project testDir. ' +
|
|
109
|
-
'Ensure your playwright.config.ts has projects configured with testDir.');
|
|
110
|
-
}
|
|
111
|
-
const testId = buildTestIdFromRuntime(testInfo.file, testInfo.titlePath, {
|
|
112
|
-
projectName: testInfo.project.name,
|
|
113
|
-
baseDir: testDir,
|
|
114
|
-
});
|
|
115
|
-
const isAllowed = allowedTestIds.has(testId);
|
|
116
|
-
// Debug: Write to stderr for visibility in CI logs
|
|
117
|
-
if (process.env.ORCHESTRATOR_DEBUG === '1') {
|
|
118
|
-
process.stderr.write(`[Fixture] testDir=${testInfo.project.testDir} | testId=${testId} | allowed=${isAllowed}\n`);
|
|
119
|
-
}
|
|
120
|
-
if (!isAllowed) {
|
|
121
|
-
test.skip(true, 'Not in shard');
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
await use();
|
|
125
|
-
},
|
|
126
|
-
{ auto: true },
|
|
127
|
-
],
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Check if a test should run based on the shard file.
|
|
132
|
-
* Can be called manually in individual tests.
|
|
133
|
-
*
|
|
134
|
-
* @param testInfo - The testInfo object from Playwright
|
|
135
|
-
* @returns true if the test should run, false if it should be skipped
|
|
136
|
-
* @throws Error if project testDir is not configured
|
|
137
|
-
*/
|
|
138
|
-
export function shouldRunTest(testInfo) {
|
|
139
|
-
const allowedTestIds = loadShardFile();
|
|
140
|
-
if (!allowedTestIds)
|
|
141
|
-
return true;
|
|
142
|
-
const testId = buildTestIdFromRuntime(testInfo.file, testInfo.titlePath, {
|
|
143
|
-
projectName: testInfo.project.name,
|
|
144
|
-
baseDir: testInfo.project.testDir,
|
|
145
|
-
});
|
|
146
|
-
return allowedTestIds.has(testId);
|
|
147
|
-
}
|
|
148
|
-
//# sourceMappingURL=fixture.js.map
|
package/dist/fixture.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"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"}
|
package/dist/reporter.d.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Playwright Orchestrator Reporter
|
|
3
|
-
*
|
|
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)
|
|
12
|
-
*
|
|
13
|
-
* Usage:
|
|
14
|
-
* 1. Add to playwright.config.ts:
|
|
15
|
-
* reporter: [['@nsxbet/playwright-orchestrator/reporter'], ['json', {...}]]
|
|
16
|
-
* 2. Set ORCHESTRATOR_SHARD_FILE env var to path of JSON file with test IDs
|
|
17
|
-
*
|
|
18
|
-
* Environment variables:
|
|
19
|
-
* - ORCHESTRATOR_SHARD_FILE: Path to JSON file with array of test IDs
|
|
20
|
-
* - ORCHESTRATOR_DEBUG: Set to "1" to show filtered tests
|
|
21
|
-
*
|
|
22
|
-
* @module @nsxbet/playwright-orchestrator/reporter
|
|
23
|
-
*/
|
|
24
|
-
import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
|
|
25
|
-
interface OrchestratorReporterOptions {
|
|
26
|
-
filterJson?: string;
|
|
27
|
-
}
|
|
28
|
-
export default class OrchestratorReporter implements Reporter {
|
|
29
|
-
private allowedTestIds;
|
|
30
|
-
private debug;
|
|
31
|
-
private startTime;
|
|
32
|
-
private rootDir;
|
|
33
|
-
private testDir;
|
|
34
|
-
private filterJsonPath;
|
|
35
|
-
private passed;
|
|
36
|
-
private failed;
|
|
37
|
-
private skipped;
|
|
38
|
-
private filtered;
|
|
39
|
-
constructor(options?: OrchestratorReporterOptions);
|
|
40
|
-
onBegin(config: FullConfig, suite: Suite): void;
|
|
41
|
-
onTestEnd(test: TestCase, result: TestResult): void;
|
|
42
|
-
onEnd(_result: FullResult): void;
|
|
43
|
-
/**
|
|
44
|
-
* Print a test result line
|
|
45
|
-
*/
|
|
46
|
-
private printTestResult;
|
|
47
|
-
/**
|
|
48
|
-
* Print a filtered test (debug mode only)
|
|
49
|
-
*/
|
|
50
|
-
private printFiltered;
|
|
51
|
-
/**
|
|
52
|
-
* Get display title for a test (file > describe > test)
|
|
53
|
-
*/
|
|
54
|
-
private getDisplayTitle;
|
|
55
|
-
/**
|
|
56
|
-
* Filter titlePath to get only describe blocks and test title.
|
|
57
|
-
* Uses shared filterRuntimeTitlePath function for consistency.
|
|
58
|
-
*/
|
|
59
|
-
private getFilteredTitles;
|
|
60
|
-
/**
|
|
61
|
-
* Format duration in human readable format
|
|
62
|
-
*/
|
|
63
|
-
private formatDuration;
|
|
64
|
-
onExit(): Promise<void>;
|
|
65
|
-
/**
|
|
66
|
-
* Filter specs by checking test IDs against the allowedTestIds set.
|
|
67
|
-
* Builds test IDs from the JSON report structure (file path + describe chain + spec title),
|
|
68
|
-
* matching the same format used by discovery (buildTestId) and runtime (buildTestIdFromRuntime).
|
|
69
|
-
*
|
|
70
|
-
* This correctly handles ALL non-shard tests, including genuinely skipped tests
|
|
71
|
-
* (test.skip, test.fixme, test.describe.skip) that never receive the "Not in shard" annotation
|
|
72
|
-
* because the orchestrator fixture doesn't run for them.
|
|
73
|
-
*/
|
|
74
|
-
private filterSuitesById;
|
|
75
|
-
private resolveReportFilePath;
|
|
76
|
-
/**
|
|
77
|
-
* Recalculate the stats object to match the filtered suites.
|
|
78
|
-
* Playwright JSON stats use: expected (passed), skipped, unexpected (failed), flaky.
|
|
79
|
-
*/
|
|
80
|
-
private recalculateStats;
|
|
81
|
-
private countTestStatuses;
|
|
82
|
-
private countSpecs;
|
|
83
|
-
/**
|
|
84
|
-
* Build test ID from TestCase.
|
|
85
|
-
* Uses shared buildTestIdFromRuntime function for consistency with fixture.
|
|
86
|
-
*
|
|
87
|
-
* CRITICAL: Must use project.testDir to match discovery-generated test IDs.
|
|
88
|
-
* No fallback to rootDir or process.cwd() - these cause path mismatch bugs.
|
|
89
|
-
*/
|
|
90
|
-
private buildTestId;
|
|
91
|
-
}
|
|
92
|
-
export {};
|
|
93
|
-
//# sourceMappingURL=reporter.d.ts.map
|
package/dist/reporter.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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,UAAU,2BAA2B;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,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;IACrB,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,cAAc,CAAqB;IAG3C,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAK;gBAET,OAAO,CAAC,EAAE,2BAA2B;IAIjD,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK;IAuCxC,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;IAahB,MAAM;IAoDZ;;;;;;;;OAQG;IACH,OAAO,CAAC,gBAAgB;IAoDxB,OAAO,CAAC,qBAAqB;IAO7B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,UAAU;IAalB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;CAepB"}
|