/**
* WidgetGrid Component Tests
* Following TDD - write tests first!
*/
import { describe, it, expect, vi, beforeAll } from "vitest";
import { render, screen } from "@testing-library/react";
import { WidgetGrid } from "../WidgetGrid";
import type { WidgetPlacement } from "@mosaic/shared";
// ResizeObserver is not available in jsdom
beforeAll((): void => {
global.ResizeObserver = vi.fn().mockImplementation(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));
});
// Mock react-grid-layout
vi.mock("react-grid-layout", () => ({
default: ({ children }: { children: React.ReactNode }): React.JSX.Element => (
{children}
),
Responsive: ({ children }: { children: React.ReactNode }): React.JSX.Element => (
{children}
),
}));
describe("WidgetGrid", (): void => {
const mockLayout: WidgetPlacement[] = [
{ i: "tasks-1", x: 0, y: 0, w: 2, h: 2 },
{ i: "calendar-1", x: 2, y: 0, w: 2, h: 2 },
];
const mockOnLayoutChange = vi.fn();
it("should render grid layout", (): void => {
render();
expect(screen.getByTestId("grid-layout")).toBeInTheDocument();
});
it("should render widgets from layout", (): void => {
render();
// Should render correct number of widgets
const widgets = screen.getAllByTestId(/widget-/);
expect(widgets).toHaveLength(mockLayout.length);
});
it("should call onLayoutChange when layout changes", (): void => {
const { rerender } = render(
);
const newLayout: WidgetPlacement[] = [
{ i: "tasks-1", x: 1, y: 0, w: 2, h: 2 },
{ i: "calendar-1", x: 2, y: 0, w: 2, h: 2 },
];
rerender();
// Layout change handler should be set up (actual calls handled by react-grid-layout)
expect(mockOnLayoutChange).toBeDefined();
});
it("should support edit mode", (): void => {
render();
// In edit mode, widgets should have edit controls
expect(screen.getByTestId("grid-layout")).toBeInTheDocument();
});
it("should support read-only mode", (): void => {
render(
);
expect(screen.getByTestId("grid-layout")).toBeInTheDocument();
});
it("should render empty state when no widgets", (): void => {
render();
expect(screen.getByText(/no widgets/i)).toBeInTheDocument();
});
it("should handle widget removal", (): void => {
const mockOnRemoveWidget = vi.fn();
render(
);
// Widget removal should be supported
expect(mockOnRemoveWidget).toBeDefined();
});
it("should apply custom className", (): void => {
const { container } = render(
);
expect(container.querySelector(".custom-grid")).toBeInTheDocument();
});
});