diff --git a/packages/html-reporter/src/index.tsx b/packages/html-reporter/src/index.tsx
index 43b4f5bb9e..0c3f0a6dc0 100644
--- a/packages/html-reporter/src/index.tsx
+++ b/packages/html-reporter/src/index.tsx
@@ -55,7 +55,14 @@ class ZipReport implements LoadedReport {
private _json!: HTMLReport;
async load() {
- const zipReader = new zipjs.ZipReader(new zipjs.Data64URIReader(window.playwrightReportBase64!), { useWebWorkers: false });
+ const zipURI = await new Promise(resolve => {
+ if (window.playwrightReportBase64)
+ return resolve(window.playwrightReportBase64);
+ window.addEventListener('message', event => event.source === window.opener && resolve(event.data), { once: true });
+ window.opener.postMessage('ready', '*');
+ });
+
+ const zipReader = new zipjs.ZipReader(new zipjs.Data64URIReader(zipURI), { useWebWorkers: false });
for (const entry of await zipReader.getEntries())
this._entries.set(entry.filename, entry);
this._json = await this.entry('report.json') as HTMLReport;
diff --git a/packages/playwright/src/reporters/html.ts b/packages/playwright/src/reporters/html.ts
index 584c11bae8..a5c9e31798 100644
--- a/packages/playwright/src/reporters/html.ts
+++ b/packages/playwright/src/reporters/html.ts
@@ -310,6 +310,33 @@ class HtmlBuilder {
this._addDataFile('report.json', htmlReport);
+ let singleTestId: string | undefined;
+ if (htmlReport.stats.total === 1) {
+ const testFile: TestFile = data.values().next().value.testFile;
+ singleTestId = testFile.tests[0].testId;
+ }
+
+ if (process.env.PW_HMR === '1') {
+ const redirectFile = path.join(this._reportFolder, 'index.html');
+
+ await this._writeReportData(redirectFile);
+
+ async function redirect() {
+ const hmrURL = new URL('http://localhost:44224'); // dev server, port is harcoded in build.js
+ const popup = window.open(hmrURL);
+ window.addEventListener('message', evt => {
+ if (evt.source === popup && evt.data === 'ready') {
+ popup!.postMessage((window as any).playwrightReportBase64, hmrURL.origin);
+ window.close();
+ }
+ }, { once: true });
+ }
+
+ fs.appendFileSync(redirectFile, ``);
+
+ return { ok, singleTestId };
+ }
+
// Copy app.
const appFolder = path.join(require.resolve('playwright-core'), '..', 'lib', 'vite', 'htmlReport');
await copyFileAndMakeWritable(path.join(appFolder, 'index.html'), path.join(this._reportFolder, 'index.html'));
@@ -332,25 +359,22 @@ class HtmlBuilder {
}
}
- // Inline report data.
- const indexFile = path.join(this._reportFolder, 'index.html');
- fs.appendFileSync(indexFile, '');
-
- let singleTestId: string | undefined;
- if (htmlReport.stats.total === 1) {
- const testFile: TestFile = data.values().next().value.testFile;
- singleTestId = testFile.tests[0].testId;
- }
-
- return { ok, singleTestId };
+ fs.appendFileSync(filePath, '";');
}
private _addDataFile(fileName: string, data: any) {
diff --git a/utils/build/build.js b/utils/build/build.js
index 908c219737..a9c4f0336b 100644
--- a/utils/build/build.js
+++ b/utils/build/build.js
@@ -316,6 +316,13 @@ if (watchMode) {
cwd: path.join(__dirname, '..', '..', 'packages', 'trace-viewer'),
concurrent: true,
});
+ steps.push({
+ command: 'npx',
+ args: ['vite', '--port', '44224'],
+ shell: true,
+ cwd: path.join(__dirname, '..', '..', 'packages', 'html-reporter'),
+ concurrent: true,
+ });
}
// Generate injected.