Skip to content

Commit 7efa7bf

Browse files
awaliuddinclaude
andcommitted
fix: Resolve all 8 failing tests and test suite hanging
- Mock apiFetch module instead of global.fetch in 3 test files (useForgeCommands, GovernanceHUD, ContextWindowHUD) after apiFetch migration - Fix activity-service subscriber error test to verify behavior instead of checking console.error (service uses structured logger) - Add compliance-service.ts to frontend-health server-side allowlist - Add destroy() method to AgentCoordinationProtocol to clean up setInterval - Add null guards to ProjectContextCard and BlockingDecisionsCard for mismatched API response shapes - Fix smoke integration test worker hang with detached process group kill Result: 64 files pass, 1953 tests pass, 0 failures, clean exit. Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent a6b58bf commit 7efa7bf

10 files changed

Lines changed: 130 additions & 103 deletions

File tree

src/components/governance/BlockingDecisionsCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export const BlockingDecisionsCard: React.FC<{ className?: string }> = ({
101101
};
102102
}, []);
103103

104-
if (!data) return null;
104+
if (!data || !data.summary) return null;
105105

106106
const { blockedWorkstreams, actionItems, pendingDecisions, summary } = data;
107107
const totalIssues =

src/components/governance/ProjectContextCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export const ProjectContextCard: React.FC<{ className?: string }> = ({
103103
};
104104
}, []);
105105

106-
if (!ctx) return null;
106+
if (!ctx || !ctx.tests || !ctx.health) return null;
107107

108108
const { git, tests, health } = ctx;
109109
const totalTests = tests.passing + tests.failing + tests.skipped;

src/components/governance/__tests__/GovernanceHUD.test.tsx

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,18 @@ vi.mock("../AgentActivityFeed", () => ({
8080
),
8181
}));
8282

83+
// Mock apiFetch module
84+
vi.mock("../../../utils/api-fetch", () => ({
85+
apiFetch: vi.fn(),
86+
}));
87+
8388
// Import after mocks are set up
8489
import { GovernanceHUD } from "../GovernanceHUD";
90+
import { apiFetch } from "../../../utils/api-fetch";
91+
92+
const mockApiFetch = apiFetch as ReturnType<typeof vi.fn>;
8593

