import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { act, renderHook } from "@testing-library/react-hooks";
import { mock } from "vitest-mock-extended";
import { fetchItems, fetchTags } from "./base";
import { useDeleteTags, useImportCitoids, useModifyTags } from "./mutations";
import { apiKeys, citoids, goodIdentifier, libraries } from "Mocks";
import { DataRequest } from "Types/extension";
import { isFulfilled } from "Types/helpers";
const { keyWithFullAccess: { key: masterKey } } = apiKeys;
const { groupLibrary, userLibrary } = libraries;
const queryClient = new QueryClient({
defaultOptions: {
queries: {
// Set global defaults here
}
},
logger: {
log: console.log,
warn: console.warn,
error: () => { }
}
});
const invalidateQueriesSpy = vi.spyOn(queryClient, "invalidateQueries");
const dispatchEventSpy = vi.spyOn(document, "dispatchEvent");
// https://tkdodo.eu/blog/testing-react-query
const wrapper = ({ children }) => {
return (
{children}
);
};
describe("Mutation hooks for the Zotero API", () => {
afterEach(() => {
queryClient.clear();
});
describe("useDeleteTags", () => {
beforeEach(async() => {
const mockData = await fetchTags({ apikey: masterKey, path: userLibrary.path });
queryClient.setQueryData(["tags", { library: userLibrary.path }], () => mockData);
});
test("callback on success", async () => {
const { result, waitFor } = renderHook(() => useDeleteTags(), { wrapper });
expect(result.current.status).toBe("idle");
act(() => {
result.current.mutate({
library: { apikey: masterKey, path: userLibrary.path },
tags: ["systems"]
});
});
await waitFor(() => result.current.status == "success");
expect(invalidateQueriesSpy).toHaveBeenCalledWith(
["items", userLibrary.path],
{ refetchType: "all" },
{ throwOnError: true }
);
expect((dispatchEventSpy.mock.calls[0][0] as CustomEvent).detail).toEqual({
args: { tags: ["systems"] },
error: null,
library: userLibrary.path,
_type: "tags-deleted"
});
});
});
describe("useImportCitoids", () => {
test("callback on success", async () => {
const { result, waitFor } = renderHook(() => useImportCitoids(), { wrapper });
expect(result.current.status).toBe("idle");
act(() => {
result.current.mutate({
collections: [],
items: [citoids[goodIdentifier]],
library: { apikey: masterKey, path: userLibrary.path },
tags: []
});
});
await waitFor(() => result.current.status == "success");
expect(invalidateQueriesSpy).toHaveBeenCalledWith(
["items", userLibrary.path],
{ refetchType: "all" }
);
expect((dispatchEventSpy.mock.calls[0][0] as CustomEvent).detail).toEqual({
args: {
collections: [],
items: [citoids[goodIdentifier]],
tags: []
},
data: {
failed: [],
successful: result.current.data?.filter(isFulfilled).map(res => res.value.data)
},
error: null,
library: userLibrary.path,
_type: "write"
});
});
});
describe("useModifyTags", () => {
const sample_req = mock({ apikey: masterKey, dataURI: `${groupLibrary.path}/items`, library: { path: groupLibrary.path } });
beforeEach(async() => {
const mockData = await fetchItems(
{ ...sample_req, since: 0 },
{ match: [] },
queryClient
);
queryClient.setQueryData(["items", groupLibrary.path, {}], () => mockData);
});
test("callback on success", async () => {
const { result, waitFor } = renderHook(() => useModifyTags(), { wrapper });
expect(result.current.status).toBe("idle");
act(() => {
result.current.mutate({
into: "HOUSING",
library: { apikey: masterKey, path: groupLibrary.path },
tags: ["housing"]
});
});
await waitFor(() => result.current.status == "success");
expect(invalidateQueriesSpy).toHaveBeenCalledWith(
["items", groupLibrary.path],
{ refetchType: "all" }
);
expect((dispatchEventSpy.mock.calls[0][0] as CustomEvent).detail).toEqual({
args: {
into: "HOUSING",
tags: ["housing"]
},
data: {
failed: [],
successful: result.current.data?.filter(isFulfilled).map(res => res.value.data)
},
error: null,
library: groupLibrary.path,
_type: "tags-modified"
});
});
});
});