diff --git a/apps/web/app/(dashboard)/issues/[id]/page.test.tsx b/apps/web/app/(dashboard)/issues/[id]/page.test.tsx index 1bccf306..e4fa7515 100644 --- a/apps/web/app/(dashboard)/issues/[id]/page.test.tsx +++ b/apps/web/app/(dashboard)/issues/[id]/page.test.tsx @@ -63,34 +63,11 @@ vi.mock("@/features/workspace", () => ({ }), })); -// Mock issue store — supply a stable full issue object so storeIssue -// doesn't create a new reference each render (avoids infinite effect loop) -// and has all required fields for rendering. -const stableStoreIssues = vi.hoisted(() => [ - { - id: "issue-1", - workspace_id: "ws-1", - number: 1, - identifier: "TES-1", - title: "Implement authentication", - description: "Add JWT auth to the backend", - status: "in_progress", - priority: "high", - assignee_type: "member", - assignee_id: "user-1", - creator_type: "member", - creator_id: "user-1", - parent_issue_id: null, - position: 0, - due_date: "2026-06-01T00:00:00Z", - created_at: "2026-01-15T00:00:00Z", - updated_at: "2026-01-20T00:00:00Z", - }, -]); +// Mock issue store — only client state remains (activeIssueId) vi.mock("@/features/issues", () => ({ useIssueStore: Object.assign( - (selector: (s: any) => any) => selector({ issues: stableStoreIssues }), - { getState: () => ({ issues: stableStoreIssues, addIssue: vi.fn(), updateIssue: vi.fn(), removeIssue: vi.fn() }) }, + (selector: (s: any) => any) => selector({ activeIssueId: null }), + { getState: () => ({ activeIssueId: null, setActiveIssue: vi.fn() }) }, ), })); diff --git a/apps/web/app/(dashboard)/issues/page.test.tsx b/apps/web/app/(dashboard)/issues/page.test.tsx index d307602d..261287fc 100644 --- a/apps/web/app/(dashboard)/issues/page.test.tsx +++ b/apps/web/app/(dashboard)/issues/page.test.tsx @@ -71,28 +71,19 @@ vi.mock("@/shared/api", () => ({ }, })); -// Mock the issue store -let mockStoreState: { - issues: Issue[]; - loading: boolean; - fetch: () => Promise; - setIssues: (issues: Issue[]) => void; - addIssue: (issue: Issue) => void; - updateIssue: (id: string, updates: Partial) => void; - removeIssue: (id: string) => void; -}; - +// Mock issue store — only client state remains +const mockIssueClientState = { activeIssueId: null, setActiveIssue: vi.fn() }; vi.mock("@/features/issues/store", () => ({ useIssueStore: Object.assign( - (selector?: any) => (selector ? selector(mockStoreState) : mockStoreState), - { getState: () => mockStoreState }, + (selector?: any) => (selector ? selector(mockIssueClientState) : mockIssueClientState), + { getState: () => mockIssueClientState }, ), })); vi.mock("@/features/issues", () => ({ useIssueStore: Object.assign( - (selector?: any) => (selector ? selector(mockStoreState) : mockStoreState), - { getState: () => mockStoreState }, + (selector?: any) => (selector ? selector(mockIssueClientState) : mockIssueClientState), + { getState: () => mockIssueClientState }, ), StatusIcon: () => null, PriorityIcon: () => null, @@ -292,30 +283,18 @@ function renderWithQuery(ui: React.ReactElement) { describe("IssuesPage", () => { beforeEach(() => { vi.clearAllMocks(); - mockStoreState = { - issues: [], - loading: true, - fetch: vi.fn(), - setIssues: vi.fn(), - addIssue: vi.fn(), - updateIssue: vi.fn(), - removeIssue: vi.fn(), - }; + mockListIssues.mockResolvedValue({ issues: [], total: 0 }); mockViewState.viewMode = "board"; mockViewState.statusFilters = []; mockViewState.priorityFilters = []; }); it("shows loading state initially", () => { - mockStoreState.loading = true; - mockStoreState.issues = []; renderWithQuery(); expect(screen.getAllByRole("generic").some(el => el.getAttribute("data-slot") === "skeleton")).toBe(true); }); it("renders issues in board view after loading", async () => { - mockStoreState.loading = false; - mockStoreState.issues = mockIssues; mockListIssues.mockResolvedValue({ issues: mockIssues, total: mockIssues.length }); renderWithQuery(); @@ -326,8 +305,6 @@ describe("IssuesPage", () => { }); it("renders board columns", async () => { - mockStoreState.loading = false; - mockStoreState.issues = mockIssues; mockListIssues.mockResolvedValue({ issues: mockIssues, total: mockIssues.length }); renderWithQuery(); @@ -340,18 +317,12 @@ describe("IssuesPage", () => { }); it("shows workspace breadcrumb", async () => { - mockStoreState.loading = false; - mockStoreState.issues = []; - renderWithQuery(); await screen.findByText("Issues"); }); it("shows scope buttons", async () => { - mockStoreState.loading = false; - mockStoreState.issues = []; - renderWithQuery(); await screen.findByText("All"); @@ -360,8 +331,6 @@ describe("IssuesPage", () => { }); it("shows filter and display icon buttons", async () => { - mockStoreState.loading = false; - mockStoreState.issues = mockIssues; mockListIssues.mockResolvedValue({ issues: mockIssues, total: mockIssues.length }); renderWithQuery(); @@ -373,9 +342,6 @@ describe("IssuesPage", () => { }); it("shows empty board view when no issues exist", () => { - mockStoreState.loading = false; - mockStoreState.issues = []; - renderWithQuery(); // Should still render the board/list view, not a "no issues" message