diff --git a/packages/html-reporter/index.html b/packages/html-reporter/index.html
index 970a975b12..6a52233a36 100644
--- a/packages/html-reporter/index.html
+++ b/packages/html-reporter/index.html
@@ -21,7 +21,6 @@
Playwright Test Report | Summary
-
diff --git a/packages/html-reporter/src/headerView.tsx b/packages/html-reporter/src/headerView.tsx
index 925bc64721..fa341dd5c3 100644
--- a/packages/html-reporter/src/headerView.tsx
+++ b/packages/html-reporter/src/headerView.tsx
@@ -23,6 +23,7 @@ import * as icons from './icons';
import { Link, navigate } from './links';
import { statusIcon } from './statusIcon';
import { filterWithToken } from './filter';
+import { setDefaultFavIconAndTitle } from './uiUtils';
export const HeaderView: React.FC {
const params = new URLSearchParams(window.location.hash.slice(1));
setFilterText(params.get('q') || '');
+ setDefaultFavIconAndTitle();
};
window.addEventListener('popstate', popstateFn);
diff --git a/packages/html-reporter/src/index.tsx b/packages/html-reporter/src/index.tsx
index 683113f32a..062cab5d48 100644
--- a/packages/html-reporter/src/index.tsx
+++ b/packages/html-reporter/src/index.tsx
@@ -23,6 +23,7 @@ import * as ReactDOM from 'react-dom';
import './colors.css';
import type { LoadedReport } from './loadedReport';
import { ReportView } from './reportView';
+import { setDefaultFavIconAndTitle } from './uiUtils';
// @ts-ignore
const zipjs = zipImport as typeof zip;
@@ -34,6 +35,10 @@ const ReportLoader: React.FC = () => {
const zipReport = new ZipReport();
zipReport.load().then(() => setReport(zipReport));
}, [report]);
+
+ React.useEffect(() => {
+ setDefaultFavIconAndTitle();
+ }, []);
return ;
};
diff --git a/packages/html-reporter/src/testCaseView.spec.tsx b/packages/html-reporter/src/testCaseView.spec.tsx
index edfa6f7bc6..fdf99703fe 100644
--- a/packages/html-reporter/src/testCaseView.spec.tsx
+++ b/packages/html-reporter/src/testCaseView.spec.tsx
@@ -79,14 +79,14 @@ test('should render test case', async ({ mount }) => {
test('should correctly set the page title and favicon', async ({ mount, page }) => {
await mount();
- expect(await page.locator('link[rel="icon"]').getAttribute('href')).toEqual('../logo_expected.svg');
+ expect(await page.locator('link[rel="icon"]').getAttribute('href')).toMatch(/\/assets\/logo_expected-[A-Za-z0-9]+\.svg/);
expect(await page.title()).toEqual(`| ${testCase.title}`);
});
test('should fallback to default title and favicon', async ({ mount, page }) => {
await mount();
- expect(await page.locator('link[rel="icon"]').getAttribute('href')).toEqual('../logo_default.svg');
- expect(await page.title()).toEqual('Playwright Test Report');
+ expect(await page.locator('link[rel="icon"]').getAttribute('href')).toMatch(/\/assets\/logo_default-[A-Za-z0-9]+\.svg/);
+ expect(await page.title()).toEqual('Playwright Test Report | Summary');
});
const linkRenderingTestCase: TestCase = {
diff --git a/packages/html-reporter/src/testCaseView.tsx b/packages/html-reporter/src/testCaseView.tsx
index 81311edecc..a0a4477822 100644
--- a/packages/html-reporter/src/testCaseView.tsx
+++ b/packages/html-reporter/src/testCaseView.tsx
@@ -14,7 +14,7 @@
limitations under the License.
*/
-import type { TestCase, TestCaseAnnotation, TestCaseSummary } from './types';
+import type { TestCase, TestCaseAnnotation } from './types';
import * as React from 'react';
import { TabbedPane } from './tabbedPane';
import { AutoChip } from './chip';
@@ -24,7 +24,7 @@ import { statusIcon } from './statusIcon';
import './testCaseView.css';
import { TestResultView } from './testResultView';
import { hashStringToInt } from './labelUtils';
-import { msToString } from './uiUtils';
+import { msToString, setDefaultFavIconAndTitle, setFavIcon } from './uiUtils';
export const TestCaseView: React.FC<{
projectNames: string[],
@@ -46,9 +46,9 @@ export const TestCaseView: React.FC<{
React.useEffect(() => {
document.title = test?.title ? `| ${test.title}` : 'Playwright Test Report';
- test?.outcome ? setFavicon({ outcome: test.outcome }) : setFavicon('default');
+ test?.outcome ? setFavIcon({ outcome: test.outcome }) : setDefaultFavIconAndTitle();
const resetFaviconOnBack = () => {
- setFavicon('default');
+ setDefaultFavIconAndTitle();
};
window.addEventListener('popstate', resetFaviconOnBack);
@@ -144,13 +144,3 @@ const LabelsLinkView: React.FC | 'default') {
- let link: HTMLLinkElement | null = document.querySelector("link[rel*='icon']");
- if (!link) {
- link = document.createElement('link');
- link.rel = 'icon';
- document.getElementsByTagName('head')[0].appendChild(link);
- }
- const outcomeValue = outcome instanceof Object ? outcome.outcome : outcome;
- link.href = `../logo_${outcomeValue}.svg`;
-}
\ No newline at end of file
diff --git a/packages/html-reporter/src/uiUtils.ts b/packages/html-reporter/src/uiUtils.ts
index 00022b4204..571b7e3e81 100644
--- a/packages/html-reporter/src/uiUtils.ts
+++ b/packages/html-reporter/src/uiUtils.ts
@@ -13,6 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
+import favIconExpected from '../logo_expected.svg';
+import favIconDefault from '../logo_default.svg';
+import favIconUnExpected from '../logo_unexpected.svg';
+import favIconSkipped from '../logo_skipped.svg';
+import favIconFlaky from '../logo_flaky.svg';
+import type { TestCaseSummary } from './types';
export function msToString(ms: number): string {
if (!isFinite(ms))
@@ -39,3 +45,37 @@ export function msToString(ms: number): string {
const days = hours / 24;
return days.toFixed(1) + 'd';
}
+
+export function setFavIcon(outcome: Pick) {
+ const link: HTMLLinkElement | null = getLinkIconElement();
+ const outcomeValue = outcome.outcome;
+
+ if (outcomeValue === 'expected') {
+ link.href = favIconExpected;
+ } else if (outcomeValue === 'unexpected') {
+ link.href = favIconUnExpected;
+ } else if (outcomeValue === 'skipped') {
+ link.href = favIconSkipped;
+ } else if (outcomeValue === 'flaky') {
+ link.href = favIconFlaky;
+ } else {
+ link.href = favIconDefault;
+ document.title = 'Playwright Test Report | Summary';
+ }
+}
+
+export function setDefaultFavIconAndTitle() {
+ const link: HTMLLinkElement | null = getLinkIconElement();
+ link.href = favIconDefault;
+ document.title = 'Playwright Test Report | Summary';
+}
+
+function getLinkIconElement() {
+ let link: HTMLLinkElement | null = document.querySelector("link[rel*='icon']");
+ if (!link) {
+ link = document.createElement('link');
+ link.rel = 'icon';
+ document.getElementsByTagName('head')[0].appendChild(link);
+ }
+ return link;
+}
\ No newline at end of file