From 2024485b8bb09c841025288a0beb27eee866b6bc Mon Sep 17 00:00:00 2001 From: arttu Date: Tue, 18 Jun 2024 19:47:57 +0300 Subject: [PATCH] Use one UpdateTab component for all; add tests for it --- backend/src/services/species.ts | 23 +++++++- backend/src/services/timeBound.ts | 24 ++++++++- backend/src/services/timeUnit.ts | 25 ++++++++- cypress.config.js | 2 + cypress/e2e/misc.cy.js | 23 ++++++++ cypress/e2e/{tests.cy.js => overview.cy.js} | 0 .../DetailView/common/EditingModal.tsx | 4 +- .../Tabs => DetailView/common}/UpdateTab.tsx | 52 +++++++++++++------ .../components/Locality/LocalityDetails.tsx | 4 +- .../src/components/Species/SpeciesDetails.tsx | 4 +- .../src/components/Species/Tabs/UpdateTab.tsx | 41 --------------- .../components/TimeBound/Tabs/UpdateTab.tsx | 39 -------------- .../components/TimeBound/TimeBoundDetails.tsx | 4 +- .../components/TimeUnit/Tabs/UpdateTab.tsx | 41 --------------- .../components/TimeUnit/TimeUnitDetails.tsx | 4 +- 15 files changed, 138 insertions(+), 152 deletions(-) create mode 100644 cypress/e2e/misc.cy.js rename cypress/e2e/{tests.cy.js => overview.cy.js} (100%) rename frontend/src/components/{Locality/Tabs => DetailView/common}/UpdateTab.tsx (62%) delete mode 100644 frontend/src/components/Species/Tabs/UpdateTab.tsx delete mode 100644 frontend/src/components/TimeBound/Tabs/UpdateTab.tsx delete mode 100644 frontend/src/components/TimeUnit/Tabs/UpdateTab.tsx diff --git a/backend/src/services/species.ts b/backend/src/services/species.ts index 234b3303..1c3ca2a3 100644 --- a/backend/src/services/species.ts +++ b/backend/src/services/species.ts @@ -1,4 +1,4 @@ -import { nowDb } from '../utils/db' +import { logDb, nowDb } from '../utils/db' export const getAllSpecies = async (onlyPublic: boolean) => { const where = onlyPublic ? { sp_status: false } : {} @@ -43,12 +43,31 @@ export const getSpeciesDetails = async (id: number) => { com_taxa_synonym: {}, now_sau: { include: { - now_sr: true, + now_sr: { + include: { + ref_ref: { + include: { + ref_authors: true, + ref_journal: true, + }, + }, + }, + }, }, }, }, }) if (!result) return null + + const suids = result.now_sau.map(sau => sau.suid) + + const logResult = await logDb.log.findMany({ where: { suid: { in: suids } } }) + + result.now_sau = result.now_sau.map(sau => ({ + ...sau, + updates: logResult.filter(logRow => logRow.suid === sau.suid), + })) + return result } diff --git a/backend/src/services/timeBound.ts b/backend/src/services/timeBound.ts index 81ec1878..be942272 100644 --- a/backend/src/services/timeBound.ts +++ b/backend/src/services/timeBound.ts @@ -1,4 +1,4 @@ -import { nowDb } from '../utils/db' +import { logDb, nowDb } from '../utils/db' export const getAllTimeBounds = async () => { const result = await nowDb.now_tu_bound.findMany({ @@ -20,11 +20,31 @@ export const getTimeBoundDetails = async (id: number) => { include: { now_bau: { include: { - now_br: true, + now_br: { + include: { + ref_ref: { + include: { + ref_authors: true, + ref_journal: true, + }, + }, + }, + }, }, }, }, }) + if (!result) return null + + const buids = result.now_bau.map(bau => bau.buid) + + const logResult = await logDb.log.findMany({ where: { buid: { in: buids } } }) + + result.now_bau = result.now_bau.map(bau => ({ + ...bau, + updates: logResult.filter(logRow => logRow.buid === bau.buid), + })) + return result } diff --git a/backend/src/services/timeUnit.ts b/backend/src/services/timeUnit.ts index 98b9c145..c4181529 100644 --- a/backend/src/services/timeUnit.ts +++ b/backend/src/services/timeUnit.ts @@ -1,4 +1,4 @@ -import { nowDb } from '../utils/db' +import { logDb, nowDb } from '../utils/db' export const getAllTimeUnits = async () => { const result = await nowDb.now_time_unit.findMany({ @@ -42,11 +42,32 @@ export const getTimeUnitDetails = async (id: string) => { now_tu_bound_now_time_unit_up_bndTonow_tu_bound: {}, now_tau: { include: { - now_tr: true, + now_tr: { + include: { + ref_ref: { + include: { + ref_authors: true, + ref_journal: true, + }, + }, + }, + }, }, }, }, }) + + if (!result) return null + + const tuids = result.now_tau.map(tau => tau.tuid) + + const logResult = await logDb.log.findMany({ where: { suid: { in: tuids } } }) + + result.now_tau = result.now_tau.map(tau => ({ + ...tau, + updates: logResult.filter(logRow => logRow.tuid === tau.tuid), + })) + return result } diff --git a/cypress.config.js b/cypress.config.js index e67da506..b7f4c2f2 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -11,4 +11,6 @@ module.exports = defineConfig({ requestTimeout: 80000, responseTimeout: 80000, }, + viewportHeight: 900, + viewportWidth: 1200, }); diff --git a/cypress/e2e/misc.cy.js b/cypress/e2e/misc.cy.js new file mode 100644 index 00000000..cac5fd4c --- /dev/null +++ b/cypress/e2e/misc.cy.js @@ -0,0 +1,23 @@ +const baseUrl = 'http://localhost:5173' + +/* + This suite is meant to add tests for individual features, including things such as + visiting specific url's directly. +*/ + +describe('Test individual features across the app', () => { + it('Locality update tab opens, detailed modal works, view-link works', () => { + cy.visit(`${baseUrl}/locality/24750?tab=10`) + cy.contains('2006-10-16') + cy.contains('A new geomagnetic polarity time scale for the Late Cretaceous and Cenozoic Geology 1992') + cy.get('[data-cy="update-details-button"]').first().click() + cy.contains('now_syn_loc') + cy.contains('24750') + cy.contains(`Romanya d'Emporda`) + cy.contains('Add') + cy.contains('A new geomagnetic polarity time scale for the Late Cretaceous and Cenozoic Geology 1992') + cy.contains('View').click() + cy.contains('Reference type') + }) +}) + diff --git a/cypress/e2e/tests.cy.js b/cypress/e2e/overview.cy.js similarity index 100% rename from cypress/e2e/tests.cy.js rename to cypress/e2e/overview.cy.js diff --git a/frontend/src/components/DetailView/common/EditingModal.tsx b/frontend/src/components/DetailView/common/EditingModal.tsx index a38b7a6c..c01503c9 100644 --- a/frontend/src/components/DetailView/common/EditingModal.tsx +++ b/frontend/src/components/DetailView/common/EditingModal.tsx @@ -13,10 +13,12 @@ export const EditingModal = ({ buttonText, children, onSave, + dataCy, }: { buttonText: string children: ReactNode | ReactNode[] onSave?: () => Promise + dataCy?: string }) => { const [open, setOpen] = useState(false) const closeWithSave = async () => { @@ -28,7 +30,7 @@ export const EditingModal = ({ return ( - diff --git a/frontend/src/components/Locality/Tabs/UpdateTab.tsx b/frontend/src/components/DetailView/common/UpdateTab.tsx similarity index 62% rename from frontend/src/components/Locality/Tabs/UpdateTab.tsx rename to frontend/src/components/DetailView/common/UpdateTab.tsx index b4142f83..8a9f3af0 100644 --- a/frontend/src/components/Locality/Tabs/UpdateTab.tsx +++ b/frontend/src/components/DetailView/common/UpdateTab.tsx @@ -1,10 +1,10 @@ -import { LocalityDetailsType, LocalityReference, LocalityUpdate, ReferenceDetailsType, UpdateLog } from '@/backendTypes' +import { ReferenceDetailsType, UpdateLog } from '@/backendTypes' import { useDetailContext } from '@/components/DetailView/Context/DetailContext' import { EditingModal } from '@/components/DetailView/common/EditingModal' import { SimpleTable } from '@/components/DetailView/common/SimpleTable' import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers' import { Card, Stack } from '@mui/material' -import { MRT_ColumnDef, MRT_Row } from 'material-react-table' +import { MRT_ColumnDef, MRT_Row, MRT_RowData } from 'material-react-table' import { Link } from 'react-router-dom' const ReferenceList = ({ references, big }: { references: ReferenceDetailsType[]; big: boolean }) => { @@ -29,51 +29,71 @@ const ReferenceList = ({ references, big }: { references: ReferenceDetailsType[] ) } -export const UpdateTab = () => { - const { data } = useDetailContext() +export const UpdateTab = ({ + prefix, + refFieldName, + updatesFieldName, +}: { + prefix: string + refFieldName: keyof UpdateType + updatesFieldName: keyof T +}) => { + const { data } = useDetailContext() const formatDate = (date: Date | null) => { if (!date) return 'No date' return new Date(date).toISOString().split('T')[0] } - const columns: MRT_ColumnDef[] = [ + const columns: MRT_ColumnDef[] = [ { - accessorKey: 'lau_date', + accessorKey: `${prefix}_date`, header: 'Date', Cell: ({ cell }) => formatDate(cell.getValue() as Date | null), }, { - accessorKey: 'lau_authorizer', + accessorKey: `${prefix}_authorizer`, header: 'Editor', }, { - accessorKey: 'lau_coordinator', + accessorKey: `${prefix}_coordinator`, header: 'Coordinator', }, { - accessorKey: 'now_lr', + accessorKey: refFieldName as string, header: 'Reference', - Cell: ({ row }: { row: MRT_Row }) => ( - lr.ref_ref)} big={false} /> + Cell: ({ row }: { row: MRT_Row }) => ( + item.ref_ref)} + big={false} + /> ), }, { header: 'Details', - Cell: ({ row }: { row: MRT_Row }) => ( - + Cell: ({ row }: { row: MRT_Row }) => ( + ), }, ] return ( - + ) } -const DetailsModal = ({ updates, references }: { updates: UpdateLog[]; references: LocalityReference[] }) => { +const DetailsModal = ({ + updates, + references, +}: { + updates: UpdateLog[] + references: RefType[] +}) => { const columns: MRT_ColumnDef[] = [ { header: 'Table', @@ -98,7 +118,7 @@ const DetailsModal = ({ updates, references }: { updates: UpdateLog[]; reference ] return ( - + ref.ref_ref)} big /> diff --git a/frontend/src/components/Locality/LocalityDetails.tsx b/frontend/src/components/Locality/LocalityDetails.tsx index 49cac436..7f06d117 100644 --- a/frontend/src/components/Locality/LocalityDetails.tsx +++ b/frontend/src/components/Locality/LocalityDetails.tsx @@ -12,9 +12,9 @@ import { MuseumTab } from './Tabs/MuseumTab' import { ProjectTab } from './Tabs/ProjectTab' import { SpeciesTab } from './Tabs/SpeciesTab' import { TaphonomyTab } from './Tabs/TaphonomyTab' -import { UpdateTab } from './Tabs/UpdateTab' import { EditDataType, LocalityDetailsType } from '@/backendTypes' import { validateLocality } from '@/validators/locality' +import { UpdateTab } from '../DetailView/common/UpdateTab' export const LocalityDetails = () => { const { id } = useParams() @@ -70,7 +70,7 @@ export const LocalityDetails = () => { }, { title: 'Updates', - content: , + content: , }, ] diff --git a/frontend/src/components/Species/SpeciesDetails.tsx b/frontend/src/components/Species/SpeciesDetails.tsx index e0d5a365..e29f860f 100644 --- a/frontend/src/components/Species/SpeciesDetails.tsx +++ b/frontend/src/components/Species/SpeciesDetails.tsx @@ -10,7 +10,7 @@ import { SizeTab } from './Tabs/SizeTab' import { SynonymTab } from './Tabs/SynonymTab' import { TaxonomyTab } from './Tabs/TaxonomyTab' import { TeethTab } from './Tabs/TeethTab' -import { UpdateTab } from './Tabs/UpdateTab' +import { UpdateTab } from '../DetailView/common/UpdateTab' export const SpeciesDetails = () => { const { id } = useParams() @@ -54,7 +54,7 @@ export const SpeciesDetails = () => { }, { title: 'Updates', - content: , + content: , }, ] diff --git a/frontend/src/components/Species/Tabs/UpdateTab.tsx b/frontend/src/components/Species/Tabs/UpdateTab.tsx deleted file mode 100644 index 9eebb4b3..00000000 --- a/frontend/src/components/Species/Tabs/UpdateTab.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { SpeciesDetailsType, SpeciesUpdate } from '@/backendTypes' -import { useDetailContext } from '@/components/DetailView/Context/DetailContext' -import { SimpleTable } from '@/components/DetailView/common/SimpleTable' -import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers' -import { Box } from '@mui/material' -import { MRT_ColumnDef } from 'material-react-table' - -export const UpdateTab = () => { - const { data } = useDetailContext() - const formatDate = (date: Date | null) => { - if (!date) return 'No date' - return new Date(date).toISOString().split('T')[0] - } - - const columns: MRT_ColumnDef[] = [ - { - accessorKey: 'sau_date', - header: 'Date', - Cell: ({ cell }) => formatDate(cell.getValue() as Date | null), - }, - { - accessorKey: 'sau_authorizer', - header: 'Editor', - }, - { - accessorKey: 'sau_coordinator', - header: 'Coordinator', - }, - { - accessorKey: 'now_sr', - header: 'Reference', - Cell: () => not implemented, - }, - ] - - return ( - - - - ) -} diff --git a/frontend/src/components/TimeBound/Tabs/UpdateTab.tsx b/frontend/src/components/TimeBound/Tabs/UpdateTab.tsx deleted file mode 100644 index e6455ab1..00000000 --- a/frontend/src/components/TimeBound/Tabs/UpdateTab.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Editable, TimeBoundDetailsType, TimeBoundUpdate } from '@/backendTypes' -import { EditableTable } from '@/components/DetailView/common/EditableTable' -import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers' -import { Box } from '@mui/material' -import { MRT_ColumnDef } from 'material-react-table' - -export const UpdateTab = () => { - const formatDate = (date: Date | null) => { - if (!date) return 'No date' - return new Date(date).toISOString().split('T')[0] - } - - const columns: MRT_ColumnDef[] = [ - { - accessorKey: 'bau_date', - header: 'Date', - Cell: ({ cell }) => formatDate(cell.getValue() as Date | null), - }, - { - accessorKey: 'bau_authorizer', - header: 'Editor', - }, - { - accessorKey: 'bau_coordinator', - header: 'Coordinator', - }, - { - accessorKey: 'now_br', - header: 'Reference', - Cell: () => not implemented, - }, - ] - - return ( - - , TimeBoundDetailsType> columns={columns} field="now_bau" /> - - ) -} diff --git a/frontend/src/components/TimeBound/TimeBoundDetails.tsx b/frontend/src/components/TimeBound/TimeBoundDetails.tsx index ba66eb57..1dbb16f5 100644 --- a/frontend/src/components/TimeBound/TimeBoundDetails.tsx +++ b/frontend/src/components/TimeBound/TimeBoundDetails.tsx @@ -4,7 +4,7 @@ import { CircularProgress } from '@mui/material' import { DetailView, TabType } from '../DetailView/DetailView' import { BoundTab } from './Tabs/BoundTab' import { TimeUnitTab } from './Tabs/TimeUnitTab.tsx' -import { UpdateTab } from './Tabs/UpdateTab' +import { UpdateTab } from '../DetailView/common/UpdateTab.tsx' export const TimeBoundDetails = () => { const { id } = useParams() @@ -24,7 +24,7 @@ export const TimeBoundDetails = () => { }, { title: 'Updates', - content: , + content: , }, ] diff --git a/frontend/src/components/TimeUnit/Tabs/UpdateTab.tsx b/frontend/src/components/TimeUnit/Tabs/UpdateTab.tsx deleted file mode 100644 index a2bcdf78..00000000 --- a/frontend/src/components/TimeUnit/Tabs/UpdateTab.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { TimeUnitDetailsType, TimeUnitUpdate } from '@/backendTypes' -import { useDetailContext } from '@/components/DetailView/Context/DetailContext' -import { SimpleTable } from '@/components/DetailView/common/SimpleTable' -import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers' -import { Box } from '@mui/material' -import { MRT_ColumnDef } from 'material-react-table' - -export const UpdateTab = () => { - const { data } = useDetailContext() - const formatDate = (date: Date | null) => { - if (!date) return 'No date' - return new Date(date).toISOString().split('T')[0] - } - - const columns: MRT_ColumnDef[] = [ - { - accessorKey: 'tau_date', - header: 'Date', - Cell: ({ cell }) => formatDate(cell.getValue() as Date | null), - }, - { - accessorKey: 'tau_authorizer', - header: 'Editor', - }, - { - accessorKey: 'tau_coordinator', - header: 'Coordinator', - }, - { - accessorKey: 'now_tr', - header: 'Reference', - Cell: () => not implemented, - }, - ] - - return ( - - - - ) -} diff --git a/frontend/src/components/TimeUnit/TimeUnitDetails.tsx b/frontend/src/components/TimeUnit/TimeUnitDetails.tsx index ea8da696..ddcdbaa8 100644 --- a/frontend/src/components/TimeUnit/TimeUnitDetails.tsx +++ b/frontend/src/components/TimeUnit/TimeUnitDetails.tsx @@ -4,7 +4,7 @@ import { CircularProgress } from '@mui/material' import { DetailView, TabType } from '../DetailView/DetailView' import { LocalityTab } from './Tabs/LocalityTab' import { TimeUnitTab } from './Tabs/TimeUnitTab' -import { UpdateTab } from './Tabs/UpdateTab' +import { UpdateTab } from '../DetailView/common/UpdateTab' export const TimeUnitDetails = () => { const { id } = useParams() @@ -24,7 +24,7 @@ export const TimeUnitDetails = () => { }, { title: 'Updates', - content: , + content: , }, ]