/** * @file BackupSettings.test.tsx * @description Settings → Data → Backup: a save sends only the fields that * changed, "Back up now" is off until a folder is saved, and the newest backup * in the folder is shown. * @author Nguyễn Ngọc Trí Vĩ */ import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { beforeEach, describe, expect, it, vi } from "vitest"; import i18n from "i18next"; const { backup } = vi.hoisted(() => ({ backup: { get: vi.fn(), save: vi.fn(), run: vi.fn() }, })); vi.mock("../../../lib/api", () => ({ api: { settings: { backup } } })); import { BackupSettings } from "../BackupSettings"; const off = { dir: "", hour: 2, keep: 7, running: false, last: null, files: [], dir_error: null, env_owned: { dir: false, hour: false, keep: false }, }; beforeEach(() => { i18n.changeLanguage("en"); vi.clearAllMocks(); }); describe("BackupSettings", () => { it("saves only the folder when only the folder changed, then allows a run", async () => { const user = userEvent.setup(); backup.get.mockResolvedValue(off); backup.save.mockImplementation((p) => Promise.resolve({ ok: true, ...off, ...p })); render(); const run = await screen.findByRole("button", { name: /Back up now/ }); expect(run).toBeDisabled(); expect(screen.getByText("Backups are off.")).toBeInTheDocument(); await user.type(screen.getByLabelText("Backup folder"), "/mnt/hdd/b"); await user.click(screen.getByRole("button", { name: "Save" })); await waitFor(() => expect(backup.save).toHaveBeenCalledWith({ dir: "/mnt/hdd/b" })); await waitFor(() => expect(run).toBeEnabled()); }); it("shows the newest backup", async () => { backup.get.mockResolvedValue({ ...off, dir: "/mnt/hdd/b", files: [ { name: "agenthub-20261008-020000.db", size: 2048, mtime: "2026-10-08T02:00:30Z" }, { name: "agenthub-20261007-020000.db", size: 1024, mtime: "2026-10-07T02:00:30Z" }, ], }); render(); expect(await screen.findByText(/2\.0 KB · 2 kept, 3\.0 KB in all/)).toBeInTheDocument(); }); });