mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(screenshot): provide nice error message during navigation (#456)
This commit is contained in:
parent
02af0e5285
commit
63f16a9ef8
@ -32,6 +32,7 @@ import * as network from '../network';
|
||||
import * as types from '../types';
|
||||
import * as accessibility from '../accessibility';
|
||||
import * as platform from '../platform';
|
||||
import { kScreenshotDuringNavigationError } from '../screenshotter';
|
||||
|
||||
export class FFPage implements PageDelegate {
|
||||
readonly rawMouse: RawMouseImpl;
|
||||
@ -278,6 +279,10 @@ export class FFPage implements PageDelegate {
|
||||
mimeType: ('image/' + format) as ('image/png' | 'image/jpeg'),
|
||||
fullPage: options.fullPage,
|
||||
clip: options.clip,
|
||||
}).catch(e => {
|
||||
if (e instanceof Error && e.message.includes('document.documentElement is null'))
|
||||
e.message = kScreenshotDuringNavigationError;
|
||||
throw e;
|
||||
});
|
||||
return platform.Buffer.from(data, 'base64');
|
||||
}
|
||||
|
@ -43,13 +43,22 @@ export class Screenshotter {
|
||||
const viewport = this._page.viewport();
|
||||
let viewportSize: types.Size | undefined;
|
||||
if (!viewport) {
|
||||
viewportSize = await this._page.evaluate(() => ({
|
||||
viewportSize = await this._page.evaluate(() => {
|
||||
if (!document.body || !document.documentElement)
|
||||
return null;
|
||||
return {
|
||||
width: Math.max(document.body.offsetWidth, document.documentElement.offsetWidth),
|
||||
height: Math.max(document.body.offsetHeight, document.documentElement.offsetHeight)
|
||||
}));
|
||||
height: Math.max(document.body.offsetHeight, document.documentElement.offsetHeight),
|
||||
};
|
||||
});
|
||||
if (!viewportSize)
|
||||
throw new Error(kScreenshotDuringNavigationError);
|
||||
}
|
||||
if (options.fullPage && !this._page._delegate.canScreenshotOutsideViewport()) {
|
||||
const fullPageRect = await this._page.evaluate(() => ({
|
||||
const fullPageRect = await this._page.evaluate(() => {
|
||||
if (!document.body || !document.documentElement)
|
||||
return null;
|
||||
return {
|
||||
width: Math.max(
|
||||
document.body.scrollWidth, document.documentElement.scrollWidth,
|
||||
document.body.offsetWidth, document.documentElement.offsetWidth,
|
||||
@ -59,8 +68,11 @@ export class Screenshotter {
|
||||
document.body.scrollHeight, document.documentElement.scrollHeight,
|
||||
document.body.offsetHeight, document.documentElement.offsetHeight,
|
||||
document.body.clientHeight, document.documentElement.clientHeight
|
||||
)
|
||||
}));
|
||||
),
|
||||
};
|
||||
});
|
||||
if (!fullPageRect)
|
||||
throw new Error(kScreenshotDuringNavigationError);
|
||||
overridenViewport = viewport ? { ...viewport, ...fullPageRect } : fullPageRect;
|
||||
await this._page.setViewport(overridenViewport);
|
||||
} else if (options.clip) {
|
||||
@ -76,7 +88,7 @@ export class Screenshotter {
|
||||
await this._page._delegate.resetViewport(viewportSize);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}).catch(rewriteError);
|
||||
}
|
||||
|
||||
async screenshotElement(handle: dom.ElementHandle, options: types.ElementScreenshotOptions = {}): Promise<platform.BufferType> {
|
||||
@ -115,7 +127,7 @@ export class Screenshotter {
|
||||
await this._page.setViewport(viewport);
|
||||
|
||||
return result;
|
||||
});
|
||||
}).catch(rewriteError);
|
||||
}
|
||||
|
||||
private async _screenshot(format: 'png' | 'jpeg', options: types.ScreenshotOptions, viewport: types.Viewport): Promise<platform.BufferType> {
|
||||
@ -201,3 +213,10 @@ function enclosingIntRect(rect: types.Rect): types.Rect {
|
||||
const y2 = Math.ceil(rect.y + rect.height - 1e-3);
|
||||
return { x, y, width: x2 - x, height: y2 - y };
|
||||
}
|
||||
|
||||
export const kScreenshotDuringNavigationError = 'Cannot take a screenshot while page is navigating';
|
||||
function rewriteError(e: any) {
|
||||
if (typeof e === 'object' && e instanceof Error && e.message.includes('Execution context was destroyed'))
|
||||
e.message = kScreenshotDuringNavigationError;
|
||||
throw e;
|
||||
}
|
||||
|
9
test/assets/redirectloop1.html
Normal file
9
test/assets/redirectloop1.html
Normal file
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
const iter = window.localStorage.iter || '';
|
||||
window.localStorage.iter = iter + 'a';
|
||||
if (iter.length === 10)
|
||||
return;
|
||||
window.location.href = window.location.href.replace('loop1', 'loop2');
|
||||
}, 1);
|
||||
</script>>
|
5
test/assets/redirectloop2.html
Normal file
5
test/assets/redirectloop2.html
Normal file
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
window.location.href = window.location.href.replace('loop2', 'loop1');
|
||||
}, 1);
|
||||
</script>
|
@ -181,6 +181,18 @@ module.exports.describe = function({testRunner, expect, product, FFOX, CHROME, W
|
||||
const screenshot = await page.screenshot();
|
||||
expect(screenshot).toBeGolden('screenshot-webgl.png');
|
||||
});
|
||||
it('should work while navigating', async({page, server}) => {
|
||||
await page.setViewport({width: 500, height: 500});
|
||||
await page.goto(server.PREFIX + '/redirectloop1.html');
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const screenshot = await page.screenshot({ fullPage: true }).catch(e => {
|
||||
if (e.message.includes('Cannot take a screenshot while page is navigating'))
|
||||
return Buffer.from('');
|
||||
throw e;
|
||||
});
|
||||
expect(screenshot).toBeInstanceOf(Buffer);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('ElementHandle.screenshot', function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user