From e7a4317f96ee88f7b095f70a80fdaeb32850222a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 16 Jan 2026 16:36:18 +0000
Subject: [PATCH 1/4] Initial plan
From 590da94f2a72fdbcc8fafee550e965d83abac17d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 16 Jan 2026 16:45:01 +0000
Subject: [PATCH 2/4] Add expected fail tracking to CLI and UI reporters
Co-authored-by: sheremet-va <16173870+sheremet-va@users.noreply.github.com>
---
.../client/components/dashboard/TestsEntry.vue | 12 ++++++++++++
.../ui/client/composables/explorer/collector.ts | 17 ++++++++++++++---
packages/ui/client/composables/explorer/tree.ts | 1 +
.../ui/client/composables/explorer/types.ts | 2 ++
packages/vitest/src/node/reporters/summary.ts | 12 ++++++++++--
5 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/packages/ui/client/components/dashboard/TestsEntry.vue b/packages/ui/client/components/dashboard/TestsEntry.vue
index 76825c216f29..7be0fe7bcc90 100644
--- a/packages/ui/client/components/dashboard/TestsEntry.vue
+++ b/packages/ui/client/components/dashboard/TestsEntry.vue
@@ -47,6 +47,18 @@ function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
{{ explorerTree.summary.testsFailed }}
+
+
+ Expected Fail
+
+
+ {{ explorerTree.summary.testsExpectedFail }}
+
+
Date: Fri, 16 Jan 2026 16:51:05 +0000
Subject: [PATCH 3/4] Update getStateString to track expected failures in base
reporter
Co-authored-by: sheremet-va <16173870+sheremet-va@users.noreply.github.com>
---
.../vitest/src/node/reporters/renderers/utils.ts | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/packages/vitest/src/node/reporters/renderers/utils.ts b/packages/vitest/src/node/reporters/renderers/utils.ts
index ce97d6ff5676..29b5c641a2d7 100644
--- a/packages/vitest/src/node/reporters/renderers/utils.ts
+++ b/packages/vitest/src/node/reporters/renderers/utils.ts
@@ -149,15 +149,29 @@ export function getStateString(
return c.dim(`no ${name}`)
}
- const passed = tasks.reduce((acc, i) => i.result?.state === 'pass' ? acc + 1 : acc, 0)
+ const passed = tasks.reduce((acc, i) => {
+ // Exclude expected failures from passed count
+ if (i.result?.state === 'pass' && i.type === 'test' && (i as any).fails) {
+ return acc
+ }
+ return i.result?.state === 'pass' ? acc + 1 : acc
+ }, 0)
const failed = tasks.reduce((acc, i) => i.result?.state === 'fail' ? acc + 1 : acc, 0)
const skipped = tasks.reduce((acc, i) => i.mode === 'skip' ? acc + 1 : acc, 0)
const todo = tasks.reduce((acc, i) => i.mode === 'todo' ? acc + 1 : acc, 0)
+ const expectedFail = tasks.reduce((acc, i) => {
+ // Count tests that are marked as .fails and passed (which means they failed as expected)
+ if (i.result?.state === 'pass' && i.type === 'test' && (i as any).fails) {
+ return acc + 1
+ }
+ return acc
+ }, 0)
return (
[
failed ? c.bold(c.red(`${failed} failed`)) : null,
passed ? c.bold(c.green(`${passed} passed`)) : null,
+ expectedFail ? c.cyan(`${expectedFail} expected fail`) : null,
skipped ? c.yellow(`${skipped} skipped`) : null,
todo ? c.gray(`${todo} todo`) : null,
]
From 7df9d0878f07a993631462a28463f6b4272ec8c6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 21 Jan 2026 18:18:34 +0000
Subject: [PATCH 4/4] Remove type casts and use proper type narrowing for fails
property
Co-authored-by: sheremet-va <16173870+sheremet-va@users.noreply.github.com>
---
packages/vitest/src/node/reporters/renderers/utils.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/vitest/src/node/reporters/renderers/utils.ts b/packages/vitest/src/node/reporters/renderers/utils.ts
index 29b5c641a2d7..fdf7d7c76d0d 100644
--- a/packages/vitest/src/node/reporters/renderers/utils.ts
+++ b/packages/vitest/src/node/reporters/renderers/utils.ts
@@ -151,7 +151,7 @@ export function getStateString(
const passed = tasks.reduce((acc, i) => {
// Exclude expected failures from passed count
- if (i.result?.state === 'pass' && i.type === 'test' && (i as any).fails) {
+ if (i.result?.state === 'pass' && i.type === 'test' && i.fails) {
return acc
}
return i.result?.state === 'pass' ? acc + 1 : acc
@@ -161,7 +161,7 @@ export function getStateString(
const todo = tasks.reduce((acc, i) => i.mode === 'todo' ? acc + 1 : acc, 0)
const expectedFail = tasks.reduce((acc, i) => {
// Count tests that are marked as .fails and passed (which means they failed as expected)
- if (i.result?.state === 'pass' && i.type === 'test' && (i as any).fails) {
+ if (i.result?.state === 'pass' && i.type === 'test' && i.fails) {
return acc + 1
}
return acc