chore: propagate status along the tree (#21507)

This commit is contained in:
Pavel Feldman 2023-03-08 18:24:45 -08:00 committed by GitHub
parent adc895d31f
commit 72c41db668
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -203,34 +203,12 @@ export const TestList: React.FC<{
</div>; </div>;
}} }}
icon={treeItem => { icon={treeItem => {
if (treeItem.kind === 'case') { if (treeItem.status === 'running')
let allOk = true; return 'codicon-loading';
let hasFailed = false; if (treeItem.status === 'failed')
let hasRunning = false; return 'codicon-error';
for (const test of treeItem.tests) { if (treeItem.status === 'passed')
allOk = allOk && test.outcome() === 'expected'; return 'codicon-check';
hasFailed = hasFailed || (!!test.results.length && test.outcome() !== 'expected');
hasRunning = hasRunning || test.results.some(r => r.duration === -1);
}
if (hasRunning)
return 'codicon-loading';
if (allOk)
return 'codicon-check';
if (hasFailed)
return 'codicon-error';
}
if (treeItem.kind === 'test') {
const ok = treeItem.test.outcome() === 'expected';
const failed = treeItem.test.results.length && treeItem.test.outcome() !== 'expected';
const running = treeItem.test.results.some(r => r.duration === -1);
if (running)
return 'codicon-loading';
if (ok)
return 'codicon-check';
if (failed)
return 'codicon-error';
}
return 'codicon-circle-outline'; return 'codicon-circle-outline';
}} }}
selectedItem={selectedTreeItem} selectedItem={selectedTreeItem}
@ -254,15 +232,15 @@ export const SettingsView: React.FC<{
<ToolbarButton icon='close' title='Close settings' toggled={false} onClick={onClose}></ToolbarButton> <ToolbarButton icon='close' title='Close settings' toggled={false} onClick={onClose}></ToolbarButton>
</div> </div>
{[...projects.entries()].map(([projectName, value]) => { {[...projects.entries()].map(([projectName, value]) => {
return <div style={{ display: 'flex', alignItems: 'center', lineHeight: '24px', cursor: 'pointer' }}> return <div style={{ display: 'flex', alignItems: 'center', lineHeight: '24px' }}>
<input id={`project-${projectName}`} type='checkbox' checked={value} onClick={() => { <input id={`project-${projectName}`} type='checkbox' checked={value} style={{ cursor: 'pointer' }} onClick={() => {
const copy = new Map(projects); const copy = new Map(projects);
copy.set(projectName, !copy.get(projectName)); copy.set(projectName, !copy.get(projectName));
if (![...copy.values()].includes(true)) if (![...copy.values()].includes(true))
copy.set(projectName, true); copy.set(projectName, true);
setProjects(copy); setProjects(copy);
}} style={{ margin: '0 5px 0 10px' }} /> }}/>
<label htmlFor={`project-${projectName}`}> <label htmlFor={`project-${projectName}`} style={{ cursor: 'pointer' }}>
{projectName} {projectName}
</label> </label>
</div>; </div>;
@ -441,7 +419,7 @@ type TreeItemBase = {
title: string; title: string;
parent: TreeItem | null; parent: TreeItem | null;
children: TreeItem[]; children: TreeItem[];
expanded?: boolean; status: 'none' | 'running' | 'passed' | 'failed';
}; };
type RootItem = TreeItemBase & { type RootItem = TreeItemBase & {
@ -475,6 +453,7 @@ function createTree(rootSuite: Suite | undefined, projects: Map<string, boolean>
title: '', title: '',
parent: null, parent: null,
children: [], children: [],
status: 'none',
}; };
const fileItems = new Map<string, FileItem>(); const fileItems = new Map<string, FileItem>();
for (const projectSuite of rootSuite?.suites || []) { for (const projectSuite of rootSuite?.suites || []) {
@ -492,7 +471,7 @@ function createTree(rootSuite: Suite | undefined, projects: Map<string, boolean>
file, file,
parent: null, parent: null,
children: [], children: [],
expanded: false, status: 'none',
}; };
fileItems.set(fileSuite.location!.file, fileItem); fileItems.set(fileSuite.location!.file, fileItem);
rootItem.children.push(fileItem); rootItem.children.push(fileItem);
@ -509,11 +488,20 @@ function createTree(rootSuite: Suite | undefined, projects: Map<string, boolean>
parent: fileItem, parent: fileItem,
children: [], children: [],
tests: [], tests: [],
expanded: false,
location: test.location, location: test.location,
status: 'none',
}; };
fileItem.children.push(testCaseItem); fileItem.children.push(testCaseItem);
} }
let status: 'none' | 'running' | 'passed' | 'failed' = 'none';
if (test.results.some(r => r.duration === -1))
status = 'running';
else if (test.results.length && test.outcome() !== 'expected')
status = 'failed';
else if (test.outcome() === 'expected')
status = 'passed';
testCaseItem.tests.push(test); testCaseItem.tests.push(test);
testCaseItem.children.push({ testCaseItem.children.push({
kind: 'test', kind: 'test',
@ -522,11 +510,35 @@ function createTree(rootSuite: Suite | undefined, projects: Map<string, boolean>
parent: testCaseItem, parent: testCaseItem,
test, test,
children: [], children: [],
status,
}); });
} }
(fileItem.children as TestCaseItem[]).sort((a, b) => a.location.line - b.location.line); (fileItem.children as TestCaseItem[]).sort((a, b) => a.location.line - b.location.line);
} }
} }
const propagateStatus = (treeItem: TreeItem) => {
for (const child of treeItem.children)
propagateStatus(child);
let allPassed = treeItem.children.length > 0;
let hasFailed = false;
let hasRunning = false;
for (const child of treeItem.children) {
allPassed = allPassed && child.status === 'passed';
hasFailed = hasFailed || child.status === 'failed';
hasRunning = hasRunning || child.status === 'running';
}
if (hasRunning)
treeItem.status = 'running';
else if (hasFailed)
treeItem.status = 'failed';
else if (allPassed)
treeItem.status = 'passed';
};
propagateStatus(rootItem);
return rootItem; return rootItem;
} }