feat(web): authoring query/mutation hooks + MSW handlers + shadcn select/checkbox/alert-dialog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { renderHook, waitFor } from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import {
|
||||
useAuthorities,
|
||||
useCreateObject,
|
||||
useDeleteObject,
|
||||
useSetFields,
|
||||
useTerms,
|
||||
useUpdateObject,
|
||||
} from "./queries";
|
||||
|
||||
function wrapper({ children }: { children: ReactNode }) {
|
||||
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
|
||||
return <QueryClientProvider client={qc}>{children}</QueryClientProvider>;
|
||||
}
|
||||
|
||||
describe("authoring hooks", () => {
|
||||
test("useTerms loads a vocabulary's terms", async () => {
|
||||
const { result } = renderHook(() => useTerms("v-material"), { wrapper });
|
||||
|
||||
await waitFor(() => expect(result.current.data).toBeDefined());
|
||||
expect(result.current.data?.[0].id).toBe("t-bronze");
|
||||
});
|
||||
|
||||
test("useAuthorities loads by kind", async () => {
|
||||
const { result } = renderHook(() => useAuthorities("person"), { wrapper });
|
||||
|
||||
await waitFor(() => expect(result.current.data?.length).toBe(1));
|
||||
expect(result.current.data?.[0].id).toBe("a-ada");
|
||||
});
|
||||
|
||||
test("useCreateObject returns the new id", async () => {
|
||||
const { result } = renderHook(() => useCreateObject(), { wrapper });
|
||||
|
||||
const created = await result.current.mutateAsync({
|
||||
object_number: "A-1",
|
||||
object_name: "x",
|
||||
number_of_objects: 1,
|
||||
visibility: "draft",
|
||||
});
|
||||
|
||||
expect(created.id).toBe("11111111-1111-1111-1111-111111111111");
|
||||
});
|
||||
|
||||
test("useSetFields / useUpdateObject / useDeleteObject resolve", async () => {
|
||||
const setFields = renderHook(() => useSetFields(), { wrapper });
|
||||
|
||||
await setFields.result.current.mutateAsync({ id: "o1", fields: { inscription: "hi" } });
|
||||
|
||||
const update = renderHook(() => useUpdateObject(), { wrapper });
|
||||
|
||||
await update.result.current.mutateAsync({
|
||||
id: "o1",
|
||||
body: { object_number: "A-1", object_name: "x", number_of_objects: 1 },
|
||||
});
|
||||
|
||||
const del = renderHook(() => useDeleteObject(), { wrapper });
|
||||
|
||||
await del.result.current.mutateAsync("o1");
|
||||
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -95,3 +95,107 @@ export function useLogout() {
|
||||
onSuccess: () => qc.setQueryData(["me"], null),
|
||||
});
|
||||
}
|
||||
|
||||
type ObjectCreateRequest = components["schemas"]["ObjectCreateRequest"];
|
||||
type ObjectUpdateRequest = components["schemas"]["ObjectUpdateRequest"];
|
||||
|
||||
export function useTerms(vocabularyId: string | null | undefined) {
|
||||
return useQuery({
|
||||
queryKey: ["terms", vocabularyId],
|
||||
enabled: !!vocabularyId,
|
||||
queryFn: async () => {
|
||||
const { data, error } = await api.GET("/api/admin/vocabularies/{id}/terms", {
|
||||
params: { path: { id: vocabularyId! } },
|
||||
});
|
||||
|
||||
if (error || !data) throw new Error("failed to load terms");
|
||||
|
||||
return data;
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useAuthorities(kind: string | null | undefined) {
|
||||
return useQuery({
|
||||
queryKey: ["authorities", kind],
|
||||
enabled: !!kind,
|
||||
queryFn: async () => {
|
||||
const { data, error } = await api.GET("/api/admin/authorities", {
|
||||
params: { query: { kind: kind! } },
|
||||
});
|
||||
|
||||
if (error || !data) throw new Error("failed to load authorities");
|
||||
|
||||
return data;
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateObject() {
|
||||
const qc = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (body: ObjectCreateRequest) => {
|
||||
const { data, error } = await api.POST("/api/admin/objects", { body });
|
||||
|
||||
if (error || !data) throw new Error("create failed");
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["objects"] }),
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateObject() {
|
||||
const qc = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ id, body }: { id: string; body: ObjectUpdateRequest }) => {
|
||||
const { response } = await api.PUT("/api/admin/objects/{id}", {
|
||||
params: { path: { id } },
|
||||
body,
|
||||
});
|
||||
|
||||
if (response.status !== 204) throw new Error("update failed");
|
||||
},
|
||||
onSuccess: (_d, { id }) => {
|
||||
void qc.invalidateQueries({ queryKey: ["objects"] });
|
||||
void qc.invalidateQueries({ queryKey: ["object", id] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useSetFields() {
|
||||
const qc = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ id, fields }: { id: string; fields: Record<string, unknown> }) => {
|
||||
const { response } = await api.PUT("/api/admin/objects/{id}/fields", {
|
||||
params: { path: { id } },
|
||||
body: fields as Record<string, never>,
|
||||
});
|
||||
|
||||
if (response.status !== 204) throw new Error("set fields failed");
|
||||
},
|
||||
onSuccess: (_d, { id }) => {
|
||||
void qc.invalidateQueries({ queryKey: ["object", id] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteObject() {
|
||||
const qc = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { response } = await api.DELETE("/api/admin/objects/{id}", {
|
||||
params: { path: { id } },
|
||||
});
|
||||
|
||||
if (response.status !== 204) throw new Error("delete failed");
|
||||
},
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["objects"] }),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user