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;
|
||||
};
|
||||
|
||||
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)[] => {
|
||||
roots.push(root);
|
||||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
||||
@ -61,19 +64,39 @@ function inPagePrepareForScreenshots(screenshotStyle: string, disableAnimations:
|
||||
|
||||
const roots = collectRoots(document);
|
||||
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(() => {
|
||||
styleTag.remove();
|
||||
});
|
||||
if (screenshotStyle) {
|
||||
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) {
|
||||
const infiniteAnimationsToResume: Set<Animation> = new Set();
|
||||
const handleAnimations = (root: Document|ShadowRoot): void => {
|
||||
@ -172,7 +195,7 @@ export class Screenshotter {
|
||||
return this._queue.postTask(async () => {
|
||||
progress.log('taking page screenshot');
|
||||
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.
|
||||
|
||||
if (options.fullPage) {
|
||||
@ -201,7 +224,7 @@ export class Screenshotter {
|
||||
progress.log('taking element screenshot');
|
||||
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.
|
||||
|
||||
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)
|
||||
progress.log(' disabled all CSS animations');
|
||||
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) {
|
||||
progress.log('waiting for fonts to load...');
|
||||
@ -359,16 +382,3 @@ export function validateScreenshotOptions(options: ScreenshotOptions): 'png' | '
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
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');
|
||||
const div = page.locator('div');
|
||||
await div.evaluate(el => {
|
||||
@ -714,7 +715,8 @@ it.describe('page screenshot animations', () => {
|
||||
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');
|
||||
const div = page.locator('div');
|
||||
await div.evaluate(el => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user