import { describe, it, expect, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import BackupJobsTable from "../BackupJobsTable"; import type { BackupJob, BackupRun } from "../../types/backups"; function job(overrides: Partial = {}): BackupJob { return { id: "j1", name: "nightly", source: "/data", target: "s3://bucket", schedule_interval_seconds: 86400, created_at: 1_700_000_000, ...overrides, }; } function run(overrides: Partial = {}): BackupRun { return { id: "r1", job_id: "j1", started_at: 1_700_000_000, ended_at: null, status: "success", bytes_transferred: 2048, duration_ms: 1500, error_message: null, details_json: null, created_at: 1_700_000_000, ...overrides, }; } // jsdom lacks matchMedia; default to desktop so the table renders. function setMatchMedia(matches: boolean) { window.matchMedia = ((query: string) => ({ matches: query.includes("768") ? matches : false, media: query, onchange: null, addEventListener: () => {}, removeEventListener: () => {}, addListener: () => {}, removeListener: () => {}, dispatchEvent: () => false, })) as unknown as typeof window.matchMedia; } beforeEach(() => setMatchMedia(false)); describe("BackupJobsTable (desktop)", () => { it("renders job name and schedule interval", () => { render( , ); expect(screen.getByText("nightly")).toBeInTheDocument(); expect(screen.getByText("1d")).toBeInTheDocument(); }); }); describe("BackupJobsTable (mobile card layout — slice 5)", () => { it("renders cards with job name as primary below md", () => { setMatchMedia(true); render( } />, ); expect(screen.getByText("nightly")).toBeInTheDocument(); expect(screen.getAllByText("Source")).toHaveLength(1); expect(screen.getAllByText("Schedule")).toHaveLength(1); expect(screen.getAllByText("Last status")).toHaveLength(1); }); });