diff --git a/packages/playwright-test/src/runner/uiMode.ts b/packages/playwright-test/src/runner/uiMode.ts index 52347846d09b5..b8fb56d6e5a63 100644 --- a/packages/playwright-test/src/runner/uiMode.ts +++ b/packages/playwright-test/src/runner/uiMode.ts @@ -161,7 +161,8 @@ class UIMode { const context: TaskRunnerState = { config: this._config, reporter, phases: [] }; clearCompilationCache(); reporter.onConfigure(this._config); - await taskRunner.run(context, 0); + const status = await taskRunner.run(context, 0); + reporter.onExit({ status }); } private async _runTests(testIds: string[]) { diff --git a/packages/trace-viewer/src/ui/watchMode.tsx b/packages/trace-viewer/src/ui/watchMode.tsx index 81a6ff90b9820..6473e1fae7b46 100644 --- a/packages/trace-viewer/src/ui/watchMode.tsx +++ b/packages/trace-viewer/src/ui/watchMode.tsx @@ -22,7 +22,7 @@ import { TreeView } from '@web/components/treeView'; import type { TreeState } from '@web/components/treeView'; import { baseFullConfig, TeleReporterReceiver, TeleSuite } from '@testIsomorphic/teleReceiver'; import type { TeleTestCase } from '@testIsomorphic/teleReceiver'; -import type { FullConfig, Suite, TestCase, Location } from '../../../playwright-test/types/testReporter'; +import type { FullConfig, Suite, TestCase, Location, TestError } from '../../../playwright-test/types/testReporter'; import { SplitView } from '@web/components/splitView'; import { MultiTraceModel } from './modelUtil'; import './watchMode.css'; @@ -368,8 +368,8 @@ const TestList: React.FC<{ } else { const fileNames = new Set(); for (const itemId of watchedTreeIds.value) { - const treeItem = treeItemMap.get(itemId)!; - const fileName = treeItem.location.file; + const treeItem = treeItemMap.get(itemId); + const fileName = treeItem?.location.file; if (fileName) fileNames.add(fileName); } @@ -396,8 +396,8 @@ const TestList: React.FC<{ visit(rootItem); } else { for (const treeId of watchedTreeIds.value) { - const treeItem = treeItemMap.get(treeId)!; - const fileName = treeItem.location.file; + const treeItem = treeItemMap.get(treeId); + const fileName = treeItem?.location.file; if (fileName && set.has(fileName)) testIds.push(...collectTestIds(treeItem)); } @@ -577,6 +577,10 @@ const refreshRootSuite = (eraseResults: boolean): Promise => { ++progress.passed; throttleUpdateRootSuite(config, rootSuite, progress); }, + + onError: (error: TestError) => { + xtermDataSource.write((error.stack || error.value || '') + '\n'); + }, }); return sendMessage('list', {}); }; diff --git a/packages/web/src/components/xtermWrapper.tsx b/packages/web/src/components/xtermWrapper.tsx index 6c60e7a93b079..d5ccab5b010d1 100644 --- a/packages/web/src/components/xtermWrapper.tsx +++ b/packages/web/src/components/xtermWrapper.tsx @@ -101,7 +101,7 @@ export const XtermWrapper: React.FC<{ source: XtermDataSource }> = ({ terminal.current.terminal.options.theme = theme === 'dark-mode' ? darkTheme : lightTheme; }, [theme]); - return
; + return
; }; const lightTheme: ITheme = { diff --git a/tests/playwright-test/ui-mode-load-errors.spec.ts b/tests/playwright-test/ui-mode-load-errors.spec.ts new file mode 100644 index 0000000000000..e3608581db9fb --- /dev/null +++ b/tests/playwright-test/ui-mode-load-errors.spec.ts @@ -0,0 +1,32 @@ +/** + * 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 './ui-mode-fixtures'; + +test.describe.configure({ mode: 'parallel' }); + +test('should list tests', async ({ runUITest }) => { + const page = await runUITest({ + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + test('syntax error', () => { + await 1; + }); + `, + }); + await page.getByTitle('Toggle output').click(); + await expect(page.getByTestId('output')).toContainText(`Unexpected reserved word 'await'`); +});