mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
parent
ea7fe340c1
commit
facec88c99
@ -46,7 +46,10 @@ export type ScreenshotOptions = {
|
|||||||
style?: string;
|
style?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function inPagePrepareForScreenshots(screenshotStyle: string, disableAnimations: boolean) {
|
function inPagePrepareForScreenshots(screenshotStyle: string, hideCaret: boolean, disableAnimations: boolean) {
|
||||||
|
if (!screenshotStyle && !hideCaret && !disableAnimations)
|
||||||
|
return;
|
||||||
|
|
||||||
const collectRoots = (root: Document | ShadowRoot, roots: (Document|ShadowRoot)[] = []): (Document|ShadowRoot)[] => {
|
const collectRoots = (root: Document | ShadowRoot, roots: (Document|ShadowRoot)[] = []): (Document|ShadowRoot)[] => {
|
||||||
roots.push(root);
|
roots.push(root);
|
||||||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
||||||
@ -61,19 +64,39 @@ function inPagePrepareForScreenshots(screenshotStyle: string, disableAnimations:
|
|||||||
|
|
||||||
const roots = collectRoots(document);
|
const roots = collectRoots(document);
|
||||||
const cleanupCallbacks: (() => void)[] = [];
|
const cleanupCallbacks: (() => void)[] = [];
|
||||||
for (const root of roots) {
|
|
||||||
const styleTag = document.createElement('style');
|
|
||||||
styleTag.textContent = screenshotStyle;
|
|
||||||
if (root === document)
|
|
||||||
document.documentElement.append(styleTag);
|
|
||||||
else
|
|
||||||
root.append(styleTag);
|
|
||||||
|
|
||||||
cleanupCallbacks.push(() => {
|
if (screenshotStyle) {
|
||||||
styleTag.remove();
|
for (const root of roots) {
|
||||||
});
|
const styleTag = document.createElement('style');
|
||||||
|
styleTag.textContent = screenshotStyle;
|
||||||
|
if (root === document)
|
||||||
|
document.documentElement.append(styleTag);
|
||||||
|
else
|
||||||
|
root.append(styleTag);
|
||||||
|
|
||||||
|
cleanupCallbacks.push(() => {
|
||||||
|
styleTag.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hideCaret) {
|
||||||
|
const elements = new Map<HTMLElement, { value: string, priority: string }>();
|
||||||
|
for (const root of roots) {
|
||||||
|
root.querySelectorAll('input,textarea,[contenteditable]').forEach(element => {
|
||||||
|
elements.set(element as HTMLElement, {
|
||||||
|
value: (element as HTMLElement).style.getPropertyValue('caret-color'),
|
||||||
|
priority: (element as HTMLElement).style.getPropertyPriority('caret-color')
|
||||||
|
});
|
||||||
|
(element as HTMLElement).style.setProperty('caret-color', 'transparent', 'important');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cleanupCallbacks.push(() => {
|
||||||
|
for (const [element, value] of elements)
|
||||||
|
element.style.setProperty('caret-color', value.value, value.priority);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (disableAnimations) {
|
if (disableAnimations) {
|
||||||
const infiniteAnimationsToResume: Set<Animation> = new Set();
|
const infiniteAnimationsToResume: Set<Animation> = new Set();
|
||||||
const handleAnimations = (root: Document|ShadowRoot): void => {
|
const handleAnimations = (root: Document|ShadowRoot): void => {
|
||||||
@ -172,7 +195,7 @@ export class Screenshotter {
|
|||||||
return this._queue.postTask(async () => {
|
return this._queue.postTask(async () => {
|
||||||
progress.log('taking page screenshot');
|
progress.log('taking page screenshot');
|
||||||
const { viewportSize } = await this._originalViewportSize(progress);
|
const { viewportSize } = await this._originalViewportSize(progress);
|
||||||
await this._preparePageForScreenshot(progress, screenshotStyle(options), options.animations === 'disabled');
|
await this._preparePageForScreenshot(progress, options.style, options.caret !== 'initial', options.animations === 'disabled');
|
||||||
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
|
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
|
||||||
|
|
||||||
if (options.fullPage) {
|
if (options.fullPage) {
|
||||||
@ -201,7 +224,7 @@ export class Screenshotter {
|
|||||||
progress.log('taking element screenshot');
|
progress.log('taking element screenshot');
|
||||||
const { viewportSize } = await this._originalViewportSize(progress);
|
const { viewportSize } = await this._originalViewportSize(progress);
|
||||||
|
|
||||||
await this._preparePageForScreenshot(progress, screenshotStyle(options), options.animations === 'disabled');
|
await this._preparePageForScreenshot(progress, options.style, options.caret !== 'initial', options.animations === 'disabled');
|
||||||
progress.throwIfAborted(); // Do not do extra work.
|
progress.throwIfAborted(); // Do not do extra work.
|
||||||
|
|
||||||
await handle._waitAndScrollIntoViewIfNeeded(progress, true /* waitForVisible */);
|
await handle._waitAndScrollIntoViewIfNeeded(progress, true /* waitForVisible */);
|
||||||
@ -225,11 +248,11 @@ export class Screenshotter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _preparePageForScreenshot(progress: Progress, screenshotStyle: string, disableAnimations: boolean) {
|
async _preparePageForScreenshot(progress: Progress, screenshotStyle: string | undefined, hideCaret: boolean, disableAnimations: boolean) {
|
||||||
if (disableAnimations)
|
if (disableAnimations)
|
||||||
progress.log(' disabled all CSS animations');
|
progress.log(' disabled all CSS animations');
|
||||||
await Promise.all(this._page.frames().map(async frame => {
|
await Promise.all(this._page.frames().map(async frame => {
|
||||||
await frame.nonStallingEvaluateInExistingContext('(' + inPagePrepareForScreenshots.toString() + `)(${JSON.stringify(screenshotStyle)}, ${disableAnimations})`, false, 'utility').catch(() => {});
|
await frame.nonStallingEvaluateInExistingContext('(' + inPagePrepareForScreenshots.toString() + `)(${JSON.stringify(screenshotStyle)}, ${hideCaret}, ${disableAnimations})`, false, 'utility').catch(() => {});
|
||||||
}));
|
}));
|
||||||
if (!process.env.PW_TEST_SCREENSHOT_NO_FONTS_READY) {
|
if (!process.env.PW_TEST_SCREENSHOT_NO_FONTS_READY) {
|
||||||
progress.log('waiting for fonts to load...');
|
progress.log('waiting for fonts to load...');
|
||||||
@ -359,16 +382,3 @@ export function validateScreenshotOptions(options: ScreenshotOptions): 'png' | '
|
|||||||
}
|
}
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
function screenshotStyle(options: ScreenshotOptions): string {
|
|
||||||
const parts: string[] = [];
|
|
||||||
if (options.caret !== 'initial') {
|
|
||||||
parts.push(`
|
|
||||||
*:not(#playwright-aaaaaaaaaa.playwright-bbbbbbbbbbb.playwright-cccccccccc.playwright-dddddddddd.playwright-eeeeeeeee) {
|
|
||||||
caret-color: transparent !important;
|
|
||||||
}`);
|
|
||||||
}
|
|
||||||
if (options.style)
|
|
||||||
parts.push(options.style);
|
|
||||||
return parts.join('\n');
|
|
||||||
}
|
|
||||||
|
@ -688,7 +688,8 @@ it.describe('page screenshot animations', () => {
|
|||||||
expect(comparePNGs(buffer1, buffer2, { maxDiffPixels: 50 })).not.toBe(null);
|
expect(comparePNGs(buffer1, buffer2, { maxDiffPixels: 50 })).not.toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fire transitionend for finite transitions', async ({ page, server }) => {
|
it('should fire transitionend for finite transitions', async ({ page, server, browserName, platform }) => {
|
||||||
|
it.fixme(browserName === 'webkit' && platform === 'linux');
|
||||||
await page.goto(server.PREFIX + '/css-transition.html');
|
await page.goto(server.PREFIX + '/css-transition.html');
|
||||||
const div = page.locator('div');
|
const div = page.locator('div');
|
||||||
await div.evaluate(el => {
|
await div.evaluate(el => {
|
||||||
@ -714,7 +715,8 @@ it.describe('page screenshot animations', () => {
|
|||||||
expect(await page.evaluate(() => window['__TRANSITION_END'])).toBe(true);
|
expect(await page.evaluate(() => window['__TRANSITION_END'])).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should capture screenshots after layoutchanges in transitionend event', async ({ page, server }) => {
|
it('should capture screenshots after layoutchanges in transitionend event', async ({ page, server, browserName, platform }) => {
|
||||||
|
it.fixme(browserName === 'webkit' && platform === 'linux');
|
||||||
await page.goto(server.PREFIX + '/css-transition.html');
|
await page.goto(server.PREFIX + '/css-transition.html');
|
||||||
const div = page.locator('div');
|
const div = page.locator('div');
|
||||||
await div.evaluate(el => {
|
await div.evaluate(el => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user