chore: use consistent asLocator() in all logs (#18586)

References #18524.
This commit is contained in:
Dmitry Gozman 2022-11-04 15:19:16 -07:00 committed by GitHub
parent 25dc0bfacb
commit 6a65a43e9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 51 additions and 53 deletions

View File

@ -1015,14 +1015,14 @@ export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' |
if (lastElement !== element) { if (lastElement !== element) {
lastElement = element; lastElement = element;
if (!element) { if (!element) {
progress.log(` selector did not resolve to any element`); progress.log(` locator did not resolve to any element`);
} else { } else {
if (elements.length > 1) { if (elements.length > 1) {
if (strict) if (strict)
throw injected.strictModeViolationError(parsed, elements); throw injected.strictModeViolationError(parsed, elements);
progress.log(` selector resolved to ${elements.length} elements. Proceeding with the first one.`); progress.log(` locator resolved to ${elements.length} elements. Proceeding with the first one.`);
} }
progress.log(` selector resolved to ${visible ? 'visible' : 'hidden'} ${injected.previewNode(element)}`); progress.log(` locator resolved to ${visible ? 'visible' : 'hidden'} ${injected.previewNode(element)}`);
} }
} }

View File

@ -804,7 +804,7 @@ export class Frame extends SdkObject {
if (!['attached', 'detached', 'visible', 'hidden'].includes(state)) if (!['attached', 'detached', 'visible', 'hidden'].includes(state))
throw new Error(`state: expected one of (attached|detached|visible|hidden)`); throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
return controller.run(async progress => { return controller.run(async progress => {
progress.log(`waiting for "${this._asLocator(selector)}"${state === 'attached' ? '' : ' to be ' + state}`); progress.log(`waiting for ${this._asLocator(selector)}${state === 'attached' ? '' : ' to be ' + state}`);
return this.retryWithProgress(progress, selector, options, async (selectorInFrame, continuePolling) => { return this.retryWithProgress(progress, selector, options, async (selectorInFrame, continuePolling) => {
// Be careful, |this| can be different from |frame|. // Be careful, |this| can be different from |frame|.
// We did not pass omitAttached, so it is non-null. // We did not pass omitAttached, so it is non-null.
@ -1114,7 +1114,7 @@ export class Frame extends SdkObject {
const { frame, info } = selectorInFrame!; const { frame, info } = selectorInFrame!;
// Be careful, |this| can be different from |frame|. // Be careful, |this| can be different from |frame|.
const task = dom.waitForSelectorTask(info, 'attached'); const task = dom.waitForSelectorTask(info, 'attached');
progress.log(`waiting for "${this._asLocator(selector)}"`); progress.log(`waiting for ${this._asLocator(selector)}`);
const handle = await frame._scheduleRerunnableHandleTask(progress, info.world, task); const handle = await frame._scheduleRerunnableHandleTask(progress, info.world, task);
const element = handle.asElement() as dom.ElementHandle<Element>; const element = handle.asElement() as dom.ElementHandle<Element>;
try { try {
@ -1268,7 +1268,7 @@ export class Frame extends SdkObject {
async isVisible(metadata: CallMetadata, selector: string, options: types.StrictOptions = {}): Promise<boolean> { async isVisible(metadata: CallMetadata, selector: string, options: types.StrictOptions = {}): Promise<boolean> {
const controller = new ProgressController(metadata, this); const controller = new ProgressController(metadata, this);
return controller.run(async progress => { return controller.run(async progress => {
progress.log(` checking visibility of "${selector}"`); progress.log(` checking visibility of ${this._asLocator(selector)}`);
const pair = await this.resolveFrameForSelectorNoWait(selector, options); const pair = await this.resolveFrameForSelectorNoWait(selector, options);
if (!pair) if (!pair)
return false; return false;
@ -1515,7 +1515,7 @@ export class Frame extends SdkObject {
const callbackText = body.toString(); const callbackText = body.toString();
return this.retryWithProgress(progress, selector, options, async selectorInFrame => { return this.retryWithProgress(progress, selector, options, async selectorInFrame => {
// Be careful, |this| can be different from |frame|. // Be careful, |this| can be different from |frame|.
progress.log(`waiting for "${this._asLocator(selector)}"`); progress.log(`waiting for ${this._asLocator(selector)}`);
const { frame, info } = selectorInFrame || { frame: this, info: { parsed: { parts: [{ name: 'internal:control', body: 'return-empty', source: 'internal:control=return-empty' }] }, world: 'utility', strict: !!options.strict } }; const { frame, info } = selectorInFrame || { frame: this, info: { parsed: { parts: [{ name: 'internal:control', body: 'return-empty', source: 'internal:control=return-empty' }] }, world: 'utility', strict: !!options.strict } };
return await frame._scheduleRerunnableTaskInFrame(progress, info, callbackText, taskData, options); return await frame._scheduleRerunnableTaskInFrame(progress, info, callbackText, taskData, options);
}); });
@ -1542,12 +1542,12 @@ export class Frame extends SdkObject {
if (querySelectorAll) { if (querySelectorAll) {
elements = injected.querySelectorAll(info.parsed, document); elements = injected.querySelectorAll(info.parsed, document);
element = elements[0]; element = elements[0];
progress.logRepeating(` selector resolved to ${elements.length} element${elements.length === 1 ? '' : 's'}`); progress.logRepeating(` locator resolved to ${elements.length} element${elements.length === 1 ? '' : 's'}`);
} else { } else {
element = injected.querySelector(info.parsed, document, info.strict); element = injected.querySelector(info.parsed, document, info.strict);
elements = element ? [element] : []; elements = element ? [element] : [];
if (element) if (element)
progress.logRepeating(` selector resolved to ${injected.previewNode(element)}`); progress.logRepeating(` locator resolved to ${injected.previewNode(element)}`);
} }
if (!element && !omitAttached) if (!element && !omitAttached)
@ -1667,7 +1667,7 @@ export class Frame extends SdkObject {
for (let i = 0; i < frameChunks.length - 1 && progress.isRunning(); ++i) { for (let i = 0; i < frameChunks.length - 1 && progress.isRunning(); ++i) {
const info = this._page.parseSelector(frameChunks[i], options); const info = this._page.parseSelector(frameChunks[i], options);
const task = dom.waitForSelectorTask(info, 'attached', false, i === 0 ? scope : undefined); const task = dom.waitForSelectorTask(info, 'attached', false, i === 0 ? scope : undefined);
progress.log(` waiting for frame "${stringifySelector(frameChunks[i])}"`); progress.log(` waiting for frameLocator('${stringifySelector(frameChunks[i])}')`);
const handle = i === 0 && scope ? await frame._runWaitForSelectorTaskOnce(progress, stringifySelector(info.parsed), info.world, task) const handle = i === 0 && scope ? await frame._runWaitForSelectorTaskOnce(progress, stringifySelector(info.parsed), info.world, task)
: await frame._scheduleRerunnableHandleTask(progress, info.world, task); : await frame._scheduleRerunnableHandleTask(progress, info.world, task);
const element = handle.asElement() as dom.ElementHandle<Element>; const element = handle.asElement() as dom.ElementHandle<Element>;
@ -1710,7 +1710,7 @@ export class Frame extends SdkObject {
progress.cleanupWhenAborted(() => result.dispose()); progress.cleanupWhenAborted(() => result.dispose());
return result; return result;
} catch (e) { } catch (e) {
throw new Error(`Error: frame navigated while waiting for "${this._asLocator(selector)}"`); throw new Error(`Error: frame navigated while waiting for ${this._asLocator(selector)}`);
} }
} }

View File

@ -1018,10 +1018,10 @@ export class InjectedScript {
preview: this.previewNode(m), preview: this.previewNode(m),
selector: this.generateSelector(m), selector: this.generateSelector(m),
})); }));
const lines = infos.map((info, i) => `\n ${i + 1}) ${info.preview} aka page.${asLocator(this._sdkLanguage, info.selector)}`); const lines = infos.map((info, i) => `\n ${i + 1}) ${info.preview} aka ${asLocator(this._sdkLanguage, info.selector)}`);
if (infos.length < matches.length) if (infos.length < matches.length)
lines.push('\n ...'); lines.push('\n ...');
return this.createStacklessError(`strict mode violation: "${stringifySelector(selector)}" resolved to ${matches.length} elements:${lines.join('')}\n`); return this.createStacklessError(`strict mode violation: ${asLocator(this._sdkLanguage, stringifySelector(selector))} resolved to ${matches.length} elements:${lines.join('')}\n`);
} }
createStacklessError(message: string): Error { createStacklessError(message: string): Error {

View File

@ -296,8 +296,8 @@ it.describe('pause', () => {
expect(await sanitizeLog(recorderPage)).toEqual([ expect(await sanitizeLog(recorderPage)).toEqual([
'page.pause- XXms', 'page.pause- XXms',
'page.getByRole(\'button\').isChecked()- XXms', 'page.getByRole(\'button\').isChecked()- XXms',
'waiting for \"getByRole(\'button\')"', 'waiting for getByRole(\'button\')',
'selector resolved to <button onclick=\"console.log(1)\">Submit</button>', 'locator resolved to <button onclick=\"console.log(1)\">Submit</button>',
'error: Error: Not a checkbox or radio button', 'error: Error: Not a checkbox or radio button',
]); ]);
const error = await scriptPromise; const error = await scriptPromise;

View File

@ -59,7 +59,7 @@ test.describe('toBeChecked', () => {
const locator = page.locator('input'); const locator = page.locator('input');
const error = await expect(locator).not.toBeChecked({ timeout: 1000 }).catch(e => e); const error = await expect(locator).not.toBeChecked({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`expect.toBeChecked with timeout 1000ms`); expect(error.message).toContain(`expect.toBeChecked with timeout 1000ms`);
expect(error.message).toContain(`selector resolved to <input checked type="checkbox"/>`); expect(error.message).toContain(`locator resolved to <input checked type="checkbox"/>`);
}); });
test('fail with checked:false', async ({ page }) => { test('fail with checked:false', async ({ page }) => {
@ -74,7 +74,7 @@ test.describe('toBeChecked', () => {
const locator2 = page.locator('input2'); const locator2 = page.locator('input2');
const error = await expect(locator2).not.toBeChecked({ timeout: 1000 }).catch(e => e); const error = await expect(locator2).not.toBeChecked({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`expect.toBeChecked with timeout 1000ms`); expect(error.message).toContain(`expect.toBeChecked with timeout 1000ms`);
expect(error.message).toContain('waiting for "locator(\'input2\')"'); expect(error.message).toContain('waiting for locator(\'input2\')');
}); });
test('with role', async ({ page }) => { test('with role', async ({ page }) => {
@ -143,7 +143,7 @@ test.describe('toBeEnabled', () => {
await page.setContent('<button disabled>Text</button>'); await page.setContent('<button disabled>Text</button>');
const locator = page.locator('button'); const locator = page.locator('button');
const error = await expect(locator).toBeEnabled({ timeout: 1000 }).catch(e => e); const error = await expect(locator).toBeEnabled({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`selector resolved to <button disabled>Text</button>`); expect(error.message).toContain(`locator resolved to <button disabled>Text</button>`);
}); });
test('eventually', async ({ page }) => { test('eventually', async ({ page }) => {
@ -272,14 +272,14 @@ test.describe('toBeVisible', () => {
await page.setContent('<button style="display: none"></button>'); await page.setContent('<button style="display: none"></button>');
const locator = page.locator('button'); const locator = page.locator('button');
const error = await expect(locator).toBeVisible({ timeout: 1000 }).catch(e => e); const error = await expect(locator).toBeVisible({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`selector resolved to <button></button>`); expect(error.message).toContain(`locator resolved to <button></button>`);
}); });
test('fail with not', async ({ page }) => { test('fail with not', async ({ page }) => {
await page.setContent('<input></input>'); await page.setContent('<input></input>');
const locator = page.locator('input'); const locator = page.locator('input');
const error = await expect(locator).not.toBeVisible({ timeout: 1000 }).catch(e => e); const error = await expect(locator).not.toBeVisible({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`selector resolved to <input/>`); expect(error.message).toContain(`locator resolved to <input/>`);
}); });
}); });
@ -324,14 +324,14 @@ test.describe('toBeHidden', () => {
await page.setContent('<input></input>'); await page.setContent('<input></input>');
const locator = page.locator('input'); const locator = page.locator('input');
const error = await expect(locator).toBeHidden({ timeout: 1000 }).catch(e => e); const error = await expect(locator).toBeHidden({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`selector resolved to <input/>`); expect(error.message).toContain(`locator resolved to <input/>`);
}); });
test('fail with not', async ({ page }) => { test('fail with not', async ({ page }) => {
await page.setContent('<button style="display: none"></button>'); await page.setContent('<button style="display: none"></button>');
const locator = page.locator('button'); const locator = page.locator('button');
const error = await expect(locator).not.toBeHidden({ timeout: 1000 }).catch(e => e); const error = await expect(locator).not.toBeHidden({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain(`selector resolved to <button></button>`); expect(error.message).toContain(`locator resolved to <button></button>`);
}); });
test('fail with not when nothing matching', async ({ page }) => { test('fail with not when nothing matching', async ({ page }) => {

View File

@ -152,7 +152,7 @@ test.describe('not.toHaveText', () => {
const error = await expect(page.locator('span')).not.toHaveText('hello', { timeout: 1000 }).catch(e => e); const error = await expect(page.locator('span')).not.toHaveText('hello', { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain('Expected string: not "hello"'); expect(stripAnsi(error.message)).toContain('Expected string: not "hello"');
expect(stripAnsi(error.message)).toContain('Received string: ""'); expect(stripAnsi(error.message)).toContain('Received string: ""');
expect(stripAnsi(error.message)).toContain('waiting for "locator(\'span\')"'); expect(stripAnsi(error.message)).toContain('waiting for locator(\'span\')');
}); });
}); });
@ -217,15 +217,15 @@ test.describe('toHaveText with array', () => {
const error = await expect(locator).toHaveText(['Text 1', /Text \d/, 'Extra'], { timeout: 1000 }).catch(e => e); const error = await expect(locator).toHaveText(['Text 1', /Text \d/, 'Extra'], { timeout: 1000 }).catch(e => e);
expect(stripAnsi(error.message)).toContain('- "Extra"'); expect(stripAnsi(error.message)).toContain('- "Extra"');
expect(error.message).toContain('expect.toHaveText with timeout 1000ms'); expect(error.message).toContain('expect.toHaveText with timeout 1000ms');
expect(error.message).toContain('waiting for "locator(\'div\')"'); expect(error.message).toContain('waiting for locator(\'div\')');
expect(error.message).toContain('selector resolved to 2 elements'); expect(error.message).toContain('locator resolved to 2 elements');
}); });
test('fail on repeating array matchers', async ({ page }) => { test('fail on repeating array matchers', async ({ page }) => {
await page.setContent('<div>KekFoo</div>'); await page.setContent('<div>KekFoo</div>');
const locator = page.locator('div'); const locator = page.locator('div');
const error = await expect(locator).toContainText(['KekFoo', 'KekFoo', 'KekFoo'], { timeout: 1000 }).catch(e => e); const error = await expect(locator).toContainText(['KekFoo', 'KekFoo', 'KekFoo'], { timeout: 1000 }).catch(e => e);
expect(error.message).toContain('selector resolved to 1 element'); expect(error.message).toContain('locator resolved to 1 element');
}); });
}); });

View File

@ -85,7 +85,7 @@ it('innerText should produce log', async ({ page, server }) => {
await page.setContent(`<div>Hello</div>`); await page.setContent(`<div>Hello</div>`);
const locator = page.locator('span'); const locator = page.locator('span');
const error = await locator.innerText({ timeout: 1000 }).catch(e => e); const error = await locator.innerText({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain('waiting for "locator(\'span\')"'); expect(error.message).toContain('waiting for locator(\'span\')');
}); });
it('textContent should work', async ({ page, server }) => { it('textContent should work', async ({ page, server }) => {

View File

@ -98,7 +98,7 @@ it('should work for $ and $$', async ({ page, server }) => {
it('should wait for frame', async ({ page, server }) => { it('should wait for frame', async ({ page, server }) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
const error = await page.frameLocator('iframe').locator('span').click({ timeout: 1000 }).catch(e => e); const error = await page.frameLocator('iframe').locator('span').click({ timeout: 1000 }).catch(e => e);
expect(error.message).toContain('waiting for frame "iframe"'); expect(error.message).toContain('waiting for frameLocator(\'iframe\')');
}); });
it('should wait for frame 2', async ({ page, server }) => { it('should wait for frame 2', async ({ page, server }) => {
@ -225,7 +225,7 @@ it('locator.frameLocator should throw on ambiguity', async ({ page, server }) =>
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
const button = page.locator('body').frameLocator('iframe').locator('button'); const button = page.locator('body').frameLocator('iframe').locator('button');
const error = await button.waitFor().catch(e => e); const error = await button.waitFor().catch(e => e);
expect(error.message).toContain('Error: strict mode violation: "body >> iframe" resolved to 3 elements'); expect(error.message).toContain(`Error: strict mode violation: locator('body').locator('iframe') resolved to 3 elements`);
}); });
it('locator.frameLocator should not throw on first/last/nth', async ({ page, server }) => { it('locator.frameLocator should not throw on first/last/nth', async ({ page, server }) => {

View File

@ -20,8 +20,8 @@ it('should fail page.textContent in strict mode', async ({ page }) => {
await page.setContent(`<span>span1</span><div><span>target</span></div>`); await page.setContent(`<span>span1</span><div><span>target</span></div>`);
const error = await page.textContent('span', { strict: true }).catch(e => e); const error = await page.textContent('span', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation'); expect(error.message).toContain('strict mode violation');
expect(error.message).toContain(`1) <span>span1</span> aka page.getByText('span1')`); expect(error.message).toContain(`1) <span>span1</span> aka getByText('span1')`);
expect(error.message).toContain(`2) <span>target</span> aka page.getByText('target')`); expect(error.message).toContain(`2) <span>target</span> aka getByText('target')`);
}); });
it('should fail page.getAttribute in strict mode', async ({ page }) => { it('should fail page.getAttribute in strict mode', async ({ page }) => {
@ -34,8 +34,8 @@ it('should fail page.fill in strict mode', async ({ page }) => {
await page.setContent(`<input></input><div><input></input></div>`); await page.setContent(`<input></input><div><input></input></div>`);
const error = await page.fill('input', 'text', { strict: true }).catch(e => e); const error = await page.fill('input', 'text', { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation'); expect(error.message).toContain('strict mode violation');
expect(error.message).toContain(`1) <input/> aka page.locator('input').first()`); expect(error.message).toContain(`1) <input/> aka locator('input').first()`);
expect(error.message).toContain(`2) <input/> aka page.locator('div input')`); expect(error.message).toContain(`2) <input/> aka locator('div input')`);
}); });
it('should fail page.$ in strict mode', async ({ page }) => { it('should fail page.$ in strict mode', async ({ page }) => {
@ -54,8 +54,8 @@ it('should fail page.dispatchEvent in strict mode', async ({ page }) => {
await page.setContent(`<span></span><div><span></span></div>`); await page.setContent(`<span></span><div><span></span></div>`);
const error = await page.dispatchEvent('span', 'click', {}, { strict: true }).catch(e => e); const error = await page.dispatchEvent('span', 'click', {}, { strict: true }).catch(e => e);
expect(error.message).toContain('strict mode violation'); expect(error.message).toContain('strict mode violation');
expect(error.message).toContain(`1) <span></span> aka page.locator('span').first()`); expect(error.message).toContain(`1) <span></span> aka locator('span').first()`);
expect(error.message).toContain(`2) <span></span> aka page.locator('div span')`); expect(error.message).toContain(`2) <span></span> aka locator('div span')`);
}); });
it('should properly format :nth-child() in strict mode message', async ({ page }) => { it('should properly format :nth-child() in strict mode message', async ({ page }) => {

View File

@ -81,8 +81,7 @@ it('elementHandle.waitForSelector should throw on navigation', async ({ page, se
await page.evaluate(() => 1); await page.evaluate(() => 1);
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
const error = await promise; const error = await promise;
expect(error.message).toContain('Error: frame navigated while waiting for'); expect(error.message).toContain('Error: frame navigated while waiting for locator(\'span\')');
expect(error.message).toContain('"locator(\'span\')"');
}); });
it('should work with removed MutationObserver', async ({ page, server }) => { it('should work with removed MutationObserver', async ({ page, server }) => {
@ -134,10 +133,10 @@ it('should report logs while waiting for visible', async ({ page, server }) => {
const error = await watchdog.catch(e => e); const error = await watchdog.catch(e => e);
expect(error.message).toContain(`frame.waitForSelector: Timeout 5000ms exceeded.`); expect(error.message).toContain(`frame.waitForSelector: Timeout 5000ms exceeded.`);
expect(error.message).toContain(`waiting for "locator(\'div\')" to be visible`); expect(error.message).toContain(`waiting for locator(\'div\') to be visible`);
expect(error.message).toContain(`selector resolved to hidden <div id="mydiv" class="foo bar" foo="1234567890123456…>abcdefghijklmnopqrstuvwyxzabcdefghijklmnopqrstuvw…</div>`); expect(error.message).toContain(`locator resolved to hidden <div id="mydiv" class="foo bar" foo="1234567890123456…>abcdefghijklmnopqrstuvwyxzabcdefghijklmnopqrstuvw…</div>`);
expect(error.message).toContain(`selector did not resolve to any element`); expect(error.message).toContain(`locator did not resolve to any element`);
expect(error.message).toContain(`selector resolved to hidden <div class="another"></div>`); expect(error.message).toContain(`locator resolved to hidden <div class="another"></div>`);
}); });
it('should report logs while waiting for hidden', async ({ page, server }) => { it('should report logs while waiting for hidden', async ({ page, server }) => {
@ -165,9 +164,9 @@ it('should report logs while waiting for hidden', async ({ page, server }) => {
const error = await watchdog.catch(e => e); const error = await watchdog.catch(e => e);
expect(error.message).toContain(`frame.waitForSelector: Timeout 5000ms exceeded.`); expect(error.message).toContain(`frame.waitForSelector: Timeout 5000ms exceeded.`);
expect(error.message).toContain(`waiting for "locator(\'div\')" to be hidden`); expect(error.message).toContain(`waiting for locator(\'div\') to be hidden`);
expect(error.message).toContain(`selector resolved to visible <div id="mydiv" class="foo bar">hello</div>`); expect(error.message).toContain(`locator resolved to visible <div id="mydiv" class="foo bar">hello</div>`);
expect(error.message).toContain(`selector resolved to visible <div class="another">hello</div>`); expect(error.message).toContain(`locator resolved to visible <div class="another">hello</div>`);
}); });
it('should report logs when the selector resolves to multiple elements', async ({ page, server }) => { it('should report logs when the selector resolves to multiple elements', async ({ page, server }) => {
@ -183,7 +182,7 @@ it('should report logs when the selector resolves to multiple elements', async (
const error = await page.click('text=Reset', { const error = await page.click('text=Reset', {
timeout: 1000 timeout: 1000
}).catch(e => e); }).catch(e => e);
expect(error.toString()).toContain('selector resolved to 2 elements. Proceeding with the first one.'); expect(error.toString()).toContain('locator resolved to 2 elements. Proceeding with the first one.');
}); });
it('should resolve promise when node is added in shadow dom', async ({ page, server }) => { it('should resolve promise when node is added in shadow dom', async ({ page, server }) => {

View File

@ -131,7 +131,7 @@ it('should respect timeout', async ({ page, playwright }) => {
await page.waitForSelector('div', { timeout: 3000, state: 'attached' }).catch(e => error = e); await page.waitForSelector('div', { timeout: 3000, state: 'attached' }).catch(e => error = e);
expect(error).toBeTruthy(); expect(error).toBeTruthy();
expect(error.message).toContain('page.waitForSelector: Timeout 3000ms exceeded'); expect(error.message).toContain('page.waitForSelector: Timeout 3000ms exceeded');
expect(error.message).toContain('waiting for "locator(\'div\')"'); expect(error.message).toContain('waiting for locator(\'div\')');
expect(error).toBeInstanceOf(playwright.errors.TimeoutError); expect(error).toBeInstanceOf(playwright.errors.TimeoutError);
}); });
@ -141,7 +141,7 @@ it('should have an error message specifically for awaiting an element to be hidd
await page.waitForSelector('div', { state: 'hidden', timeout: 1000 }).catch(e => error = e); await page.waitForSelector('div', { state: 'hidden', timeout: 1000 }).catch(e => error = e);
expect(error).toBeTruthy(); expect(error).toBeTruthy();
expect(error.message).toContain('page.waitForSelector: Timeout 1000ms exceeded'); expect(error.message).toContain('page.waitForSelector: Timeout 1000ms exceeded');
expect(error.message).toContain('waiting for "locator(\'div\')" to be hidden'); expect(error.message).toContain('waiting for locator(\'div\') to be hidden');
}); });
it('should respond to node attribute mutation', async ({ page, server }) => { it('should respond to node attribute mutation', async ({ page, server }) => {
@ -233,7 +233,7 @@ it('should respect timeout xpath', async ({ page, playwright }) => {
await page.waitForSelector('//div', { state: 'attached', timeout: 3000 }).catch(e => error = e); await page.waitForSelector('//div', { state: 'attached', timeout: 3000 }).catch(e => error = e);
expect(error).toBeTruthy(); expect(error).toBeTruthy();
expect(error.message).toContain('page.waitForSelector: Timeout 3000ms exceeded'); expect(error.message).toContain('page.waitForSelector: Timeout 3000ms exceeded');
expect(error.message).toContain('waiting for "locator(\'xpath=//div\')"'); expect(error.message).toContain('waiting for locator(\'xpath=//div\')');
expect(error).toBeInstanceOf(playwright.errors.TimeoutError); expect(error).toBeInstanceOf(playwright.errors.TimeoutError);
}); });
@ -326,6 +326,5 @@ it('should fail when navigating while on handle', async ({ page, mode, server })
const body = await page.waitForSelector('body'); const body = await page.waitForSelector('body');
const error = await body.waitForSelector('div', { __testHookBeforeAdoptNode } as any).catch(e => e); const error = await body.waitForSelector('div', { __testHookBeforeAdoptNode } as any).catch(e => e);
expect(error.message).toContain('Error: frame navigated while waiting for'); expect(error.message).toContain('Error: frame navigated while waiting for locator(\'div\')');
expect(error.message).toContain('"locator(\'div\')"');
}); });

View File

@ -507,7 +507,7 @@ test('should print pending operations for toHaveText', async ({ runInlineTest })
expect(output).toContain('Error: expect(received).toHaveText(expected)'); expect(output).toContain('Error: expect(received).toHaveText(expected)');
expect(output).toContain('Expected string: "Text"'); expect(output).toContain('Expected string: "Text"');
expect(output).toContain('Received string: ""'); expect(output).toContain('Received string: ""');
expect(output).toContain('waiting for "locator(\'no-such-thing\')"'); expect(output).toContain('waiting for locator(\'no-such-thing\')');
}); });
test('should print expected/received on Ctrl+C', async ({ runInlineTest }) => { test('should print expected/received on Ctrl+C', async ({ runInlineTest }) => {

View File

@ -366,7 +366,7 @@ test('should report error on timeout with shared page', async ({ runInlineTest }
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.failed).toBe(1); expect(result.failed).toBe(1);
expect(result.output).toContain('waiting for "getByText(\'Missing\')"'); expect(result.output).toContain('waiting for getByText(\'Missing\')');
expect(stripAnsi(result.output)).toContain(`14 | await page.getByText('Missing').click();`); expect(stripAnsi(result.output)).toContain(`14 | await page.getByText('Missing').click();`);
}); });

View File

@ -394,7 +394,7 @@ test('should report api step failure', async ({ runInlineTest }) => {
`%% begin {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`, `%% begin {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`, `%% end {\"title\":\"page.setContent\",\"category\":\"pw:api\"}`,
`%% begin {\"title\":\"page.click(input)\",\"category\":\"pw:api\"}`, `%% begin {\"title\":\"page.click(input)\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"page.click(input)\",\"category\":\"pw:api\",\"error\":{\"message\":\"page.click: Timeout 1ms exceeded.\\n=========================== logs ===========================\\nwaiting for \\\"locator('input')\\\"\\n============================================================\",\"stack\":\"<stack>\"}}`, `%% end {\"title\":\"page.click(input)\",\"category\":\"pw:api\",\"error\":{\"message\":\"page.click: Timeout 1ms exceeded.\\n=========================== logs ===========================\\nwaiting for locator('input')\\n============================================================\",\"stack\":\"<stack>\"}}`,
`%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`, `%% begin {\"title\":\"After Hooks\",\"category\":\"hook\"}`,
`%% begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `%% begin {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,
`%% end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`, `%% end {\"title\":\"browserContext.close\",\"category\":\"pw:api\"}`,