chore: allow running failing (#21569)

This commit is contained in:
Pavel Feldman 2023-03-10 12:41:00 -08:00 committed by GitHub
parent 8abe9fcf22
commit 1073e42686
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 15 deletions

2
package-lock.json generated
View File

@ -9888,7 +9888,7 @@
"requires": {
"codemirror": "^5.65.9",
"xterm": "^5.1.0",
"xterm-addon-fit": "*"
"xterm-addon-fit": "^0.7.0"
}
},
"which": {

View File

@ -166,9 +166,7 @@ export class TeleReporterReceiver {
private _onTestBegin(testId: string, payload: JsonTestResultStart) {
const test = this._tests.get(testId)!;
test.results = [];
test.resultsMap.clear();
const testResult = test._appendTestResult(payload.id);
const testResult = test._createTestResult(payload.id);
testResult.retry = payload.retry;
testResult.workerIndex = payload.workerIndex;
testResult.parallelIndex = payload.parallelIndex;
@ -398,7 +396,9 @@ export class TeleTestCase implements reporterTypes.TestCase {
return status === 'expected' || status === 'flaky' || status === 'skipped';
}
_appendTestResult(id: string): reporterTypes.TestResult {
_createTestResult(id: string): reporterTypes.TestResult {
this.results = [];
this.resultsMap.clear();
const result: TeleTestResult = {
retry: this.results.length,
parallelIndex: -1,

View File

@ -68,6 +68,43 @@
margin: 0 5px;
}
.list-view {
margin-top: 5px;
}
.list-view-entry:not(.selected):not(.highlighted) .toolbar-button {
display: none;
}
.filters {
flex: none;
margin-left: 5px;
line-height: 24px;
}
.filters > span {
color: var(--vscode-panelTitle-inactiveForeground);
padding-left: 3px;
}
.filters > div {
display: inline-block;
margin: 0 5px;
user-select: none;
cursor: pointer;
}
.filters > div:hover,
.filters > div.filters-toggled {
color: var(--vscode-notificationLink-foreground);
}
.watch-mode-sidebar input[type=search] {
padding: 0 5px;
line-height: 24px;
outline: none;
margin: 0 4px;
border: none;
color: var(--vscode-input-foreground);
background-color: var(--vscode-input-background);
}

View File

@ -21,6 +21,7 @@ import React from 'react';
import { TreeView } from '@web/components/treeView';
import type { TreeState } from '@web/components/treeView';
import { TeleReporterReceiver } from '../../../playwright-test/src/isomorphic/teleReceiver';
import type { TeleTestCase } from '../../../playwright-test/src/isomorphic/teleReceiver';
import type { FullConfig, Suite, TestCase, TestResult, TestStep, Location } from '../../../playwright-test/types/testReporter';
import { SplitView } from '@web/components/splitView';
import { MultiTraceModel } from './modelUtil';
@ -32,6 +33,7 @@ import type { ContextEntry } from '../entries';
import type * as trace from '@trace/trace';
import type { XtermDataSource } from '@web/components/xtermWrapper';
import { XtermWrapper } from '@web/components/xtermWrapper';
import { Expandable } from '@web/components/expandable';
let updateRootSuite: (rootSuite: Suite, progress: Progress) => void = () => {};
let updateStepsProgress: () => void = () => {};
@ -59,6 +61,7 @@ export const WatchModeView: React.FC<{}> = ({
const [isWatchingFiles, setIsWatchingFiles] = React.useState<boolean>(true);
const [visibleTestIds, setVisibleTestIds] = React.useState<string[]>([]);
const [filterText, setFilterText] = React.useState<string>('');
const [filterExpanded, setFilterExpanded] = React.useState<boolean>(false);
const inputRef = React.useRef<HTMLInputElement>(null);
React.useEffect(() => {
@ -89,7 +92,7 @@ export const WatchModeView: React.FC<{}> = ({
const testIdSet = new Set(testIds);
for (const test of rootSuite.value?.allTests() || []) {
if (testIdSet.has(test.id))
test.results = [];
(test as TeleTestCase)._createTestResult('pending');
}
setRootSuite({ ...rootSuite });
}
@ -103,6 +106,24 @@ export const WatchModeView: React.FC<{}> = ({
});
};
const updateFilter = (name: string, value: string) => {
const result: string[] = [];
const prefix = name + ':';
for (const t of filterText.split(' ')) {
if (t.startsWith(prefix)) {
if (value) {
result.push(prefix + value);
value = '';
}
} else {
result.push(t);
}
}
if (value)
result.unshift(prefix + value);
setFilterText(result.join(' '));
};
const result = selectedTest?.results[0];
return <div className='vbox'>
<SplitView sidebarSize={250} orientation='horizontal' sidebarIsFirst={true}>
@ -117,16 +138,29 @@ export const WatchModeView: React.FC<{}> = ({
<div className='spacer'></div>
<ToolbarButton icon='gear' title='Toggle color mode' toggled={settingsVisible} onClick={() => { setSettingsVisible(!settingsVisible); }}></ToolbarButton>
</Toolbar>
<Toolbar>
<input ref={inputRef} type='search' placeholder='Filter (e.g. text, @tag)' spellCheck={false} value={filterText}
{!settingsVisible && <Expandable
title={<input ref={inputRef} type='search' placeholder='Filter (e.g. text, @tag)' spellCheck={false} value={filterText}
onChange={e => {
setFilterText(e.target.value);
}}
onKeyDown={e => {
if (e.key === 'Enter')
runTests(visibleTestIds);
}}></input>
</Toolbar>
}}></input>}
style={{ flex: 'none', marginTop: 8 }}
expanded={filterExpanded}
setExpanded={setFilterExpanded}>
<div className='filters'>
<span>Status:</span>
<div onClick={() => updateFilter('s', '')}>all</div>
{['failed', 'passed', 'skipped'].map(s => <div className={filterText.includes('s:' + s) ? 'filters-toggled' : ''} onClick={() => updateFilter('s', s)}>{s}</div>)}
</div>
{[...projects.values()].filter(v => v).length > 1 && <div className='filters'>
<span>Project:</span>
<div onClick={() => updateFilter('p', '')}>all</div>
{[...projects].filter(([k, v]) => v).map(([k, v]) => k).map(p => <div className={filterText.includes('p:' + p) ? 'filters-toggled' : ''} onClick={() => updateFilter('p', p)}>{p}</div>)}
</div>}
</Expandable>}
<TestList
projects={projects}
filterText={filterText}
@ -459,11 +493,13 @@ type GroupItem = TreeItemBase & {
type TestCaseItem = TreeItemBase & {
kind: 'case',
tests: TestCase[];
children: TestItem[];
};
type TestItem = TreeItemBase & {
kind: 'test',
test: TestCase;
project: string;
};
type TreeItem = GroupItem | TestCaseItem | TestItem;
@ -531,6 +567,7 @@ function createTree(rootSuite: Suite | undefined, projects: Map<string, boolean>
test,
children: [],
status,
project: projectName
});
}
};
@ -573,13 +610,27 @@ function createTree(rootSuite: Suite | undefined, projects: Map<string, boolean>
function filterTree(rootItem: GroupItem, filterText: string) {
const trimmedFilterText = filterText.trim();
const filterTokens = trimmedFilterText.toLowerCase().split(' ');
const textTokens = filterTokens.filter(token => !token.match(/^[sp]:/));
const statuses = new Set(filterTokens.filter(t => t.startsWith('s:')).map(t => t.substring(2)));
if (statuses.size)
statuses.add('running');
const projects = new Set(filterTokens.filter(t => t.startsWith('p:')).map(t => t.substring(2)));
const filter = (testCase: TestCaseItem) => {
const title = testCase.tests[0].titlePath().join(' ').toLowerCase();
if (!textTokens.every(token => title.includes(token)))
return false;
testCase.children = (testCase.children as TestItem[]).filter(test => !statuses.size || statuses.has(test.status));
testCase.children = (testCase.children as TestItem[]).filter(test => !projects.size || projects.has(test.project));
testCase.tests = (testCase.children as TestItem[]).map(c => c.test);
return !!testCase.children.length;
};
const visit = (treeItem: GroupItem) => {
const newChildren: (GroupItem | TestCaseItem)[] = [];
for (const child of treeItem.children) {
if (child.kind === 'case') {
const title = child.tests[0].titlePath().join(' ').toLowerCase();
if (filterTokens.every(token => title.includes(token)))
if (filter(child))
newChildren.push(child);
} else {
visit(child);

View File

@ -26,10 +26,10 @@ export const Expandable: React.FunctionComponent<React.PropsWithChildren<{
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', whiteSpace: 'nowrap' }}>
<div
className={'codicon codicon-' + (expanded ? 'chevron-down' : 'chevron-right')}
style={{ cursor: 'pointer', color: 'var(--vscode-foreground)', marginRight: '4px' }}
style={{ cursor: 'pointer', color: 'var(--vscode-foreground)', marginLeft: '5px' }}
onClick={() => setExpanded(!expanded)} />
{title}
</div>
{ expanded && <div style={{ display: 'flex', flex: 'auto', margin: '5px 0 5px 20px' }}>{children}</div> }
{ expanded && <div style={{ margin: '5px 0 5px 20px' }}>{children}</div> }
</div>;
};

View File

@ -41,5 +41,5 @@
}
.toolbar-button.toggled {
color: var(--vscode-inputOption-activeBorder);
color: var(--vscode-notificationLink-foreground);
}