Skip to content

Commit

Permalink
chore: filter skipped tests (#21938)
Browse files Browse the repository at this point in the history
Fixes #21918
  • Loading branch information
pavelfeldman committed Mar 23, 2023
1 parent 6b83631 commit 31e70c1
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 53 deletions.
8 changes: 6 additions & 2 deletions packages/playwright-test/src/isomorphic/teleReceiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export class TeleReporterReceiver {
testResult.workerIndex = payload.workerIndex;
testResult.parallelIndex = payload.parallelIndex;
testResult.startTime = new Date(payload.startTime);
testResult.statusEx = 'running';
this._reporter.onTestBegin?.(test, testResult);
}

Expand All @@ -183,6 +184,7 @@ export class TeleReporterReceiver {
const result = test.resultsMap.get(payload.id)!;
result.duration = payload.duration;
result.status = payload.status;
result.statusEx = payload.status;
result.errors = payload.errors;
result.attachments = payload.attachments;
this._reporter.onTestEnd?.(test, result);
Expand Down Expand Up @@ -380,7 +382,7 @@ export class TeleSuite implements SuitePrivate {
export class TeleTestCase implements reporterTypes.TestCase {
title: string;
fn = () => {};
results: reporterTypes.TestResult[] = [];
results: TeleTestResult[] = [];
location: Location;
parent!: TeleSuite;

Expand Down Expand Up @@ -426,7 +428,7 @@ export class TeleTestCase implements reporterTypes.TestCase {
this.resultsMap.clear();
}

_createTestResult(id: string): reporterTypes.TestResult {
_createTestResult(id: string): TeleTestResult {
this._clearResults();
const result: TeleTestResult = {
retry: this.results.length,
Expand All @@ -438,6 +440,7 @@ export class TeleTestCase implements reporterTypes.TestCase {
stderr: [],
attachments: [],
status: 'skipped',
statusEx: 'scheduled',
steps: [],
errors: [],
stepMap: new Map(),
Expand All @@ -453,6 +456,7 @@ export class TeleTestCase implements reporterTypes.TestCase {
export type TeleTestResult = reporterTypes.TestResult & {
stepMap: Map<string, reporterTypes.TestStep>;
stepStack: (reporterTypes.TestStep | reporterTypes.TestResult)[];
statusEx: reporterTypes.TestResult['status'] | 'scheduled' | 'running';
};

export type TeleFullProject = FullProject & { id: string };
Expand Down
108 changes: 57 additions & 51 deletions packages/trace-viewer/src/ui/watchMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,11 @@ const TestList: React.FC<{

// Build the test tree.
const { rootItem, treeItemMap, fileNames } = React.useMemo(() => {
const rootItem = createTree(testModel.rootSuite, projectFilters);
let rootItem = createTree(testModel.rootSuite, projectFilters);
filterTree(rootItem, filterText, statusFilters, runningState?.testIds);
sortAndPropagateStatus(rootItem);
rootItem = shortenRoot(rootItem);

hideOnlyTests(rootItem);
const treeItemMap = new Map<string, TreeItem>();
const visibleTestIds = new Set<string>();
Expand Down Expand Up @@ -769,18 +772,19 @@ function createTree(rootSuite: Suite | undefined, projectFilters: Map<string, bo
parentGroup.children.push(testCaseItem);
}

const result = (test as TeleTestCase).results[0];
let status: 'none' | 'running' | 'scheduled' | 'passed' | 'failed' | 'skipped' = 'none';
if (test.results.some(r => r.workerIndex === -1))
if (result?.statusEx === 'scheduled')
status = 'scheduled';
else if (test.results.some(r => r.duration === -1))
else if (result?.statusEx === 'running')
status = 'running';
else if (test.results.length && test.results[0].status === 'skipped')
else if (result?.status === 'skipped')
status = 'skipped';
else if (test.results.length && test.results[0].status === 'interrupted')
else if (result?.status === 'interrupted')
status = 'none';
else if (test.results.length && test.outcome() !== 'expected')
else if (result && test.outcome() !== 'expected')
status = 'failed';
else if (test.results.length && test.outcome() === 'expected')
else if (result && test.outcome() === 'expected')
status = 'passed';

testCaseItem.tests.push(test);
Expand Down Expand Up @@ -809,50 +813,7 @@ function createTree(rootSuite: Suite | undefined, projectFilters: Map<string, bo
visitSuite(projectSuite.title, fileSuite, fileItem);
}
}

const sortAndPropagateStatus = (treeItem: TreeItem) => {
for (const child of treeItem.children)
sortAndPropagateStatus(child);

if (treeItem.kind === 'group') {
treeItem.children.sort((a, b) => {
const fc = a.location.file.localeCompare(b.location.file);
return fc || a.location.line - b.location.line;
});
}

let allPassed = treeItem.children.length > 0;
let allSkipped = treeItem.children.length > 0;
let hasFailed = false;
let hasRunning = false;
let hasScheduled = false;

for (const child of treeItem.children) {
allSkipped = allSkipped && child.status === 'skipped';
allPassed = allPassed && (child.status === 'passed' || child.status === 'skipped');
hasFailed = hasFailed || child.status === 'failed';
hasRunning = hasRunning || child.status === 'running';
hasScheduled = hasScheduled || child.status === 'scheduled';
}

if (hasRunning)
treeItem.status = 'running';
else if (hasScheduled)
treeItem.status = 'scheduled';
else if (hasFailed)
treeItem.status = 'failed';
else if (allSkipped)
treeItem.status = 'skipped';
else if (allPassed)
treeItem.status = 'passed';
};
sortAndPropagateStatus(rootItem);

let shortRoot = rootItem;
while (shortRoot.children.length === 1 && shortRoot.children[0].kind === 'group' && shortRoot.children[0].subKind === 'folder')
shortRoot = shortRoot.children[0];
shortRoot.location = rootItem.location;
return shortRoot;
return rootItem;
}

function filterTree(rootItem: GroupItem, filterText: string, statusFilters: Map<string, boolean>, runningTestIds: Set<string> | undefined) {
Expand Down Expand Up @@ -887,6 +848,51 @@ function filterTree(rootItem: GroupItem, filterText: string, statusFilters: Map<
visit(rootItem);
}

function sortAndPropagateStatus(treeItem: TreeItem) {
for (const child of treeItem.children)
sortAndPropagateStatus(child);

if (treeItem.kind === 'group') {
treeItem.children.sort((a, b) => {
const fc = a.location.file.localeCompare(b.location.file);
return fc || a.location.line - b.location.line;
});
}

let allPassed = treeItem.children.length > 0;
let allSkipped = treeItem.children.length > 0;
let hasFailed = false;
let hasRunning = false;
let hasScheduled = false;

for (const child of treeItem.children) {
allSkipped = allSkipped && child.status === 'skipped';
allPassed = allPassed && (child.status === 'passed' || child.status === 'skipped');
hasFailed = hasFailed || child.status === 'failed';
hasRunning = hasRunning || child.status === 'running';
hasScheduled = hasScheduled || child.status === 'scheduled';
}

if (hasRunning)
treeItem.status = 'running';
else if (hasScheduled)
treeItem.status = 'scheduled';
else if (hasFailed)
treeItem.status = 'failed';
else if (allSkipped)
treeItem.status = 'skipped';
else if (allPassed)
treeItem.status = 'passed';
}

function shortenRoot(rootItem: GroupItem): GroupItem {
let shortRoot = rootItem;
while (shortRoot.children.length === 1 && shortRoot.children[0].kind === 'group' && shortRoot.children[0].subKind === 'folder')
shortRoot = shortRoot.children[0];
shortRoot.location = rootItem.location;
return shortRoot;
}

function hideOnlyTests(rootItem: GroupItem) {
const visit = (treeItem: TreeItem) => {
if (treeItem.kind === 'case' && treeItem.children.length === 1)
Expand Down
25 changes: 25 additions & 0 deletions tests/playwright-test/ui-mode-test-filters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,28 @@ test('should not hide filtered while running', async ({ runUITest, createLatch }
↻ fails <=
`);
});

test('should filter skipped', async ({ runUITest, createLatch }) => {
const page = await runUITest({
'a.test.ts': `
import { test, expect } from '@playwright/test';
test('passes', () => {});
test.skip('fails', async () => {
expect(1).toBe(2);
});
`,
});
await page.getByTitle('Run all').click();
await expect.poll(dumpTestTree(page), { timeout: 15000 }).toBe(`
▼ ✅ a.test.ts
✅ passes
⊘ fails
`);

await page.getByText('Status:').click();
await page.getByLabel('skipped').setChecked(true);
await expect.poll(dumpTestTree(page), { timeout: 15000 }).toBe(`
▼ ⊘ a.test.ts
⊘ fails
`);
});

0 comments on commit 31e70c1

Please sign in to comment.