Skip to content

Commit 2539a97

Browse files
author
Zoo (VP)
committed
fix(test): resolve PR #1134 visual test timeout and codecov coverage gap
- Move data-testid in ProviderBreakdownFixture from outer div to table (Playwright CT cannot find data-testid on root-level mount element) - Add CI-generated baseline screenshots for StatsPanel visual tests - Add 5 coverage tests for handleRebuildUsageStats and handleGetDashboardTaskDetail error branches (79.86% -> 80%+)
1 parent b94d91d commit 2539a97

5 files changed

Lines changed: 160 additions & 2 deletions

File tree

src/core/webview/__tests__/usageStatsMessageHandler.spec.ts

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
handleGetUsageStats,
4545
handleClearUsageStats,
4646
handleExportUsageStats,
47+
handleRebuildUsageStats,
4748
handleRequestClearNonce,
4849
handleGetDashboardSessions,
4950
handleGetDashboardSessionDetail,
@@ -1688,6 +1689,98 @@ describe("usageStatsMessageHandler", () => {
16881689
})
16891690
})
16901691

1692+
// ── handleRebuildUsageStats ───────────────────────────────────────────────
1693+
1694+
describe("handleRebuildUsageStats", () => {
1695+
it("rebuilds rollups and posts success result", async () => {
1696+
const rebuildRollupsFromEvents = vi.fn()
1697+
const getDatabase = vi.fn(() => ({ rebuildRollupsFromEvents }))
1698+
const provider = createMockProvider({ getDatabase } as any)
1699+
1700+
const message: WebviewMessage = {
1701+
type: "rebuildUsageStats",
1702+
requestId: "req-rebuild-1",
1703+
}
1704+
1705+
await handleRebuildUsageStats(provider, message)
1706+
1707+
expect(rebuildRollupsFromEvents).toHaveBeenCalledTimes(1)
1708+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1709+
type: "usageStatsChanged",
1710+
})
1711+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1712+
type: "rebuildUsageStatsResponse",
1713+
requestId: "req-rebuild-1",
1714+
rebuildUsageStatsResult: { success: true },
1715+
})
1716+
})
1717+
1718+
it("returns error when service is unavailable", async () => {
1719+
const provider = createMockProvider(undefined)
1720+
1721+
const message: WebviewMessage = {
1722+
type: "rebuildUsageStats",
1723+
requestId: "req-rebuild-2",
1724+
}
1725+
1726+
await handleRebuildUsageStats(provider, message)
1727+
1728+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1729+
type: "rebuildUsageStatsResponse",
1730+
requestId: "req-rebuild-2",
1731+
rebuildUsageStatsResult: {
1732+
success: false,
1733+
error: expect.stringContaining("STATS_HANDLER/rebuild/002"),
1734+
},
1735+
})
1736+
})
1737+
1738+
it("returns error when database is not initialized", async () => {
1739+
const getDatabase = vi.fn(() => null)
1740+
const provider = createMockProvider({ getDatabase } as any)
1741+
1742+
const message: WebviewMessage = {
1743+
type: "rebuildUsageStats",
1744+
requestId: "req-rebuild-3",
1745+
}
1746+
1747+
await handleRebuildUsageStats(provider, message)
1748+
1749+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1750+
type: "rebuildUsageStatsResponse",
1751+
requestId: "req-rebuild-3",
1752+
rebuildUsageStatsResult: {
1753+
success: false,
1754+
error: expect.stringContaining("STATS_HANDLER/rebuild/001"),
1755+
},
1756+
})
1757+
})
1758+
1759+
it("returns error when rebuild throws", async () => {
1760+
const rebuildRollupsFromEvents = vi.fn(() => {
1761+
throw new Error("disk full")
1762+
})
1763+
const getDatabase = vi.fn(() => ({ rebuildRollupsFromEvents }))
1764+
const provider = createMockProvider({ getDatabase } as any)
1765+
1766+
const message: WebviewMessage = {
1767+
type: "rebuildUsageStats",
1768+
requestId: "req-rebuild-4",
1769+
}
1770+
1771+
await handleRebuildUsageStats(provider, message)
1772+
1773+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1774+
type: "rebuildUsageStatsResponse",
1775+
requestId: "req-rebuild-4",
1776+
rebuildUsageStatsResult: {
1777+
success: false,
1778+
error: expect.stringContaining("STATS_HANDLER/rebuild/003"),
1779+
},
1780+
})
1781+
})
1782+
})
1783+
16911784
// ── History-first Dashboard task handlers ──────────────────────────────────
16921785

