feat(web): useCreateFieldDefinition mutation + MSW handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
import { expect, test } from "vitest";
|
||||||
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
import { renderHook, waitFor } from "@testing-library/react";
|
||||||
|
import { http, HttpResponse } from "msw";
|
||||||
|
import { server } from "../test/server";
|
||||||
|
import { useCreateFieldDefinition } from "./queries";
|
||||||
|
|
||||||
|
function wrapper({ children }: { children: React.ReactNode }) {
|
||||||
|
const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } });
|
||||||
|
|
||||||
|
return <QueryClientProvider client={qc}>{children}</QueryClientProvider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
test("useCreateFieldDefinition POSTs the request body", async () => {
|
||||||
|
let body: unknown;
|
||||||
|
|
||||||
|
server.use(
|
||||||
|
http.post("/api/admin/field-definitions", async ({ request }) => {
|
||||||
|
body = await request.json();
|
||||||
|
|
||||||
|
return HttpResponse.json({ key: "technique" }, { status: 201 });
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useCreateFieldDefinition(), { wrapper });
|
||||||
|
|
||||||
|
result.current.mutate({
|
||||||
|
key: "technique",
|
||||||
|
data_type: "term",
|
||||||
|
vocabulary_id: "v-technique",
|
||||||
|
authority_kind: null,
|
||||||
|
required: false,
|
||||||
|
group: "Provenance",
|
||||||
|
labels: [{ lang: "en", label: "Technique" }],
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
||||||
|
expect((body as { key: string }).key).toBe("technique");
|
||||||
|
expect((body as { data_type: string }).data_type).toBe("term");
|
||||||
|
});
|
||||||
@@ -315,6 +315,23 @@ export function useSearch(q: string, visibility: string | null) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NewFieldDefinitionRequest = components["schemas"]["NewFieldDefinitionRequest"];
|
||||||
|
|
||||||
|
export function useCreateFieldDefinition() {
|
||||||
|
const qc = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async (body: NewFieldDefinitionRequest) => {
|
||||||
|
const { data, response } = await api.POST("/api/admin/field-definitions", { body });
|
||||||
|
|
||||||
|
if (response.status !== 201 || !data) throw new Error("failed to create field definition");
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["field-definitions"] }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
type Visibility = "draft" | "internal" | "public";
|
type Visibility = "draft" | "internal" | "public";
|
||||||
|
|
||||||
/** Error carrying the HTTP status so callers can branch 422-gate vs 409-illegal. */
|
/** Error carrying the HTTP status so callers can branch 422-gate vs 409-illegal. */
|
||||||
|
|||||||
@@ -68,4 +68,8 @@ export const handlers = [
|
|||||||
http.post("/api/admin/logout", () => new HttpResponse(null, { status: 204 })),
|
http.post("/api/admin/logout", () => new HttpResponse(null, { status: 204 })),
|
||||||
|
|
||||||
http.post("/api/admin/objects/:id/visibility", () => new HttpResponse(null, { status: 204 })),
|
http.post("/api/admin/objects/:id/visibility", () => new HttpResponse(null, { status: 204 })),
|
||||||
|
|
||||||
|
http.post("/api/admin/field-definitions", () =>
|
||||||
|
HttpResponse.json({ key: "new_field" }, { status: 201 }),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user