Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use selected project options for codegen #417

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: flex;
}
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
63 changes: 41 additions & 22 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 @@ -109,37 +109,20 @@ export class SettingsView extends DisposableBase implements vscodeTypes.WebviewV

private _updateActions() {
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>`,
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>`,
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>`,
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 +226,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 +252,33 @@ 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');
for (const { command, title, icon } of [{
command: 'pw.extension.command.recordNew',
title: '${vscode.l10n.t('Record new')}',
icon: 'recordNew',
}, {
command: 'pw.extension.command.recordAtCursor',
title: '${vscode.l10n.t('Record at cursor')}',
icon: 'recordAtCursor',
}, {
command: 'pw.extension.command.inspect',
title: '${vscode.l10n.t('Pick locator')}',
icon: 'inspect',
}]) {
const label = document.createElement('label');
label.role = 'button';
label.title = title;
const svg = document.createElement('svg');
label.appendChild(svg);
span.appendChild(label);
span.addEventListener('click', event => {
vscode.postMessage({ method: 'execute', params: { command, args: [name] }});
});
svg.outerHTML = icons[icon];
}
div.appendChild(span);
projectsElement.appendChild(div);
}
}
Expand Down Expand Up @@ -309,7 +328,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
Loading