fix(trace): account for last child node removal (#7332)

This commit is contained in:
Pavel Feldman 2021-06-25 18:52:36 -07:00 committed by GitHub
parent ec47b03722
commit 02538fb587
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 8 deletions

View File

@ -44,6 +44,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
// Symbols for our own info on Nodes/StyleSheets.
const kSnapshotFrameId = Symbol('__playwright_snapshot_frameid_');
const kCachedData = Symbol('__playwright_snapshot_cache_');
const kEndOfList = Symbol('__playwright_end_of_list_');
type CachedData = {
cached?: any[], // Cached values to determine whether the snapshot will be the same.
ref?: [number, number], // Previous snapshotNumber and nodeIndex.
@ -355,6 +356,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
}
for (let child = node.firstChild; child; child = child.nextSibling)
visitChild(child);
expectValue(kEndOfList);
let documentOrShadowRoot = null;
if (node.ownerDocument!.documentElement === node)
documentOrShadowRoot = node.ownerDocument;
@ -363,20 +365,19 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
if (documentOrShadowRoot) {
for (const sheet of (documentOrShadowRoot as any).adoptedStyleSheets || [])
visitChildStyleSheet(sheet);
expectValue(kEndOfList);
}
}
// Process iframe src attribute before bailing out since it depends on a symbol, not the DOM.
if (nodeName === 'IFRAME' || nodeName === 'FRAME') {
const element = node as Element;
for (let i = 0; i < element.attributes.length; i++) {
const frameId = (element as any)[kSnapshotFrameId];
const name = 'src';
const value = frameId ? `/snapshot/${frameId}` : '';
expectValue(name);
expectValue(value);
attrs[name] = value;
}
const frameId = (element as any)[kSnapshotFrameId];
const name = 'src';
const value = frameId ? `/snapshot/${frameId}` : '';
expectValue(name);
expectValue(value);
attrs[name] = value;
}
// We can skip attributes comparison because nothing else has changed,
@ -409,6 +410,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
expectValue(value);
attrs[name] = value;
}
expectValue(kEndOfList);
}
if (result.length === 2 && !Object.keys(attrs).length)

View File

@ -75,6 +75,26 @@ it.describe('snapshots', () => {
expect(distillSnapshot(snapshot2)).toBe('<style>button { color: blue; }</style><BUTTON>Hello</BUTTON>');
});
it('should respect node removal', async ({ page, toImpl, snapshotter }) => {
page.on('console', console.log);
await page.setContent('<div><button id="button1"></button><button id="button2"></button></div>');
const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot1');
expect(distillSnapshot(snapshot1)).toBe('<DIV><BUTTON id=\"button1\"></BUTTON><BUTTON id=\"button2\"></BUTTON></DIV>');
await page.evaluate(() => document.getElementById('button2').remove());
const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot2');
expect(distillSnapshot(snapshot2)).toBe('<DIV><BUTTON id=\"button1\"></BUTTON></DIV>');
});
it('should respect attr removal', async ({ page, toImpl, snapshotter }) => {
page.on('console', console.log);
await page.setContent('<div id="div" attr1="1" attr2="2"></div>');
const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot1');
expect(distillSnapshot(snapshot1)).toBe('<DIV id=\"div\" attr1=\"1\" attr2=\"2\"></DIV>');
await page.evaluate(() => document.getElementById('div').removeAttribute('attr2'));
const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot2');
expect(distillSnapshot(snapshot2)).toBe('<DIV id=\"div\" attr1=\"1\"></DIV>');
});
it('should have a custom doctype', async ({page, server, toImpl, snapshotter}) => {
await page.goto(server.EMPTY_PAGE);
await page.setContent('<!DOCTYPE foo><body>hi</body>');