mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(recorder): remove waitForNavigation from codegen (#14166)
This commit is contained in:
parent
b5beeab98b
commit
d5ea1b38f0
@ -136,7 +136,6 @@ export class CodeGenerator extends EventEmitter {
|
|||||||
return;
|
return;
|
||||||
if (signal.name === 'download' && signals.length && signals[signals.length - 1].name === 'navigation')
|
if (signal.name === 'download' && signals.length && signals[signals.length - 1].name === 'navigation')
|
||||||
signals.length = signals.length - 1;
|
signals.length = signals.length - 1;
|
||||||
signal.isAsync = true;
|
|
||||||
this._lastAction.action.signals.push(signal);
|
this._lastAction.action.signals.push(signal);
|
||||||
this.emit('change');
|
this.emit('change');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -70,17 +70,7 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
|
|||||||
|
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
const actionCall = this._generateActionCall(action, actionInContext.frame.isMainFrame);
|
const actionCall = this._generateActionCall(action, actionInContext.frame.isMainFrame);
|
||||||
if (signals.waitForNavigation) {
|
lines.push(`await ${subject}.${actionCall};`);
|
||||||
lines.push(`await ${pageAlias}.RunAndWaitForNavigationAsync(async () =>`);
|
|
||||||
lines.push(`{`);
|
|
||||||
lines.push(` await ${subject}.${actionCall};`);
|
|
||||||
lines.push(`}/*, new ${actionInContext.frame.isMainFrame ? 'Page' : 'Frame'}WaitForNavigationOptions`);
|
|
||||||
lines.push(`{`);
|
|
||||||
lines.push(` UrlString = ${quote(signals.waitForNavigation.url)}`);
|
|
||||||
lines.push(`}*/);`);
|
|
||||||
} else {
|
|
||||||
lines.push(`await ${subject}.${actionCall};`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signals.download) {
|
if (signals.download) {
|
||||||
lines.unshift(`var download${signals.download.downloadAlias} = await ${pageAlias}.RunAndWaitForDownloadAsync(async () =>\n{`);
|
lines.unshift(`var download${signals.download.downloadAlias} = await ${pageAlias}.RunAndWaitForDownloadAsync(async () =>\n{`);
|
||||||
@ -96,7 +86,7 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
|
|||||||
formatter.add(line);
|
formatter.add(line);
|
||||||
|
|
||||||
if (signals.assertNavigation)
|
if (signals.assertNavigation)
|
||||||
formatter.add(` // Assert.AreEqual(${quote(signals.assertNavigation.url)}, ${pageAlias}.Url);`);
|
formatter.add(`await ${pageAlias}.WaitForURLAsync(${quote(signals.assertNavigation.url)});`);
|
||||||
return formatter.format();
|
return formatter.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -81,18 +81,10 @@ export class JavaLanguageGenerator implements LanguageGenerator {
|
|||||||
});`;
|
});`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signals.waitForNavigation) {
|
|
||||||
code = `
|
|
||||||
// ${pageAlias}.waitForNavigation(new Page.WaitForNavigationOptions().setUrl(${quote(signals.waitForNavigation.url)}), () ->
|
|
||||||
${pageAlias}.waitForNavigation(() -> {
|
|
||||||
${code}
|
|
||||||
});`;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatter.add(code);
|
formatter.add(code);
|
||||||
|
|
||||||
if (signals.assertNavigation)
|
if (signals.assertNavigation)
|
||||||
formatter.add(`// assertThat(${pageAlias}).hasURL(${quote(signals.assertNavigation.url)});`);
|
formatter.add(`assertThat(${pageAlias}).hasURL(${quote(signals.assertNavigation.url)});`);
|
||||||
return formatter.format();
|
return formatter.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
|
|||||||
});`);
|
});`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const emitPromiseAll = signals.waitForNavigation || signals.popup || signals.download;
|
const emitPromiseAll = signals.popup || signals.download;
|
||||||
if (emitPromiseAll) {
|
if (emitPromiseAll) {
|
||||||
// Generate either await Promise.all([]) or
|
// Generate either await Promise.all([]) or
|
||||||
// const [popup1] = await Promise.all([]).
|
// const [popup1] = await Promise.all([]).
|
||||||
@ -91,26 +91,22 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
|
|||||||
if (signals.popup)
|
if (signals.popup)
|
||||||
formatter.add(`${pageAlias}.waitForEvent('popup'),`);
|
formatter.add(`${pageAlias}.waitForEvent('popup'),`);
|
||||||
|
|
||||||
// Navigation signal.
|
|
||||||
if (signals.waitForNavigation)
|
|
||||||
formatter.add(`${pageAlias}.waitForNavigation(/*{ url: ${quote(signals.waitForNavigation.url)} }*/),`);
|
|
||||||
|
|
||||||
// Download signals.
|
// Download signals.
|
||||||
if (signals.download)
|
if (signals.download)
|
||||||
formatter.add(`${pageAlias}.waitForEvent('download'),`);
|
formatter.add(`${pageAlias}.waitForEvent('download'),`);
|
||||||
|
|
||||||
const prefix = (signals.popup || signals.waitForNavigation || signals.download) ? '' : 'await ';
|
const prefix = (signals.popup || signals.download) ? '' : 'await ';
|
||||||
const actionCall = this._generateActionCall(action);
|
const actionCall = this._generateActionCall(action);
|
||||||
const suffix = (signals.waitForNavigation || emitPromiseAll) ? '' : ';';
|
const suffix = emitPromiseAll ? '' : ';';
|
||||||
formatter.add(`${prefix}${subject}.${actionCall}${suffix}`);
|
formatter.add(`${prefix}${subject}.${actionCall}${suffix}`);
|
||||||
|
|
||||||
if (emitPromiseAll) {
|
if (emitPromiseAll) {
|
||||||
formatter.add(`]);`);
|
formatter.add(`]);`);
|
||||||
} else if (signals.assertNavigation) {
|
} else if (signals.assertNavigation) {
|
||||||
if (this._isTest)
|
if (this._isTest)
|
||||||
formatter.add(` await expect(${pageAlias}).toHaveURL(${quote(signals.assertNavigation.url)});`);
|
formatter.add(`await expect(${pageAlias}).toHaveURL(${quote(signals.assertNavigation.url)});`);
|
||||||
else
|
else
|
||||||
formatter.add(` // assert.equal(${pageAlias}.url(), ${quote(signals.assertNavigation.url)});`);
|
formatter.add(`await ${pageAlias}.waitForURL(${quote(signals.assertNavigation.url)});`);
|
||||||
}
|
}
|
||||||
return formatter.format();
|
return formatter.format();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,15 +47,12 @@ export function sanitizeDeviceOptions(device: any, options: BrowserContextOption
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function toSignalMap(action: Action) {
|
export function toSignalMap(action: Action) {
|
||||||
let waitForNavigation: NavigationSignal | undefined;
|
|
||||||
let assertNavigation: NavigationSignal | undefined;
|
let assertNavigation: NavigationSignal | undefined;
|
||||||
let popup: PopupSignal | undefined;
|
let popup: PopupSignal | undefined;
|
||||||
let download: DownloadSignal | undefined;
|
let download: DownloadSignal | undefined;
|
||||||
let dialog: DialogSignal | undefined;
|
let dialog: DialogSignal | undefined;
|
||||||
for (const signal of action.signals) {
|
for (const signal of action.signals) {
|
||||||
if (signal.name === 'navigation' && signal.isAsync)
|
if (signal.name === 'navigation')
|
||||||
waitForNavigation = signal;
|
|
||||||
else if (signal.name === 'navigation' && !signal.isAsync)
|
|
||||||
assertNavigation = signal;
|
assertNavigation = signal;
|
||||||
else if (signal.name === 'popup')
|
else if (signal.name === 'popup')
|
||||||
popup = signal;
|
popup = signal;
|
||||||
@ -65,7 +62,6 @@ export function toSignalMap(action: Action) {
|
|||||||
dialog = signal;
|
dialog = signal;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
waitForNavigation,
|
|
||||||
assertNavigation,
|
assertNavigation,
|
||||||
popup,
|
popup,
|
||||||
download,
|
download,
|
||||||
|
|||||||
@ -95,18 +95,14 @@ export class PythonLanguageGenerator implements LanguageGenerator {
|
|||||||
download = ${this._awaitPrefix}download_info.value`;
|
download = ${this._awaitPrefix}download_info.value`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signals.waitForNavigation) {
|
|
||||||
code = `
|
|
||||||
# ${this._asyncPrefix}with ${pageAlias}.expect_navigation(url=${quote(signals.waitForNavigation.url)}):
|
|
||||||
${this._asyncPrefix}with ${pageAlias}.expect_navigation() {
|
|
||||||
${code}
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
formatter.add(code);
|
formatter.add(code);
|
||||||
|
|
||||||
if (signals.assertNavigation)
|
if (signals.assertNavigation) {
|
||||||
formatter.add(` # ${this._awaitPrefix}expect(${pageAlias}).to_have_url(${quote(signals.assertNavigation.url)})`);
|
if (this._isPyTest)
|
||||||
|
formatter.add(`${this._awaitPrefix}expect(${pageAlias}).to_have_url(${quote(signals.assertNavigation.url)})`);
|
||||||
|
else
|
||||||
|
formatter.add(`${this._awaitPrefix}${pageAlias}.wait_for_url(${quote(signals.assertNavigation.url)})`);
|
||||||
|
}
|
||||||
return formatter.format();
|
return formatter.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -96,7 +96,6 @@ export type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageActi
|
|||||||
// Signals.
|
// Signals.
|
||||||
|
|
||||||
export type BaseSignal = {
|
export type BaseSignal = {
|
||||||
isAsync?: boolean,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NavigationSignal = BaseSignal & {
|
export type NavigationSignal = BaseSignal & {
|
||||||
|
|||||||
@ -607,39 +607,44 @@ test.describe('cli codegen', () => {
|
|||||||
expect(selector).toBe('text=link');
|
expect(selector).toBe('text=link');
|
||||||
const [, sources] = await Promise.all([
|
const [, sources] = await Promise.all([
|
||||||
page.waitForNavigation(),
|
page.waitForNavigation(),
|
||||||
recorder.waitForOutput('JavaScript', 'assert'),
|
recorder.waitForOutput('JavaScript', 'waitForURL'),
|
||||||
page.dispatchEvent('a', 'click', { detail: 1 })
|
page.dispatchEvent('a', 'click', { detail: 1 })
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(sources.get('JavaScript').text).toContain(`
|
expect.soft(sources.get('JavaScript').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
await page.locator('text=link').click();
|
await page.locator('text=link').click();
|
||||||
// assert.equal(page.url(), 'about:blank#foo');`);
|
await page.waitForURL('about:blank#foo');`);
|
||||||
|
|
||||||
expect(sources.get('Playwright Test').text).toContain(`
|
expect.soft(sources.get('Playwright Test').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
await page.locator('text=link').click();
|
await page.locator('text=link').click();
|
||||||
await expect(page).toHaveURL('about:blank#foo');`);
|
await expect(page).toHaveURL('about:blank#foo');`);
|
||||||
|
|
||||||
expect(sources.get('Java').text).toContain(`
|
expect.soft(sources.get('Java').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
page.locator("text=link").click();
|
page.locator("text=link").click();
|
||||||
// assertThat(page).hasURL("about:blank#foo");`);
|
assertThat(page).hasURL("about:blank#foo");`);
|
||||||
|
|
||||||
expect(sources.get('Python').text).toContain(`
|
expect.soft(sources.get('Python').text).toContain(`
|
||||||
# Click text=link
|
# Click text=link
|
||||||
page.locator(\"text=link\").click()
|
page.locator("text=link").click()
|
||||||
# expect(page).to_have_url(\"about:blank#foo\")`);
|
page.wait_for_url("about:blank#foo")`);
|
||||||
|
|
||||||
expect(sources.get('Python Async').text).toContain(`
|
expect.soft(sources.get('Python Async').text).toContain(`
|
||||||
# Click text=link
|
# Click text=link
|
||||||
await page.locator(\"text=link\").click()
|
await page.locator("text=link").click()
|
||||||
# await expect(page).to_have_url(\"about:blank#foo\")`);
|
await page.wait_for_url("about:blank#foo")`);
|
||||||
|
|
||||||
expect(sources.get('C#').text).toContain(`
|
expect.soft(sources.get('Pytest').text).toContain(`
|
||||||
|
# Click text=link
|
||||||
|
page.locator("text=link").click()
|
||||||
|
expect(page).to_have_url("about:blank#foo")`);
|
||||||
|
|
||||||
|
expect.soft(sources.get('C#').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
await page.Locator(\"text=link\").ClickAsync();
|
await page.Locator("text=link").ClickAsync();
|
||||||
// Assert.AreEqual(\"about:blank#foo\", page.Url);`);
|
await page.WaitForURLAsync("about:blank#foo");`);
|
||||||
|
|
||||||
expect(page.url()).toContain('about:blank#foo');
|
expect(page.url()).toContain('about:blank#foo');
|
||||||
});
|
});
|
||||||
@ -655,45 +660,34 @@ test.describe('cli codegen', () => {
|
|||||||
|
|
||||||
const [, sources] = await Promise.all([
|
const [, sources] = await Promise.all([
|
||||||
page.waitForNavigation(),
|
page.waitForNavigation(),
|
||||||
recorder.waitForOutput('JavaScript', 'waitForNavigation'),
|
recorder.waitForOutput('JavaScript', 'waitForURL'),
|
||||||
page.dispatchEvent('a', 'click', { detail: 1 })
|
page.dispatchEvent('a', 'click', { detail: 1 })
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(sources.get('JavaScript').text).toContain(`
|
expect.soft(sources.get('JavaScript').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
await Promise.all([
|
await page.locator('text=link').click();
|
||||||
page.waitForNavigation(/*{ url: 'about:blank#foo' }*/),
|
await page.waitForURL('about:blank#foo');`);
|
||||||
page.locator('text=link').click()
|
|
||||||
]);`);
|
|
||||||
|
|
||||||
expect(sources.get('Java').text).toContain(`
|
expect.soft(sources.get('Java').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
// page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("about:blank#foo"), () ->
|
page.locator("text=link").click();
|
||||||
page.waitForNavigation(() -> {
|
assertThat(page).hasURL("about:blank#foo");`);
|
||||||
page.locator("text=link").click();
|
|
||||||
});`);
|
|
||||||
|
|
||||||
expect(sources.get('Python').text).toContain(`
|
expect.soft(sources.get('Python').text).toContain(`
|
||||||
# Click text=link
|
# Click text=link
|
||||||
# with page.expect_navigation(url=\"about:blank#foo\"):
|
page.locator(\"text=link\").click()
|
||||||
with page.expect_navigation():
|
page.wait_for_url("about:blank#foo")`);
|
||||||
page.locator(\"text=link\").click()`);
|
|
||||||
|
|
||||||
expect(sources.get('Python Async').text).toContain(`
|
expect.soft(sources.get('Python Async').text).toContain(`
|
||||||
# Click text=link
|
# Click text=link
|
||||||
# async with page.expect_navigation(url=\"about:blank#foo\"):
|
await page.locator(\"text=link\").click()
|
||||||
async with page.expect_navigation():
|
await page.wait_for_url("about:blank#foo")`);
|
||||||
await page.locator(\"text=link\").click()`);
|
|
||||||
|
|
||||||
expect(sources.get('C#').text).toContain(`
|
expect.soft(sources.get('C#').text).toContain(`
|
||||||
// Click text=link
|
// Click text=link
|
||||||
await page.RunAndWaitForNavigationAsync(async () =>
|
await page.Locator(\"text=link\").ClickAsync();
|
||||||
{
|
await page.WaitForURLAsync(\"about:blank#foo\");`);
|
||||||
await page.Locator(\"text=link\").ClickAsync();
|
|
||||||
}/*, new PageWaitForNavigationOptions
|
|
||||||
{
|
|
||||||
UrlString = \"about:blank#foo\"
|
|
||||||
}*/);`);
|
|
||||||
|
|
||||||
expect(page.url()).toContain('about:blank#foo');
|
expect(page.url()).toContain('about:blank#foo');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -532,10 +532,10 @@ test.describe('cli codegen', () => {
|
|||||||
const [, sources] = await Promise.all([
|
const [, sources] = await Promise.all([
|
||||||
// This will click, finish the click, then mouse move, then navigate.
|
// This will click, finish the click, then mouse move, then navigate.
|
||||||
page.click('button'),
|
page.click('button'),
|
||||||
recorder.waitForOutput('JavaScript', 'waitForNavigation'),
|
recorder.waitForOutput('JavaScript', 'waitForURL'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(sources.get('JavaScript').text).toContain(`page.waitForNavigation(/*{ url: '${server.EMPTY_PAGE}' }*/)`);
|
expect(sources.get('JavaScript').text).toContain(`page.waitForURL('${server.EMPTY_PAGE}')`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should --save-trace', async ({ runCLI }, testInfo) => {
|
test('should --save-trace', async ({ runCLI }, testInfo) => {
|
||||||
|
|||||||
@ -115,18 +115,12 @@ class Recorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async waitForOutput(file: string, text: string): Promise<Map<string, Source>> {
|
async waitForOutput(file: string, text: string): Promise<Map<string, Source>> {
|
||||||
const sources: Source[] = await this.recorderPage.evaluate((params: { text: string, file: string }) => {
|
const handle = await this.recorderPage.waitForFunction((params: { text: string, file: string }) => {
|
||||||
const w = window as any;
|
const w = window as any;
|
||||||
return new Promise(f => {
|
const source = (w.playwrightSourcesEchoForTest || []).find((s: Source) => s.file === params.file);
|
||||||
const poll = () => {
|
return source && source.text.includes(params.text) ? w.playwrightSourcesEchoForTest : null;
|
||||||
const source = (w.playwrightSourcesEchoForTest || []).find((s: Source) => s.file === params.file);
|
}, { text, file }, { timeout: 8000, polling: 300 });
|
||||||
if (source && source.text.includes(params.text))
|
const sources: Source[] = await handle.jsonValue();
|
||||||
f(w.playwrightSourcesEchoForTest);
|
|
||||||
setTimeout(poll, 300);
|
|
||||||
};
|
|
||||||
poll();
|
|
||||||
});
|
|
||||||
}, { text, file });
|
|
||||||
for (const source of sources)
|
for (const source of sources)
|
||||||
this._sources.set(source.file, source);
|
this._sources.set(source.file, source);
|
||||||
return this._sources;
|
return this._sources;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user