chore: implement project filter (#21402)

This commit is contained in:
Pavel Feldman 2023-03-04 19:39:55 -08:00 committed by GitHub
parent ec056a6312
commit d8d410db6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -27,20 +27,19 @@ import './watchMode.css';
import { ToolbarButton } from '@web/components/toolbarButton'; import { ToolbarButton } from '@web/components/toolbarButton';
import { Toolbar } from '@web/components/toolbar'; import { Toolbar } from '@web/components/toolbar';
let rootSuite: Suite | undefined; let updateRootSuite: (rootSuite: Suite) => void = () => {};
let updateList: () => void = () => {};
let updateProgress: () => void = () => {}; let updateProgress: () => void = () => {};
let runWatchedTests = () => {}; let runWatchedTests = () => {};
const expandedItems = new Map<string, boolean | undefined>();
export const WatchModeView: React.FC<{}> = ({ export const WatchModeView: React.FC<{}> = ({
}) => { }) => {
const [updateCounter, setUpdateCounter] = React.useState(0); const [rootSuite, setRootSuite] = React.useState<{ value: Suite | undefined }>({ value: undefined });
updateList = () => setUpdateCounter(updateCounter + 1); updateRootSuite = (rootSuite: Suite) => setRootSuite({ value: rootSuite });
const [selectedTreeItemId, setSelectedTreeItemId] = React.useState<string | undefined>(); const [selectedTreeItemId, setSelectedTreeItemId] = React.useState<string | undefined>();
const [isRunningTest, setIsRunningTest] = React.useState<boolean>(false); const [isRunningTest, setIsRunningTest] = React.useState<boolean>(false);
const [filterText, setFilterText] = React.useState<string>(''); const [filterText, setFilterText] = React.useState<string>('');
const [projectNames, setProjectNames] = React.useState<string[]>([]);
const [expandedItems, setExpandedItems] = React.useState<Map<string, boolean>>(new Map());
const inputRef = React.useRef<HTMLInputElement>(null); const inputRef = React.useRef<HTMLInputElement>(null);
@ -49,10 +48,13 @@ export const WatchModeView: React.FC<{}> = ({
sendMessageNoReply('list'); sendMessageNoReply('list');
}, []); }, []);
const { treeItemMap, visibleTestIds, listItems } = React.useMemo(() => { React.useEffect(() => {
// updateCounter is used to trigger the compute. if (projectNames.length === 0 && rootSuite.value?.suites.length)
noop(updateCounter); setProjectNames([rootSuite.value?.suites[0].title]);
const treeItems = createTree(rootSuite); }, [projectNames, rootSuite]);
const { filteredItems, treeItemMap, visibleTestIds } = React.useMemo(() => {
const treeItems = createTree(rootSuite.value, projectNames);
const filteredItems = filterTree(treeItems, filterText); const filteredItems = filterTree(treeItems, filterText);
const treeItemMap = new Map<string, TreeItem>(); const treeItemMap = new Map<string, TreeItem>();
@ -64,9 +66,14 @@ export const WatchModeView: React.FC<{}> = ({
treeItemMap.set(treeItem.id, treeItem); treeItemMap.set(treeItem.id, treeItem);
}; };
filteredItems.forEach(visit); filteredItems.forEach(visit);
return { treeItemMap, visibleTestIds, filteredItems };
}, [filterText, rootSuite, projectNames]);
const { listItems } = React.useMemo(() => {
const listItems = flattenTree(filteredItems, expandedItems, !!filterText.trim()); const listItems = flattenTree(filteredItems, expandedItems, !!filterText.trim());
return { treeItemMap, visibleTestIds, listItems }; return { listItems };
}, [filterText, updateCounter]); }, [filteredItems, filterText, expandedItems]);
const selectedTreeItem = selectedTreeItemId ? treeItemMap.get(selectedTreeItemId) : undefined; const selectedTreeItem = selectedTreeItemId ? treeItemMap.get(selectedTreeItemId) : undefined;
@ -136,16 +143,19 @@ export const WatchModeView: React.FC<{}> = ({
selectedItem={selectedTreeItem} selectedItem={selectedTreeItem}
onAccepted={runTreeItem} onAccepted={runTreeItem}
onLeftArrow={(treeItem: TreeItem) => { onLeftArrow={(treeItem: TreeItem) => {
if (treeItem.children && treeItem.expanded) if (treeItem.children && treeItem.expanded) {
expandedItems.set(treeItem.id, false); expandedItems.set(treeItem.id, false);
else setExpandedItems(new Map(expandedItems));
} else {
setSelectedTreeItemId(treeItem.parent?.id); setSelectedTreeItemId(treeItem.parent?.id);
updateList(); }
}} }}
onRightArrow={(treeItem: TreeItem) => { onRightArrow={(treeItem: TreeItem) => {
if (treeItem.children) if (treeItem.children) {
expandedItems.set(treeItem.id, true); expandedItems.set(treeItem.id, true);
updateList(); setExpandedItems(new Map(expandedItems));
}
setRootSuite({ ...rootSuite });
}} }}
onSelected={(treeItem: TreeItem) => { onSelected={(treeItem: TreeItem) => {
setSelectedTreeItemId(treeItem.id); setSelectedTreeItemId(treeItem.id);
@ -157,9 +167,25 @@ export const WatchModeView: React.FC<{}> = ({
expandedItems.set(treeItem.id, false); expandedItems.set(treeItem.id, false);
else else
expandedItems.set(treeItem.id, true); expandedItems.set(treeItem.id, true);
updateList(); setExpandedItems(new Map(expandedItems));
}} }}
showNoItemsMessage={true}></ListView> showNoItemsMessage={true}></ListView>
{(rootSuite.value?.suites.length || 0) > 1 && <div style={{ flex: 'none', borderTop: '1px solid var(--vscode-panel-border)' }}>
<ListView
items={rootSuite.value!.suites}
onSelected={(suite: Suite) => {
const copy = [...projectNames];
copy.includes(suite.title) ? copy.splice(copy.indexOf(suite.title), 1) : copy.push(suite.title);
setProjectNames(copy);
}}
itemRender={(suite: Suite) => {
return <label style={{ display: 'flex', pointerEvents: 'none' }}>
<input type='checkbox' checked={projectNames.includes(suite.title)} />
{suite.title}
</label>;
}}
/>
</div>}
</div> </div>
</SplitView>; </SplitView>;
}; };
@ -229,19 +255,21 @@ declare global {
} }
} }
const receiver = new TeleReporterReceiver({ {
let rootSuite: Suite;
const receiver = new TeleReporterReceiver({
onBegin: (config: FullConfig, suite: Suite) => { onBegin: (config: FullConfig, suite: Suite) => {
if (!rootSuite) if (!rootSuite)
rootSuite = suite; rootSuite = suite;
updateList(); updateRootSuite(rootSuite);
}, },
onTestBegin: () => { onTestBegin: () => {
updateList(); updateRootSuite(rootSuite);
}, },
onTestEnd: () => { onTestEnd: () => {
updateList(); updateRootSuite(rootSuite);
}, },
onStepBegin: () => { onStepBegin: () => {
@ -251,15 +279,16 @@ const receiver = new TeleReporterReceiver({
onStepEnd: () => { onStepEnd: () => {
updateProgress(); updateProgress();
}, },
}); });
(window as any).dispatch = (message: any) => { (window as any).dispatch = (message: any) => {
if (message.method === 'fileChanged') if (message.method === 'fileChanged')
runWatchedTests(); runWatchedTests();
else else
receiver.dispatch(message); receiver.dispatch(message);
}; };
}
const sendMessage = async (method: string, params: any) => { const sendMessage = async (method: string, params: any) => {
await (window as any).sendMessage({ method, params }); await (window as any).sendMessage({ method, params });
@ -318,9 +347,11 @@ type TestItem = TreeItemBase & {
type TreeItem = FileItem | TestCaseItem | TestItem; type TreeItem = FileItem | TestCaseItem | TestItem;
function createTree(rootSuite?: Suite): FileItem[] { function createTree(rootSuite: Suite | undefined, projectNames: string[]): FileItem[] {
const fileItems = new Map<string, FileItem>(); const fileItems = new Map<string, FileItem>();
for (const projectSuite of rootSuite?.suites || []) { for (const projectSuite of rootSuite?.suites || []) {
if (!projectNames.includes(projectSuite.title))
continue;
for (const fileSuite of projectSuite.suites) { for (const fileSuite of projectSuite.suites) {
const file = fileSuite.location!.file; const file = fileSuite.location!.file;
@ -391,8 +422,8 @@ function flattenTree(fileItems: FileItem[], expandedItems: Map<string, boolean |
result.push(fileItem); result.push(fileItem);
const expandState = expandedItems.get(fileItem.id); const expandState = expandedItems.get(fileItem.id);
const autoExpandMatches = result.length < 100 && (hasFilter && expandState !== false); const autoExpandMatches = result.length < 100 && (hasFilter && expandState !== false);
if (expandState || autoExpandMatches) { fileItem.expanded = expandState || autoExpandMatches;
fileItem.expanded = true; if (fileItem.expanded) {
for (const testCaseItem of fileItem.children!) { for (const testCaseItem of fileItem.children!) {
result.push(testCaseItem); result.push(testCaseItem);
testCaseItem.expanded = !!expandedItems.get(testCaseItem.id); testCaseItem.expanded = !!expandedItems.get(testCaseItem.id);
@ -403,5 +434,3 @@ function flattenTree(fileItems: FileItem[], expandedItems: Map<string, boolean |
} }
return result; return result;
} }
function noop(_: any) {}