diff --git a/packages/playwright-core/src/cli/cli.ts b/packages/playwright-core/src/cli/cli.ts index d5a844b762..4b751ec065 100755 --- a/packages/playwright-core/src/cli/cli.ts +++ b/packages/playwright-core/src/cli/cli.ts @@ -57,7 +57,7 @@ program commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', []) .action(function(url, options) { - open(options, url, language()).catch(logErrorAndExit); + open(options, url, codegenId()).catch(logErrorAndExit); }) .addHelpText('afterAll', ` Examples: @@ -68,7 +68,7 @@ Examples: commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [ ['-o, --output ', 'saves the generated script to a file'], - ['--target ', `language to generate, one of javascript, test, python, python-async, pytest, csharp, csharp-mstest, csharp-nunit, java`, language()], + ['--target ', `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java`, codegenId()], ['--save-trace ', 'record a trace for the session and save it to a file'], ]).action(function(url, options) { codegen(options, url, options.target, options.output).catch(logErrorAndExit); @@ -267,13 +267,12 @@ program program .command('run-server', { hidden: true }) - .option('--reuse-browser', 'Whether to reuse the browser instance') .option('--port ', 'Server port') .option('--path ', 'Endpoint Path', '/') .option('--max-clients ', 'Maximum clients') .option('--no-socks-proxy', 'Disable Socks Proxy') .action(function(options) { - runServer(options.port ? +options.port : undefined, options.path, options.maxClients ? +options.maxClients : Infinity, options.socksProxy, options.reuseBrowser).catch(logErrorAndExit); + runServer(options.port ? +options.port : undefined, options.path, options.maxClients ? +options.maxClients : Infinity, options.socksProxy).catch(logErrorAndExit); }); program @@ -682,8 +681,8 @@ function logErrorAndExit(e: Error) { process.exit(1); } -function language(): string { - return process.env.PW_LANG_NAME || 'test'; +function codegenId(): string { + return process.env.PW_LANG_NAME || 'playwright-test'; } function commandWithOpenOptions(command: string, description: string, options: any[][]): Command { diff --git a/packages/playwright-core/src/cli/driver.ts b/packages/playwright-core/src/cli/driver.ts index 9af655c792..587fd6a36a 100644 --- a/packages/playwright-core/src/cli/driver.ts +++ b/packages/playwright-core/src/cli/driver.ts @@ -21,12 +21,9 @@ import * as playwright from '../..'; import type { BrowserType } from '../client/browserType'; import type { LaunchServerOptions } from '../client/types'; import { createPlaywright, DispatcherConnection, RootDispatcher, PlaywrightDispatcher } from '../server'; -import type { Playwright } from '../server/playwright'; import { IpcTransport, PipeTransport } from '../protocol/transport'; import { PlaywrightServer } from '../remote/playwrightServer'; import { gracefullyCloseAll } from '../utils/processLauncher'; -import type { Mode } from '@recorder/recorderTypes'; -import { DebugController } from '../server/debugController'; export function printApiJson() { // Note: this file is generated by build-playwright-driver.sh @@ -49,14 +46,12 @@ export function runDriver() { }; } -export async function runServer(port: number | undefined, path = '/', maxConnections = Infinity, enableSocksProxy = true, reuseBrowser = false) { +export async function runServer(port: number | undefined, path = '/', maxConnections = Infinity, enableSocksProxy = true) { const server = new PlaywrightServer({ path, maxConnections, enableSocksProxy }); const wsEndpoint = await server.listen(port); process.on('exit', () => server.close().catch(console.error)); console.log('Listening on ' + wsEndpoint); // eslint-disable-line no-console process.stdin.on('close', () => selfDestruct()); - if (reuseBrowser && process.send) - wireController(server.preLaunchedPlaywright(), wsEndpoint); } export async function launchBrowserServer(browserName: string, configFile?: string) { @@ -76,67 +71,3 @@ function selfDestruct() { process.exit(0); }); } - -class ProtocolHandler { - private _controller: DebugController; - - constructor(playwright: Playwright) { - this._controller = playwright.debugController; - this._controller.setAutoCloseAllowed(true); - this._controller.setReportStateChanged(true); - this._controller.on(DebugController.Events.BrowsersChanged, browsers => { - process.send!({ method: 'browsersChanged', params: { browsers } }); - }); - this._controller.on(DebugController.Events.InspectRequested, ({ selector, locators }) => { - process.send!({ method: 'inspectRequested', params: { selector, locators } }); - }); - this._controller.on(DebugController.Events.SourcesChanged, sources => { - process.send!({ method: 'sourcesChanged', params: { sources } }); - }); - } - - async resetForReuse() { - await this._controller.resetForReuse(); - } - - async navigate(params: { url: string }) { - await this._controller.navigate(params.url); - } - - async setMode(params: { mode: Mode, language?: string, file?: string }) { - await this._controller.setRecorderMode(params); - } - - async setAutoClose(params: { enabled: boolean }) { - await this._controller.setAutoCloseEnabled(params.enabled); - } - - async highlight(params: { selector: string }) { - await this._controller.highlight(params.selector); - } - - async hideHighlight() { - await this._controller.hideHighlight(); - } - - async closeAllBrowsers() { - await this._controller.closeAllBrowsers(); - } - - async kill() { - await this._controller.kill(); - } -} - -function wireController(playwright: Playwright, wsEndpoint: string) { - process.send!({ method: 'ready', params: { wsEndpoint } }); - const handler = new ProtocolHandler(playwright); - process.on('message', async message => { - try { - const result = await (handler as any)[message.method](message.params); - process.send!({ id: message.id, result }); - } catch (e) { - process.send!({ id: message.id, error: e.toString() }); - } - }); -} diff --git a/packages/playwright-core/src/common/userAgent.ts b/packages/playwright-core/src/common/userAgent.ts index b31cc04bc2..1ee9336284 100644 --- a/packages/playwright-core/src/common/userAgent.ts +++ b/packages/playwright-core/src/common/userAgent.ts @@ -58,21 +58,21 @@ function determineUserAgent(): string { additionalTokens.push('CI/1'); const serializedTokens = additionalTokens.length ? ' ' + additionalTokens.join(' ') : ''; - const { langName, langVersion } = getClientLanguage(); - return `Playwright/${getPlaywrightVersion()} (${os.arch()}; ${osIdentifier} ${osVersion}) ${langName}/${langVersion}${serializedTokens}`; + const { embedderName, embedderVersion } = getEmbedderName(); + return `Playwright/${getPlaywrightVersion()} (${os.arch()}; ${osIdentifier} ${osVersion}) ${embedderName}/${embedderVersion}${serializedTokens}`; } -export function getClientLanguage(): { langName: string, langVersion: string } { - let langName = 'unknown'; - let langVersion = 'unknown'; +export function getEmbedderName(): { embedderName: string, embedderVersion: string } { + let embedderName = 'unknown'; + let embedderVersion = 'unknown'; if (!process.env.PW_LANG_NAME) { - langName = 'node'; - langVersion = process.version.substring(1).split('.').slice(0, 2).join('.'); + embedderName = 'node'; + embedderVersion = process.version.substring(1).split('.').slice(0, 2).join('.'); } else if (['node', 'python', 'java', 'csharp'].includes(process.env.PW_LANG_NAME)) { - langName = process.env.PW_LANG_NAME; - langVersion = process.env.PW_LANG_NAME_VERSION ?? 'unknown'; + embedderName = process.env.PW_LANG_NAME; + embedderVersion = process.env.PW_LANG_NAME_VERSION ?? 'unknown'; } - return { langName, langVersion }; + return { embedderName, embedderVersion }; } export function getPlaywrightVersion(majorMinorOnly = false): string { diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 44cca2fcb7..21f19a427a 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -333,11 +333,14 @@ scheme.RecorderSource = tObject({ scheme.DebugControllerInitializer = tOptional(tObject({})); scheme.DebugControllerInspectRequestedEvent = tObject({ selector: tString, - locators: tArray(tType('NameValue')), + locator: tString, }); scheme.DebugControllerStateChangedEvent = tObject({ pageCount: tNumber, }); +scheme.DebugControllerSourceChangedEvent = tObject({ + text: tString, +}); scheme.DebugControllerBrowsersChangedEvent = tObject({ browsers: tArray(tObject({ contexts: tArray(tObject({ @@ -345,9 +348,11 @@ scheme.DebugControllerBrowsersChangedEvent = tObject({ })), })), }); -scheme.DebugControllerSourcesChangedEvent = tObject({ - sources: tArray(tType('RecorderSource')), +scheme.DebugControllerInitializeParams = tObject({ + codegenId: tString, + sdkLanguage: tEnum(['javascript', 'python', 'java', 'csharp']), }); +scheme.DebugControllerInitializeResult = tOptional(tObject({})); scheme.DebugControllerSetReportStateChangedParams = tObject({ enabled: tBoolean, }); @@ -360,8 +365,6 @@ scheme.DebugControllerNavigateParams = tObject({ scheme.DebugControllerNavigateResult = tOptional(tObject({})); scheme.DebugControllerSetRecorderModeParams = tObject({ mode: tEnum(['inspecting', 'recording', 'none']), - language: tOptional(tString), - file: tOptional(tString), }); scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({})); scheme.DebugControllerHighlightParams = tObject({ diff --git a/packages/playwright-core/src/server/debugController.ts b/packages/playwright-core/src/server/debugController.ts index 87b7af7766..7f2aa33830 100644 --- a/packages/playwright-core/src/server/debugController.ts +++ b/packages/playwright-core/src/server/debugController.ts @@ -25,7 +25,6 @@ import { Recorder } from './recorder'; import { EmptyRecorderApp } from './recorder/recorderApp'; import { asLocator } from './isomorphic/locatorGenerators'; import type { Language } from './isomorphic/locatorGenerators'; -import type { NameValue } from '../common/types'; const internalMetadata = serverSideCallMetadata(); @@ -34,7 +33,7 @@ export class DebugController extends SdkObject { BrowsersChanged: 'browsersChanged', StateChanged: 'stateChanged', InspectRequested: 'inspectRequested', - SourcesChanged: 'sourcesChanged', + SourceChanged: 'sourceChanged', }; private _autoCloseTimer: NodeJS.Timeout | undefined; @@ -42,12 +41,19 @@ export class DebugController extends SdkObject { private _autoCloseAllowed = false; private _trackHierarchyListener: InstrumentationListener | undefined; private _playwright: Playwright; + _sdkLanguage: Language = 'javascript'; + _codegenId: string = 'playwright-test'; constructor(playwright: Playwright) { super({ attribution: { isInternalPlaywright: true }, instrumentation: createInstrumentation() } as any, undefined, 'DebugController'); this._playwright = playwright; } + initialize(codegenId: string, sdkLanguage: Language) { + this._codegenId = codegenId; + this._sdkLanguage = sdkLanguage; + } + setAutoCloseAllowed(allowed: boolean) { this._autoCloseAllowed = allowed; } @@ -83,7 +89,8 @@ export class DebugController extends SdkObject { await p.mainFrame().goto(internalMetadata, url); } - async setRecorderMode(params: { mode: Mode, language?: string, file?: string }) { + async setRecorderMode(params: { mode: Mode, file?: string }) { + // TODO: |file| is only used in the legacy mode. await this._closeBrowsersWithoutPages(); if (params.mode === 'none') { @@ -108,7 +115,7 @@ export class DebugController extends SdkObject { for (const recorder of await this._allRecorders()) { recorder.setHighlightedSelector(''); if (params.mode === 'recording') - recorder.setOutput(params.language!, params.file); + recorder.setOutput(this._codegenId, params.file); recorder.setMode(params.mode); } this.setAutoCloseEnabled(true); @@ -216,11 +223,12 @@ class InspectingRecorderApp extends EmptyRecorderApp { } override async setSelector(selector: string): Promise { - const locators: NameValue[] = ['javascript', 'python', 'java', 'csharp'].map(l => ({ name: l, value: asLocator(l as Language, selector) })); - this._debugController.emit(DebugController.Events.InspectRequested, { selector, locators }); + const locator: string = asLocator(this._debugController._sdkLanguage, selector); + this._debugController.emit(DebugController.Events.InspectRequested, { selector, locator }); } override async setSources(sources: Source[]): Promise { - this._debugController.emit(DebugController.Events.SourcesChanged, sources); + const source = sources.find(s => s.id === this._debugController._codegenId); + this._debugController.emit(DebugController.Events.SourceChanged, source?.text || ''); } } diff --git a/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts b/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts index b2ebcc99c2..438bf4836b 100644 --- a/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts @@ -28,14 +28,18 @@ export class DebugControllerDispatcher extends Dispatcher { this._dispatchEvent('stateChanged', params); }); - this._object.on(DebugController.Events.InspectRequested, ({ selector, locators }) => { - this._dispatchEvent('inspectRequested', { selector, locators }); + this._object.on(DebugController.Events.InspectRequested, ({ selector, locator }) => { + this._dispatchEvent('inspectRequested', { selector, locator }); }); - this._object.on(DebugController.Events.SourcesChanged, sources => { - this._dispatchEvent('sourcesChanged', { sources }); + this._object.on(DebugController.Events.SourceChanged, text => { + this._dispatchEvent('sourceChanged', { text }); }); } + async initialize(params: channels.DebugControllerInitializeParams) { + this._object.initialize(params.codegenId, params.sdkLanguage); + } + async setReportStateChanged(params: channels.DebugControllerSetReportStateChangedParams) { this._object.setReportStateChanged(params.enabled); } diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 7abd400aab..0c67bc2f88 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -214,8 +214,8 @@ export class Recorder implements InstrumentationListener { this._refreshOverlay(); } - setOutput(language: string, outputFile: string | undefined) { - this._contextRecorder.setOutput(language, outputFile); + setOutput(codegenId: string, outputFile: string | undefined) { + this._contextRecorder.setOutput(codegenId, outputFile); } private _refreshOverlay() { @@ -367,7 +367,7 @@ class ContextRecorder extends EventEmitter { this._generator = generator; } - setOutput(language: string, outputFile: string | undefined) { + setOutput(codegenId: string, outputFile?: string) { const languages = new Set([ new JavaLanguageGenerator(), new JavaScriptLanguageGenerator(/* isPlaywrightTest */false), @@ -379,10 +379,9 @@ class ContextRecorder extends EventEmitter { new CSharpLanguageGenerator('nunit'), new CSharpLanguageGenerator('library'), ]); - const primaryLanguage = [...languages].find(l => l.id === language); + const primaryLanguage = [...languages].find(l => l.id === codegenId); if (!primaryLanguage) - throw new Error(`\n===============================\nUnsupported language: '${language}'\n===============================\n`); - + throw new Error(`\n===============================\nUnsupported language: '${codegenId}'\n===============================\n`); languages.delete(primaryLanguage); this._orderedLanguages = [primaryLanguage, ...languages]; this._throttledOutputFile = outputFile ? new ThrottledFile(outputFile) : null; diff --git a/packages/playwright-core/src/server/recorder/javascript.ts b/packages/playwright-core/src/server/recorder/javascript.ts index 9acd68db01..31d21c86ce 100644 --- a/packages/playwright-core/src/server/recorder/javascript.ts +++ b/packages/playwright-core/src/server/recorder/javascript.ts @@ -33,7 +33,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { private _isTest: boolean; constructor(isTest: boolean) { - this.id = isTest ? 'test' : 'javascript'; + this.id = isTest ? 'playwright-test' : 'javascript'; this.name = isTest ? 'Test Runner' : 'Library'; this._isTest = isTest; } @@ -175,7 +175,7 @@ ${useText ? '\ntest.use(' + useText + ');\n' : ''} } generateTestFooter(saveStorage: string | undefined): string { - return `\n});`; + return `});`; } generateStandaloneHeader(options: LanguageGeneratorOptions): string { diff --git a/packages/playwright-core/src/server/recorder/python.ts b/packages/playwright-core/src/server/recorder/python.ts index aae6415ca1..302c7acec7 100644 --- a/packages/playwright-core/src/server/recorder/python.ts +++ b/packages/playwright-core/src/server/recorder/python.ts @@ -37,7 +37,7 @@ export class PythonLanguageGenerator implements LanguageGenerator { private _isPyTest: boolean; constructor(isAsync: boolean, isPyTest: boolean) { - this.id = isPyTest ? 'pytest' : (isAsync ? 'python-async' : 'python'); + this.id = isPyTest ? 'python-pytest' : (isAsync ? 'python-async' : 'python'); this.name = isPyTest ? 'Pytest' : (isAsync ? 'Library Async' : 'Library'); this._isAsync = isAsync; this._isPyTest = isPyTest; diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index ff008f5873..91c3893434 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -22,7 +22,7 @@ import * as fs from 'fs'; import { lockfile } from '../../utilsBundle'; import { getLinuxDistributionInfo } from '../../utils/linuxUtils'; import { fetchData } from '../../common/netUtils'; -import { getClientLanguage } from '../../common/userAgent'; +import { getEmbedderName } from '../../common/userAgent'; import { getFromENV, getAsBooleanFromENV, calculateSha1, wrapInASCIIBox } from '../../utils'; import { removeFolders, existsAsync, canAccessFile } from '../../utils/fileUtils'; import { hostPlatform } from '../../utils/hostPlatform'; @@ -696,9 +696,9 @@ export class Registry { if (!executable._install) throw new Error(`ERROR: Playwright does not support installing ${executable.name}`); - const { langName } = getClientLanguage(); - if (!getAsBooleanFromENV('CI') && !executable._isHermeticInstallation && !forceReinstall && executable.executablePath(langName)) { - const command = buildPlaywrightCLICommand(langName, 'install --force ' + executable.name); + const { embedderName } = getEmbedderName(); + if (!getAsBooleanFromENV('CI') && !executable._isHermeticInstallation && !forceReinstall && executable.executablePath(embedderName)) { + const command = buildPlaywrightCLICommand(embedderName, 'install --force ' + executable.name); throw new Error('\n' + wrapInASCIIBox([ `ATTENTION: "${executable.name}" is already installed on the system!`, ``, diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index d5c1279a99..ef53f73a8b 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -591,11 +591,12 @@ export type DebugControllerInitializer = {}; export interface DebugControllerEventTarget { on(event: 'inspectRequested', callback: (params: DebugControllerInspectRequestedEvent) => void): this; on(event: 'stateChanged', callback: (params: DebugControllerStateChangedEvent) => void): this; + on(event: 'sourceChanged', callback: (params: DebugControllerSourceChangedEvent) => void): this; on(event: 'browsersChanged', callback: (params: DebugControllerBrowsersChangedEvent) => void): this; - on(event: 'sourcesChanged', callback: (params: DebugControllerSourcesChangedEvent) => void): this; } export interface DebugControllerChannel extends DebugControllerEventTarget, Channel { _type_DebugController: boolean; + initialize(params: DebugControllerInitializeParams, metadata?: Metadata): Promise; setReportStateChanged(params: DebugControllerSetReportStateChangedParams, metadata?: Metadata): Promise; resetForReuse(params?: DebugControllerResetForReuseParams, metadata?: Metadata): Promise; navigate(params: DebugControllerNavigateParams, metadata?: Metadata): Promise; @@ -607,11 +608,14 @@ export interface DebugControllerChannel extends DebugControllerEventTarget, Chan } export type DebugControllerInspectRequestedEvent = { selector: string, - locators: NameValue[], + locator: string, }; export type DebugControllerStateChangedEvent = { pageCount: number, }; +export type DebugControllerSourceChangedEvent = { + text: string, +}; export type DebugControllerBrowsersChangedEvent = { browsers: { contexts: { @@ -619,9 +623,14 @@ export type DebugControllerBrowsersChangedEvent = { }[], }[], }; -export type DebugControllerSourcesChangedEvent = { - sources: RecorderSource[], +export type DebugControllerInitializeParams = { + codegenId: string, + sdkLanguage: 'javascript' | 'python' | 'java' | 'csharp', }; +export type DebugControllerInitializeOptions = { + +}; +export type DebugControllerInitializeResult = void; export type DebugControllerSetReportStateChangedParams = { enabled: boolean, }; @@ -641,12 +650,9 @@ export type DebugControllerNavigateOptions = { export type DebugControllerNavigateResult = void; export type DebugControllerSetRecorderModeParams = { mode: 'inspecting' | 'recording' | 'none', - language?: string, - file?: string, }; export type DebugControllerSetRecorderModeOptions = { - language?: string, - file?: string, + }; export type DebugControllerSetRecorderModeResult = void; export type DebugControllerHighlightParams = { @@ -669,8 +675,8 @@ export type DebugControllerCloseAllBrowsersResult = void; export interface DebugControllerEvents { 'inspectRequested': DebugControllerInspectRequestedEvent; 'stateChanged': DebugControllerStateChangedEvent; + 'sourceChanged': DebugControllerSourceChangedEvent; 'browsersChanged': DebugControllerBrowsersChangedEvent; - 'sourcesChanged': DebugControllerSourcesChangedEvent; } // ----------- SocksSupport ----------- diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index 02922cfcea..cfccfdd3e7 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -660,6 +660,17 @@ DebugController: type: interface commands: + initialize: + parameters: + codegenId: string + sdkLanguage: + type: enum + literals: + - javascript + - python + - java + - csharp + setReportStateChanged: parameters: enabled: boolean @@ -678,8 +689,6 @@ DebugController: - inspecting - recording - none - language: string? - file: string? highlight: parameters: @@ -695,14 +704,16 @@ DebugController: inspectRequested: parameters: selector: string - locators: - type: array - items: NameValue + locator: string stateChanged: parameters: pageCount: number + sourceChanged: + parameters: + text: string + # Deprecated browsersChanged: parameters: @@ -720,12 +731,6 @@ DebugController: type: array items: string - sourcesChanged: - parameters: - sources: - type: array - items: RecorderSource - SocksSupport: type: interface diff --git a/tests/library/debug-controller.spec.ts b/tests/library/debug-controller.spec.ts index 5242380705..ef6320c2e3 100644 --- a/tests/library/debug-controller.spec.ts +++ b/tests/library/debug-controller.spec.ts @@ -70,20 +70,10 @@ test('should pick element', async ({ backend, connectedBrowser }) => { expect(events).toEqual([ { selector: 'body', - locators: [ - { name: 'javascript', value: 'locator(\'body\')' }, - { name: 'python', value: 'locator("body")' }, - { name: 'java', value: 'locator("body")' }, - { name: 'csharp', value: 'Locator("body")' } - ] + locator: 'locator(\'body\')', }, { selector: 'body', - locators: [ - { name: 'javascript', value: 'locator(\'body\')' }, - { name: 'python', value: 'locator("body")' }, - { name: 'java', value: 'locator("body")' }, - { name: 'csharp', value: 'Locator("body")' } - ] + locator: 'locator(\'body\')', }, ]); @@ -156,3 +146,29 @@ test('should highlight all', async ({ backend, connectedBrowser }) => { await expect(page1.getByText('locator(\'button\')')).toBeHidden({ timeout: 1000000 }); await expect(page2.getByText('locator(\'button\')')).toBeHidden(); }); + +test('should record', async ({ backend, connectedBrowser }) => { + const events = []; + backend.on('sourceChanged', event => events.push(event)); + + await backend.setMode({ mode: 'recording' }); + + const context = await connectedBrowser._newContextForReuse(); + const [page] = context.pages(); + + await page.locator('body').click(); + + await expect.poll(() => events[events.length - 1]).toEqual({ + text: `import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('about:blank'); + await page.locator('body').click(); +});` + }); + const length = events.length; + // No events after mode disabled + await backend.setMode({ mode: 'none' }); + await page.locator('body').click(); + expect(events).toHaveLength(length); +}); diff --git a/tests/library/inspector/cli-codegen-pytest.spec.ts b/tests/library/inspector/cli-codegen-pytest.spec.ts index e3e5b30b85..968a2d4676 100644 --- a/tests/library/inspector/cli-codegen-pytest.spec.ts +++ b/tests/library/inspector/cli-codegen-pytest.spec.ts @@ -21,7 +21,7 @@ import { test, expect } from './inspectorTest'; const emptyHTML = new URL('file://' + path.join(__dirname, '..', '..', 'assets', 'empty.html')).toString(); test('should print the correct imports and context options', async ({ runCLI }) => { - const cli = runCLI(['--target=pytest', emptyHTML]); + const cli = runCLI(['--target=python-pytest', emptyHTML]); const expectedResult = `from playwright.sync_api import Page, expect @@ -34,7 +34,7 @@ test('should print the correct context options when using a device and lang', as test.skip(browserName !== 'webkit'); const tmpFile = testInfo.outputPath('script.js'); - const cli = runCLI(['--target=pytest', '--device=iPhone 11', '--lang=en-US', '--output', tmpFile, emptyHTML]); + const cli = runCLI(['--target=python-pytest', '--device=iPhone 11', '--lang=en-US', '--output', tmpFile, emptyHTML]); await cli.exited; const content = fs.readFileSync(tmpFile); expect(content.toString()).toBe(`import pytest @@ -54,7 +54,7 @@ def test_example(page: Page) -> None: test('should save the codegen output to a file if specified', async ({ runCLI }, testInfo) => { const tmpFile = testInfo.outputPath('test_example.py'); - const cli = runCLI(['--target=pytest', '--output', tmpFile, emptyHTML]); + const cli = runCLI(['--target=python-pytest', '--output', tmpFile, emptyHTML]); await cli.exited; const content = fs.readFileSync(tmpFile); expect(content.toString()).toBe(`from playwright.sync_api import Page, expect diff --git a/tests/library/inspector/cli-codegen-test.spec.ts b/tests/library/inspector/cli-codegen-test.spec.ts index 7f32c22183..9066469dd7 100644 --- a/tests/library/inspector/cli-codegen-test.spec.ts +++ b/tests/library/inspector/cli-codegen-test.spec.ts @@ -25,7 +25,6 @@ test('should print the correct imports and context options', async ({ runCLI }) const expectedResult = `import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { - });`; await cli.waitFor(expectedResult); expect(cli.text()).toContain(expectedResult); @@ -93,7 +92,7 @@ test('test', async ({ page }) => {`; test('should work with --save-har', async ({ runCLI }, testInfo) => { const harFileName = testInfo.outputPath('har.har'); - const cli = runCLI(['--target=test', `--save-har=${harFileName}`]); + const cli = runCLI(['--target=playwright-test', `--save-har=${harFileName}`]); const expectedResult = ` recordHar: { mode: 'minimal', diff --git a/tests/library/inspector/inspectorTest.ts b/tests/library/inspector/inspectorTest.ts index 588952522e..94ebd16dc2 100644 --- a/tests/library/inspector/inspectorTest.ts +++ b/tests/library/inspector/inspectorTest.ts @@ -33,11 +33,11 @@ const codegenLang2Id: Map = new Map([ ['Java', 'java'], ['Python', 'python'], ['Python Async', 'python-async'], - ['Pytest', 'pytest'], + ['Pytest', 'python-pytest'], ['C#', 'csharp'], ['C# NUnit', 'csharp-nunit'], ['C# MSTest', 'csharp-mstest'], - ['Playwright Test', 'test'], + ['Playwright Test', 'playwright-test'], ]); const codegenLangId2lang = new Map([...codegenLang2Id.entries()].map(([lang, langId]) => [langId, lang]));