Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCC-3762 - Patron Eligibility Errors #415

Merged
merged 11 commits into from
Dec 17, 2024
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Added and integrated hold confirmation details fetcher function (SCC-3762)
- Added server-side auth redirect to hold confirmation page (SCC-3762)
- Added fetchPatronEligibility server function that requests a patron's hold request eligibility status from Discovery API (SCC-3762)
- Added patron ineligibility error messaging to HoldRequestErrorBanner component (SCC-3762)
- Added eligibility checks to EDD and on-site request hold pages and API routes (SCC-3762)

### Updated

Expand Down
151 changes: 115 additions & 36 deletions __test__/pages/hold/eddRequestPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import {
BASE_URL,
PATHS,
EDD_FORM_FIELD_COPY,
HOLD_PAGE_ERROR_HEADINGS,
} from "../../../src/config/constants"
import { fetchDeliveryLocations } from "../../../src/server/api/hold"
import { EDDPageStatusMessages } from "../../../src/utils/holdPageUtils"

jest.mock("../../../src/server/auth")
jest.mock("../../../src/server/api/bib")
Expand All @@ -44,6 +44,26 @@ const mockReq = {
},
}

const fillRequiredEDDFormFields = async () => {
// Fill in all required form fields
await userEvent.type(
screen.getByPlaceholderText(EDD_FORM_FIELD_COPY.emailAddress.placeholder),
dgcohen marked this conversation as resolved.
Show resolved Hide resolved
EDD_FORM_FIELD_COPY.emailAddress.placeholder
)
await userEvent.type(
screen.getByPlaceholderText(EDD_FORM_FIELD_COPY.startPage.placeholder),
EDD_FORM_FIELD_COPY.startPage.placeholder
)
await userEvent.type(
screen.getByPlaceholderText(EDD_FORM_FIELD_COPY.endPage.placeholder),
EDD_FORM_FIELD_COPY.endPage.placeholder
)
await userEvent.type(
screen.getByPlaceholderText(EDD_FORM_FIELD_COPY.chapterTitle.placeholder),
EDD_FORM_FIELD_COPY.chapterTitle.placeholder
)
}

