fix(#101): Remediate code review findings for TaskProgressWidget
- Fix CRITICAL: Replace .sort() state mutation with [...tasks].sort() - Fix CRITICAL: Replace PDA-unfriendly red colors with calm amber tones - Fix IMPORTANT: Add TaskProgressWidget + ActiveProjectsWidget to WidgetComponentType - Fix IMPORTANT: Add tests for interval cleanup, HTTP error responses, slice limit - 3 new tests added (10 total) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
* TaskProgressWidget Component Tests
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { render, screen, waitFor, cleanup } from "@testing-library/react";
|
||||
import { TaskProgressWidget } from "../TaskProgressWidget";
|
||||
|
||||
const mockFetch = vi.fn();
|
||||
@@ -14,6 +14,10 @@ describe("TaskProgressWidget", (): void => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach((): void => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
it("should render loading state initially", (): void => {
|
||||
mockFetch.mockImplementation(
|
||||
() =>
|
||||
@@ -148,6 +152,62 @@ describe("TaskProgressWidget", (): void => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should display error for non-ok HTTP responses", async (): Promise<void> => {
|
||||
mockFetch.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 500,
|
||||
} as unknown as Response);
|
||||
|
||||
render(<TaskProgressWidget id="task-progress-1" />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/unable to reach orchestrator/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("should clear interval on unmount", async (): Promise<void> => {
|
||||
const clearIntervalSpy = vi.spyOn(global, "clearInterval");
|
||||
|
||||
mockFetch.mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve([]),
|
||||
} as unknown as Response);
|
||||
|
||||
const { unmount } = render(<TaskProgressWidget id="task-progress-1" />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/no agent tasks in progress/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
unmount();
|
||||
|
||||
expect(clearIntervalSpy).toHaveBeenCalled();
|
||||
clearIntervalSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should limit displayed tasks to 10", async (): Promise<void> => {
|
||||
const mockTasks = Array.from({ length: 15 }, (_, i) => ({
|
||||
agentId: `agent-${String(i)}`,
|
||||
taskId: `SLICE-${String(i).padStart(3, "0")}`,
|
||||
status: "running",
|
||||
agentType: "worker",
|
||||
spawnedAt: new Date().toISOString(),
|
||||
}));
|
||||
|
||||
mockFetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: () => Promise.resolve(mockTasks),
|
||||
} as unknown as Response);
|
||||
|
||||
render(<TaskProgressWidget id="task-progress-1" />);
|
||||
|
||||
await waitFor(() => {
|
||||
// Only 10 task cards should be rendered despite 15 tasks
|
||||
const workerBadges = screen.getAllByText("Worker");
|
||||
expect(workerBadges).toHaveLength(10);
|
||||
});
|
||||
});
|
||||
|
||||
it("should sort active tasks before completed ones", async (): Promise<void> => {
|
||||
const mockTasks = [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user