@@ -87,29 +94,29 @@ export const TestResultView: React.FC<{
})}
}
{!!result.steps.length &&
- {result.steps.map((step, i) => )}
+ {result.steps.map((step, i) => )}
}
{diffs.map((diff, index) =>
-
-
+
+
)}
- {!!screenshots.length &&
+ {!!screenshots.length &&
{screenshots.map((a, i) => {
- return
+ return
- ;
+ ;
})}
}
- {!!traces.length &&
+ {!!traces.length &&
{}
}
- {!!videos.length &&
+ {!!videos.length &&
{videos.map((a, i) =>
)}
}
- {!!(otherAttachments.size + htmls.length) &&
- {[...htmls].map((a, i) => (
- )
+ {!!otherAttachments.size &&
+ {[...otherAttachments].map((a, i) =>
+
+
+
)}
- {[...otherAttachments].map((a, i) => )}
}
;
};
@@ -161,19 +169,23 @@ function classifyErrors(testErrors: string[], diffs: ImageDiff[]) {
}
const StepTreeItem: React.FC<{
+ test: TestCase;
+ result: TestResult;
step: TestStep;
depth: number,
-}> = ({ step, depth }) => {
- return
+}> = ({ test, step, result, depth }) => {
+ const attachmentName = step.title.match(/^attach "(.*)"$/)?.[1];
+ return
{msToString(step.duration)}
+ {attachmentName && { evt.stopPropagation(); }}>{icons.attachment()}}
{statusIcon(step.error || step.duration === -1 ? 'failed' : 'passed')}
{step.title}
{step.count > 1 && <> ✕ {step.count}>}
{step.location && — {step.location.file}:{step.location.line}}
} loadChildren={step.steps.length + (step.snippet ? 1 : 0) ? () => {
- const children = step.steps.map((s, i) => );
+ const children = step.steps.map((s, i) => );
if (step.snippet)
- children.unshift();
+ children.unshift();
return children;
- } : undefined} depth={depth}>;
+ } : undefined} depth={depth}/>;
};
diff --git a/packages/html-reporter/src/treeItem.css b/packages/html-reporter/src/treeItem.css
index a8cedc4f6af38..f37a759c2d4fa 100644
--- a/packages/html-reporter/src/treeItem.css
+++ b/packages/html-reporter/src/treeItem.css
@@ -25,6 +25,11 @@
cursor: pointer;
}
+.tree-item-title.selected {
+ text-decoration: underline var(--color-underlinenav-icon);
+ text-decoration-thickness: 1.5px;
+}
+
.tree-item-body {
min-height: 18px;
}
diff --git a/packages/html-reporter/src/treeItem.tsx b/packages/html-reporter/src/treeItem.tsx
index 507a9c0e716f5..926a398a053f7 100644
--- a/packages/html-reporter/src/treeItem.tsx
+++ b/packages/html-reporter/src/treeItem.tsx
@@ -17,6 +17,7 @@
import * as React from 'react';
import './treeItem.css';
import * as icons from './icons';
+import { clsx } from '@web/uiUtils';
export const TreeItem: React.FunctionComponent<{
title: JSX.Element,
@@ -28,9 +29,8 @@ export const TreeItem: React.FunctionComponent<{
style?: React.CSSProperties,
}> = ({ title, loadChildren, onClick, expandByDefault, depth, selected, style }) => {
const [expanded, setExpanded] = React.useState(expandByDefault || false);
- const className = selected ? 'tree-item-title selected' : 'tree-item-title';
return
- { onClick?.(); setExpanded(!expanded); }} >
+ { onClick?.(); setExpanded(!expanded); }} >
{loadChildren && !!expanded && icons.downArrow()}
{loadChildren && !expanded && icons.rightArrow()}
{!loadChildren && {icons.rightArrow()}}
diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts
index 048976ea2326e..5568455d6320d 100644
--- a/tests/playwright-test/reporter-html.spec.ts
+++ b/tests/playwright-test/reporter-html.spec.ts
@@ -847,7 +847,7 @@ for (const useIntermediateMergeReport of [true, false] as const) {
'a.test.js': `
import { test, expect } from '@playwright/test';
test('passing', async ({ page }, testInfo) => {
- testInfo.attach('axe-report.html', {
+ await testInfo.attach('axe-report.html', {
contentType: 'text/html',
body: 'Axe Report
',
});
@@ -916,6 +916,28 @@ for (const useIntermediateMergeReport of [true, false] as const) {
]));
});
+ test('should link from attach step to attachment view', async ({ runInlineTest, page, showReport }) => {
+ const result = await runInlineTest({
+ 'a.test.js': `
+ import { test, expect } from '@playwright/test';
+ test('passing', async ({ page }, testInfo) => {
+ for (let i = 0; i < 100; i++)
+ await testInfo.attach('foo-1', { body: 'bar' });
+ await testInfo.attach('foo-2', { body: 'bar' });
+ });
+ `,
+ }, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' });
+ expect(result.exitCode).toBe(0);
+
+ await showReport();
+ await page.getByRole('link', { name: 'passing' }).click();
+
+ const attachment = page.getByText('foo-2', { exact: true });
+ await expect(attachment).not.toBeInViewport();
+ await page.getByLabel('attach "foo-2"').getByTitle('link to attachment').click();
+ await expect(attachment).toBeInViewport();
+ });
+
test('should highlight textual diff', async ({ runInlineTest, showReport, page }) => {
const result = await runInlineTest({
'helper.ts': `