import * as React from "react"; import { renderWithProviders } from "../testUtils/withProviders"; import userEvent from "@testing-library/user-event"; import { bookEditorApiEndpoints, PER_LIBRARY_SUPPRESS_REL, PER_LIBRARY_UNSUPPRESS_REL, } from "../../../src/features/book/bookEditorSlice"; import { BookDetailsEditor } from "../../../src/components/BookDetailsEditor"; import { expect } from "chai"; import { store } from "../../../src/store"; import * as fetchMock from "fetch-mock-jest"; describe("BookDetails", () => { const suppressPerLibraryLink = { href: "/suppress/href", rel: PER_LIBRARY_SUPPRESS_REL, }; const unsuppressPerLibraryLink = { href: "/unsuppress/href", rel: PER_LIBRARY_UNSUPPRESS_REL, }; let fetchBookData; let fetchRoles; let fetchMedia; let fetchLanguages; let postBookData; let dispatchProps; const suppressBook = jest.fn().mockImplementation((url: string) => store.dispatch( bookEditorApiEndpoints.endpoints.suppressBook.initiate({ url, csrfToken: "token", }) ) ); const unsuppressBook = jest.fn().mockImplementation((url: string) => store.dispatch( bookEditorApiEndpoints.endpoints.unsuppressBook.initiate({ url, csrfToken: "token", }) ) ); beforeAll(() => { fetchMock .post("/suppress/href", { status: 200, body: { message: "Successfully suppressed book availability." }, }) .delete("/unsuppress/href", { status: 200, body: { message: "Successfully unsuppressed book availability." }, }); }); beforeEach(() => { fetchBookData = jest.fn(); fetchRoles = jest.fn(); fetchMedia = jest.fn(); fetchLanguages = jest.fn(); postBookData = jest.fn(); dispatchProps = { fetchBookData, fetchRoles, fetchMedia, fetchLanguages, postBookData, suppressBook, unsuppressBook, }; }); afterEach(() => { jest.clearAllMocks(); fetchMock.resetHistory(); }); afterAll(() => { jest.restoreAllMocks(); fetchMock.restore(); }); it("don't show hide button if not a library's admin", () => { const { queryByRole } = renderWithProviders( ); const hideButton = queryByRole("button", { name: "Hide" }); const restoreButton = queryByRole("button", { name: "Restore" }); expect(hideButton).to.be.null; expect(restoreButton).to.be.null; }); it("don't show restore button if not a library's admin", () => { const { queryByRole } = renderWithProviders( ); const hideButton = queryByRole("button", { name: "Hide" }); const restoreButton = queryByRole("button", { name: "Restore" }); expect(hideButton).to.be.null; expect(restoreButton).to.be.null; }); it("uses modal for suppress book confirmation", async () => { // Configure standard constructors so that RTK Query works in tests with FetchMockJest Object.assign(fetchMock.config, { fetch, Headers, Request, Response, }); const user = userEvent.setup(); const { getByRole, getByText, queryByRole } = renderWithProviders( ); // The `Hide` button should be present. const hideButton = getByRole("button", { name: "Hide" }); // Clicking `Hide` should show the book suppression modal. await user.click(hideButton); getByRole("heading", { level: 4, name: "Suppressing Availability" }); getByText(/to hide this title from your library's catalog/); let confirmButton = getByRole("button", { name: "Suppress Availability" }); let cancelButton = getByRole("button", { name: "Cancel" }); // Clicking `Cancel` should close the modal. await user.click(cancelButton); confirmButton = queryByRole("button", { name: "Suppress Availability" }); cancelButton = queryByRole("button", { name: "Cancel" }); expect(confirmButton).to.be.null; expect(cancelButton).to.be.null; // Clicking `Hide` again should show the modal again. await user.click(hideButton); confirmButton = getByRole("button", { name: "Suppress Availability" }); // Clicking the confirmation button should invoke the API and show a confirmation. await user.click(confirmButton); getByRole("heading", { level: 4, name: "Result" }); getByText(/Successfully suppressed book availability/); getByRole("button", { name: "Dismiss" }); // Check that the API was invoked. expect(suppressBook.mock.calls.length).to.equal(1); expect(suppressBook.mock.calls[0][0]).to.equal("/suppress/href"); const fetchCalls = fetchMock.calls(); expect(fetchCalls.length).to.equal(1); const fetchCall = fetchCalls[0]; const fetchOptions = fetchCalls[0][1]; expect(fetchCall[0]).to.equal("/suppress/href"); expect(fetchOptions["headers"]["X-CSRF-Token"]).to.contain("token"); expect(fetchOptions["method"]).to.equal("POST"); }); it("uses modal for unsuppress book confirmation", async () => { // Configure standard constructors so that RTK Query works in tests with FetchMockJest Object.assign(fetchMock.config, { fetch, Headers, Request, Response, }); const user = userEvent.setup(); const { getByRole, getByText, queryByRole } = renderWithProviders( ); // The `Restore` button should be present. const restoreButton = getByRole("button", { name: "Restore" }); // Clicking `Restore` should show the book un/suppression modal. await user.click(restoreButton); getByRole("heading", { level: 4, name: "Restoring Availability" }); getByText(/to make this title visible in your library's catalog/); let confirmButton = getByRole("button", { name: "Restore Availability" }); let cancelButton = getByRole("button", { name: "Cancel" }); // Clicking `Cancel` should close the modal. await user.click(cancelButton); confirmButton = queryByRole("button", { name: "Restore Availability" }); cancelButton = queryByRole("button", { name: "Cancel" }); expect(confirmButton).to.be.null; expect(cancelButton).to.be.null; // Clicking `Restore` again should show the modal again. await user.click(restoreButton); confirmButton = getByRole("button", { name: "Restore Availability" }); // Clicking the confirmation button should invoke the API and show a confirmation. await user.click(confirmButton); getByRole("heading", { level: 4, name: "Result" }); getByText(/Successfully unsuppressed book availability/); getByRole("button", { name: "Dismiss" }); // Check that the API was invoked. expect(unsuppressBook.mock.calls.length).to.equal(1); expect(unsuppressBook.mock.calls[0][0]).to.equal("/unsuppress/href"); const fetchCalls = fetchMock.calls(); expect(fetchCalls.length).to.equal(1); const fetchCall = fetchCalls[0]; const fetchOptions = fetchCalls[0][1]; expect(fetchCall[0]).to.equal("/unsuppress/href"); expect(fetchOptions["headers"]["X-CSRF-Token"]).to.contain("token"); expect(fetchOptions["method"]).to.equal("DELETE"); }); });