Skip to content

Commit

Permalink
feat: use selected project options for codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
mxschmitt committed Mar 19, 2024
1 parent b460ad1 commit f95ab88
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 27 deletions.
8 changes: 8 additions & 0 deletions media/settingsView.css
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,11 @@ div.separator {
body[data-vscode-theme-kind=vscode-dark] div.separator {
border-color: rgba(204, 204, 204, 0.2);
}

.list#projects > div .actions {
display: none;
}

.list#projects > div:hover .actions {
display: block;
}
2 changes: 2 additions & 0 deletions src/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export class BackendServer<T extends BackendClient> {
fulfill(client);
});
serverProcess.on('exit', () => {
if (this._options.dumpIO)
console.log('[server exit]');
fulfill(null);
client._onCloseEvent.fire();
});
Expand Down
35 changes: 30 additions & 5 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,21 @@ export class Extension implements RunHooks {
vscode.commands.registerCommand('pw.extension.command.closeBrowsers', () => {
this._reusedBrowser.closeAllBrowsers();
}),
vscode.commands.registerCommand('pw.extension.command.recordNew', async () => {
if (!this._models.hasEnabledModels()) {
vscode.commands.registerCommand('pw.extension.command.recordNew', async (projectName?: string) => {
const selectedProject = await this._getRecorderProject(projectName);
if (!selectedProject) {
vscode.window.showWarningMessage(messageNoPlaywrightTestsFound);
return;
}
await this._reusedBrowser.record(this._models, true);
await this._reusedBrowser.record(selectedProject, true);
}),
vscode.commands.registerCommand('pw.extension.command.recordAtCursor', async () => {
if (!this._models.hasEnabledModels()) {
const selectedProject = await this._getRecorderProject();
if (!selectedProject) {
vscode.window.showWarningMessage(messageNoPlaywrightTestsFound);
return;
}
await this._reusedBrowser.record(this._models, false);
await this._reusedBrowser.record(selectedProject, false);
}),
vscode.commands.registerCommand('pw.extension.command.toggleModels', async () => {
this._settingsView.toggleModels();
Expand Down Expand Up @@ -255,6 +257,29 @@ export class Extension implements RunHooks {
context.subscriptions.push(this);
}

private async _getRecorderProject(externalSelectedProjectName?: string): Promise<TestProject | undefined> {
const selectedModel = this._models.selectedModel();
if (!selectedModel) {
await this._vscode.window.showWarningMessage(this._vscode.l10n.t('No Playwright config selected.'));
return;
}
const enabledProjects = selectedModel.enabledProjects();
if (!enabledProjects.length)
return selectedModel.projects()[0];
if (externalSelectedProjectName) {
const selectedProject = selectedModel.projects().find(project => project.name === externalSelectedProjectName);
if (selectedProject)
return selectedProject;
}
if (enabledProjects.length === 1)
return enabledProjects[0];
const selectedProject = await this._vscode.window.showQuickPick(enabledProjects.map(project => project.name), {
placeHolder: this._vscode.l10n.t('Select a project to run'),
canPickMany: false,
});
return selectedProject ? enabledProjects.find(project => project.name === selectedProject) : undefined;
}

private async _rebuildModels(showWarnings: boolean): Promise<vscodeTypes.Uri[]> {
this._models.clear();
this._testTree.startedLoading();
Expand Down
11 changes: 9 additions & 2 deletions src/listTests.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@

import type { TestError } from './reporter';

// This matches the structs in packages/playwright-test/src/runner/runner.ts.
// This matches the structs in packages/playwright/src/runner/runner.ts

export type ProjectUse = {
testIdAttribute?: string;
browserName?: string;
contextOptions: Record<string, string>;
launchOptions: Record<string, string>;
};

export type ProjectConfigWithFiles = {
name: string;
testDir: string;
use: { testIdAttribute?: string };
use: ProjectUse;
files: string[];
};

Expand Down
1 change: 0 additions & 1 deletion src/playwrightTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export type TestConfig = {
configFile: string;
cli: string;
version: number;
testIdAttributeName?: string;
};

const pathSeparator = process.platform === 'win32' ? ';' : ':';
Expand Down
31 changes: 22 additions & 9 deletions src/reusedBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { TestConfig } from './playwrightTest';
import type { TestModel, TestModelCollection } from './testModel';
import type { TestModel, TestModelCollection, TestProject } from './testModel';
import { createGuid } from './utils';
import * as vscodeTypes from './vscodeTypes';
import path from 'path';
Expand Down Expand Up @@ -44,6 +44,7 @@ export class ReusedBrowser implements vscodeTypes.Disposable {
private _editOperations = Promise.resolve();
private _pausedOnPagePause = false;
private _settingsModel: SettingsModel;
private _autoCloseTimer?: NodeJS.Timeout;

constructor(vscode: vscodeTypes.VSCode, settingsModel: SettingsModel, envProvider: () => NodeJS.ProcessEnv) {
this._vscode = vscode;
Expand Down Expand Up @@ -182,13 +183,19 @@ export class ReusedBrowser implements vscodeTypes.Disposable {
}

private _pageCountChanged(pageCount: number) {
if (this._autoCloseTimer)
clearTimeout(this._autoCloseTimer);
this._pageCount = pageCount;
this._onPageCountChangedEvent.fire(pageCount);
if (this._isRunningTests)
return;
if (pageCount)
return;
this._stop();
const heartBeat = () => {
if (!this._pageCount)
this._stop();
};
this._autoCloseTimer = setTimeout(heartBeat, 5000);
}

browserServerWSEndpoint() {
Expand Down Expand Up @@ -242,9 +249,8 @@ export class ReusedBrowser implements vscodeTypes.Disposable {
return !this._isRunningTests && !!this._pageCount;
}

async record(models: TestModelCollection, recordNew: boolean) {
const selectedModel = models.selectedModel();
if (!selectedModel || !this._checkVersion(selectedModel.config))
async record(project: TestProject, recordNew: boolean) {
if (!this._checkVersion(project.model.config))
return;
if (!this.canRecord()) {
this._vscode.window.showWarningMessage(
Expand All @@ -256,7 +262,7 @@ export class ReusedBrowser implements vscodeTypes.Disposable {
location: this._vscode.ProgressLocation.Notification,
title: 'Playwright codegen',
cancellable: true
}, async (progress, token) => this._doRecord(progress, selectedModel, recordNew, token));
}, async (progress, token) => this._doRecord(progress, project, recordNew, token));
}

highlight(selector: string) {
Expand Down Expand Up @@ -290,7 +296,8 @@ export class ReusedBrowser implements vscodeTypes.Disposable {
return true;
}

private async _doRecord(progress: vscodeTypes.Progress<{ message?: string; increment?: number }>, model: TestModel, recordNew: boolean, token: vscodeTypes.CancellationToken) {
private async _doRecord(progress: vscodeTypes.Progress<{ message?: string; increment?: number }>, selectedProject: TestProject, recordNew: boolean, token: vscodeTypes.CancellationToken) {
const model = selectedProject.model;
const startBackend = this._startBackendIfNeeded(model.config);
let editor: vscodeTypes.TextEditor | undefined;
if (recordNew)
Expand All @@ -309,7 +316,13 @@ export class ReusedBrowser implements vscodeTypes.Disposable {
}

try {
await this._backend?.setMode({ mode: 'recording', testIdAttributeName: model.config.testIdAttributeName });
await this._backend?.setMode({
mode: 'recording',
testIdAttributeName: selectedProject.useOptions.testIdAttribute,
browserName: selectedProject.useOptions.browserName,
launchOptions: selectedProject.useOptions.launchOptions,
contextOptions: selectedProject.useOptions.contextOptions,
});
} catch (e) {
showExceptionAsUserError(this._vscode, model, e as Error);
this._stop();
Expand Down Expand Up @@ -446,7 +459,7 @@ export class Backend extends BackendClient {
await this.send('navigate', params);
}

async setMode(params: { mode: 'none' | 'inspecting' | 'recording', testIdAttributeName?: string }) {
async setMode(params: { mode: 'none' | 'inspecting' | 'recording', testIdAttributeName?: string, browserName?: string, launchOptions?: Record<string, any>, contextOptions?: Record<string, any> }) {
await this.send('setRecorderMode', params);
}

Expand Down
40 changes: 32 additions & 8 deletions src/settingsView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class SettingsView extends DisposableBase implements vscodeTypes.WebviewV
webviewView.webview.html = htmlForWebview(this._vscode, this._extensionUri, webviewView.webview);
this._disposables.push(webviewView.webview.onDidReceiveMessage(data => {
if (data.method === 'execute') {
this._vscode.commands.executeCommand(data.params.command);
this._vscode.commands.executeCommand(data.params.command, ...(data.params.args ?? []));
} else if (data.method === 'toggle') {
this._vscode.commands.executeCommand(`pw.extension.toggle.${data.params.setting}`);
} else if (data.method === 'setProjectEnabled') {
Expand Down Expand Up @@ -111,35 +111,35 @@ export class SettingsView extends DisposableBase implements vscodeTypes.WebviewV
const actions = [
{
command: 'pw.extension.command.inspect',
svg: `<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M18 42h-7.5c-3 0-4.5-1.5-4.5-4.5v-27C6 7.5 7.5 6 10.5 6h27C42 6 42 10.404 42 10.5V18h-3V9H9v30h9v3Zm27-15-9 6 9 9-3 3-9-9-6 9-6-24 24 6Z"/></svg>`,
icon: 'inspect',
text: this._vscode.l10n.t('Pick locator'),
},
{
command: 'pw.extension.command.recordNew',
svg: `<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M22.65 34h3v-8.3H34v-3h-8.35V14h-3v8.7H14v3h8.65ZM24 44q-4.1 0-7.75-1.575-3.65-1.575-6.375-4.3-2.725-2.725-4.3-6.375Q4 28.1 4 23.95q0-4.1 1.575-7.75 1.575-3.65 4.3-6.35 2.725-2.7 6.375-4.275Q19.9 4 24.05 4q4.1 0 7.75 1.575 3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24q0 4.1-1.575 7.75-1.575 3.65-4.275 6.375t-6.35 4.3Q28.15 44 24 44Zm.05-3q7.05 0 12-4.975T41 23.95q0-7.05-4.95-12T24 7q-7.05 0-12.025 4.95Q7 16.9 7 24q0 7.05 4.975 12.025Q16.95 41 24.05 41ZM24 24Z"/></svg>`,
icon: 'recordNew',
text: this._vscode.l10n.t('Record new'),
disabled: !this._reusedBrowser.canRecord(),
},
{
command: 'pw.extension.command.recordAtCursor',
svg: `<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M9 39h2.2l22.15-22.15-2.2-2.2L9 36.8Zm30.7-24.3-6.4-6.4 2.1-2.1q.85-.85 2.1-.85t2.1.85l2.2 2.2q.85.85.85 2.1t-.85 2.1Zm-2.1 2.1L12.4 42H6v-6.4l25.2-25.2Zm-5.35-1.05-1.1-1.1 2.2 2.2Z"/></svg>`,
icon: 'recordAtCursor',
text: this._vscode.l10n.t('Record at cursor'),
disabled: !this._reusedBrowser.canRecord(),
},
{
command: 'testing.showMostRecentOutput',
svg: `<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M11.85 25.3H29.9v-3H11.85Zm0-6.45H29.9v-3H11.85ZM7 40q-1.2 0-2.1-.9Q4 38.2 4 37V11q0-1.2.9-2.1Q5.8 8 7 8h34q1.2 0 2.1.9.9.9.9 2.1v26q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h34V11H7v26Zm0 0V11v26Z"/></svg>`,
icon: 'showMostRecentOutput',
text: this._vscode.l10n.t('Reveal test output'),
},
{
command: 'pw.extension.command.closeBrowsers',
svg: `<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path xmlns="http://www.w3.org/2000/svg" d="m12.45 37.65-2.1-2.1L21.9 24 10.35 12.45l2.1-2.1L24 21.9l11.55-11.55 2.1 2.1L26.1 24l11.55 11.55-2.1 2.1L24 26.1Z"/></svg>`,
icon: 'closeBrowsers',
text: this._vscode.l10n.t('Close all browsers'),
disabled: !this._reusedBrowser.canClose(),
},
{
command: 'pw.extension.command.toggleModels',
svg: `<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="m388-80-20-126q-19-7-40-19t-37-25l-118 54-93-164 108-79q-2-9-2.5-20.5T185-480q0-9 .5-20.5T188-521L80-600l93-164 118 54q16-13 37-25t40-18l20-127h184l20 126q19 7 40.5 18.5T669-710l118-54 93 164-108 77q2 10 2.5 21.5t.5 21.5q0 10-.5 21t-2.5 21l108 78-93 164-118-54q-16 13-36.5 25.5T592-206L572-80H388Zm48-60h88l14-112q33-8 62.5-25t53.5-41l106 46 40-72-94-69q4-17 6.5-33.5T715-480q0-17-2-33.5t-7-33.5l94-69-40-72-106 46q-23-26-52-43.5T538-708l-14-112h-88l-14 112q-34 7-63.5 24T306-642l-106-46-40 72 94 69q-4 17-6.5 33.5T245-480q0 17 2.5 33.5T254-413l-94 69 40 72 106-46q24 24 53.5 41t62.5 25l14 112Zm44-210q54 0 92-38t38-92q0-54-38-92t-92-38q-54 0-92 38t-38 92q0 54 38 92t92 38Zm0-130Z"/></svg>`,
icon: 'toggleModels',
title: this._vscode.l10n.t('Toggle Playwright Configs'),
location: 'configToolbar',
},
Expand Down Expand Up @@ -243,6 +243,15 @@ function htmlForWebview(vscode: vscodeTypes.VSCode, extensionUri: vscodeTypes.Ur
<div id="actions" class="list"></div>
</body>
<script nonce="${nonce}">
const icons = {
'inspect': '<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M18 42h-7.5c-3 0-4.5-1.5-4.5-4.5v-27C6 7.5 7.5 6 10.5 6h27C42 6 42 10.404 42 10.5V18h-3V9H9v30h9v3Zm27-15-9 6 9 9-3 3-9-9-6 9-6-24 24 6Z"/></svg>',
'recordNew': '<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M22.65 34h3v-8.3H34v-3h-8.35V14h-3v8.7H14v3h8.65ZM24 44q-4.1 0-7.75-1.575-3.65-1.575-6.375-4.3-2.725-2.725-4.3-6.375Q4 28.1 4 23.95q0-4.1 1.575-7.75 1.575-3.65 4.3-6.35 2.725-2.7 6.375-4.275Q19.9 4 24.05 4q4.1 0 7.75 1.575 3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24q0 4.1-1.575 7.75-1.575 3.65-4.275 6.375t-6.35 4.3Q28.15 44 24 44Zm.05-3q7.05 0 12-4.975T41 23.95q0-7.05-4.95-12T24 7q-7.05 0-12.025 4.95Q7 16.9 7 24q0 7.05 4.975 12.025Q16.95 41 24.05 41ZM24 24Z"/></svg>',
'recordAtCursor': '<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M9 39h2.2l22.15-22.15-2.2-2.2L9 36.8Zm30.7-24.3-6.4-6.4 2.1-2.1q.85-.85 2.1-.85t2.1.85l2.2 2.2q.85.85.85 2.1t-.85 2.1Zm-2.1 2.1L12.4 42H6v-6.4l25.2-25.2Zm-5.35-1.05-1.1-1.1 2.2 2.2Z"/></svg>',
'showMostRecentOutput': '<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M11.85 25.3H29.9v-3H11.85Zm0-6.45H29.9v-3H11.85ZM7 40q-1.2 0-2.1-.9Q4 38.2 4 37V11q0-1.2.9-2.1Q5.8 8 7 8h34q1.2 0 2.1.9.9.9.9 2.1v26q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h34V11H7v26Zm0 0V11v26Z"/></svg>',
'closeBrowsers': '<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path xmlns="http://www.w3.org/2000/svg" d="m12.45 37.65-2.1-2.1L21.9 24 10.35 12.45l2.1-2.1L24 21.9l11.55-11.55 2.1 2.1L26.1 24l11.55 11.55-2.1 2.1L24 26.1Z"/></svg>',
'toggleModels': '<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="m388-80-20-126q-19-7-40-19t-37-25l-118 54-93-164 108-79q-2-9-2.5-20.5T185-480q0-9 .5-20.5T188-521L80-600l93-164 118 54q16-13 37-25t40-18l20-127h184l20 126q19 7 40.5 18.5T669-710l118-54 93 164-108 77q2 10 2.5 21.5t.5 21.5q0 10-.5 21t-2.5 21l108 78-93 164-118-54q-16 13-36.5 25.5T592-206L572-80H388Zm48-60h88l14-112q33-8 62.5-25t53.5-41l106 46 40-72-94-69q4-17 6.5-33.5T715-480q0-17-2-33.5t-7-33.5l94-69-40-72-106 46q-23-26-52-43.5T538-708l-14-112h-88l-14 112q-34 7-63.5 24T306-642l-106-46-40 72 94 69q-4 17-6.5 33.5T245-480q0 17 2.5 33.5T254-413l-94 69 40 72 106-46q24 24 53.5 41t62.5 25l14 112Zm44-210q54 0 92-38t38-92q0-54-38-92t-92-38q-54 0-92 38t-38 92q0 54 38 92t92 38Zm0-130Z"/></svg>',
};
let selectConfig;
function updateProjects(projects) {
const projectsElement = document.getElementById('projects');
Expand All @@ -260,6 +269,21 @@ function htmlForWebview(vscode: vscodeTypes.VSCode, extensionUri: vscodeTypes.Ur
label.appendChild(input);
label.appendChild(document.createTextNode(name || '<untitled>'));
div.appendChild(label);
{
const span = document.createElement('span');
span.classList.add('actions');
const label = document.createElement('label');
label.role = 'button';
label.title = 'Record new test for ' + name;
const svg = document.createElement('svg');
label.appendChild(svg);
span.appendChild(label);
div.appendChild(span);
div.addEventListener('click', event => {
vscode.postMessage({ method: 'execute', params: { command: 'pw.extension.command.recordNew', args: [name] }});
});
svg.outerHTML = icons['inspect'];
}
projectsElement.appendChild(div);
}
}
Expand Down Expand Up @@ -309,7 +333,7 @@ function htmlForWebview(vscode: vscodeTypes.VSCode, extensionUri: vscodeTypes.Ur
configToolbarElement.appendChild(actionElement);
else
actionsElement.appendChild(actionElement);
svg.outerHTML = action.svg;
svg.outerHTML = icons[action.icon];
}
} else if (method === 'models') {
const { configs } = params;
Expand Down
5 changes: 3 additions & 2 deletions src/testModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { PlaywrightTest, RunHooks, TestConfig } from './playwrightTest';
import { WorkspaceChange } from './workspaceObserver';
import * as vscodeTypes from './vscodeTypes';
import { resolveSourceMap } from './utils';
import { ProjectConfigWithFiles } from './listTests';
import { ProjectConfigWithFiles, ProjectUse } from './listTests';
import * as reporterTypes from './reporter';
import { TeleSuite } from './upstream/teleReceiver';
import type { SettingsModel, WorkspaceSettings } from './settingsModel';
Expand All @@ -34,6 +34,7 @@ export type TestProject = {
suite: reporterTypes.Suite;
project: reporterTypes.FullProject;
isEnabled: boolean;
useOptions: ProjectUse;
};

export type TestModelOptions = {
Expand Down Expand Up @@ -123,7 +124,6 @@ export class TestModel {
for (const file of project.files)
files.push(...await resolveSourceMap(file, this._fileToSources, this._sourceToFile));
project.files = files;
this.config.testIdAttributeName = project.use?.testIdAttribute;
}

const projectsToKeep = new Set<string>();
Expand Down Expand Up @@ -167,6 +167,7 @@ export class TestModel {
suite: projectSuite,
project: projectSuite._project,
isEnabled: false,
useOptions: projectReport.use
};
this._projects.set(project.name, project);
return project;
Expand Down

0 comments on commit f95ab88

Please sign in to comment.