16931786
describe("handleGetDashboardTaskDetail", () => {
@@ -1766,6 +1859,71 @@ describe("usageStatsMessageHandler", () => {
17661859
toMs: Date.parse("2026-08-15T00:00:00.000Z"),
17671860
})
17681861
})
1862+
1863+
it("returns error when taskId is missing", async () => {
1864+
const provider = createMockProvider({ getDatabase: () => null } as any)
1865+
1866+
await handleGetDashboardTaskDetail(provider, {
1867+
type: "getDashboardTaskDetail",
1868+
requestId: "task-detail-missing",
1869+
// No taskId or text
1870+
})
1871+
1872+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1873+
type: "dashboardTaskDetailResponse",
1874+
requestId: "task-detail-missing",
1875+
dashboardTaskDetail: null,
1876+
error: expect.stringContaining("STATS_HANDLER/taskDetail/001"),
1877+
})
1878+
})
1879+
1880+
it("returns error when database or task catalog is unavailable", async () => {
1881+
const provider = createMockProvider({
1882+
getDatabase: () => null,
1883+
getTaskCatalog: () => null,
1884+
} as any)
1885+
1886+
await handleGetDashboardTaskDetail(provider, {
1887+
type: "getDashboardTaskDetail",
1888+
requestId: "task-detail-unavailable",
1889+
taskId: "root",
1890+
})
1891+
1892+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1893+
type: "dashboardTaskDetailResponse",
1894+
requestId: "task-detail-unavailable",
1895+
dashboardTaskDetail: null,
1896+
error: expect.stringContaining("STATS_HANDLER/taskDetail/002"),
1897+
})
1898+
})
1899+
1900+
it("returns error when the projection throws", async () => {
1901+
const mockDb = createMockDatabase()
1902+
const taskCatalog = {
1903+
byId: new Map([["root", { id: "root", task: "History root", ts: 123 }]]),
1904+
getDescendantTaskIds: vi.fn(() => {
1905+
throw new Error("catalog corrupted")
1906+
}),
1907+
}
1908+
const provider = createMockProvider({
1909+
getDatabase: () => mockDb,
1910+
getTaskCatalog: () => taskCatalog,
1911+
getCoordinator: () => null,
1912+
} as any)
1913+
1914+
await handleGetDashboardTaskDetail(provider, {
1915+
type: "getDashboardTaskDetail",
1916+
requestId: "task-detail-throw",
1917+
taskId: "root",
1918+
})
1919+
1920+
expect(provider.postMessageToWebview).toHaveBeenCalledWith({
1921+
type: "dashboardTaskDetailResponse",
1922+
requestId: "task-detail-throw",
1923+
dashboardTaskDetail: null,
1924+
error: expect.stringContaining("STATS_HANDLER/taskDetail/003"),
1925+
})
1926+
})
17691927
})
17701928

17711929
describe("handleGetDashboardTaskPage", () => {

webview-ui/src/components/dashboard/__tests__/StatsPanel.visual.fixture.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ export const ProviderBreakdownFixture = () => {
9393
]
9494

9595
return (
96-
<div style={{ width: 480, padding: 8 }} data-testid="provider-breakdown">
97-
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}>
96+
<div style={{ width: 480, padding: 8 }}>
97+
<table data-testid="provider-breakdown" style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}>
9898
<thead>
9999
<tr style={{ textAlign: "left", opacity: 0.7 }}>
100100
<th style={{ padding: "4px 8px" }}>Provider</th>
9.27 KB
Loading
3.7 KB
Loading
9.51 KB
Loading

0 commit comments

Comments
 (0)