fix(tracing): trace frame (#10846)

This commit is contained in:
musou1500 2021-12-18 03:43:19 +09:00 committed by GitHub
parent 551c8d1309
commit 7d39d345c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 13 deletions

View file

@ -437,6 +437,8 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
continue; continue;
if (nodeName === 'IFRAME' && (name === 'src' || name === 'sandbox')) if (nodeName === 'IFRAME' && (name === 'src' || name === 'sandbox'))
continue; continue;
if (nodeName === 'FRAME' && name === 'src')
continue;
let value = element.attributes[i].value; let value = element.attributes[i].value;
if (nodeName === 'META') if (nodeName === 'META')
value = this.__sanitizeMetaAttribute(name, value, (node as HTMLMetaElement).httpEquiv); value = this.__sanitizeMetaAttribute(name, value, (node as HTMLMetaElement).httpEquiv);

View file

@ -85,12 +85,12 @@ export class SnapshotRenderer {
return { html: '', pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index }; return { html: '', pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index };
// Hide the document in order to prevent flickering. We will unhide once script has processed shadow. // 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}>` : '';
const prefix = snapshot.doctype ? `<!DOCTYPE ${snapshot.doctype}>` + hideAllStyle : hideAllStyle; html = prefix + [
html = prefix + html + ` '<style>*,*::before,*::after { visibility: hidden }</style>',
<style>*[__playwright_target__="${this.snapshotName}"] { background-color: #6fa8dc7f; }</style> `<style>*[__playwright_target__="${this.snapshotName}"] { background-color: #6fa8dc7f; }</style>`,
<script>${snapshotScript()}</script> `<script>${snapshotScript()}</script>`
`; ].join('') + html;
return { html, pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index }; return { html, pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index };
} }
@ -184,7 +184,7 @@ function snapshotScript() {
for (const e of root.querySelectorAll(`[${scrollLeftAttribute}]`)) for (const e of root.querySelectorAll(`[${scrollLeftAttribute}]`))
scrollLefts.push(e); scrollLefts.push(e);
for (const iframe of root.querySelectorAll('iframe')) { for (const iframe of root.querySelectorAll('iframe, frame')) {
const src = iframe.getAttribute('__playwright_src__'); const src = iframe.getAttribute('__playwright_src__');
if (!src) { if (!src) {
iframe.setAttribute('src', 'data:text/html,<body style="background: #ddd"></body>'); iframe.setAttribute('src', 'data:text/html,<body style="background: #ddd"></body>');
@ -221,7 +221,6 @@ function snapshotScript() {
(root as any).adoptedStyleSheets = adoptedSheets; (root as any).adoptedStyleSheets = adoptedSheets;
} }
}; };
visit(document);
const onLoad = () => { const onLoad = () => {
window.removeEventListener('load', onLoad); window.removeEventListener('load', onLoad);
@ -252,7 +251,11 @@ function snapshotScript() {
} }
document.styleSheets[0].disabled = true; document.styleSheets[0].disabled = true;
}; };
const onDOMContentLoaded = () => visit(document);
window.addEventListener('load', onLoad); window.addEventListener('load', onLoad);
window.addEventListener('DOMContentLoaded', onDOMContentLoaded);
} }
const kShadowAttribute = '__playwright_shadow_root_'; const kShadowAttribute = '__playwright_shadow_root_';

View file

@ -133,6 +133,32 @@ it.describe('snapshots', () => {
expect((await snapshotter.resourceContentForTest(resource.response.content._sha1)).toString()).toBe('button { color: blue; }'); expect((await snapshotter.resourceContentForTest(resource.response.content._sha1)).toString()).toBe('button { color: blue; }');
}); });
it('should capture frame', async ({ page, server, toImpl, browserName, snapshotter }) => {
it.skip(browserName === 'firefox');
await page.route('**/empty.html', route => {
route.fulfill({
body: '<frameset><frame src="frame.html"></frameset>',
contentType: 'text/html'
}).catch(() => {});
});
await page.route('**/frame.html', route => {
route.fulfill({
body: '<html><button>Hello iframe</button></html>',
contentType: 'text/html'
}).catch(() => {});
});
await page.goto(server.EMPTY_PAGE);
for (let counter = 0; ; ++counter) {
const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot' + counter);
const text = distillSnapshot(snapshot).replace(/frame@[^"]+["]/, '<id>"');
if (text === '<FRAMESET><FRAME __playwright_src__=\"/snapshot/<id>\"></FRAME></FRAMESET>')
break;
await page.waitForTimeout(250);
}
});
it('should capture iframe', async ({ page, server, toImpl, browserName, snapshotter }) => { it('should capture iframe', async ({ page, server, toImpl, browserName, snapshotter }) => {
it.skip(browserName === 'firefox'); it.skip(browserName === 'firefox');
@ -151,10 +177,8 @@ it.describe('snapshots', () => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
// Marking iframe hierarchy is racy, do not expect snapshot, wait for it. // Marking iframe hierarchy is racy, do not expect snapshot, wait for it.
let counter = 0; for (let counter = 0; ; ++counter) {
let snapshot: any; const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot' + counter);
for (; ; ++counter) {
snapshot = await snapshotter.captureSnapshot(toImpl(page), 'snapshot' + counter);
const text = distillSnapshot(snapshot).replace(/frame@[^"]+["]/, '<id>"'); const text = distillSnapshot(snapshot).replace(/frame@[^"]+["]/, '<id>"');
if (text === '<IFRAME __playwright_src__=\"/snapshot/<id>\"></IFRAME>') if (text === '<IFRAME __playwright_src__=\"/snapshot/<id>\"></IFRAME>')
break; break;
@ -232,7 +256,7 @@ function distillSnapshot(snapshot, distillTarget = true) {
return html return html
.replace(/<style>\*,\*::before,\*::after { visibility: hidden }<\/style>/, '') .replace(/<style>\*,\*::before,\*::after { visibility: hidden }<\/style>/, '')
.replace(/<script>[.\s\S]+<\/script>/, '') .replace(/<script>[.\s\S]+<\/script>/, '')
.replace(/<style>.*__playwright_target__.*<\/style>/, '') .replace(/<style>.*__playwright_target__.*?<\/style>/, '')
.replace(/<BASE href="about:blank">/, '') .replace(/<BASE href="about:blank">/, '')
.replace(/<BASE href="http:\/\/localhost:[\d]+\/empty.html">/, '') .replace(/<BASE href="http:\/\/localhost:[\d]+\/empty.html">/, '')
.replace(/<HTML>/, '') .replace(/<HTML>/, '')