mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(trace-viewer): redirect, time and missing snapshot bugfixes (#10055)
This commit is contained in:
parent
5c9dcffd67
commit
806b5706a5
@ -80,9 +80,10 @@ export class SnapshotRenderer {
|
||||
if (!html)
|
||||
return { html: '', pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index };
|
||||
|
||||
if (snapshot.doctype)
|
||||
html = `<!DOCTYPE ${snapshot.doctype}>` + html;
|
||||
html += `
|
||||
// Hide the document in order to prevent flickering. We will unhide once script has processed shadow.
|
||||
const hideAllStyle = '<style>*,*::before,*::after { visibility: hidden }</style>';
|
||||
const prefix = snapshot.doctype ? `<!DOCTYPE ${snapshot.doctype}>` + hideAllStyle : hideAllStyle;
|
||||
html = prefix + html + `
|
||||
<style>*[__playwright_target__="${this.snapshotName}"] { background-color: #6fa8dc7f; }</style>
|
||||
<script>${snapshotScript()}</script>
|
||||
`;
|
||||
@ -240,6 +241,7 @@ function snapshotScript() {
|
||||
pointElement.style.top = pointY + 'px';
|
||||
document.documentElement.appendChild(pointElement);
|
||||
}
|
||||
document.styleSheets[0].disabled = true;
|
||||
};
|
||||
window.addEventListener('load', onLoad);
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ResourceSnapshot } from '../../server/trace/common/snapshotTypes';
|
||||
import { SnapshotStorage } from './snapshotStorage';
|
||||
import type { Point } from '../../common/types';
|
||||
import { URLSearchParams } from 'url';
|
||||
@ -44,7 +43,9 @@ export class SnapshotServer {
|
||||
return this._respondWithJson(snapshot ? {
|
||||
viewport: snapshot.viewport(),
|
||||
url: snapshot.snapshot().frameUrl
|
||||
} : {});
|
||||
} : {
|
||||
error: 'No snapshot found'
|
||||
});
|
||||
}
|
||||
|
||||
private _snapshot(pathname: string, params: URLSearchParams) {
|
||||
@ -70,15 +71,7 @@ export class SnapshotServer {
|
||||
return new Response(null, { status: 404 });
|
||||
|
||||
const sha1 = resource.response.content._sha1;
|
||||
if (!sha1)
|
||||
return new Response(null, { status: 404 });
|
||||
return this._innerServeResource(sha1, resource);
|
||||
}
|
||||
|
||||
private async _innerServeResource(sha1: string, resource: ResourceSnapshot): Promise<Response> {
|
||||
const content = await this._snapshotStorage.resourceContent(sha1);
|
||||
if (!content)
|
||||
return new Response(null, { status: 404 });
|
||||
const content = sha1 ? await this._snapshotStorage.resourceContent(sha1) || new Blob([]) : new Blob([]);
|
||||
|
||||
let contentType = resource.response.content.mimeType;
|
||||
const isTextEncoding = /^text\/|^application\/(javascript|json)/.test(contentType);
|
||||
@ -95,7 +88,11 @@ export class SnapshotServer {
|
||||
headers.delete('Content-Length');
|
||||
headers.set('Content-Length', String(content.size));
|
||||
headers.set('Cache-Control', 'public, max-age=31536000');
|
||||
return new Response(content, { headers });
|
||||
return new Response(content, {
|
||||
headers,
|
||||
status: resource.response.status,
|
||||
statusText: resource.response.statusText,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ export const CallTab: React.FunctionComponent<{
|
||||
<div className='call-line'>{action.metadata.apiName}</div>
|
||||
{<>
|
||||
<div className='call-section'>Time</div>
|
||||
<div className='call-line'>wall time: <span className='datetime' title={wallTime}>{wallTime}</span></div>
|
||||
{action.metadata.wallTime && <div className='call-line'>wall time: <span className='datetime' title={wallTime}>{wallTime}</span></div>}
|
||||
<div className='call-line'>duration: <span className='datetime' title={duration}>{duration}</span></div>
|
||||
</>}
|
||||
{ !!paramKeys.length && <div className='call-section'>Parameters</div> }
|
||||
|
@ -63,7 +63,8 @@ export const SnapshotTab: React.FunctionComponent<{
|
||||
if (snapshotInfoUrl) {
|
||||
const response = await fetch(snapshotInfoUrl);
|
||||
const info = await response.json();
|
||||
setSnapshotInfo(info);
|
||||
if (!info.error)
|
||||
setSnapshotInfo(info);
|
||||
}
|
||||
if (!iframeRef.current)
|
||||
return;
|
||||
|
@ -216,6 +216,7 @@ function distillSnapshot(snapshot, distillTarget = true) {
|
||||
if (distillTarget)
|
||||
html = html.replace(/\s__playwright_target__="[^"]+"/g, '');
|
||||
return html
|
||||
.replace(/<style>\*,\*::before,\*::after { visibility: hidden }<\/style>/, '')
|
||||
.replace(/<script>[.\s\S]+<\/script>/, '')
|
||||
.replace(/<style>.*__playwright_target__.*<\/style>/, '')
|
||||
.replace(/<BASE href="about:blank">/, '')
|
||||
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import type { Browser, Frame, Locator, Page } from 'playwright-core';
|
||||
import { showTraceViewer } from '../../packages/playwright-core/lib/server/trace/viewer/traceViewer';
|
||||
@ -552,3 +553,29 @@ test('should show action source', async ({ showTraceViewer }) => {
|
||||
await expect(page.locator('.source-line-running')).toContainText('page.click');
|
||||
await expect(page.locator('.stack-trace-frame.selected')).toHaveText(/doClick.*trace-viewer\.spec\.ts:[\d]+/);
|
||||
});
|
||||
|
||||
test('should follow redirects', async ({ page, runAndTrace, server, asset }) => {
|
||||
server.setRoute('/empty.html', (req, res) => {
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
res.end(`<div><img id=img src="image.png"></img></div>`);
|
||||
});
|
||||
server.setRoute('/image.png', (req, res) => {
|
||||
res.writeHead(301, { location: '/image-301.png' });
|
||||
res.end();
|
||||
});
|
||||
server.setRoute('/image-301.png', (req, res) => {
|
||||
res.writeHead(302, { location: '/image-302.png' });
|
||||
res.end();
|
||||
});
|
||||
server.setRoute('/image-302.png', (req, res) => {
|
||||
res.writeHead(200, { 'content-type': 'image/png' });
|
||||
res.end(fs.readFileSync(asset('digits/0.png')));
|
||||
});
|
||||
|
||||
const traceViewer = await runAndTrace(async () => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
expect(await page.evaluate(() => (window as any).img.naturalWidth)).toBe(10);
|
||||
});
|
||||
const snapshotFrame = await traceViewer.snapshotFrame('page.evaluate');
|
||||
await expect(snapshotFrame.locator('img')).toHaveJSProperty('naturalWidth', 10);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user