diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 57a9336abe..7a5d86edcf 100755 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -240,6 +240,8 @@ async function launchContext(options: Options, headless: boolean, executablePath if (contextOptions.isMobile && browserType.name() === 'firefox') contextOptions.isMobile = undefined; + contextOptions.acceptDownloads = true; + // Proxy if (options.proxyServer) { @@ -335,7 +337,9 @@ async function launchContext(options: Options, headless: boolean, executablePath // Omit options that we add automatically for presentation purpose. delete launchOptions.headless; + delete launchOptions.executablePath; delete contextOptions.deviceScaleFactor; + delete contextOptions.acceptDownloads; return { browser, browserName: browserType.name(), context, contextOptions, launchOptions }; } diff --git a/src/server/supplements/recorder/codeGenerator.ts b/src/server/supplements/recorder/codeGenerator.ts index 9b9e404df4..3a2f5a8de5 100644 --- a/src/server/supplements/recorder/codeGenerator.ts +++ b/src/server/supplements/recorder/codeGenerator.ts @@ -40,8 +40,9 @@ export class CodeGenerator extends EventEmitter { constructor(browserName: string, generateHeaders: boolean, launchOptions: LaunchOptions, contextOptions: BrowserContextOptions, deviceName: string | undefined, saveStorage: string | undefined) { super(); + // Make a copy of options to modify them later. launchOptions = { headless: false, ...launchOptions }; - delete launchOptions.executablePath; + contextOptions = { ...contextOptions }; this._enabled = generateHeaders; this._options = { browserName, generateHeaders, launchOptions, contextOptions, deviceName, saveStorage }; this.restart(); @@ -127,6 +128,11 @@ export class CodeGenerator extends EventEmitter { signal(pageAlias: string, frame: Frame, signal: Signal) { if (!this._enabled) return; + + // We'll need to pass acceptDownloads for any generated downloads code to work. + if (signal.name === 'download') + this._options.contextOptions.acceptDownloads = true; + // Signal either arrives while action is being performed or shortly after. if (this._currentAction) { this._currentAction.action.signals.push(signal); diff --git a/tests/inspector/cli-codegen-2.spec.ts b/tests/inspector/cli-codegen-2.spec.ts index 93597e5544..f3c14ede06 100644 --- a/tests/inspector/cli-codegen-2.spec.ts +++ b/tests/inspector/cli-codegen-2.spec.ts @@ -250,6 +250,10 @@ test.describe('cli codegen', () => { ]); const sources = await recorder.waitForOutput('', 'waitForEvent'); + expect(sources.get('').text).toContain(` + const context = await browser.newContext({ + acceptDownloads: true + });`); expect(sources.get('').text).toContain(` // Click text=Download const [download] = await Promise.all([ @@ -257,24 +261,36 @@ test.describe('cli codegen', () => { page.click('text=Download') ]);`); + // TODO: fix generated options in java. + expect(sources.get('').text).toContain(` + BrowserContext context = browser.newContext(new Browser.NewContextOptions());`); expect(sources.get('').text).toContain(` // Click text=Download Download download = page.waitForDownload(() -> { page.click("text=Download"); });`); + expect(sources.get('').text).toContain(` + context = browser.new_context(accept_downloads=True)`); expect(sources.get('').text).toContain(` # Click text=Download with page.expect_download() as download_info: page.click(\"text=Download\") download = download_info.value`); + expect(sources.get('').text).toContain(` + context = await browser.new_context(accept_downloads=True)`); expect(sources.get('').text).toContain(` # Click text=Download async with page.expect_download() as download_info: await page.click(\"text=Download\") download = await download_info.value`); + expect(sources.get('').text).toContain(` + var context = await browser.NewContextAsync(new BrowserNewContextOptions + { + AcceptDownloads = true, + });`); expect(sources.get('').text).toContain(` // Click text=Download var download1 = await page.RunAndWaitForEventAsync(PageEvent.Download, async () =>