From e85a3a5a41b3a8c2d4ffa3961f1f94eb305166ab Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 22 Sep 2021 10:40:15 -0700 Subject: [PATCH] fix(page.content): throw a nice error when navigation intervenes (#9080) --- src/server/frames.ts | 24 +++++++++++++++--------- tests/page/page-set-content.spec.ts | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/server/frames.ts b/src/server/frames.ts index 72879510d2..ab1b1f9629 100644 --- a/src/server/frames.ts +++ b/src/server/frames.ts @@ -769,15 +769,21 @@ export class Frame extends SdkObject { } async content(): Promise { - const context = await this._utilityContext(); - return context.evaluate(() => { - let retVal = ''; - if (document.doctype) - retVal = new XMLSerializer().serializeToString(document.doctype); - if (document.documentElement) - retVal += document.documentElement.outerHTML; - return retVal; - }); + try { + const context = await this._utilityContext(); + return await context.evaluate(() => { + let retVal = ''; + if (document.doctype) + retVal = new XMLSerializer().serializeToString(document.doctype); + if (document.documentElement) + retVal += document.documentElement.outerHTML; + return retVal; + }); + } catch (e) { + if (js.isJavaScriptErrorInEvaluate(e) || isSessionClosedError(e)) + throw e; + throw new Error(`Unable to retrieve content because the page is navigating and changing the content.`); + } } async setContent(metadata: CallMetadata, html: string, options: types.NavigateOptions = {}): Promise { diff --git a/tests/page/page-set-content.spec.ts b/tests/page/page-set-content.spec.ts index 8492d97f79..418ffe1ab8 100644 --- a/tests/page/page-set-content.spec.ts +++ b/tests/page/page-set-content.spec.ts @@ -101,3 +101,18 @@ it('should work with newline', async ({page, server}) => { await page.setContent('
\n
'); expect(await page.$eval('div', div => div.textContent)).toBe('\n'); }); + +it('content() should throw nice error during navigation', async ({page, server}) => { + for (let timeout = 0; timeout < 200; timeout += 20) { + await page.setContent('
hello
'); + const promise = page.goto(server.EMPTY_PAGE); + await page.waitForTimeout(timeout); + const [contentOrError] = await Promise.all([ + page.content().catch(e => e), + promise, + ]); + const emptyOutput = ''; + if (contentOrError !== expectedOutput && contentOrError !== emptyOutput) + expect(contentOrError?.message).toContain('Unable to retrieve content because the page is navigating and changing the content.'); + } +});