src/fragmentarium/ui/info/Details.test.tsx
import React from 'react'
import { MemoryRouter } from 'react-router-dom'
import { waitForSpinnerToBeRemoved } from 'test-support/waitForSpinnerToBeRemoved'
import _ from 'lodash'
import { screen, render } from '@testing-library/react'
import Details from './Details'
import { Museums } from 'fragmentarium/domain/museum'
import { Fragment } from 'fragmentarium/domain/fragment'
import Promise from 'bluebird'
import { Genres } from 'fragmentarium/domain/Genres'
import { fragmentFactory } from 'test-support/fragment-fixtures'
import {
archaeologyFactory,
externalNumbersFactory,
measuresFactory,
} from 'test-support/fragment-data-fixtures'
import { joinFactory } from 'test-support/join-fixtures'
import { Periods } from 'common/period'
import FragmentService from 'fragmentarium/application/FragmentService'
jest.mock('fragmentarium/application/FragmentService')
const MockFragmentService = FragmentService as jest.Mock<
jest.Mocked<FragmentService>
>
const fragmentService = new MockFragmentService()
const updateGenres = jest.fn()
const updateScript = jest.fn()
const updateDate = jest.fn()
const updateDatesInText = jest.fn()
let fragment: Fragment
async function renderDetails() {
render(
<MemoryRouter>
<Details
fragment={fragment}
updateGenres={updateGenres}
updateScript={updateScript}
updateDate={updateDate}
updateDatesInText={updateDatesInText}
fragmentService={fragmentService}
/>
</MemoryRouter>
)
await waitForSpinnerToBeRemoved(screen)
}
describe('All details', () => {
beforeEach(async () => {
fragmentService.fetchGenres.mockReturnValue(
Promise.resolve([['ARCHIVAL'], ['ARCHIVAL', 'Administrative']])
)
fragmentService.fetchPeriods.mockReturnValue(
Promise.resolve([...Object.keys(Periods)])
)
const number = 'X.1'
const museum = Museums['THE_BRITISH_MUSEUM']
fragment = fragmentFactory.build(
{
number,
collection: 'The Collection',
museum,
},
{
associations: {
genres: new Genres([]),
joins: [
[
joinFactory.build({
museumNumber: number,
isInFragmentarium: true,
}),
joinFactory.build({ isInFragmentarium: true }),
],
[
joinFactory.build({ isInFragmentarium: false }),
joinFactory.build({ isInFragmentarium: true }),
joinFactory.build({ isEnvelope: true }),
],
],
},
}
)
await renderDetails()
})
it('Renders museum', () => {
expect(screen.getByText(fragment.museum.name)).toBeInTheDocument()
})
it('Links to museum home', () => {
expect(screen.getByText(fragment.museum.name)).toHaveAttribute(
'href',
fragment.museum.url
)
})
it('Renders colection', () => {
expect(
screen.getByText(`(${fragment.collection} Collection)`)
).toBeInTheDocument()
})
it(`Renders envelope icon for joins`, () => {
expect(screen.queryAllByLabelText('envelope icon').length).toBeGreaterThan(
0
)
})
it('Does not link to self', () => {
fragment.joins
.flat()
.filter((join) => join.museumNumber === fragment.number)
.forEach((join) => {
expect(screen.getByText(join.museumNumber)).not.toHaveAttribute('href')
})
})
it('Does not link to missing joins', () => {
fragment.joins
.flat()
.filter((join) => !join.isInFragmentarium)
.forEach((join) => {
expect(
screen.getByText(new RegExp(_.escapeRegExp(join.museumNumber)))
).not.toHaveAttribute('href')
})
})
it('Links to other joins', () => {
fragment.joins
.flat()
.filter((join) => join.museumNumber !== fragment.number)
.filter((join) => join.isInFragmentarium)
.forEach((join) => {
expect(
screen.getByRole('link', { name: join.museumNumber })
).toHaveAttribute('href', `/fragmentarium/${join.museumNumber}`)
})
})
it('Renders measures', () => {
const expectedMeasures = `${fragment.measures.length} × ${fragment.measures.width} × ${fragment.measures.thickness} cm`
expect(screen.getByText(expectedMeasures)).toBeInTheDocument()
})
it('Renders accession', () => {
expect(
screen.getByText(`Accession no.: ${fragment.accession}`)
).toBeInTheDocument()
})
it('Renders excavation', () => {
expect(
screen.getByText(
`Excavation no.: ${fragment.archaeology?.excavationNumber}`
)
).toBeInTheDocument()
})
it('Renders provenance', () => {
expect(
screen.getByText(`Provenance: ${fragment.archaeology?.site?.name}`)
).toBeInTheDocument()
})
})
describe('Missing details', () => {
beforeEach(async () => {
const archaeology = archaeologyFactory.build({
excavationNumber: undefined,
site: undefined,
})
fragment = fragmentFactory.build(
{
collection: '',
accession: '',
archaeology,
},
{
associations: {
joins: [],
measures: measuresFactory.build({
width: null,
}),
externalNumbers: externalNumbersFactory.build({
cdliNumber: '',
bmIdNumber: '',
}),
},
}
)
fragmentService.fetchGenres.mockReturnValue(Promise.resolve([]))
fragmentService.fetchPeriods.mockReturnValue(Promise.resolve([]))
await renderDetails()
})
it('Does not render undefined', () =>
expect(screen.queryByText('undefined')).not.toBeInTheDocument())
it('Does not render colection', () =>
expect(screen.queryByText('Collection')).not.toBeInTheDocument())
it(`Renders dash for joins`, () => {
expect(screen.getByText(/Joins:/)).toHaveTextContent('-')
})
it('Does not renders missing measures', () => {
expect(
screen.getByText(
`${fragment.measures.length} × ${fragment.measures.thickness} cm`
)
).toBeInTheDocument()
})
it('Renders dash for accession', () => {
expect(screen.getByText('Accession no.: -')).toBeInTheDocument()
})
it('Renders dash for excavation', () => {
expect(screen.getByText('Excavation no.: -')).toBeInTheDocument()
})
it('Renders dash for provenance', () => {
expect(screen.getByText('Provenance: -')).toBeInTheDocument()
})
})