feat: hide blinking cursor when making screenshots (#11854)
References #9938
This commit is contained in:
parent
c9e99d5d97
commit
547a32885b
|
|
@ -84,6 +84,7 @@ export class DragManager {
|
||||||
const val = await didStartDrag;
|
const val = await didStartDrag;
|
||||||
window.removeEventListener('mousemove', mouseListener, { capture: true });
|
window.removeEventListener('mousemove', mouseListener, { capture: true });
|
||||||
window.removeEventListener('dragstart', dragListener, { capture: true });
|
window.removeEventListener('dragstart', dragListener, { capture: true });
|
||||||
|
delete window.__cleanupDrag;
|
||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
}).toString(), true, 'utility').catch(() => {});
|
}).toString(), true, 'utility').catch(() => {});
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ import * as types from './types';
|
||||||
import { Progress } from './progress';
|
import { Progress } from './progress';
|
||||||
import { assert } from '../utils/utils';
|
import { assert } from '../utils/utils';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__cleanupScreenshot?: () => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Screenshotter {
|
export class Screenshotter {
|
||||||
private _queue = new TaskQueue();
|
private _queue = new TaskQueue();
|
||||||
private _page: Page;
|
private _page: Page;
|
||||||
|
|
@ -115,8 +121,36 @@ export class Screenshotter {
|
||||||
progress.cleanupWhenAborted(() => this._page._delegate.setBackgroundColor());
|
progress.cleanupWhenAborted(() => this._page._delegate.setBackgroundColor());
|
||||||
}
|
}
|
||||||
progress.throwIfAborted(); // Avoid extra work.
|
progress.throwIfAborted(); // Avoid extra work.
|
||||||
|
|
||||||
|
const restoreBlinkingCaret = async () => {
|
||||||
|
await Promise.all(this._page.frames().map(async frame => {
|
||||||
|
frame.nonStallingEvaluateInExistingContext('window.__cleanupScreenshot && window.__cleanupScreenshot()', false, 'utility').catch(() => {});
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
await Promise.all(this._page.frames().map(async frame => {
|
||||||
|
await frame.nonStallingEvaluateInExistingContext((function() {
|
||||||
|
const styleTag = document.createElement('style');
|
||||||
|
styleTag.textContent = `
|
||||||
|
* { caret-color: transparent !important; }
|
||||||
|
* > * { caret-color: transparent !important; }
|
||||||
|
* > * > * { caret-color: transparent !important; }
|
||||||
|
* > * > * > * { caret-color: transparent !important; }
|
||||||
|
* > * > * > * > * { caret-color: transparent !important; }
|
||||||
|
`;
|
||||||
|
document.documentElement.append(styleTag);
|
||||||
|
window.__cleanupScreenshot = () => {
|
||||||
|
styleTag.remove();
|
||||||
|
delete window.__cleanupScreenshot;
|
||||||
|
};
|
||||||
|
}).toString(), true, 'utility').catch(() => {});
|
||||||
|
}));
|
||||||
|
progress.cleanupWhenAborted(() => restoreBlinkingCaret());
|
||||||
|
progress.throwIfAborted(); // Avoid extra work.
|
||||||
|
|
||||||
const buffer = await this._page._delegate.takeScreenshot(progress, format, documentRect, viewportRect, options.quality, fitsViewport);
|
const buffer = await this._page._delegate.takeScreenshot(progress, format, documentRect, viewportRect, options.quality, fitsViewport);
|
||||||
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
|
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
|
||||||
|
await restoreBlinkingCaret();
|
||||||
|
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
|
||||||
if (shouldSetDefaultBackground)
|
if (shouldSetDefaultBackground)
|
||||||
await this._page._delegate.setBackgroundColor();
|
await this._page._delegate.setBackgroundColor();
|
||||||
progress.throwIfAborted(); // Avoid side effects.
|
progress.throwIfAborted(); // Avoid side effects.
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,23 @@ it.describe('page screenshot', () => {
|
||||||
expect(screenshot).toMatchSnapshot('screenshot-sanity.png');
|
expect(screenshot).toMatchSnapshot('screenshot-sanity.png');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not capture blinking caret', async ({ page, server }) => {
|
||||||
|
await page.setContent(`
|
||||||
|
<div contenteditable="true"></div>
|
||||||
|
`);
|
||||||
|
const div = page.locator('div');
|
||||||
|
await div.type('foo bar');
|
||||||
|
const screenshot = await div.screenshot();
|
||||||
|
for (let i = 0; i < 10; ++i) {
|
||||||
|
// Caret blinking time is set to 500ms.
|
||||||
|
// Try to capture variety of screenshots to make
|
||||||
|
// sure we don't capture blinking caret.
|
||||||
|
await new Promise(x => setTimeout(x, 150));
|
||||||
|
const newScreenshot = await div.screenshot();
|
||||||
|
expect(newScreenshot.equals(screenshot)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should clip rect', async ({ page, server }) => {
|
it('should clip rect', async ({ page, server }) => {
|
||||||
await page.setViewportSize({ width: 500, height: 500 });
|
await page.setViewportSize({ width: 500, height: 500 });
|
||||||
await page.goto(server.PREFIX + '/grid.html');
|
await page.goto(server.PREFIX + '/grid.html');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue