Skip to content

Commit 657fbf2

Browse files
h4x0rclaude
andcommitted
test(export): add failing tests for ExportButton component
8 tests for dropdown toggle, JSON/CSV/Metrics export options. All fail. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a21e456 commit 657fbf2

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RED STUB
2+
import React from "react";
3+
import type { MetricsExport } from "../../lib/export";
4+
5+
interface Props {
6+
metrics?: MetricsExport;
7+
}
8+
9+
export const ExportButton: React.FC<Props> = () => null;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { describe, it, expect, vi, beforeEach } from "vitest";
2+
import { render, screen, fireEvent } from "@testing-library/react";
3+
import { ExportButton } from "../ExportButton";
4+
5+
vi.mock("../../../lib/export", () => ({
6+
exportTasksAsJson: vi.fn().mockReturnValue('{"tasks":[]}'),
7+
exportTasksAsCsv: vi.fn().mockReturnValue("id,title\n"),
8+
exportMetricsAsJson: vi.fn().mockReturnValue('{"metrics":{}}'),
9+
triggerDownload: vi.fn(),
10+
}));
11+
12+
vi.mock("../../../store", () => ({
13+
useStore: vi.fn((selector: (s: { tasks: Record<string, unknown> }) => unknown) => selector({ tasks: {} })),
14+
}));
15+
16+
import { triggerDownload } from "../../../lib/export";
17+
const mockDownload = triggerDownload as ReturnType<typeof vi.fn>;
18+
19+
describe("ExportButton", () => {
20+
beforeEach(() => vi.clearAllMocks());
21+
22+
it("renders Export button", () => {
23+
render(<ExportButton />);
24+
expect(screen.getByText("Export")).toBeInTheDocument();
25+
});
26+
27+
it("shows dropdown on click", () => {
28+
render(<ExportButton />);
29+
fireEvent.click(screen.getByText("Export"));
30+
expect(screen.getByText("Tasks as JSON")).toBeInTheDocument();
31+
expect(screen.getByText("Tasks as CSV")).toBeInTheDocument();
32+
});
33+
34+
it("closes dropdown on second click", () => {
35+
render(<ExportButton />);
36+
fireEvent.click(screen.getByText("Export"));
37+
fireEvent.click(screen.getByText("Export"));
38+
expect(screen.queryByText("Tasks as JSON")).not.toBeInTheDocument();
39+
});
40+
41+
it("calls triggerDownload with JSON when Tasks as JSON clicked", () => {
42+
render(<ExportButton />);
43+
fireEvent.click(screen.getByText("Export"));
44+
fireEvent.click(screen.getByText("Tasks as JSON"));
45+
expect(mockDownload).toHaveBeenCalledWith(expect.any(String), expect.stringContaining(".json"), "application/json");
46+
});
47+
48+
it("calls triggerDownload with CSV when Tasks as CSV clicked", () => {
49+
render(<ExportButton />);
50+
fireEvent.click(screen.getByText("Export"));
51+
fireEvent.click(screen.getByText("Tasks as CSV"));
52+
expect(mockDownload).toHaveBeenCalledWith(expect.any(String), expect.stringContaining(".csv"), "text/csv");
53+
});
54+
55+
it("shows Metrics as JSON option when metrics prop provided", () => {
56+
const metrics = { total_cost_usd: 5, total_tasks: 2, cost_by_agent: {}, cost_by_day: [] };
57+
render(<ExportButton metrics={metrics} />);
58+
fireEvent.click(screen.getByText("Export"));
59+
expect(screen.getByText("Metrics as JSON")).toBeInTheDocument();
60+
});
61+
62+
it("hides Metrics as JSON option when no metrics prop", () => {
63+
render(<ExportButton />);
64+
fireEvent.click(screen.getByText("Export"));
65+
expect(screen.queryByText("Metrics as JSON")).not.toBeInTheDocument();
66+
});
67+
68+
it("calls triggerDownload when Metrics as JSON clicked", () => {
69+
const metrics = { total_cost_usd: 5, total_tasks: 2, cost_by_agent: {}, cost_by_day: [] };
70+
render(<ExportButton metrics={metrics} />);
71+
fireEvent.click(screen.getByText("Export"));
72+
fireEvent.click(screen.getByText("Metrics as JSON"));
73+
expect(mockDownload).toHaveBeenCalledWith(expect.any(String), expect.stringContaining(".json"), "application/json");
74+
});
75+
});

0 commit comments

Comments
 (0)