describe("EDD Request page", () => {
describe("logout redirect handling", () => {
beforeEach(() => {
Expand Down Expand Up @@ -74,14 +94,12 @@ describe("EDD Request page", () => {
params: { id },
req: mockReq,
res: mockRes,
query: {},
})
expect(responseWithZeroRedirects.redirect).toBeDefined()
const responseWithTwoRedirects = await getServerSideProps({
params: { id: "123-456" },
req: { ...mockReq, cookies: { nyplAccountRedirects: 2 } },
res: mockRes,
query: {},
})
expect(responseWithTwoRedirects.redirect).toBeDefined()
})
Expand All @@ -98,7 +116,6 @@ describe("EDD Request page", () => {
params: { id },
req: mockReq,
res: mockRes,
query: {},
})
expect(responseWithoutRedirect.redirect).not.toBeDefined()
})
Expand All @@ -107,7 +124,6 @@ describe("EDD Request page", () => {
params: { id },
req: mockReq,
res: mockRes,
query: {},
})
expect(response.redirect).toBeUndefined()
})
Expand All @@ -123,7 +139,6 @@ describe("EDD Request page", () => {
params: { id },
res: mockRes,
req: mockReq,
query: {},
})
expect(mockRes.setHeader.mock.calls[0]).toStrictEqual([
"Set-Cookie",
Expand All @@ -149,7 +164,6 @@ describe("EDD Request page", () => {
params: { id },
res: mockRes,
req: mockReq,
query: {},
})
expect(responseWithAeonRedirect.redirect).toStrictEqual({
destination: bibWithSingleAeonItem.resource.items[0].aeonUrl[0],
Expand Down Expand Up @@ -204,32 +218,12 @@ describe("EDD Request page", () => {

global.fetch = jest.fn().mockImplementationOnce(() =>
Promise.resolve({
status: 404,
status: 500,
json: () => Promise.resolve({ success: true }),
})
)

// Fill in all required form fields
await userEvent.type(
screen.getByPlaceholderText(
EDD_FORM_FIELD_COPY.emailAddress.placeholder
),
EDD_FORM_FIELD_COPY.emailAddress.placeholder
)
await userEvent.type(
screen.getByPlaceholderText(EDD_FORM_FIELD_COPY.startPage.placeholder),
EDD_FORM_FIELD_COPY.startPage.placeholder
)
await userEvent.type(
screen.getByPlaceholderText(EDD_FORM_FIELD_COPY.endPage.placeholder),
EDD_FORM_FIELD_COPY.endPage.placeholder
)
await userEvent.type(
screen.getByPlaceholderText(
EDD_FORM_FIELD_COPY.chapterTitle.placeholder
),
EDD_FORM_FIELD_COPY.chapterTitle.placeholder
)
await fillRequiredEDDFormFields()
})

it("shows an error when the request fails", async () => {
Expand All @@ -238,7 +232,9 @@ describe("EDD Request page", () => {
expect(screen.getByTestId("hold-request-error")).toBeInTheDocument()
})

expect(screen.getByText("Request failed")).toBeInTheDocument()
expect(
screen.getByText("Request failed.", { exact: false })
).toBeInTheDocument()

expect(
screen.queryByText(
Expand Down Expand Up @@ -307,11 +303,11 @@ describe("EDD Request page", () => {
discoveryItemResult={bibWithItems.resource.items[0]}
patronId="123"
isAuthenticated={true}
pageStatus="unavailable"
errorStatus="eddUnavailable"
/>
)
expect(
screen.getByText(EDDPageStatusMessages.unavailable.heading)
screen.getByText(HOLD_PAGE_ERROR_HEADINGS.eddUnavailable)
).toBeInTheDocument()
})
it("shows a failed error message when the page loads with an failed status", async () => {
Expand All @@ -321,11 +317,11 @@ describe("EDD Request page", () => {
discoveryItemResult={bibWithItems.resource.items[0]}
patronId="123"
isAuthenticated={true}
pageStatus="failed"
errorStatus="failed"
/>
)
expect(
screen.getByText(EDDPageStatusMessages.failed.heading)
screen.getByText(HOLD_PAGE_ERROR_HEADINGS.failed)
).toBeInTheDocument()
})
it("shows an invalid error message when the page loads with an invalid status", async () => {
Expand All @@ -335,11 +331,94 @@ describe("EDD Request page", () => {
discoveryItemResult={bibWithItems.resource.items[0]}
patronId="123"
isAuthenticated={true}
pageStatus="invalid"
errorStatus="invalid"
/>
)
expect(
screen.getByText(EDDPageStatusMessages.invalid.message)
screen.getByText(
"Some fields contain errors. Please correct and submit again."
)
).toBeInTheDocument()
})
})
describe("EDD Request patron ineligibility messaging", () => {
beforeEach(async () => {
render(
<EDDRequestPage
discoveryBibResult={bibWithItems.resource}
discoveryItemResult={bibWithItems.resource.items[0]}
patronId="123"
isAuthenticated={true}
/>
)

global.fetch = jest.fn().mockImplementationOnce(() =>
Promise.resolve({
status: 401,
json: () =>
Promise.resolve({
success: false,
patronEligibilityStatus: {
eligibility: false,
expired: true,
moneyOwed: true,
ptypeDisallowsHolds: true,
reachedHoldLimit: true,
},
}),
})
)

await fillRequiredEDDFormFields()

await fireEvent(
screen.getByText("Submit request"),
new MouseEvent("click")
)
})

it("shows an error listing ineligibility reasons when the patron is ineligibile to place holds", async () => {
await waitFor(() => {
expect(screen.getByTestId("hold-request-error")).toBeInTheDocument()
})

expect(
screen.getByText(HOLD_PAGE_ERROR_HEADINGS.patronIneligible, {
exact: false,
})
).toBeInTheDocument()

expect(
screen.getByText("This is because:", {
exact: false,
})
).toBeInTheDocument()

expect(
screen.getByText("Your account has expired", {
exact: false,
})
).toBeInTheDocument()

expect(
screen.getByText("Your fines have exceeded the limit", {
exact: false,
})
).toBeInTheDocument()

expect(
screen.getByText(
"Your card does not permit placing holds on ReCAP materials.",
{
exact: false,
}
)
).toBeInTheDocument()

expect(
screen.getByText("You have reached the allowed number of holds.", {
exact: false,
})
).toBeInTheDocument()
})
})
Expand Down
Loading
Loading