From facbc067cc026d841278772475fd0f165060315c Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 18 Nov 2024 15:49:49 +0100 Subject: [PATCH] chore: delete embedded trace viewer (#555) --- playwright.config.ts | 19 +- src/embeddedTraceViewer.ts | 280 -------------- src/extension.ts | 2 +- src/playwrightTestServer.ts | 31 +- src/settingsModel.ts | 33 +- src/testModel.ts | 17 +- src/vscodeTypes.ts | 1 - tests/embedded-trace-viewer-legacy.spec.ts | 66 ---- tests/embedded-trace-viewer.spec.ts | 416 --------------------- tests/mock/vscode.ts | 1 - tests/trace-viewer.spec.ts | 22 +- tests/utils.ts | 6 +- 12 files changed, 19 insertions(+), 875 deletions(-) delete mode 100644 src/embeddedTraceViewer.ts delete mode 100644 tests/embedded-trace-viewer-legacy.spec.ts delete mode 100644 tests/embedded-trace-viewer.spec.ts diff --git a/playwright.config.ts b/playwright.config.ts index b4f8f511c..e50287a99 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -41,14 +41,7 @@ export default defineConfig({ { name: 'default-trace', use: { - showTrace: 'spawn', - } - }, - { - name: 'default-trace-embedded', - testMatch: '*trace-viewer*.spec.ts', - use: { - showTrace: 'embedded', + showTrace: true, } }, { @@ -68,15 +61,7 @@ export default defineConfig({ name: 'legacy-trace', use: { overridePlaywrightVersion: 1.43, - showTrace: 'spawn', - } - }, - { - name: 'legacy-trace-embedded', - testMatch: '*trace-viewer*.spec.ts', - use: { - overridePlaywrightVersion: 1.43, - showTrace: 'embedded', + showTrace: true, } }, ] diff --git a/src/embeddedTraceViewer.ts b/src/embeddedTraceViewer.ts deleted file mode 100644 index 0c87792bb..000000000 --- a/src/embeddedTraceViewer.ts +++ /dev/null @@ -1,280 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { TestConfig } from './playwrightTestTypes'; -import { getNonce } from './utils'; -import * as vscodeTypes from './vscodeTypes'; -import { DisposableBase } from './disposableBase'; -import { PlaywrightTestServer } from './playwrightTestServer'; -import { TraceViewer } from './traceViewer'; - -export class EmbeddedTraceViewer implements TraceViewer { - readonly vscode: vscodeTypes.VSCode; - readonly extensionUri: vscodeTypes.Uri; - private _currentFile?: string; - private _traceViewerPanelPromise?: Promise; - private _config: TestConfig; - private _testServer: PlaywrightTestServer; - - constructor(vscode: vscodeTypes.VSCode, extensionUri: vscodeTypes.Uri, config: TestConfig, testServer: PlaywrightTestServer) { - this.vscode = vscode; - this.extensionUri = extensionUri; - this._config = config; - this._testServer = testServer; - } - - currentFile() { - return this._currentFile; - } - - async willRunTests() { - await this._startIfNeeded(); - } - - async open(file?: string) { - this._currentFile = file; - if (!file && !this._traceViewerPanelPromise) - return; - const traceViewerPanel = await this._startIfNeeded(); - traceViewerPanel?.loadTraceRequested(file); - } - - close() { - this._traceViewerPanelPromise?.then(panel => panel?.dispose()).catch(() => {}); - this._traceViewerPanelPromise = undefined; - this._currentFile = undefined; - } - - private async _startIfNeeded() { - if (!this._traceViewerPanelPromise) - this._traceViewerPanelPromise = this._createTraceViewerPanel(); - return await this._traceViewerPanelPromise; - } - - private async _createTraceViewerPanel() { - const serverUrlPrefix = await this._testServer.ensureStartedForTraceViewer(); - if (!serverUrlPrefix) - return; - return new EmbeddedTraceViewerPanel(this, serverUrlPrefix); - } - - async infoForTest() { - const traceViewerPanel = await this._traceViewerPanelPromise; - return { - type: 'embedded', - serverUrlPrefix: traceViewerPanel?.serverUrlPrefix, - testConfigFile: this._config.configFile, - traceFile: this._currentFile, - visible: !!traceViewerPanel?.visibleForTest(), - }; - } -} - -class EmbeddedTraceViewerPanel extends DisposableBase { - - public static readonly viewType = 'playwright.traceviewer.view'; - - private _vscode: vscodeTypes.VSCode; - private _extensionUri: vscodeTypes.Uri; - private _webviewPanel: vscodeTypes.WebviewPanel; - readonly serverUrlPrefix: string; - private _isVisible: boolean = false; - private _viewColumn: vscodeTypes.ViewColumn | undefined; - private _traceUrl?: string; - private _traceLoadRequestedTimeout?: NodeJS.Timeout; - - constructor( - embeddedTestViewer: EmbeddedTraceViewer, - serverUrlPrefix: string - ) { - super(); - this._vscode = embeddedTestViewer.vscode; - this._extensionUri = embeddedTestViewer.extensionUri; - this.serverUrlPrefix = serverUrlPrefix; - this._isVisible = false; - this._webviewPanel = this._vscode.window.createWebviewPanel(EmbeddedTraceViewerPanel.viewType, 'Trace Viewer', { - viewColumn: this._vscode.ViewColumn.Active, - preserveFocus: true, - }, { - enableScripts: true, - enableForms: true, - }); - this._viewColumn = this._webviewPanel.viewColumn; - this._webviewPanel.iconPath = this._vscode.Uri.joinPath(this._extensionUri, 'images', 'playwright-logo.svg'); - this._webviewPanel.webview.html = this._getHtml(); - this._disposables = [ - this._webviewPanel, - this._webviewPanel.onDidDispose(() => { - embeddedTestViewer.close(); - }), - this._webviewPanel.onDidChangeViewState(({ webviewPanel }) => { - if (this._isVisible === webviewPanel.visible && this._viewColumn === webviewPanel.viewColumn) - return; - this._isVisible = webviewPanel.visible; - this._viewColumn = webviewPanel.viewColumn; - if (this._isVisible) { - this._applyTheme(); - this.loadTraceRequested(this._traceUrl); - } else { - this._clearTraceLoadRequestedTimeout(); - } - }), - this._webviewPanel.webview.onDidReceiveMessage(message => { - const methodRequest = this._extractMethodRequest(message); - if (!methodRequest) - return; - this._executeMethod(methodRequest).catch(() => {}); - }), - this._vscode.workspace.onDidChangeConfiguration(event => { - if (event.affectsConfiguration('workbench.colorTheme')) - this._applyTheme(); - }), - ]; - } - - loadTraceRequested(traceUrl?: string) { - this._traceUrl = traceUrl; - this._fireLoadTraceRequestedIfNeeded(); - } - - dispose() { - this._clearTraceLoadRequestedTimeout(); - super.dispose(); - } - - visibleForTest() { - return this._isVisible; - } - - private _clearTraceLoadRequestedTimeout() { - if (this._traceLoadRequestedTimeout) { - clearTimeout(this._traceLoadRequestedTimeout); - this._traceLoadRequestedTimeout = undefined; - } - } - - private _fireLoadTraceRequestedIfNeeded() { - if (this._traceLoadRequestedTimeout) { - clearTimeout(this._traceLoadRequestedTimeout); - this._traceLoadRequestedTimeout = undefined; - } - if (!this._isVisible) - return; - this._webviewPanel.webview.postMessage({ method: 'loadTraceRequested', params: { traceUrl: this._traceUrl } }); - if (this._traceUrl?.endsWith('.json')) - this._traceLoadRequestedTimeout = setTimeout(() => this._fireLoadTraceRequestedIfNeeded(), 500); - } - - private _extractMethodRequest(message: any) { - const method: string | undefined = message.method ?? message.command; - if (!method) - return; - const params = message.params; - return { method, params }; - } - - private async _executeMethod({ method, params }: { method: string, params?: any }) { - if (method === 'openExternal' && params.url) - // should be a Uri, but due to https://github.com/microsoft/vscode/issues/85930 - // we pass a string instead - await this._vscode.env.openExternal(params.url); - else if (method === 'openSourceLocation' && params) - await this._openSourceFile(params); - else if (method === 'showErrorMessage') - await this._vscode.window.showErrorMessage(params.message); - } - - private async _openSourceFile({ file, line, column }: { file: string, line: number, column: number }) { - try { - const document = await this._vscode.workspace.openTextDocument(file); - // received line and column are 1-based - const pos = new this._vscode.Position(line - 1, column - 1); - const selection = new this._vscode.Range(pos, pos); - await this._vscode.window.showTextDocument(document, { selection }); - } catch (e) { - // ignore - } - } - - private _applyTheme() { - if (!this._webviewPanel.visible) - return; - const themeKind = this._vscode.window.activeColorTheme.kind; - const theme = [this._vscode.ColorThemeKind.Dark, this._vscode.ColorThemeKind.HighContrast].includes(themeKind) ? 'dark-mode' : 'light-mode'; - this._webviewPanel.webview.postMessage({ method: 'applyTheme', params: { theme } }); - } - - private _getHtml() { - const nonce = getNonce(); - const cspSource = this._webviewPanel.webview.cspSource; - const origin = new URL(this.serverUrlPrefix).origin; - const stylesheet = this._webviewPanel.webview.asWebviewUri(this._vscode.Uri.joinPath(this._extensionUri, 'media', 'traceViewer.css')); - - return /* html */ ` - - - - - - - - Playwright Trace Viewer - - - - - - - `; - } -} diff --git a/src/extension.ts b/src/extension.ts index c07261f71..8c95a2704 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -100,7 +100,7 @@ export class Extension implements RunHooks { }, }); - this._settingsModel = new SettingsModel(vscode, this._isUnderTest, context); + this._settingsModel = new SettingsModel(vscode, context); this._reusedBrowser = new ReusedBrowser(this._vscode, this._settingsModel, this._envProvider.bind(this)); this._debugHighlight = new DebugHighlight(vscode, this._reusedBrowser); this._models = new TestModelCollection(vscode, { diff --git a/src/playwrightTestServer.ts b/src/playwrightTestServer.ts index 75f72b47b..bd86d73b9 100644 --- a/src/playwrightTestServer.ts +++ b/src/playwrightTestServer.ts @@ -32,7 +32,6 @@ export class PlaywrightTestServer { private _options: PlaywrightTestOptions; private _model: TestModel; private _testServerPromise: Promise | undefined; - private _serverUrlPrefix?: string; constructor(vscode: vscodeTypes.VSCode, model: TestModel, options: PlaywrightTestOptions) { this._vscode = vscode; @@ -44,12 +43,6 @@ export class PlaywrightTestServer { this._disposeTestServer(); } - async ensureStartedForTraceViewer() { - // ensure test server is running - await this._testServer(); - return this._serverUrlPrefix; - } - async listFiles(): Promise { const testServer = await this._testServer(); if (!testServer) @@ -386,27 +379,13 @@ export class PlaywrightTestServer { return null; const testServer = new TestServerConnection(wsEndpoint); testServer.onTestFilesChanged(params => this._testFilesChanged(params.testFiles)); - const [serverUrlPrefix] = await Promise.all([ - this._computeServerUrlPrefix(wsEndpoint), - testServer.initialize({ - serializer: require.resolve('./oopReporter'), - interceptStdio: true, - closeOnDisconnect: true, - }), - ]); - this._serverUrlPrefix = serverUrlPrefix; + await testServer.initialize({ + serializer: require.resolve('./oopReporter'), + interceptStdio: true, + closeOnDisconnect: true, + }); return testServer; } - - private async _computeServerUrlPrefix(wsEndpoint: string) { - const serverUrl = new URL(wsEndpoint); - serverUrl.protocol = serverUrl.protocol === 'wss' ? 'https' : 'http'; - if (this._vscode.env.remoteName && ['[::1]', '0.0.0.0'].includes(serverUrl.hostname)) - serverUrl.hostname = 'localhost'; - const serverUri = await this._vscode.env.asExternalUri(this._vscode.Uri.parse(serverUrl.origin)); - return serverUri.toString().replace(/\/$/, ''); - } - private async _wireTestServer(testServer: TestServerConnection, reporter: reporterTypes.ReporterV2, token: vscodeTypes.CancellationToken) { const teleReceiver = new TeleReporterReceiver(reporter, { mergeProjects: true, diff --git a/src/settingsModel.ts b/src/settingsModel.ts index 674006ff1..b47aaa1fa 100644 --- a/src/settingsModel.ts +++ b/src/settingsModel.ts @@ -44,13 +44,10 @@ export class SettingsModel extends DisposableBase { showBrowser: Setting; showTrace: Setting; runGlobalSetupOnEachRun: Setting; - embeddedTraceViewer: Setting; - private _isUnderTest: boolean; - constructor(vscode: vscodeTypes.VSCode, isUnderTest: boolean, context: vscodeTypes.ExtensionContext) { + constructor(vscode: vscodeTypes.VSCode, context: vscodeTypes.ExtensionContext) { super(); this._vscode = vscode; - this._isUnderTest = isUnderTest; this._context = context; this._onChange = new vscode.EventEmitter(); this.onChange = this._onChange.event; @@ -58,7 +55,6 @@ export class SettingsModel extends DisposableBase { this.showBrowser = this._createSetting('reuseBrowser'); this.showTrace = this._createSetting('showTrace'); this.runGlobalSetupOnEachRun = this._createSetting('runGlobalSetupOnEachRun'); - this.embeddedTraceViewer = this._createHiddenSetting('embeddedTraceViewer', false); this._disposables.push( this._onChange, @@ -91,16 +87,6 @@ export class SettingsModel extends DisposableBase { return setting; } - private _createHiddenSetting(settingName: string, value: T): Setting { - if (this._isUnderTest) - return this._createSetting(settingName); - const setting = new InMemorySetting(this._vscode, settingName, value); - this._disposables.push(setting); - this._disposables.push(setting.onChange(() => this._onChange.fire())); - this._settings.set(settingName, setting); - return setting; - } - json(): Record { const result: Record = {}; for (const [key, setting] of this._settings) @@ -168,20 +154,3 @@ class PersistentSetting extends SettingBase { configuration.update(this.settingName, value, true); } } - -class InMemorySetting extends SettingBase { - private _value: T; - constructor(vscode: vscodeTypes.VSCode, settingName: string, value: T) { - super(vscode, settingName); - this._value = value; - } - - get(): T { - return this._value; - } - - async set(value: T) { - this._value = value; - this._onChange.fire(value); - } -} diff --git a/src/testModel.ts b/src/testModel.ts index 0cb9eef54..74725ae10 100644 --- a/src/testModel.ts +++ b/src/testModel.ts @@ -31,7 +31,6 @@ import { PlaywrightTestCLI } from './playwrightTestCLI'; import { upstreamTreeItem } from './testTree'; import { collectTestIds } from './upstream/testTree'; import { TraceViewer } from './traceViewer'; -import { EmbeddedTraceViewer } from './embeddedTraceViewer'; import { SpawnTraceViewer } from './spawnTraceViewer'; export type TestEntry = reporterTypes.TestCase | reporterTypes.Suite; @@ -101,7 +100,6 @@ export class TestModel extends DisposableBase { this._disposables = [ this._embedder.settingsModel.showTrace.onChange(() => this.updateTraceViewer(false)), - this._embedder.settingsModel.embeddedTraceViewer.onChange(() => this.updateTraceViewer(false)), this._collection.onUpdated(() => this.updateTraceViewer(false)), ]; } @@ -673,19 +671,8 @@ export class TestModel extends DisposableBase { return null; } - if (settingsModel.embeddedTraceViewer.get() && this._traceViewer instanceof EmbeddedTraceViewer) - return this._traceViewer; - - if (!settingsModel.embeddedTraceViewer.get() && this._traceViewer instanceof SpawnTraceViewer) - return this._traceViewer; - - if (settingsModel.embeddedTraceViewer.get()) { - if (this._checkVersion(1.46, this._vscode.l10n.t('embedded trace viewer'), userGesture)) - this._traceViewer = new EmbeddedTraceViewer(this._vscode, this._embedder.context.extensionUri, this.config, this._playwrightTest as PlaywrightTestServer); - } else { - if (this._checkVersion(1.35, this._vscode.l10n.t('this feature'), userGesture)) - this._traceViewer = new SpawnTraceViewer(this._vscode, this._embedder.envProvider, this.config); - } + if (!this._traceViewer && this._checkVersion(1.35, this._vscode.l10n.t('this feature'), userGesture)) + this._traceViewer = new SpawnTraceViewer(this._vscode, this._embedder.envProvider, this.config); return this._traceViewer; } diff --git a/src/vscodeTypes.ts b/src/vscodeTypes.ts index 2e6a96ca8..0fce597bf 100644 --- a/src/vscodeTypes.ts +++ b/src/vscodeTypes.ts @@ -55,7 +55,6 @@ export type { WebviewViewResolveContext, WorkspaceConfiguration, TerminalLink, - ViewColumn, } from 'vscode'; export type VSCode = typeof import('vscode') & { diff --git a/tests/embedded-trace-viewer-legacy.spec.ts b/tests/embedded-trace-viewer-legacy.spec.ts deleted file mode 100644 index 0b68d4be7..000000000 --- a/tests/embedded-trace-viewer-legacy.spec.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { test, expect } from './utils'; - -test.skip(({ overridePlaywrightVersion, showTrace }) => !overridePlaywrightVersion || showTrace !== 'embedded'); - -test('should fallback to spawn trace viewer on legacy projects', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - // ensure embedded trace viewer is enabled - const configuration = vscode.workspace.getConfiguration('playwright'); - configuration.update('embeddedTraceViewer', true, true); - - await testController.expandTestItems(/test.spec/); - await testController.run(); - await expect.poll(() => vscode.warnings).toEqual(['Playwright v1.46+ is required for embedded trace viewer to work, v1.43 found']); -}); - -test('should show warning message again after refreshing test config', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - // ensure embedded trace viewer is enabled - const configuration = vscode.workspace.getConfiguration('playwright'); - configuration.update('embeddedTraceViewer', true, true); - - await testController.run(); - await expect.poll(() => vscode.warnings).toEqual([ - 'Playwright v1.46+ is required for embedded trace viewer to work, v1.43 found' - ]); - - await testController.refreshHandler!(null); - - await testController.run(); - - // ensure it shows the warning again - await expect.poll(() => vscode.warnings).toEqual([ - 'Playwright v1.46+ is required for embedded trace viewer to work, v1.43 found', - 'Playwright v1.46+ is required for embedded trace viewer to work, v1.43 found', - ]); -}); diff --git a/tests/embedded-trace-viewer.spec.ts b/tests/embedded-trace-viewer.spec.ts deleted file mode 100644 index 5cdd5c05f..000000000 --- a/tests/embedded-trace-viewer.spec.ts +++ /dev/null @@ -1,416 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { enableConfigs, expect, test, selectTestItem, traceViewerInfo, selectConfig, singleWebViewByPanelType } from './utils'; - -test.skip(({ showTrace, overridePlaywrightVersion }) => !!overridePlaywrightVersion || showTrace !== 'embedded'); - -test('should show tracer when test runs', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - - const treeItem = webview.frameLocator('iframe').getByTestId('actions-tree').getByRole('treeitem'); - await expect( - treeItem, - 'action list' - ).toHaveText([ - /Before Hooks[\d.]+m?s/, - /After Hooks[\d.]+m?s/, - ]); -}); - -test('should switch trace when selected test item changes', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass test 1', ({ page }) => page.setContent('

Test 1

')); - test('should pass test 2', ({ page }) => page.setContent('

Test 2

')); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - - selectTestItem(testItems[0]); - await expect(webview.frameLocator('iframe').frameLocator('iframe.snapshot-visible').locator('h1')).toHaveText('Test 1'); - - selectTestItem(testItems[1]); - await expect(webview.frameLocator('iframe').frameLocator('iframe.snapshot-visible').locator('h1')).toHaveText('Test 2'); -}); - -test('should toggle between dark and light themes', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - const configuration = vscode.workspace.getConfiguration('workbench'); - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - - await expect(webview.frameLocator('iframe').locator('body')).toHaveClass('dark-mode'); - - await configuration.update('colorTheme', 'Light Modern', true); - await expect(webview.frameLocator('iframe').locator('body')).toHaveClass('light-mode'); - - await configuration.update('colorTheme', 'Dark Modern', true); - await expect(webview.frameLocator('iframe').locator('body')).toHaveClass('dark-mode'); -}); - -test('should reopen trace viewer if closed', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - await expect(webview.locator('iframe')).toBeVisible(); - - await webview.close(); - await expect.poll(() => vscode.webViewsByPanelType('playwright.traceviewer.view')).toHaveLength(0); - - selectTestItem(testItems[0]); - await expect.poll(() => vscode.webViewsByPanelType('playwright.traceviewer.view')).toHaveLength(1); -}); - -test('should open snapshot popout', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', ({ page }) => page.setContent('

Test

')); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - await webview.frameLocator('iframe').getByTitle('Open snapshot in a new tab').click(); - - await expect.poll(() => vscode.openExternalUrls).toHaveLength(1); - expect(vscode.openExternalUrls[0]).toContain('snapshot.html'); -}); - -test('should not change trace viewer when running tests from different test configs', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright1.config.js': `module.exports = { testDir: 'tests1' }`, - 'playwright2.config.js': `module.exports = { testDir: 'tests2' }`, - 'tests1/test.spec.ts': ` - import { test } from '@playwright/test'; - test('one', ({ page }) => page.setContent('

One

')); - `, - 'tests2/test.spec.ts': ` - import { test } from '@playwright/test'; - test('two', ({ page }) => page.setContent('

Two

')); - `, - }); - - await enableConfigs(vscode, ['playwright1.config.js', 'playwright2.config.js']); - await selectConfig(vscode, 'playwright2.config.js'); - - { - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/one/); - await testController.run(testItems); - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - const serverUrlPrefix = new URL(await webview.locator('iframe').getAttribute('src') ?? '').origin; - expect(await traceViewerInfo(vscode)).toMatchObject({ - type: 'embedded', - serverUrlPrefix, - testConfigFile: expect.stringMatching('playwright2.config.js'), - }); - } - - { - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/two/); - await testController.run(testItems); - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - const serverUrlPrefix = new URL(await webview.locator('iframe').getAttribute('src') ?? '').origin; - expect(await traceViewerInfo(vscode)).toMatchObject({ - type: 'embedded', - serverUrlPrefix, - testConfigFile: expect.stringMatching('playwright2.config.js'), - }); - } -}); - -test('should close trace viewer when selected test config is disabled', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright1.config.js': `module.exports = { testDir: 'tests1' }`, - 'playwright2.config.js': `module.exports = { testDir: 'tests2' }`, - 'tests1/test.spec.ts': ` - import { test } from '@playwright/test'; - test('one', () => {}); - `, - 'tests2/test.spec.ts': ` - import { test } from '@playwright/test'; - test('one', () => {}); - `, - }); - - await enableConfigs(vscode, ['playwright1.config.js', 'playwright2.config.js']); - await selectConfig(vscode, 'playwright1.config.js'); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/one/); - await testController.run(testItems); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - const serverUrlPrefix = new URL(await webview.locator('iframe').getAttribute('src') ?? '').origin; - - selectTestItem(testItems[0]); - expect(await traceViewerInfo(vscode)).toMatchObject({ - type: 'embedded', - serverUrlPrefix, - testConfigFile: expect.stringMatching('playwright1.config.js'), - }); - - // disables playwright1.config.js - await enableConfigs(vscode, ['playwright2.config.js']); - // config should close trace viewer - await expect.poll(() => vscode.webViewsByPanelType('playwright.traceviewer.view')).toHaveLength(0); - expect.poll(() => traceViewerInfo(vscode)).toBeUndefined(); -}); - -test('should reopen trace viewer when another test config is selected', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright1.config.js': `module.exports = { testDir: 'tests1' }`, - 'playwright2.config.js': `module.exports = { testDir: 'tests2' }`, - 'tests1/test.spec.ts': ` - import { test } from '@playwright/test'; - test('one', () => {}); - `, - 'tests2/test.spec.ts': ` - import { test } from '@playwright/test'; - test('one', () => {}); - `, - }); - - await enableConfigs(vscode, ['playwright1.config.js', 'playwright2.config.js']); - await selectConfig(vscode, 'playwright1.config.js'); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/one/); - await testController.run(testItems); - - const webview1 = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - expect(await traceViewerInfo(vscode)).toMatchObject({ - type: 'embedded', - serverUrlPrefix: new URL(await webview1.locator('iframe').getAttribute('src') ?? '').origin, - testConfigFile: expect.stringMatching('playwright1.config.js'), - }); - - await selectConfig(vscode, 'playwright2.config.js'); - selectTestItem(testItems[0]); - await webview1.waitForEvent('close'); - - const webview2 = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - expect(await traceViewerInfo(vscode)).toMatchObject({ - type: 'embedded', - serverUrlPrefix: new URL(await webview2.locator('iframe').getAttribute('src') ?? '').origin, - testConfigFile: expect.stringMatching('playwright2.config.js'), - }); -}); - -test('should not open trace viewer if selected test item did not run', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - - selectTestItem(testItems[0]); - - // wait to ensure no async webview is opened - await new Promise(f => setTimeout(f, 1000)); - await expect.poll(() => vscode.webViewsByPanelType('playwright.traceviewer.view')).toHaveLength(0); - expect(vscode.warnings).toHaveLength(0); -}); - -test('should fallback to spawn trace viewer if embedded not enabled', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - const configuration = vscode.workspace.getConfiguration('playwright'); - configuration.update('embeddedTraceViewer', false, true); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - await expect(testController).toHaveTestTree(` - - tests - - test.spec.ts - - ✅ should pass [2:0] - `); - - // wait to ensure no async webview is opened - await new Promise(f => setTimeout(f, 1000)); - await expect.poll(() => vscode.webViewsByPanelType('playwright.traceviewer.view')).toHaveLength(0); - expect(vscode.warnings).toHaveLength(0); - - await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: 'spawn', - serverUrlPrefix: expect.anything(), - testConfigFile: expect.stringContaining('playwright.config.js') - }); -}); - - -test('should switch to spawn trace viewer if embedded is disabled and test item is selected', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - await testController.run(testItems); - - await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ type: 'embedded' }); - - const configuration = vscode.workspace.getConfiguration('playwright'); - configuration.update('embeddedTraceViewer', false, true); - selectTestItem(testItems[0]); - - await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ type: 'spawn' }); -}); - -test('should switch to spawn trace viewer if embedded is disabled and tests are ran again', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.run(); - - await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ type: 'embedded' }); - - const configuration = vscode.workspace.getConfiguration('playwright'); - configuration.update('embeddedTraceViewer', false, true); - - await testController.run(); - - await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ type: 'spawn' }); -}); - -test('should restore webview state when moving', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async () => {}); - `, - }); - - await testController.expandTestItems(/test.spec/); - const testItems = testController.findTestItems(/pass/); - - await testController.run(); - - selectTestItem(testItems[0]); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - await vscode.changeVisibility(webview, 'hidden'); - - await expect(webview).toHaveURL(/hidden/); - - await vscode.changeVisibility(webview, 'visible'); - - const listItem = webview.frameLocator('iframe').getByTestId('actions-tree').getByRole('treeitem'); - await expect( - listItem, - 'action list' - ).toHaveText([ - /Before Hooks[\d.]+m?s/, - /After Hooks[\d.]+m?s/, - ]); - -}); - -test('should open source location in vscode', async ({ activate }) => { - const { vscode, testController } = await activate({ - 'playwright.config.js': `module.exports = { testDir: 'tests' }`, - 'tests/test.spec.ts': ` - import { test } from '@playwright/test'; - test('should pass', async ({ page }) => { - await page.setContent('Hello world'); - }); - `, - }); - - await testController.expandTestItems(/test.spec/); - const [testItem] = testController.findTestItems(/pass/); - - await testController.run(); - - selectTestItem(testItem); - - const webview = await singleWebViewByPanelType(vscode, 'playwright.traceviewer.view')!; - const iframe = webview.frameLocator('iframe'); - await iframe.getByTestId('actions-tree').getByRole('treeitem').filter({ hasText: 'page.setContent' }).click(); - await iframe.getByTitle('Source').click(); - await iframe.getByTitle('Open in VS Code').click(); - - await expect.poll(() => vscode.window.visibleTextEditors[0]?.document.uri.fsPath).toMatch(/test\.spec\.ts/); -}); diff --git a/tests/mock/vscode.ts b/tests/mock/vscode.ts index e6d9818ad..d4efa005c 100644 --- a/tests/mock/vscode.ts +++ b/tests/mock/vscode.ts @@ -1141,7 +1141,6 @@ export class VSCode { 'playwright.env': {}, 'playwright.reuseBrowser': false, 'playwright.showTrace': false, - 'playwright.embeddedTraceViewer': false, 'playwright.runGlobalSetupOnEachRun': false, 'workbench.colorTheme': 'Dark Modern', }; diff --git a/tests/trace-viewer.spec.ts b/tests/trace-viewer.spec.ts index 1522728b0..ea9597e87 100644 --- a/tests/trace-viewer.spec.ts +++ b/tests/trace-viewer.spec.ts @@ -17,9 +17,9 @@ import { enableConfigs, expect, selectConfig, selectTestItem, test, traceViewerInfo } from './utils'; test.skip(({ showTrace }) => !showTrace); -test.skip(({ showTrace, overridePlaywrightVersion }) => !!overridePlaywrightVersion && showTrace === 'embedded'); +test.skip(({ overridePlaywrightVersion }) => !!overridePlaywrightVersion); -test('@smoke should open trace viewer', async ({ activate, showTrace }) => { +test('@smoke should open trace viewer', async ({ activate }) => { const { vscode, testController } = await activate({ 'playwright.config.js': `module.exports = { testDir: 'tests' }`, 'tests/test.spec.ts': ` @@ -33,12 +33,11 @@ test('@smoke should open trace viewer', async ({ activate, showTrace }) => { selectTestItem(testController.findTestItems(/pass/)[0]); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: expect.stringContaining('pass'), }); }); -test('should change opened file in trace viewer', async ({ activate, showTrace }) => { +test('should change opened file in trace viewer', async ({ activate }) => { const { vscode, testController } = await activate({ 'playwright.config.js': `module.exports = { testDir: 'tests' }`, 'tests/test.spec.ts': ` @@ -54,14 +53,12 @@ test('should change opened file in trace viewer', async ({ activate, showTrace } selectTestItem(testController.findTestItems(/one/)[0]); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: expect.stringContaining('one'), }); selectTestItem(testController.findTestItems(/two/)[0]); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: expect.stringContaining('two'), }); }); @@ -83,7 +80,7 @@ test('should not open trace viewer if test did not run', async ({ activate }) => }); }); -test('should refresh trace viewer while test is running', async ({ activate, createLatch, showTrace }) => { +test('should refresh trace viewer while test is running', async ({ activate, createLatch }) => { const latch = createLatch(); const { vscode, testController } = await activate({ @@ -99,7 +96,6 @@ test('should refresh trace viewer while test is running', async ({ activate, cre const testRunPromise = testController.run(); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: expect.stringMatching(/\.json$/), }); @@ -107,12 +103,11 @@ test('should refresh trace viewer while test is running', async ({ activate, cre await testRunPromise; await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: expect.stringMatching(/\.zip$/), }); }); -test('should close trace viewer if test configs refreshed', async ({ activate, showTrace }) => { +test('should close trace viewer if test configs refreshed', async ({ activate }) => { const { vscode, testController } = await activate({ 'playwright.config.js': `module.exports = { testDir: 'tests' }`, 'tests/test.spec.ts': ` @@ -126,20 +121,18 @@ test('should close trace viewer if test configs refreshed', async ({ activate, s selectTestItem(testController.findTestItems(/pass/)[0]); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: expect.stringContaining('pass'), }); await testController.refreshHandler!(null); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: undefined, visible: false, }); }); -test('should open new trace viewer when another test config is selected', async ({ activate, showTrace }) => { +test('should open new trace viewer when another test config is selected', async ({ activate }) => { const { vscode, testController } = await activate({ 'playwright1.config.js': `module.exports = { testDir: 'tests1' }`, 'playwright2.config.js': `module.exports = { testDir: 'tests2' }`, @@ -163,7 +156,6 @@ test('should open new trace viewer when another test config is selected', async selectTestItem(testItems[0]); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, serverUrlPrefix: expect.stringContaining('http'), testConfigFile: expect.stringContaining('playwright1.config.js'), }); @@ -173,7 +165,6 @@ test('should open new trace viewer when another test config is selected', async await selectConfig(vscode, 'playwright2.config.js'); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, traceFile: undefined, visible: false, }); @@ -182,7 +173,6 @@ test('should open new trace viewer when another test config is selected', async selectTestItem(testItems[0]); await expect.poll(() => traceViewerInfo(vscode)).toMatchObject({ - type: showTrace, serverUrlPrefix: expect.stringContaining('http'), testConfigFile: expect.stringContaining('playwright2.config.js'), }); diff --git a/tests/utils.ts b/tests/utils.ts index 0a0e8c7ad..2bd2cab1b 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -44,7 +44,7 @@ type TestFixtures = { export type WorkerOptions = { overridePlaywrightVersion?: number; showBrowser: boolean; - showTrace?: 'spawn' | 'embedded'; + showTrace?: boolean; vsCodeVersion: number; }; @@ -155,8 +155,6 @@ export const test = baseTest.extend({ vscode.env.remoteName = 'ssh-remote'; process.env.PWTEST_UNDER_TEST = '1'; } - if (showTrace === 'embedded') - configuration.update('embeddedTraceViewer', true); const extension = new Extension(vscode, vscode.context); if (overridePlaywrightVersion) @@ -258,7 +256,7 @@ export async function singleWebViewByPanelType(vscode: VSCode, viewType: string) return vscode.webViewsByPanelType(viewType)[0]; } -export async function traceViewerInfo(vscode: VSCode): Promise<{ type: 'spawn' | 'embedded', serverUrlPrefix?: string, testConfigFile: string, traceFile: string } | undefined> { +export async function traceViewerInfo(vscode: VSCode): Promise<{ type: 'spawn', serverUrlPrefix?: string, testConfigFile: string, traceFile: string } | undefined> { return await vscode.extensions[0].traceViewerInfoForTest(); }