8694
describe("GovernanceHUD", () => {
87-
let mockFetch: ReturnType<typeof vi.fn>;
8895
let stateChangeHandler: ((state: WSConnectionState) => void) | null = null;
8996
let governanceUpdateHandler: ((data: any) => void) | null = null;
9097

@@ -127,10 +134,6 @@ describe("GovernanceHUD", () => {
127134
stateChangeHandler = null;
128135
governanceUpdateHandler = null;
129136

130-
// Mock fetch
131-
mockFetch = vi.fn();
132-
global.fetch = mockFetch;
133-
134137
// Clear mock calls
135138
vi.clearAllMocks();
136139

@@ -166,7 +169,7 @@ describe("GovernanceHUD", () => {
166169

167170
describe("Loading State", () => {
168171
test("shows loading state initially", async () => {
169-
mockFetch.mockImplementation(
172+
mockApiFetch.mockImplementation(
170173
() =>
171174
new Promise(() => {
172175
/* never resolves */
@@ -180,7 +183,7 @@ describe("GovernanceHUD", () => {
180183
});
181184

182185
test("shows loading spinner", async () => {
183-
mockFetch.mockImplementation(
186+
mockApiFetch.mockImplementation(
184187
() =>
185188
new Promise(() => {
186189
/* never resolves */
@@ -196,7 +199,7 @@ describe("GovernanceHUD", () => {
196199

197200
describe("Error State", () => {
198201
test("shows error state on fetch failure", async () => {
199-
mockFetch.mockRejectedValueOnce(new Error("Network error"));
202+
mockApiFetch.mockRejectedValueOnce(new Error("Network error"));
200203

201204
render(<GovernanceHUD />);
202205

@@ -206,7 +209,7 @@ describe("GovernanceHUD", () => {
206209
});
207210

208211
test("displays error message", async () => {
209-
mockFetch.mockRejectedValueOnce(new Error("API unavailable"));
212+
mockApiFetch.mockRejectedValueOnce(new Error("API unavailable"));
210213

211214
render(<GovernanceHUD />);
212215

@@ -217,7 +220,7 @@ describe("GovernanceHUD", () => {
217220
});
218221

219222
test("shows error state on API error response", async () => {
220-
mockFetch.mockResolvedValueOnce({
223+
mockApiFetch.mockResolvedValueOnce({
221224
ok: false,
222225
status: 500,
223226
text: async () => "Internal Server Error",
@@ -234,7 +237,7 @@ describe("GovernanceHUD", () => {
234237

235238
describe("Data Fetching", () => {
236239
test("fetches governance state on mount", async () => {
237-
mockFetch.mockResolvedValueOnce({
240+
mockApiFetch.mockResolvedValueOnce({
238241
ok: true,
239242
json: async () => ({
240243
success: true,
@@ -245,12 +248,12 @@ describe("GovernanceHUD", () => {
245248
render(<GovernanceHUD />);
246249

247250
await waitFor(() => {
248-
expect(mockFetch).toHaveBeenCalledWith("/api/governance/state");
251+
expect(mockApiFetch).toHaveBeenCalledWith("/api/governance/state");
249252
});
250253
});
251254

252255
test("renders governance state after successful fetch", async () => {
253-
mockFetch.mockResolvedValueOnce({
256+
mockApiFetch.mockResolvedValueOnce({
254257
ok: true,
255258
json: async () => ({
256259
success: true,
@@ -266,7 +269,7 @@ describe("GovernanceHUD", () => {
266269
});
267270

268271
test("handles response without data property", async () => {
269-
mockFetch.mockResolvedValueOnce({
272+
mockApiFetch.mockResolvedValueOnce({
270273
ok: true,
271274
json: async () => ({
272275
success: true,
@@ -285,7 +288,7 @@ describe("GovernanceHUD", () => {
285288

286289
describe("Header", () => {
287290
test("displays header with title", async () => {
288-
mockFetch.mockResolvedValueOnce({
291+
mockApiFetch.mockResolvedValueOnce({
289292
ok: true,
290293
json: async () => ({
291294
success: true,
@@ -301,7 +304,7 @@ describe("GovernanceHUD", () => {
301304
});
302305

303306
test("shows connecting status initially", async () => {
304-
mockFetch.mockResolvedValueOnce({
307+
mockApiFetch.mockResolvedValueOnce({
305308
ok: true,
306309
json: async () => ({
307310
success: true,
@@ -317,7 +320,7 @@ describe("GovernanceHUD", () => {
317320
});
318321

319322
test("displays connection status indicator", async () => {
320-
mockFetch.mockResolvedValueOnce({
323+
mockApiFetch.mockResolvedValueOnce({
321324
ok: true,
322325
json: async () => ({
323326
success: true,
@@ -336,7 +339,7 @@ describe("GovernanceHUD", () => {
336339

337340
describe("Sub-components Rendering", () => {
338341
beforeEach(async () => {
339-
mockFetch.mockResolvedValueOnce({
342+
mockApiFetch.mockResolvedValueOnce({
340343
ok: true,
341344
json: async () => ({
342345
success: true,
@@ -402,7 +405,7 @@ describe("GovernanceHUD", () => {
402405
test("component renders and uses wsManager (integration)", async () => {
403406
// This test verifies that the component successfully integrates with wsManager
404407
// The refactored component no longer creates its own WebSocket but delegates to wsManager
405-
mockFetch.mockResolvedValueOnce({
408+
mockApiFetch.mockResolvedValueOnce({
406409
ok: true,
407410
json: async () => ({
408411
success: true,
@@ -421,7 +424,7 @@ describe("GovernanceHUD", () => {
421424
});
422425

423426
test("updates to connected status when wsManager connects", async () => {
424-
mockFetch.mockResolvedValueOnce({
427+
mockApiFetch.mockResolvedValueOnce({
425428
ok: true,
426429
json: async () => ({
427430
success: true,
@@ -465,7 +468,7 @@ describe("GovernanceHUD", () => {
465468
});
466469

467470
test("handles governance state updates", async () => {
468-
mockFetch.mockResolvedValueOnce({
471+
mockApiFetch.mockResolvedValueOnce({
469472
ok: true,
470473
json: async () => ({
471474
success: true,
@@ -485,7 +488,7 @@ describe("GovernanceHUD", () => {
485488

486489
test("component lifecycle management", async () => {
487490
// Verifies that component mounts and unmounts cleanly with wsManager integration
488-
mockFetch.mockResolvedValueOnce({
491+
mockApiFetch.mockResolvedValueOnce({
489492
ok: true,
490493
json: async () => ({
491494
success: true,
@@ -507,7 +510,7 @@ describe("GovernanceHUD", () => {
507510

508511
describe("WebSocket Reconnection", () => {
509512
test("shows connecting status during reconnection", async () => {
510-
mockFetch.mockResolvedValueOnce({
513+
mockApiFetch.mockResolvedValueOnce({
511514
ok: true,
512515
json: async () => ({
513516
success: true,
@@ -536,7 +539,7 @@ describe("GovernanceHUD", () => {
536539
});
537540

538541
test("shows connecting for multiple reconnection attempts", async () => {
539-
mockFetch.mockResolvedValueOnce({
542+
mockApiFetch.mockResolvedValueOnce({
540543
ok: true,
541544
json: async () => ({
542545
success: true,
@@ -578,7 +581,7 @@ describe("GovernanceHUD", () => {
578581
});
579582

580583
test("shows fallback status after max reconnect attempts", async () => {
581-
mockFetch.mockResolvedValueOnce({
584+
mockApiFetch.mockResolvedValueOnce({
582585
ok: true,
583586
json: async () => ({
584587
success: true,
@@ -632,7 +635,7 @@ describe("GovernanceHUD", () => {
632635

633636
describe("Fallback Status Display", () => {
634637
test("shows initial connecting status", async () => {
635-
mockFetch.mockResolvedValue({
638+
mockApiFetch.mockResolvedValue({
636639
ok: true,
637640
json: async () => ({
638641
success: true,
@@ -653,7 +656,7 @@ describe("GovernanceHUD", () => {
653656
test("component displays appropriate status based on wsManager state", async () => {
654657
// The refactored component relies on wsManager for all connection logic.
655658
// It displays status but doesn't implement connection/polling itself.
656-
mockFetch.mockResolvedValue({
659+
mockApiFetch.mockResolvedValue({
657660
ok: true,
658661
json: async () => ({
659662
success: true,
@@ -698,7 +701,7 @@ describe("GovernanceHUD", () => {
698701

699702
describe("Custom className", () => {
700703
test("applies custom className prop", async () => {
701-
mockFetch.mockResolvedValueOnce({
704+
mockApiFetch.mockResolvedValueOnce({
702705
ok: true,
703706
json: async () => ({
704707
success: true,

0 commit comments

Comments
 (0)