diff --git a/superset-frontend/playwright/reporters/cypress-style-reporter.ts b/superset-frontend/playwright/reporters/cypress-style-reporter.ts index 3582c8ca9df..05aa5be04f7 100644 --- a/superset-frontend/playwright/reporters/cypress-style-reporter.ts +++ b/superset-frontend/playwright/reporters/cypress-style-reporter.ts @@ -46,6 +46,7 @@ interface FileResult { bufferedOutput: string[]; duration: number; started: boolean; + hasPromotedResults: boolean; } interface Colors { @@ -114,6 +115,7 @@ export default class CypressStyleReporter implements Reporter { bufferedOutput: [], duration: 0, started: false, + hasPromotedResults: false, }); this.fileOrder.push(fileKey); } @@ -226,6 +228,7 @@ export default class CypressStyleReporter implements Reporter { for (const [testId, pending] of file.pendingResults) { if (!file.results.has(testId)) { file.results.set(testId, pending); + file.hasPromotedResults = true; } } } @@ -435,7 +438,8 @@ export default class CypressStyleReporter implements Reporter { let passing = 0; let failing = 0; let skippedCount = 0; - const wasInterrupted = file.results.size < file.totalExpected; + const wasInterrupted = + file.hasPromotedResults || file.results.size < file.totalExpected; for (const r of file.results.values()) { if (r.outcome === 'expected' || r.outcome === 'flaky') passing += 1; @@ -445,7 +449,7 @@ export default class CypressStyleReporter implements Reporter { const tests = file.results.size; totalSpecs += 1; - if (failing > 0) failedSpecs += 1; + if (failing > 0 && !wasInterrupted) failedSpecs += 1; totalSkipped += skippedCount; const marker = wasInterrupted diff --git a/superset-frontend/spec/reporters/cypress-style-reporter.test.ts b/superset-frontend/spec/reporters/cypress-style-reporter.test.ts index ce24fc6fa18..9376dfa7cd5 100644 --- a/superset-frontend/spec/reporters/cypress-style-reporter.test.ts +++ b/superset-frontend/spec/reporters/cypress-style-reporter.test.ts @@ -859,6 +859,42 @@ test('footer counts failed specs, not individual failed tests', () => { expect(output).not.toContain('2 of 4 failed'); }); +test('promoted retry results keep spec marked as interrupted in summary', () => { + const reporter = new CypressStyleReporter(); + const t1 = mockTest({ + id: '1', + title: 'fails once', + file: 'tests/promoted.spec.ts', + retries: 2, + outcome: 'unexpected', + }); + + reporter.onBegin(mockConfig, mockSuite([t1])); + + // First attempt fails (non-terminal: retry 0 !== retries 2) + reporter.onTestEnd( + t1, + mockResult({ + status: 'failed', + retry: 0, + duration: 1000, + errors: [{ message: 'first fail' }], + }), + ); + + // Run interrupted before retry 1 — onEnd promotes pending result + reporter.onEnd({ status: 'interrupted' } as any); + + const output = getStdout(); + // Per-file box: promoted result shown with interrupted label + expect(output).toContain('✗ fails once'); + expect(output).toContain('1 of 1 (interrupted)'); + // Footer: "Run was interrupted", NOT "1 of 1 failed" + // (the failure is transient — test never exhausted its retries) + expect(output).toContain('interrupted'); + expect(output).not.toContain('1 of 1 failed'); +}); + test('interrupted test with retries is treated as terminal, not dropped', () => { const reporter = new CypressStyleReporter(); const t1 = mockTest({