From 493171cb6bb2a5ae156948a8af3e800617f2fc58 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Sun, 12 Mar 2023 10:50:21 -0700 Subject: [PATCH] chore: select files to watch explicitly (#21599) --- packages/playwright-test/src/runner/uiMode.ts | 19 +++++---- packages/trace-viewer/src/ui/watchMode.css | 2 +- packages/trace-viewer/src/ui/watchMode.tsx | 42 +++++++++++++------ packages/web/src/components/toolbarButton.tsx | 9 +++- 4 files changed, 48 insertions(+), 24 deletions(-) diff --git a/packages/playwright-test/src/runner/uiMode.ts b/packages/playwright-test/src/runner/uiMode.ts index 28bf7187d7..1c68759c55 100644 --- a/packages/playwright-test/src/runner/uiMode.ts +++ b/packages/playwright-test/src/runner/uiMode.ts @@ -35,7 +35,6 @@ class UIMode { private _testRun: { run: Promise, stop: ManualPromise } | undefined; globalCleanup: (() => Promise) | undefined; private _testWatcher: FSWatcher | undefined; - private _watchTestFile: string | undefined; private _originalStderr: (buffer: string | Uint8Array) => void; constructor(config: FullConfigInternal) { @@ -113,7 +112,7 @@ class UIMode { return; } if (method === 'watch') { - this._watchFile(params.fileName); + this._watchFiles(params.fileNames); return; } if (method === 'open' && params.location) { @@ -185,17 +184,19 @@ class UIMode { await run; } - private async _watchFile(fileName: string) { - if (this._watchTestFile === fileName) - return; + private async _watchFiles(fileNames: string[]) { if (this._testWatcher) await this._testWatcher.close(); - this._watchTestFile = fileName; - if (!fileName) + if (!fileNames.length) return; - const files = [fileName, ...dependenciesForTestFile(fileName)]; - this._testWatcher = chokidar.watch(files, { ignoreInitial: true }).on('all', async (event, file) => { + const files = new Set(); + for (const fileName of fileNames) { + files.add(fileName); + dependenciesForTestFile(fileName).forEach(file => files.add(file)); + } + + this._testWatcher = chokidar.watch([...files], { ignoreInitial: true }).on('all', async (event, file) => { if (event !== 'add' && event !== 'change') return; this._dispatchEvent({ method: 'fileChanged', params: { fileName: file } }); diff --git a/packages/trace-viewer/src/ui/watchMode.css b/packages/trace-viewer/src/ui/watchMode.css index 00093916b8..120e21a86a 100644 --- a/packages/trace-viewer/src/ui/watchMode.css +++ b/packages/trace-viewer/src/ui/watchMode.css @@ -72,7 +72,7 @@ margin-top: 5px; } -.list-view-entry:not(.selected):not(.highlighted) .toolbar-button { +.list-view-entry:not(.highlighted) .toolbar-button:not(.toggled) { display: none; } diff --git a/packages/trace-viewer/src/ui/watchMode.tsx b/packages/trace-viewer/src/ui/watchMode.tsx index d9c45726a7..cfef4cc56b 100644 --- a/packages/trace-viewer/src/ui/watchMode.tsx +++ b/packages/trace-viewer/src/ui/watchMode.tsx @@ -37,7 +37,7 @@ import { Expandable } from '@web/components/expandable'; let updateRootSuite: (rootSuite: Suite, progress: Progress) => void = () => {}; let updateStepsProgress: () => void = () => {}; -let runWatchedTests = () => {}; +let runWatchedTests = (fileName: string) => {}; let xtermSize = { cols: 80, rows: 24 }; const xtermDataSource: XtermDataSource = { @@ -52,7 +52,6 @@ const xtermDataSource: XtermDataSource = { export const WatchModeView: React.FC<{}> = ({ }) => { - const [isWatchingFiles, setIsWatchingFiles] = useSetting('test-ui-watch-files', false); const [filterText, setFilterText] = useSetting('test-ui-filter-text', ''); const [filterExpanded, setFilterExpanded] = useSetting('test-ui-filter-expanded', false); const [isShowingOutput, setIsShowingOutput] = useSetting('test-ui-show-output', false); @@ -64,6 +63,7 @@ export const WatchModeView: React.FC<{}> = ({ const [settingsVisible, setSettingsVisible] = React.useState(false); const [visibleTestIds, setVisibleTestIds] = React.useState([]); const [runningState, setRunningState] = React.useState<{ testIds: Set, itemSelectedByUser?: boolean }>(); + const inputRef = React.useRef(null); React.useEffect(() => { @@ -152,7 +152,6 @@ export const WatchModeView: React.FC<{}> = ({ runTests(visibleTestIds)} disabled={isRunningTest}> sendMessageNoReply('stop')} disabled={!isRunningTest}> refreshRootSuite(true)} disabled={isRunningTest}> - setIsWatchingFiles(!isWatchingFiles)}>
{ setSettingsVisible(!settingsVisible); }}> { setIsShowingOutput(!isShowingOutput); }}> @@ -185,7 +184,6 @@ export const WatchModeView: React.FC<{}> = ({ filterText={filterText} rootSuite={rootSuite} runningState={runningState} - isWatchingFiles={isWatchingFiles} runTests={runTests} onTestSelected={setSelectedTest} isVisible={!settingsVisible} @@ -212,13 +210,13 @@ export const TestList: React.FC<{ rootSuite: { value: Suite | undefined }, runTests: (testIds: string[]) => void, runningState?: { testIds: Set, itemSelectedByUser?: boolean }, - isWatchingFiles: boolean, isVisible: boolean, setVisibleTestIds: (testIds: string[]) => void, onTestSelected: (test: TestCase | undefined) => void, -}> = ({ projects, filterText, rootSuite, runTests, runningState, isWatchingFiles, isVisible, onTestSelected, setVisibleTestIds }) => { +}> = ({ projects, filterText, rootSuite, runTests, runningState, isVisible, onTestSelected, setVisibleTestIds }) => { const [treeState, setTreeState] = React.useState({ expandedItems: new Map() }); const [selectedTreeItemId, setSelectedTreeItemId] = React.useState(); + const [watchedTreeIds] = React.useState>(new Set()); React.useEffect(() => { refreshRootSuite(true); @@ -274,17 +272,28 @@ export const TestList: React.FC<{ return { selectedTreeItem }; }, [onTestSelected, selectedTreeItemId, treeItemMap]); - React.useEffect(() => { - sendMessageNoReply('watch', { fileName: isWatchingFiles ? fileName(selectedTreeItem) : undefined }); - }, [selectedTreeItem, isWatchingFiles]); + const setWatchedTreeIds = (watchedTreeIds: Set) => { + const fileNames = new Set(); + for (const itemId of watchedTreeIds) { + const treeItem = treeItemMap.get(itemId)!; + fileNames.add(fileNameForTreeItem(treeItem)!); + } + sendMessageNoReply('watch', { fileNames: [...fileNames] }); + }; const runTreeItem = (treeItem: TreeItem) => { setSelectedTreeItemId(treeItem.id); runTests(collectTestIds(treeItem)); }; - runWatchedTests = () => { - runTests(collectTestIds(selectedTreeItem)); + runWatchedTests = (fileName: string) => { + const testIds: string[] = []; + for (const treeId of watchedTreeIds) { + const treeItem = treeItemMap.get(treeId)!; + if (fileNameForTreeItem(treeItem) === fileName) + testIds.push(...collectTestIds(treeItem)); + } + runTests(testIds); }; if (!isVisible) @@ -299,6 +308,13 @@ export const TestList: React.FC<{
{treeItem.title}
runTreeItem(treeItem)} disabled={!!runningState}> sendMessageNoReply('open', { location: locationToOpen(treeItem) })}> + { + if (watchedTreeIds.has(treeItem.id)) + watchedTreeIds.delete(treeItem.id); + else + watchedTreeIds.add(treeItem.id); + setWatchedTreeIds(watchedTreeIds); + }} toggled={watchedTreeIds.has(treeItem.id)}> ; }} icon={treeItem => { @@ -469,7 +485,7 @@ const refreshRootSuite = (eraseResults: boolean) => { } if (message.method === 'fileChanged') { - runWatchedTests(); + runWatchedTests(message.params.fileName); return; } @@ -497,7 +513,7 @@ const sendMessageNoReply = (method: string, params?: any) => { }); }; -const fileName = (treeItem?: TreeItem): string | undefined => { +const fileNameForTreeItem = (treeItem?: TreeItem): string | undefined => { return treeItem?.location.file; }; diff --git a/packages/web/src/components/toolbarButton.tsx b/packages/web/src/components/toolbarButton.tsx index b31b444baa..9242b734a9 100644 --- a/packages/web/src/components/toolbarButton.tsx +++ b/packages/web/src/components/toolbarButton.tsx @@ -37,8 +37,15 @@ export const ToolbarButton: React.FC let className = `toolbar-button ${icon}`; if (toggled) className += ' toggled'; - return ; }; + +const preventDefault = (e: any) => e.preventDefault();