/** * TasksWidget Component Tests * Following TDD principles */ import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import { TasksWidget } from "../TasksWidget"; // Mock fetch for API calls global.fetch = vi.fn(); describe("TasksWidget", () => { beforeEach(() => { vi.clearAllMocks(); }); it("should render loading state initially", () => { (global.fetch as any).mockImplementation(() => new Promise(() => {})); render(); expect(screen.getByText(/loading/i)).toBeInTheDocument(); }); it("should render task statistics", async () => { const mockTasks = [ { id: "1", title: "Task 1", status: "IN_PROGRESS", priority: "HIGH" }, { id: "2", title: "Task 2", status: "COMPLETED", priority: "MEDIUM" }, { id: "3", title: "Task 3", status: "NOT_STARTED", priority: "LOW" }, ]; (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => mockTasks, }); render(); await waitFor(() => { expect(screen.getByText("3")).toBeInTheDocument(); // Total expect(screen.getByText("1")).toBeInTheDocument(); // In Progress expect(screen.getByText("1")).toBeInTheDocument(); // Completed }); }); it("should render task list", async () => { const mockTasks = [ { id: "1", title: "Complete documentation", status: "IN_PROGRESS", priority: "HIGH" }, { id: "2", title: "Review PRs", status: "NOT_STARTED", priority: "MEDIUM" }, ]; (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => mockTasks, }); render(); await waitFor(() => { expect(screen.getByText("Complete documentation")).toBeInTheDocument(); expect(screen.getByText("Review PRs")).toBeInTheDocument(); }); }); it("should handle empty task list", async () => { (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => [], }); render(); await waitFor(() => { expect(screen.getByText(/no tasks/i)).toBeInTheDocument(); }); }); it("should handle API errors gracefully", async () => { (global.fetch as any).mockRejectedValueOnce(new Error("API Error")); render(); await waitFor(() => { expect(screen.getByText(/error/i)).toBeInTheDocument(); }); }); it("should display priority indicators", async () => { const mockTasks = [ { id: "1", title: "High priority task", status: "IN_PROGRESS", priority: "HIGH" }, ]; (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => mockTasks, }); render(); await waitFor(() => { expect(screen.getByText("High priority task")).toBeInTheDocument(); // Priority icon should be rendered (high priority = red) }); }); it("should limit displayed tasks to 5", async () => { const mockTasks = Array.from({ length: 10 }, (_, i) => ({ id: `${i + 1}`, title: `Task ${i + 1}`, status: "NOT_STARTED", priority: "MEDIUM", })); (global.fetch as any).mockResolvedValueOnce({ ok: true, json: async () => mockTasks, }); render(); await waitFor(() => { const taskElements = screen.getAllByText(/Task \d+/); expect(taskElements.length).toBeLessThanOrEqual(5); }); }); });