Skip to content

Commit

Permalink
Merge pull request #411 from NYPL/dec-24-release-3
Browse files Browse the repository at this point in the history
QA owning institution and advanced search updates
  • Loading branch information
charmingduchess authored Dec 9, 2024
2 parents 6a9cf30 + 831f476 commit e371ca0
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 232 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.8] 2024-12-9

Note this release was not merged to main before deploying.

### Updated

- add call number and standard numbers to advanced search ([SCC-4326](https://newyorkpubliclibrary.atlassian.net/browse/SCC-4326))
- Pull in Owning institution from items to populate bib details ([SCC-4334](https://newyorkpubliclibrary.atlassian.net/browse/SCC-4334))

### [1.3.7] Hotfix 2024-11-21

- Fix analytics bug where routes without a query string do not emit the correct virtual page view event (SCC-4314)
Expand Down
177 changes: 177 additions & 0 deletions __test__/fixtures/bibFixtures.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,180 @@
export const princetonRecord = {
"@context":
"http://discovery-api-qa.nypl.org/api/v0.1/discovery/context_all.jsonld",
"@type": ["nypl:Item", "nypl:Resource"],
"@id": "res:pb2608686",
buildingLocationIds: [],
carrierType: [
{
"@id": "carriertypes:nc",
prefLabel: "volume",
},
],
contributorLiteral: ["Brown, David, journalist, joint author."],
createdString: ["1943"],
createdYear: 1943,
creatorLiteral: ["Wagg, Alfred."],
dateStartYear: 1943,
dateString: ["1943"],
dimensions: ["23 cm."],
extent: ["231 p."],
idLccn: [" 44003956 "],
identifier: [
{
"@type": "nypl:Bnumber",
"@value": "2608686",
},
{
"@type": "bf:Lccn",
"@value": " 44003956 ",
},
{
"@type": "bf:Identifier",
"@value": "(OCoLC)ocm02088006",
},
],
issuance: [
{
"@id": "urn:biblevel:m",
prefLabel: "monograph/item",
},
],
itemAggregations: [
{
"@type": "nypl:Aggregation",
"@id": "res:location",
id: "location",
field: "location",
values: [],
},
{
"@type": "nypl:Aggregation",
"@id": "res:format",
id: "format",
field: "format",
values: [],
},
{
"@type": "nypl:Aggregation",
"@id": "res:status",
id: "status",
field: "status",
values: [
{
value: "status:a",
count: 1,
label: "Available",
},
],
},
],
items: [
{
"@id": "res:pi5153471",
accessMessage: [
{
"@id": "accessMessage:1",
prefLabel: "Use in library",
},
],
catalogItemType: [
{
"@id": "catalogItemType:1",
prefLabel: "non-circ",
},
],
eddFulfillment: {
"@id": "fulfillment:recap-edd",
},
eddRequestable: true,
idBarcode: ["32101067443802"],
identifier: [
{
"@type": "bf:ShelfMark",
"@value": "D763.I8 W3 1943",
},
{
"@type": "bf:Barcode",
"@value": "32101067443802",
},
],
idNyplSourceId: {
"@type": "RecapPul",
"@value": "25791623",
},
owner: [
{
"@id": "orgs:0003",
prefLabel: "Princeton University Library",
},
],
physFulfillment: {
"@id": "fulfillment:recap-offsite",
},
physRequestable: true,
requestable: [true],
shelfMark: ["D763.I8 W3 1943"],
specRequestable: false,
status: [
{
"@id": "status:na",
prefLabel: "Not available",
},
],
uri: "pi5153471",
},
],
language: [
{
"@id": "lang:eng",
prefLabel: "English",
},
],
lccClassification: ["D763.I8 W3"],
materialType: [
{
"@id": "resourcetypes:txt",
prefLabel: "Text",
},
],
mediaType: [
{
"@id": "mediatypes:n",
prefLabel: "unmediated",
},
],
note: [
{
noteType: "Note",
"@type": "bf:Note",
prefLabel: '"First published in 1943."',
},
],
numAvailable: 1,
numItems: 1,
numItemsMatched: 1,
numItemsTotal: 1,
placeOfPublication: ["London,"],
publicationStatement: ["London, Nicholson & Watson [1943]"],
publisherLiteral: ["Nicholson & Watson"],
subjectLiteral: [
"World War, 1939-1945 -- Campaigns -- Italy.",
"World War, 1939-1945 -- Naval operations.",
"World War, 1939-1945 -- Personal narratives.",
],
title: ["No spaghetti for breakfast"],
titleDisplay: [
"No spaghetti for breakfast [by] Alfred Wagg and David Brown.",
],
type: ["nypl:Item"],
updatedAt: 1543536484228,
uri: "pb2608686",
updatedAtDate: "2018-11-30T00:08:04.228Z",
hasItemVolumes: false,
hasItemDates: false,
electronicResources: [],
}

export const bibWithItems = {
resource: {
"@context":
Expand Down
110 changes: 63 additions & 47 deletions __test__/pages/search/advancedSearchForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import React from "react"
import { fireEvent, render, screen } from "../../../src/utils/testUtils"
import {
fireEvent,
render,
screen,
waitFor,
delay,
} from "../../../src/utils/testUtils"
import mockRouter from "next-router-mock"
import userEvent from "@testing-library/user-event"

import { textInputFields } from "../../../src/utils/advancedSearchUtils"
import AdvancedSearch, {
defaultEmptySearchErrorMessage,
} from "../../../pages/search/advanced"
Expand All @@ -12,52 +19,70 @@ import { searchAggregations } from "../../../src/config/aggregations"
jest.mock("next/router", () => jest.requireActual("next-router-mock"))

describe("Advanced Search Form", () => {
beforeEach(async () => {
render(<AdvancedSearch isAuthenticated={true} />)
})
const submit = () => {
fireEvent(
screen.getByTestId("submit-advanced-search-button"),
new MouseEvent("click")
)
fireEvent.click(screen.getByTestId("submit-advanced-search-button"))
}
const updateAllFields = async () => {
const [
keywordInput,
contributorInput,
titleInput,
subjectInput,
callNumberInput,
uniqueIdentifierInput,
] = [
"Keyword",
"Title",
"Author/contributor",
"Subject",
"Call number",
"Unique identifier",
].map((field) => screen.getByLabelText(field))
fireEvent.change(subjectInput, { target: { value: "italian food" } })
fireEvent.change(keywordInput, { target: { value: "spaghetti" } })
fireEvent.change(contributorInput, { target: { value: "strega nonna" } })
fireEvent.change(titleInput, { target: { value: "il amore di pasta" } })
fireEvent.change(callNumberInput, { target: { value: "12345" } })
fireEvent.change(uniqueIdentifierInput, { target: { value: "67890" } })

// without this delay, the input is not updated until after submit is called.
await delay(500)
return [
keywordInput,
contributorInput,
titleInput,
subjectInput,
callNumberInput,
uniqueIdentifierInput,
]
}
afterEach(async () => {
await userEvent.click(screen.getByText("Clear fields"))
})
it("displays alert when no fields are submitted", () => {
render(<AdvancedSearch isAuthenticated={true} />)

submit()
screen.getByText(defaultEmptySearchErrorMessage)
})
// this test is broken due to debounce/userEvent/timing weirdness.
// this functionality works in the browser, but won't include
// final input in output string in test. the broken test is
// commented out below.
it.todo("can set keyword, contributor, title, subject")
// async () => {
// render(<AdvancedSearch isAuthenticated={true}/>)

// const [keywordInput, contributorInput, titleInput, subjectInput] = [
// "Keywords",
// "Title",
// "Author",
// "Subject",
// ].map((field) => screen.getByLabelText(field))
// await act(async () => {
// await userEvent.type(subjectInput, "italian food")
// await userEvent.type(keywordInput, "spaghetti")
// await userEvent.type(contributorInput, "strega nonna")
// await userEvent.type(titleInput, "il amore di pasta")
// // this set stimeout is to ad
// // eslint-disable-next-line @typescript-eslint/no-empty-function
// setTimeout(() => {}, 300)
// submit()
// expect(mockRouter.asPath).toBe(
// "/search?q=spaghetti&contributor=il+amore+di+pasta&title=strega+nonna&subject=italian+food"
// )
// })
// })
it("can select languages", async () => {
render(<AdvancedSearch isAuthenticated={true} />)
it("can set keyword, contributor, title, subject", async () => {
await updateAllFields()
submit()

expect(mockRouter.asPath).toBe(
"/search?q=spaghetti&title=strega+nonna&contributor=il+amore+di+pasta&callnumber=12345&standard_number=67890&subject=italian+food"
)
})
it("renders inputs for all text input fields", () => {
textInputFields.map(({ label }) => {
const input = screen.getByLabelText(label)
expect(input).toBeInTheDocument()
})
})

it("can select languages", async () => {
const languageSelect = screen.getByLabelText("Language")
await userEvent.selectOptions(languageSelect, "Azerbaijani")
submit()
Expand All @@ -67,7 +92,6 @@ describe("Advanced Search Form", () => {
)
})
it("can check material checkboxes", async () => {
render(<AdvancedSearch isAuthenticated={true} />)
await userEvent.click(screen.getByLabelText("Notated music"))
await userEvent.click(screen.getByLabelText("Cartographic"))
submit()
Expand All @@ -78,7 +102,6 @@ describe("Advanced Search Form", () => {
)
})
it("can check location checkboxes", async () => {
render(<AdvancedSearch isAuthenticated={true} />)
const location = searchAggregations.buildingLocation[0]
await userEvent.click(screen.getByLabelText(location.label as string))
submit()
Expand All @@ -88,7 +111,6 @@ describe("Advanced Search Form", () => {
})

it("can clear the form", async () => {
render(<AdvancedSearch isAuthenticated={true} />)
const notatedMusic = screen.getByLabelText("Notated music")
await userEvent.click(notatedMusic)
const cartographic = screen.getByLabelText("Cartographic")
Expand All @@ -100,14 +122,8 @@ describe("Advanced Search Form", () => {
})

await userEvent.click(schomburg)
const keywordInput = screen.getByLabelText("Keyword")
const titleInput = screen.getByLabelText("Title")
const contributorInput = screen.getByLabelText("Author")
const subjectInput = screen.getByLabelText("Subject")
await userEvent.type(keywordInput, "spaghetti")
await userEvent.type(contributorInput, "strega nonna")
await userEvent.type(titleInput, "il amore di pasta")
await userEvent.type(subjectInput, "italian food")
const [subjectInput, keywordInput, titleInput, contributorInput] =
await updateAllFields()

await userEvent.click(screen.getByText("Clear fields"))
;[notatedMusic, cartographic, schomburg].forEach((input) =>
Expand Down
7 changes: 3 additions & 4 deletions __test__/pages/search/searchResults.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react"
import userEvent from "@testing-library/user-event"
import { render, screen } from "../../../src/utils/testUtils"
import { render, screen, waitFor } from "../../../src/utils/testUtils"

import mockRouter from "next-router-mock"

Expand Down Expand Up @@ -32,11 +32,10 @@ describe("Search Results page", () => {
})
await userEvent.click(field)
await userEvent.click(screen.getByText("Apply filters"))
// This was the only way to get this test to pass. waitFor was not in fact waiting, even with same timeout.
setTimeout(() => {
waitFor(() => {
const resultsHeading = screen.getByTestId("search-results-heading")
expect(resultsHeading).toHaveFocus()
}, 500)
})
})
it("focuses on search results heading after loading a keyword search", () => {
mockRouter.push(`/search?q=${query}`)
Expand Down
1 change: 0 additions & 1 deletion pages/bib/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ export default function BibPage({
discoveryBibResult,
annotatedMarc
)

const displayLegacyCatalogLink = isNyplBibID(bib.id)

const filtersAreApplied = areFiltersApplied(appliedFilters)
Expand Down
Loading

0 comments on commit e371ca0

Please sign in to comment.