Skip to content

Commit

Permalink
feat(vscode): allow running codegen with selected browser/options
Browse files Browse the repository at this point in the history
  • Loading branch information
mxschmitt committed Mar 19, 2024
1 parent 3ee13cb commit 387293b
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
3 changes: 3 additions & 0 deletions packages/playwright-core/src/protocol/validator.ts
Expand Up @@ -400,6 +400,9 @@ scheme.DebugControllerNavigateResult = tOptional(tObject({}));
scheme.DebugControllerSetRecorderModeParams = tObject({
mode: tEnum(['inspecting', 'recording', 'none']),
testIdAttributeName: tOptional(tString),
browserName: tOptional(tEnum(['chromium', 'firefox', 'webkit'])),
contextOptions: tOptional(tType('BrowserNewContextForReuseParams')),
launchOptions: tOptional(tType('BrowserTypeLaunchParams')),
});
scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({}));
scheme.DebugControllerHighlightParams = tObject({
Expand Down
41 changes: 31 additions & 10 deletions packages/playwright-core/src/server/debugController.ts
Expand Up @@ -25,8 +25,10 @@ import { Recorder } from './recorder';
import { EmptyRecorderApp } from './recorder/recorderApp';
import { asLocator } from '../utils/isomorphic/locatorGenerators';
import type { Language } from '../utils/isomorphic/locatorGenerators';
import type { BrowserNewContextForReuseParams, BrowserTypeLaunchParams } from '@protocol/channels';

const internalMetadata = serverSideCallMetadata();
const kLaunchOptionsSymbol = Symbol('kBrowserOptions');

export class DebugController extends SdkObject {
static Events = {
Expand Down Expand Up @@ -79,20 +81,27 @@ export class DebugController extends SdkObject {
}
}

async resetForReuse() {
async resetForReuse(params: BrowserNewContextForReuseParams | null = null) {
const contexts = new Set<BrowserContext>();
for (const page of this._playwright.allPages())
contexts.add(page.context());
for (const context of contexts)
await context.resetForReuse(internalMetadata, null);
await context.resetForReuse(internalMetadata, params);
}

async navigate(url: string) {
for (const p of this._playwright.allPages())
await p.mainFrame().goto(internalMetadata, url);
}

async setRecorderMode(params: { mode: Mode, file?: string, testIdAttributeName?: string }) {
async setRecorderMode(params: {
mode: Mode,
file?: string,
testIdAttributeName?: string,
browserName?: 'chromium' | 'firefox' | 'webkit',
contextOptions?: BrowserNewContextForReuseParams,
launchOptions?: BrowserTypeLaunchParams,
}) {
// TODO: |file| is only used in the legacy mode.
await this._closeBrowsersWithoutPages();

Expand All @@ -105,15 +114,27 @@ export class DebugController extends SdkObject {
return;
}

if (!this._playwright.allBrowsers().length)
await this._playwright.chromium.launch(internalMetadata, { headless: !!process.env.PW_DEBUG_CONTROLLER_HEADLESS });
// Previous browser + launchOptions did not match the previous one.
const launchOptions = {
...params.launchOptions,
headless: !!process.env.PW_DEBUG_CONTROLLER_HEADLESS,
};
const previousBrowser = this._playwright.allBrowsers().find(browser =>
browser.options.name === (params.browserName ?? 'chromium') &&
JSON.stringify((browser as any)[kLaunchOptionsSymbol]) === JSON.stringify(launchOptions)
);
if (!previousBrowser) {
await this.closeAllBrowsers();
const browser = await this._playwright[params.browserName ?? 'chromium'].launch(internalMetadata, launchOptions);
(browser as any)[kLaunchOptionsSymbol] = launchOptions;
}
// Create page if none.
const pages = this._playwright.allPages();
if (!pages.length) {
const [browser] = this._playwright.allBrowsers();
const { context } = await browser.newContextForReuse({}, internalMetadata);
const [browser] = this._playwright.allBrowsers();
const { context, needsReset } = await browser.newContextForReuse(params.contextOptions || {}, internalMetadata);
if (needsReset)
this.resetForReuse(params.contextOptions);
if (!context.pages().length)
await context.newPage(internalMetadata);
}
// Update test id attribute.
if (params.testIdAttributeName) {
for (const page of this._playwright.allPages())
Expand Down
36 changes: 34 additions & 2 deletions packages/playwright/src/runner/runner.ts
Expand Up @@ -33,11 +33,22 @@ import type { Suite } from '../common/test';
import { wrapReporterAsV2 } from '../reporters/reporterV2';
import { affectedTestFiles } from '../transform/compilationCache';
import { installRootRedirect, openTraceInBrowser, openTraceViewerApp } from 'playwright-core/lib/server';
import type { BrowserContextOptions } from 'playwright-core/lib/client/types';
import type { BrowserTypeLaunchOptions } from '@protocol/channels';

type ProjectConfigWithFiles = {
name: string;
testDir: string;
use: { testIdAttribute?: string };
use: {
testIdAttribute?: string;
browserName?: string;
// User facing options which might relevant for codegen in VSCode:
contextOptions: Pick<BrowserContextOptions, 'viewport'
| 'ignoreHTTPSErrors' | 'javaScriptEnabled' | 'bypassCSP'
| 'userAgent' | 'locale' | 'timezoneId' | 'geolocation' | 'permissions'
| 'offline' | 'storageState' | 'extraHTTPHeaders'>;
launchOptions: Pick<BrowserTypeLaunchOptions, 'args' | 'channel'>
};
files: string[];
};

Expand Down Expand Up @@ -70,7 +81,28 @@ export class Runner {
report.projects.push({
name: project.project.name,
testDir: project.project.testDir,
use: { testIdAttribute: project.project.use.testIdAttribute },
use: {
browserName: project.project.use.browserName || project.project.use.defaultBrowserType,
testIdAttribute: project.project.use.testIdAttribute,
launchOptions: {
channel: project.project.use.channel,
args: project.project.use.launchOptions?.args,
},
contextOptions: {
viewport: project.project.use.viewport,
ignoreHTTPSErrors: project.project.use.ignoreHTTPSErrors,
javaScriptEnabled: project.project.use.javaScriptEnabled,
bypassCSP: project.project.use.bypassCSP,
userAgent: project.project.use.userAgent,
locale: project.project.use.locale,
timezoneId: project.project.use.timezoneId,
geolocation: project.project.use.geolocation,
permissions: project.project.use.permissions,
offline: project.project.use.offline,
storageState: project.project.use.storageState,
extraHTTPHeaders: project.project.use.extraHTTPHeaders,
},
},
files: await collectFilesForProject(project)
});
}
Expand Down
6 changes: 6 additions & 0 deletions packages/protocol/src/channels.ts
Expand Up @@ -701,9 +701,15 @@ export type DebugControllerNavigateResult = void;
export type DebugControllerSetRecorderModeParams = {
mode: 'inspecting' | 'recording' | 'none',
testIdAttributeName?: string,
browserName?: 'chromium' | 'firefox' | 'webkit',
contextOptions?: BrowserNewContextForReuseParams,
launchOptions?: BrowserTypeLaunchParams,
};
export type DebugControllerSetRecorderModeOptions = {
testIdAttributeName?: string,
browserName?: 'chromium' | 'firefox' | 'webkit',
contextOptions?: BrowserNewContextForReuseParams,
launchOptions?: BrowserTypeLaunchParams,
};
export type DebugControllerSetRecorderModeResult = void;
export type DebugControllerHighlightParams = {
Expand Down
8 changes: 8 additions & 0 deletions packages/protocol/src/protocol.yml
Expand Up @@ -745,6 +745,14 @@ DebugController:
- recording
- none
testIdAttributeName: string?
browserName:
type: enum?
literals:
- chromium
- firefox
- webkit
contextOptions: BrowserNewContextForReuseParams?
launchOptions: BrowserTypeLaunchParams?

highlight:
parameters:
Expand Down

0 comments on commit 387293b

Please sign in to comment.