hyapp-admin-platform/src/features/app-config/hooks/useH5ConfigPage.test.jsx
2026-07-10 20:20:58 +08:00

180 lines
5.0 KiB
JavaScript

import { act, renderHook } from "@testing-library/react";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import { setSelectedAppCode } from "@/shared/api/request";
const mocks = vi.hoisted(() => ({
appCode: "lalu",
confirm: vi.fn(),
createH5Link: vi.fn(),
deleteH5Link: vi.fn(),
listH5Links: vi.fn(),
queryFn: null,
queryOptions: null,
reload: vi.fn(),
showToast: vi.fn(),
updateH5Link: vi.fn()
}));
vi.mock("@/app/app-scope/AppScopeProvider.jsx", () => ({
useAppScope: () => ({ appCode: mocks.appCode })
}));
vi.mock("@/features/app-config/api", () => ({
createH5Link: mocks.createH5Link,
deleteH5Link: mocks.deleteH5Link,
listH5Links: mocks.listH5Links,
updateH5Link: mocks.updateH5Link
}));
vi.mock("@/features/app-config/permissions.js", () => ({
useAppConfigAbilities: () => ({ canUpdate: true, canView: true })
}));
vi.mock("@/shared/hooks/useAdminQuery.js", () => ({
useAdminQuery: (queryFn, options) => {
mocks.queryFn = queryFn;
mocks.queryOptions = options;
return {
data: { items: [], total: 0 },
error: "",
loading: false,
reload: mocks.reload
};
}
}));
vi.mock("@/shared/ui/ConfirmProvider.jsx", () => ({
useConfirm: () => mocks.confirm
}));
vi.mock("@/shared/ui/ToastProvider.jsx", () => ({
useToast: () => ({ showToast: mocks.showToast })
}));
import { useH5ConfigPage } from "./useH5ConfigPage.js";
beforeEach(() => {
mocks.appCode = "lalu";
mocks.confirm.mockResolvedValue(true);
mocks.createH5Link.mockResolvedValue({});
mocks.deleteH5Link.mockResolvedValue({ deleted: true });
mocks.listH5Links.mockResolvedValue({ items: [], total: 0 });
mocks.reload.mockResolvedValue({ items: [], total: 0 });
mocks.updateH5Link.mockResolvedValue({});
setSelectedAppCode("lalu");
});
afterEach(() => {
vi.clearAllMocks();
setSelectedAppCode("lalu");
});
test("uses appCode in the H5 query key and read request", async () => {
const { rerender } = renderHook(() => useH5ConfigPage());
expect(mocks.queryOptions.queryKey).toEqual(["app-config", "h5-links", "lalu"]);
await mocks.queryFn();
expect(mocks.listH5Links).toHaveBeenLastCalledWith("lalu");
mocks.appCode = "huwaa";
setSelectedAppCode("huwaa");
rerender();
expect(mocks.queryOptions.queryKey).toEqual(["app-config", "h5-links", "huwaa"]);
await mocks.queryFn();
expect(mocks.listH5Links).toHaveBeenLastCalledWith("huwaa");
});
test("closes an edit dialog when the selected App changes", () => {
const item = {
appCode: "lalu",
key: "achievement",
label: "成就",
updatedAtMs: 1000,
url: "https://h5.example.com/achievement"
};
const { result, rerender } = renderHook(() => useH5ConfigPage());
act(() => result.current.openEdit(item));
expect(result.current.activeAction).toBe("edit");
mocks.appCode = "huwaa";
setSelectedAppCode("huwaa");
rerender();
expect(result.current.activeAction).toBe("");
expect(result.current.editingItem).toBeNull();
expect(result.current.form).toEqual({ key: "", label: "", url: "" });
});
test("does not submit stale form state after an App switch", async () => {
const { result, rerender } = renderHook(() => useH5ConfigPage());
act(() => {
result.current.openEdit({
appCode: "lalu",
key: "achievement",
label: "成就",
updatedAtMs: 1000,
url: "https://h5.example.com/achievement"
});
});
mocks.appCode = "huwaa";
setSelectedAppCode("huwaa");
rerender();
await act(async () => {
await result.current.submitEdit({ preventDefault: vi.fn() });
});
expect(mocks.createH5Link).not.toHaveBeenCalled();
expect(mocks.updateH5Link).not.toHaveBeenCalled();
expect(mocks.showToast).toHaveBeenCalledWith("应用已切换,请重新操作", "warning");
});
test("pins an update mutation to the App that owns the edited row", async () => {
const { result } = renderHook(() => useH5ConfigPage());
act(() => {
result.current.openEdit({
appCode: "lalu",
key: "achievement",
label: "成就",
updatedAtMs: 1000,
url: "https://h5.example.com/achievement"
});
});
await act(async () => {
await result.current.submitEdit({ preventDefault: vi.fn() });
});
expect(mocks.updateH5Link).toHaveBeenCalledWith("lalu", "achievement", {
key: "achievement",
label: "成就",
url: "https://h5.example.com/achievement"
});
});
test("aborts delete when App changes while confirmation is open", async () => {
let resolveConfirm;
mocks.confirm.mockReturnValue(new Promise((resolve) => {
resolveConfirm = resolve;
}));
const { result, rerender } = renderHook(() => useH5ConfigPage());
let pendingDelete;
act(() => {
pendingDelete = result.current.removeH5Link({ key: "achievement", label: "成就" });
});
mocks.appCode = "huwaa";
setSelectedAppCode("huwaa");
rerender();
await act(async () => {
resolveConfirm(true);
await pendingDelete;
});
expect(mocks.deleteH5Link).not.toHaveBeenCalled();
expect(mocks.showToast).toHaveBeenCalledWith("应用已切换,请重新操作", "warning");
});