Skip to content

Commit 76ee48d

Browse files
Skn0ttdgozman
andauthored
chore: followup on static annotations (#35579)
Signed-off-by: Simon Knott <info@simonknott.de> Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
1 parent d79bb57 commit 76ee48d

17 files changed

Lines changed: 63 additions & 81 deletions

File tree

docs/src/test-reporter-api/class-testcase.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,7 @@
1111
- `description` ?<[string]> Optional description.
1212
- `location` ?<[Location]> Optional location in the source where the annotation is added.
1313

14-
The list of annotations applicable to the current test. Includes:
15-
* annotations defined on the test or suite via [`method: Test.(call)`] and [`method: Test.describe`];
16-
* annotations implicitly added by methods [`method: Test.skip`], [`method: Test.fixme`] and [`method: Test.fail`] prior to test execution.
17-
18-
Annotations are available during test execution through [`property: TestInfo.annotations`].
19-
20-
Learn more about [test annotations](../test-annotations.md).
14+
[`property: TestResult.annotations`] of the last test run.
2115

2216
## property: TestCase.expectedStatus
2317
* since: v1.10

docs/src/test-reporter-api/class-testresult.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ The list of files or buffers attached during the test execution through [`proper
2121
- `description` ?<[string]> Optional description.
2222
- `location` ?<[Location]> Optional location in the source where the annotation is added.
2323

24-
The list of annotations appended during test execution. Includes:
25-
* annotations implicitly added by methods [`method: Test.skip`], [`method: Test.fixme`] and [`method: Test.fail`] during test execution;
26-
* annotations appended to [`property: TestInfo.annotations`].
24+
The list of annotations applicable to the current test. Includes:
25+
* annotations defined on the test or suite via [`method: Test.(call)`] and [`method: Test.describe`];
26+
* annotations implicitly added by methods [`method: Test.skip`], [`method: Test.fixme`] and [`method: Test.fail`];
27+
* annotations appended to [`property: TestInfo.annotations`] during the test execution.
2728

2829
Annotations are available during test execution through [`property: TestInfo.annotations`].
2930

packages/html-reporter/src/testCaseView.spec.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ const result: TestResult = {
4242
}],
4343
attachments: [],
4444
}],
45-
annotations: [],
45+
annotations: [
46+
{ type: 'annotation', description: 'Annotation text' },
47+
{ type: 'annotation', description: 'Another annotation text' },
48+
{ type: '_annotation', description: 'Hidden annotation' },
49+
],
4650
attachments: [],
4751
status: 'passed',
4852
};
@@ -53,11 +57,7 @@ const testCase: TestCase = {
5357
path: [],
5458
projectName: 'chromium',
5559
location: { file: 'test.spec.ts', line: 42, column: 0 },
56-
annotations: [
57-
{ type: 'annotation', description: 'Annotation text' },
58-
{ type: 'annotation', description: 'Another annotation text' },
59-
{ type: '_annotation', description: 'Hidden annotation' },
60-
],
60+
annotations: result.annotations,
6161
tags: [],
6262
outcome: 'expected',
6363
duration: 200,
@@ -98,16 +98,18 @@ const annotationLinkRenderingTestCase: TestCase = {
9898
path: [],
9999
projectName: 'chromium',
100100
location: { file: 'test.spec.ts', line: 42, column: 0 },
101-
annotations: [
102-
{ type: 'more info', description: 'read https://playwright.dev/docs/intro and https://playwright.dev/docs/api/class-playwright' },
103-
{ type: 'related issues', description: 'https://github.com/microsoft/playwright/issues/23180, https://github.com/microsoft/playwright/issues/23181' },
104-
105-
],
101+
annotations: [],
106102
tags: [],
107103
outcome: 'expected',
108104
duration: 10,
109105
ok: true,
110-
results: [result]
106+
results: [{
107+
...result,
108+
annotations: [
109+
{ type: 'more info', description: 'read https://playwright.dev/docs/intro and https://playwright.dev/docs/api/class-playwright' },
110+
{ type: 'related issues', description: 'https://github.com/microsoft/playwright/issues/23180, https://github.com/microsoft/playwright/issues/23181' },
111+
]
112+
}]
111113
};
112114

113115
test('should correctly render links in annotations', async ({ mount }) => {

packages/html-reporter/src/testCaseView.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,7 @@ export const TestCaseView: React.FC<{
4646
return test.tags;
4747
}, [test]);
4848

49-
const visibleAnnotations = React.useMemo(() => {
50-
if (!test)
51-
return [];
52-
const annotations = [...test.annotations];
53-
if (test.results[selectedResultIndex])
54-
annotations.push(...test.results[selectedResultIndex].annotations);
55-
return annotations.filter(annotation => !annotation.type.startsWith('_'));
56-
}, [test, selectedResultIndex]);
49+
const visibleTestAnnotations = test?.annotations.filter(a => !a.type.startsWith('_')) ?? [];
5750

5851
return <div className='test-case-column vbox'>
5952
{test && <div className='hbox'>
@@ -77,8 +70,8 @@ export const TestCaseView: React.FC<{
7770
{test && !!test.projectName && <ProjectLink projectNames={projectNames} projectName={test.projectName}></ProjectLink>}
7871
{labels && <LabelsLinkView labels={labels} />}
7972
</div>}
80-
{!!visibleAnnotations.length && <AutoChip header='Annotations' dataTestId='test-case-annotations'>
81-
{visibleAnnotations.map((annotation, index) => <TestCaseAnnotationView key={index} annotation={annotation} />)}
73+
{test?.results.length === 0 && visibleTestAnnotations.length !== 0 && <AutoChip header='Annotations' dataTestId='test-case-annotations'>
74+
{visibleTestAnnotations.map((annotation, index) => <TestCaseAnnotationView key={index} annotation={annotation} />)}
8275
</AutoChip>}
8376
{test && <TabbedPane tabs={
8477
test.results.map((result, index) => ({
@@ -87,7 +80,15 @@ export const TestCaseView: React.FC<{
8780
{statusIcon(result.status)} {retryLabel(index)}
8881
{(test.results.length > 1) && <span className='test-case-run-duration'>{msToString(result.duration)}</span>}
8982
</div>,
90-
render: () => <TestResultView test={test!} result={result} />
83+
render: () => {
84+
const visibleAnnotations = result.annotations.filter(annotation => !annotation.type.startsWith('_'));
85+
return <>
86+
{!!visibleAnnotations.length && <AutoChip header='Annotations' dataTestId='test-case-annotations'>
87+
{visibleAnnotations.map((annotation, index) => <TestCaseAnnotationView key={index} annotation={annotation} />)}
88+
</AutoChip>}
89+
<TestResultView test={test!} result={result} />
90+
</>;
91+
},
9192
})) || []} selectedTab={String(selectedResultIndex)} setSelectedTab={id => setSelectedResultIndex(+id)} />}
9293
</div>;
9394
};

packages/playwright/src/isomorphic/teleReceiver.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,16 @@ export class TeleReporterReceiver {
235235
const test = this._tests.get(testEndPayload.testId)!;
236236
test.timeout = testEndPayload.timeout;
237237
test.expectedStatus = testEndPayload.expectedStatus;
238-
// Should be empty array, but if it's not, it represents all annotations for that test
239-
if (testEndPayload.annotations.length > 0)
240-
test.annotations = this._absoluteAnnotationLocations(testEndPayload.annotations);
241238
const result = test.results.find(r => r._id === payload.id)!;
242239
result.duration = payload.duration;
243240
result.status = payload.status;
244241
result.errors = payload.errors;
245242
result.error = result.errors?.[0];
246243
result.attachments = this._parseAttachments(payload.attachments);
247-
if (payload.annotations)
244+
if (payload.annotations) {
248245
result.annotations = this._absoluteAnnotationLocations(payload.annotations);
246+
test.annotations = result.annotations;
247+
}
249248
this._reporter.onTestEnd?.(test, result);
250249
// Free up the memory as won't see these step ids.
251250
result._stepMap = new Map();

packages/playwright/src/reporters/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ export function formatFailure(screen: Screen, config: FullConfig, test: TestCase
320320
const header = formatTestHeader(screen, config, test, { indent: ' ', index, mode: 'error' });
321321
lines.push(screen.colors.red(header));
322322
for (const result of test.results) {
323-
const warnings = [...result.annotations, ...test.annotations].filter(a => a.type === 'warning');
323+
const warnings = result.annotations.filter(a => a.type === 'warning');
324324
const resultLines: string[] = [];
325325
const errors = formatResultFailure(screen, test, result, ' ');
326326
if (!errors.length)

packages/playwright/src/reporters/html.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ class HtmlBuilder {
417417
projectName,
418418
location,
419419
duration,
420-
annotations: this._serializeAnnotations([...test.annotations, ...results.flatMap(r => r.annotations)]),
420+
annotations: this._serializeAnnotations(test.annotations),
421421
tags: test.tags,
422422
outcome: test.outcome(),
423423
path,

packages/playwright/src/reporters/junit.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@ class JUnitReporter implements ReporterV2 {
166166
children: [] as XMLEntry[]
167167
};
168168

169-
const annotations = [...test.annotations, ...test.results.flatMap(r => r.annotations)];
170-
for (const annotation of annotations) {
169+
for (const annotation of test.annotations) {
171170
const property: XMLEntry = {
172171
name: 'property',
173172
attributes: {

packages/playwright/src/runner/dispatcher.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ class JobDispatcher {
326326
result.error = result.errors[0];
327327
result.status = params.status;
328328
result.annotations = params.annotations;
329+
test.annotations = [...params.annotations]; // last test result wins
329330
test.expectedStatus = params.expectedStatus;
330331
test.timeout = params.timeout;
331332
const isFailure = result.status !== 'skipped' && result.status !== test.expectedStatus;

packages/playwright/src/worker/workerMain.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,6 @@ export class WorkerMain extends ProcessRunner {
293293
for (const annotation of test.annotations)
294294
processAnnotation(annotation);
295295

296-
const staticAnnotations = new Set(testInfo.annotations);
297-
298296
// Process existing annotations dynamically set for parent suites.
299297
for (const suite of suites) {
300298
const extraAnnotations = this._activeSuites.get(suite) || [];
@@ -313,7 +311,7 @@ export class WorkerMain extends ProcessRunner {
313311
if (isSkipped && nextTest && !hasAfterAllToRunBeforeNextTest) {
314312
// Fast path - this test is skipped, and there are more tests that will handle cleanup.
315313
testInfo.status = 'skipped';
316-
this.dispatchEvent('testEnd', buildTestEndPayload(testInfo, staticAnnotations));
314+
this.dispatchEvent('testEnd', buildTestEndPayload(testInfo));
317315
return;
318316
}
319317

@@ -495,7 +493,7 @@ export class WorkerMain extends ProcessRunner {
495493

496494
this._currentTest = null;
497495
setCurrentTestInfo(null);
498-
this.dispatchEvent('testEnd', buildTestEndPayload(testInfo, staticAnnotations));
496+
this.dispatchEvent('testEnd', buildTestEndPayload(testInfo));
499497

500498
const preserveOutput = this._config.config.preserveOutput === 'always' ||
501499
(this._config.config.preserveOutput === 'failures-only' && testInfo._isFailure());
@@ -615,15 +613,15 @@ function buildTestBeginPayload(testInfo: TestInfoImpl): TestBeginPayload {
615613
};
616614
}
617615

618-
function buildTestEndPayload(testInfo: TestInfoImpl, staticAnnotations: Set<TestAnnotation>): TestEndPayload {
616+
function buildTestEndPayload(testInfo: TestInfoImpl): TestEndPayload {
619617
return {
620618
testId: testInfo.testId,
621619
duration: testInfo.duration,
622620
status: testInfo.status!,
623621
errors: testInfo.errors,
624622
hasNonRetriableError: testInfo._hasNonRetriableError,
625623
expectedStatus: testInfo.expectedStatus,
626-
annotations: testInfo.annotations.filter(a => !staticAnnotations.has(a)),
624+
annotations: testInfo.annotations,
627625
timeout: testInfo.timeout,
628626
};
629627
}

0 commit comments

Comments
 (0)