fix(downloads): the quota editor opens at once and says it is loading or failed
It rendered nothing until its quota arrived and nothing at all when the load failed, so the click looked dead. The first field still takes focus when the form arrives.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// @vitest-environment jsdom
|
||||
//
|
||||
// E32 S2: the admin's download-quota editor rendered NOTHING while its quota loaded and nothing when
|
||||
// the load failed, so the click looked dead. It now opens at once and says which it is. The save
|
||||
// turns the GB field back into bytes; the reset drops the override.
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import type { ReactNode } from "react";
|
||||
import { api } from "../lib/api";
|
||||
import { QuotaModal } from "./downloadAdmin";
|
||||
|
||||
vi.mock("react-i18next", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react-i18next")>();
|
||||
return {
|
||||
...actual,
|
||||
useTranslation: () => ({ t: (key: string) => key, i18n: { language: "en" } }),
|
||||
};
|
||||
});
|
||||
|
||||
const GiB = 1024 ** 3;
|
||||
const QUOTA = { max_bytes: 5 * GiB, max_jobs: 10, max_concurrent: 2, unlimited: false };
|
||||
let qc: QueryClient;
|
||||
const wrap = (ui: ReactNode) => <QueryClientProvider client={qc}>{ui}</QueryClientProvider>;
|
||||
const open = (onClose = () => {}) =>
|
||||
render(wrap(<QuotaModal userId={4} email="a@b.c" onClose={onClose} />));
|
||||
|
||||
beforeEach(() => {
|
||||
qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
});
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe("the download-quota editor", () => {
|
||||
it("opens at once and says it is loading", () => {
|
||||
vi.spyOn(api, "adminGetDownloadQuota").mockReturnValue(new Promise(() => {}) as never);
|
||||
open();
|
||||
expect(screen.getByText("downloads.admin.quotaTitle")).toBeTruthy();
|
||||
expect(screen.getAllByRole("status").length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("says a failed load failed, and retries it", async () => {
|
||||
const get = vi
|
||||
.spyOn(api, "adminGetDownloadQuota")
|
||||
.mockRejectedValueOnce(new Error("down"))
|
||||
.mockResolvedValueOnce(QUOTA as never);
|
||||
open();
|
||||
expect((await screen.findByRole("alert")).textContent).toContain("common.loadError");
|
||||
fireEvent.click(screen.getByText("common.retry"));
|
||||
await screen.findByDisplayValue("5");
|
||||
expect(get).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("saves the GB field as bytes, and the reset drops the override", async () => {
|
||||
vi.spyOn(api, "adminGetDownloadQuota").mockResolvedValue(QUOTA as never);
|
||||
const set = vi.spyOn(api, "adminSetDownloadQuota").mockResolvedValue(QUOTA as never);
|
||||
const reset = vi.spyOn(api, "adminResetDownloadQuota").mockResolvedValue(QUOTA as never);
|
||||
const onClose = vi.fn();
|
||||
open(onClose);
|
||||
fireEvent.change(await screen.findByDisplayValue("5"), { target: { value: "1.5" } });
|
||||
fireEvent.click(screen.getByText("downloads.admin.save"));
|
||||
await waitFor(() => expect(onClose).toHaveBeenCalledTimes(1));
|
||||
expect(set).toHaveBeenCalledWith(4, {
|
||||
max_bytes: Math.round(1.5 * GiB),
|
||||
max_jobs: 10,
|
||||
max_concurrent: 2,
|
||||
unlimited: false,
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByText("downloads.admin.reset"));
|
||||
await waitFor(() => expect(reset).toHaveBeenCalledWith(4));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user