Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/server/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,7 @@ export class Frame extends SdkObject {
const data = this._contextData.get(options.mainWorld ? 'main' : info.world)!;

return controller.run(async progress => {
progress.log(`waiting for selector "${selector}"`);
const rerunnableTask = new RerunnableTask(data, progress, injectedScript => {
return injectedScript.evaluateHandle((injected, { info, taskData, callbackText, querySelectorAll, logScale }) => {
const callback = injected.eval(callbackText) as DomTaskBody<T, R>;
Expand Down
17 changes: 7 additions & 10 deletions src/test/matchers/toMatchText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,25 @@ export async function toMatchText(

const { pass, received, log } = await query(this.isNot, timeout);
const stringSubstring = options.matchSubstring ? 'substring' : 'string';
const receivedString = received || '';
const message = pass
? () =>
typeof expected === 'string'
? this.utils.matcherHint(matcherName, undefined, undefined, matcherOptions) +
'\n\n' +
`Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}\n` +
`Received string: ${printReceivedStringContainExpectedSubstring(
received!,
received!.indexOf(expected),
receivedString,
receivedString.indexOf(expected),
Comment thread
dgozman marked this conversation as resolved.
expected.length,
)}`
)}` + callLogText(log)
: this.utils.matcherHint(matcherName, undefined, undefined, matcherOptions) +
'\n\n' +
`Expected pattern: not ${this.utils.printExpected(expected)}\n` +
`Received string: ${printReceivedStringContainExpectedResult(
received!,
receivedString,
typeof expected.exec === 'function'
? expected.exec(received!)
? expected.exec(receivedString)
: null,
)}` + callLogText(log)
: () => {
Expand All @@ -95,7 +96,7 @@ export async function toMatchText(
'\n\n' +
this.utils.printDiffOrStringify(
expected,
received,
receivedString,
labelExpected,
labelReceived,
this.expand !== false,
Expand All @@ -105,10 +106,6 @@ export async function toMatchText(
return { message, pass };
}

export function normalizeWhiteSpace(s: string) {
return s.trim().replace(/\s+/g, ' ');
}

export function toExpectedTextValues(items: (string | RegExp)[], options: { matchSubstring?: boolean, normalizeWhiteSpace?: boolean } = {}): ExpectedTextValue[] {
return items.map(i => ({
string: isString(i) ? i : undefined,
Expand Down
1 change: 1 addition & 0 deletions tests/inspector/pause.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ it.describe('pause', () => {
expect(await sanitizeLog(recorderPage)).toEqual([
'page.pause- XXms',
'page.isChecked(button)- XXms',
'waiting for selector "button"',
'selector resolved to <button onclick=\"console.log(1)\">Submit</button>',
'error: Not a checkbox or radio button',
]);
Expand Down
7 changes: 7 additions & 0 deletions tests/page/locator-convenience.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ it('innerText should throw', async ({ page, server }) => {
expect(error2.message).toContain('Not an HTMLElement');
});

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

it('textContent should work', async ({ page, server }) => {
await page.goto(`${server.PREFIX}/dom.html`);
const locator = page.locator('#inner');
Expand Down
46 changes: 45 additions & 1 deletion tests/playwright-test/playwright.expect.text.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,5 +312,49 @@ test('should print nice error for toHaveText', async ({ runInlineTest }) => {
expect(output).toContain('Pending operations:');
expect(output).toContain('Error: expect(received).toHaveText(expected)');
expect(output).toContain('Expected string: "Text"');
expect(output).toContain('Received string: undefined');
expect(output).toContain('Received string: ""');
expect(output).toContain('waiting for selector "no-such-thing"');
});

test('should print expected/received on Ctrl+C', async ({ runInlineTest }) => {
test.skip(process.platform === 'win32', 'No sending SIGINT on Windows');

const result = await runInlineTest({
'a.test.ts': `
const { test } = pwt;

test('times out waiting for text', async ({ page }) => {
await page.setContent('<div id=node>Text content</div>');
const promise = expect(page.locator('#node')).toHaveText('Text 2');
await new Promise(f => setTimeout(f, 500));
console.log('\\n%%SEND-SIGINT%%');
await promise;
});
`,
}, { workers: 1 }, {}, { sendSIGINTAfter: 1 });
expect(result.exitCode).toBe(130);
expect(result.passed).toBe(0);
expect(result.skipped).toBe(1);
expect(stripAscii(result.output)).toContain('Expected string: "Text 2"');
expect(stripAscii(result.output)).toContain('Received string: "Text content"');
});

test('should support not.toHaveText when selector does not match', async ({ runInlineTest }) => {
const result = await runInlineTest({
'a.test.ts': `
const { test } = pwt;

test('fails', async ({ page }) => {
await page.setContent('<div>hello</div>');
await expect(page.locator('span')).not.toHaveText('hello', { timeout: 1000 });
});
`,
}, { workers: 1 });
expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0);
expect(result.failed).toBe(1);
const output = stripAscii(result.output);
expect(output).toContain('Expected string: not "hello"');
expect(output).toContain('Received string: ""');
expect(output).toContain('waiting for selector "span"');
});