From ad5fb48622cc75b1f5b26f8d0b794ee3650d05a4 Mon Sep 17 00:00:00 2001 From: Stuart Bennett Date: Wed, 11 Dec 2024 16:04:00 +0000 Subject: [PATCH 1/3] EES-5544 implement data file table --- .../components/DataFilesTable.module.scss | 22 ++ .../data/components/DataFilesTable.tsx | 219 ++++++++++++++++++ .../data/components/ImporterStatus.tsx | 4 +- .../components/ReleaseDataUploadsSection.tsx | 207 ++--------------- .../src/components/Tag.module.scss | 1 + 5 files changed, 268 insertions(+), 185 deletions(-) create mode 100644 src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.module.scss create mode 100644 src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx diff --git a/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.module.scss b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.module.scss new file mode 100644 index 00000000000..78e4ca7c7d5 --- /dev/null +++ b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.module.scss @@ -0,0 +1,22 @@ +@import '~govuk-frontend/dist/govuk/base'; + +.table { + td { + padding-bottom: govuk-spacing(2); + padding-top: govuk-spacing(2); + vertical-align: middle; + } + + .fileSize { + width: 5rem; + text-align: right; + } + + .fileStatus { + max-width: 164px; + } + + .actions { + margin-bottom: 0; + } +} diff --git a/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx new file mode 100644 index 00000000000..3f96a737cec --- /dev/null +++ b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx @@ -0,0 +1,219 @@ +import Link from '@admin/components/Link'; +import DataFileDetailsTable from '@admin/pages/release/data/components/DataFileDetailsTable'; +import DataUploadCancelButton from '@admin/pages/release/data/components/DataUploadCancelButton'; +import ImporterStatus, { + terminalImportStatuses, +} from '@admin/pages/release/data/components/ImporterStatus'; +import { + releaseApiDataSetDetailsRoute, + releaseDataFileReplaceRoute, + ReleaseDataFileReplaceRouteParams, + releaseDataFileRoute, + ReleaseDataFileRouteParams, + ReleaseDataSetRouteParams, +} from '@admin/routes/releaseRoutes'; +import { + DataFile, + DataFileImportStatus, +} from '@admin/services/releaseDataFileService'; +import ButtonGroup from '@common/components/ButtonGroup'; +import ButtonText from '@common/components/ButtonText'; +import Modal from '@common/components/Modal'; +import { generatePath } from 'react-router'; +import React from 'react'; +import styles from './DataFilesTable.module.scss'; + +interface Props { + dataFiles: DataFile[]; + publicationId: string; + releaseId: string; + canUpdateRelease?: boolean; + handleDeleteFile: (dataFile: DataFile) => Promise; + handleStatusChange: ( + dataFile: DataFile, + { totalRows, status }: DataFileImportStatus, + ) => Promise; +} + +const DataFilesTable = ({ + dataFiles, + publicationId, + releaseId, + canUpdateRelease, + handleDeleteFile, + handleStatusChange, +}: Props) => { + return ( + <> +

Uploaded data files

+ + + + + + {/* */} + + {/* */} + {/* + */} + + + + + + {dataFiles.map(dataFile => ( + + + + {/* */} + + {/* */} + {/* */} + + + ))} + +
Subject titleSizeRowsStatusUploaded byDate uploadedActions
{dataFile.title} + {dataFile.fileSize.size.toLocaleString()}{' '} + {dataFile.fileSize.unit} + {dataFile.rows} + + + {dataFile.userName} + + {!dataFile.created ? undefined : ( + + {dataFile.created} + + )} + + + View details} + > + + + {canUpdateRelease && + terminalImportStatuses.includes(dataFile.status) && ( + <> + {dataFile.status === 'COMPLETE' && ( + <> + ( + releaseDataFileRoute.path, + { + publicationId, + releaseId, + fileId: dataFile.id, + }, + )} + > + Edit title + + {dataFile.publicApiDataSetId ? ( + Replace data + } + > +

+ This data file has an API data set linked to + it. Please remove the API data set before + replacing the data. +

+

+ ( + releaseApiDataSetDetailsRoute.path, + { + publicationId, + releaseId, + dataSetId: dataFile.publicApiDataSetId, + }, + )} + > + Go to API data set + +

+
+ ) : ( + ( + releaseDataFileReplaceRoute.path, + { + publicationId, + releaseId, + fileId: dataFile.id, + }, + )} + > + Replace data + + )} + + )} + {dataFile.publicApiDataSetId ? ( + + Delete files + + } + > +

+ This data file has an API data set linked to it. + Please remove the API data set before deleting. +

+

+ ( + releaseApiDataSetDetailsRoute.path, + { + publicationId, + releaseId, + dataSetId: dataFile.publicApiDataSetId, + }, + )} + > + Go to API data set + +

+
+ ) : ( + handleDeleteFile(dataFile)} + variant="warning" + > + Delete files + + )} + + )} + {dataFile.permissions.canCancelImport && ( + + )} +
+
+ + ); +}; + +export default DataFilesTable; diff --git a/src/explore-education-statistics-admin/src/pages/release/data/components/ImporterStatus.tsx b/src/explore-education-statistics-admin/src/pages/release/data/components/ImporterStatus.tsx index bcc76be7166..3a1aa271f45 100644 --- a/src/explore-education-statistics-admin/src/pages/release/data/components/ImporterStatus.tsx +++ b/src/explore-education-statistics-admin/src/pages/release/data/components/ImporterStatus.tsx @@ -87,11 +87,13 @@ interface ImporterStatusProps { releaseId: string; dataFile: DataFile; onStatusChange?: ImporterStatusChangeHandler; + className?: string; } const ImporterStatus = ({ releaseId, dataFile, onStatusChange, + className, }: ImporterStatusProps) => { const [currentStatus, setCurrentStatus] = useState({ status: dataFile.status, @@ -130,7 +132,7 @@ const ImporterStatus = ({ ); return ( -
+
{ const [deleteDataFile, setDeleteDataFile] = useState(); - const [activeFileIds, setActiveFileIds] = useState(); const [dataFiles, setDataFiles] = useState([]); const [bulkUploadPlan, setBulkUploadPlan] = useState(); @@ -89,22 +72,15 @@ const ReleaseDataUploadsSection = ({ const confirmBulkUploadPlan = useCallback( async (archiveDataSetFiles: ArchiveDataSetFile[]) => { - const newFiles = await releaseDataFileService.importBulkZipDataFile( + await releaseDataFileService.importBulkZipDataFile( releaseId, archiveDataSetFiles, ); setBulkUploadPlan(undefined); - setActiveFileIds([...dataFiles, ...newFiles].map(file => file.id)); refetchDataFiles(); }, - [ - releaseId, - setBulkUploadPlan, - setActiveFileIds, - dataFiles, - refetchDataFiles, - ], + [releaseId, setBulkUploadPlan, refetchDataFiles], ); const handleStatusChange = async ( @@ -124,8 +100,6 @@ const ReleaseDataUploadsSection = ({ dataFile.id, ); - setActiveFileIds([]); - setDataFiles(currentDataFiles => currentDataFiles.map(file => file.fileName !== dataFile.fileName @@ -140,6 +114,17 @@ const ReleaseDataUploadsSection = ({ ); }; + const handleDeleteFile = async (dataFile: DataFile) => { + releaseDataFileService + .getDeleteDataFilePlan(releaseId, dataFile) + .then(plan => { + setDeleteDataFile({ + plan, + file: dataFile, + }); + }); + }; + const handleSubmit = useCallback( async (values: DataFileUploadFormValues) => { const newFiles: DataFile[] = []; @@ -185,7 +170,6 @@ const ReleaseDataUploadsSection = ({ default: break; } - setActiveFileIds(newFiles.map(file => file.id)); }, [releaseId, refetchDataFiles], ); @@ -242,159 +226,14 @@ const ReleaseDataUploadsSection = ({ {dataFiles.length > 0 ? ( - { - setDataFiles( - await releaseDataFileService.updateDataFilesOrder( - releaseId, - fileIds, - ), - ); - }} - > - {dataFiles.map(dataFile => ( - -
- {dataFile.isDeleting && ( - - )} - - {canUpdateRelease && - terminalImportStatuses.includes(dataFile.status) && ( - <> - {dataFile.status === 'COMPLETE' && ( - <> - ( - releaseDataFileRoute.path, - { - publicationId, - releaseId, - fileId: dataFile.id, - }, - )} - > - Edit title - - {dataFile.publicApiDataSetId ? ( - Replace data - } - > -

- This data file has an API data set linked to - it. Please remove the API data set before - replacing the data. -

-

- ( - releaseApiDataSetDetailsRoute.path, - { - publicationId, - releaseId, - dataSetId: - dataFile.publicApiDataSetId, - }, - )} - > - Go to API data set - -

-
- ) : ( - ( - releaseDataFileReplaceRoute.path, - { - publicationId, - releaseId, - fileId: dataFile.id, - }, - )} - > - Replace data - - )} - - )} - {dataFile.publicApiDataSetId ? ( - - Delete files - - } - > -

- This data file has an API data set linked to it. - Please remove the API data set before deleting. -

-

- ( - releaseApiDataSetDetailsRoute.path, - { - publicationId, - releaseId, - dataSetId: dataFile.publicApiDataSetId, - }, - )} - > - Go to API data set - -

-
- ) : ( - - releaseDataFileService - .getDeleteDataFilePlan(releaseId, dataFile) - .then(plan => { - setDeleteDataFile({ - plan, - file: dataFile, - }); - }) - } - > - Delete files - - )} - - )} - {dataFile.permissions.canCancelImport && ( - - )} -
-
-
- ))} -
+ ) : ( No data files have been uploaded. )} diff --git a/src/explore-education-statistics-common/src/components/Tag.module.scss b/src/explore-education-statistics-common/src/components/Tag.module.scss index ddbc3cca79d..ab6dda7af92 100644 --- a/src/explore-education-statistics-common/src/components/Tag.module.scss +++ b/src/explore-education-statistics-common/src/components/Tag.module.scss @@ -3,4 +3,5 @@ // https://github.com/alphagov/govuk-frontend/issues/4626 .tag { max-width: none; + text-wrap: balance; } From 6aa1a17d61898b181bf8082e7387f4c138bdc0a8 Mon Sep 17 00:00:00 2001 From: Stuart Bennett Date: Thu, 12 Dec 2024 13:30:15 +0000 Subject: [PATCH 2/3] EES-5544 add reorder fnality --- .../data/components/DataFilesTable.tsx | 348 +++++++++--------- .../components/ReleaseDataUploadsSection.tsx | 39 +- 2 files changed, 215 insertions(+), 172 deletions(-) diff --git a/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx index 3f96a737cec..a0112653c55 100644 --- a/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx +++ b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx @@ -19,8 +19,10 @@ import { import ButtonGroup from '@common/components/ButtonGroup'; import ButtonText from '@common/components/ButtonText'; import Modal from '@common/components/Modal'; +import ReorderableList from '@common/components/ReorderableList'; +import reorder from '@common/utils/reorder'; +import React, { useEffect, useState } from 'react'; import { generatePath } from 'react-router'; -import React from 'react'; import styles from './DataFilesTable.module.scss'; interface Props { @@ -28,86 +30,146 @@ interface Props { publicationId: string; releaseId: string; canUpdateRelease?: boolean; - handleDeleteFile: (dataFile: DataFile) => Promise; - handleStatusChange: ( + isReordering: boolean; + onCancelReordering: () => void; + onConfirmReordering: (nextSeries: DataFile[]) => void; + onDeleteFile: (dataFile: DataFile) => Promise; + onStatusChange: ( dataFile: DataFile, { totalRows, status }: DataFileImportStatus, ) => Promise; } const DataFilesTable = ({ - dataFiles, + dataFiles: initialDataFiles, publicationId, releaseId, canUpdateRelease, - handleDeleteFile, - handleStatusChange, + isReordering, + onCancelReordering, + onConfirmReordering, + onDeleteFile, + onStatusChange, }: Props) => { + const [dataFiles, setDataFiles] = useState(initialDataFiles); + + useEffect(() => { + setDataFiles(initialDataFiles); + }, [initialDataFiles]); + + if (isReordering) { + return ( + ({ + id, + label: title, + }))} + onCancel={() => { + setDataFiles(initialDataFiles); + onCancelReordering(); + }} + onConfirm={() => onConfirmReordering(dataFiles)} + onMoveItem={({ prevIndex, nextIndex }) => { + const reordered = reorder(dataFiles, prevIndex, nextIndex); + setDataFiles(reordered); + }} + onReverse={() => { + setDataFiles(dataFiles.toReversed()); + }} + /> + ); + } + return ( - <> -

Uploaded data files

- - - - - - {/* */} - - {/* */} - {/* - */} - - - +
Subject titleSizeRowsStatusUploaded byDate uploadedActions
+ + + + + + + + - - {dataFiles.map(dataFile => ( - - - - {/* */} - - {/* */} - {/* */} - + {dataFiles.map(dataFile => ( + + + + + - - ))} - -
Subject titleSizeStatusActions
{dataFile.title} - {dataFile.fileSize.size.toLocaleString()}{' '} - {dataFile.fileSize.unit} - {dataFile.rows} - - - {dataFile.userName} - - {!dataFile.created ? undefined : ( - - {dataFile.created} - - )} - - - View details} - > - - - {canUpdateRelease && - terminalImportStatuses.includes(dataFile.status) && ( - <> - {dataFile.status === 'COMPLETE' && ( - <> +
{dataFile.title} + {dataFile.fileSize.size.toLocaleString()} {dataFile.fileSize.unit} + + + + + View details} + > + + + {canUpdateRelease && + terminalImportStatuses.includes(dataFile.status) && ( + <> + {dataFile.status === 'COMPLETE' && ( + <> + ( + releaseDataFileRoute.path, + { + publicationId, + releaseId, + fileId: dataFile.id, + }, + )} + > + Edit title + + {dataFile.publicApiDataSetId ? ( + Replace data + } + > +

+ This data file has an API data set linked to it. + Please remove the API data set before replacing + the data. +

+

+ ( + releaseApiDataSetDetailsRoute.path, + { + publicationId, + releaseId, + dataSetId: dataFile.publicApiDataSetId, + }, + )} + > + Go to API data set + +

+
+ ) : ( ( - releaseDataFileRoute.path, + to={generatePath( + releaseDataFileReplaceRoute.path, { publicationId, releaseId, @@ -115,104 +177,62 @@ const DataFilesTable = ({ }, )} > - Edit title + Replace data - {dataFile.publicApiDataSetId ? ( - Replace data - } - > -

- This data file has an API data set linked to - it. Please remove the API data set before - replacing the data. -

-

- ( - releaseApiDataSetDetailsRoute.path, - { - publicationId, - releaseId, - dataSetId: dataFile.publicApiDataSetId, - }, - )} - > - Go to API data set - -

-
- ) : ( - ( - releaseDataFileReplaceRoute.path, - { - publicationId, - releaseId, - fileId: dataFile.id, - }, - )} - > - Replace data - - )} - - )} - {dataFile.publicApiDataSetId ? ( - - Delete files - - } - > -

- This data file has an API data set linked to it. - Please remove the API data set before deleting. -

-

- ( - releaseApiDataSetDetailsRoute.path, - { - publicationId, - releaseId, - dataSetId: dataFile.publicApiDataSetId, - }, - )} - > - Go to API data set - -

-
- ) : ( - handleDeleteFile(dataFile)} - variant="warning" - > - Delete files - - )} - - )} - {dataFile.permissions.canCancelImport && ( - + )} + + )} + {dataFile.publicApiDataSetId ? ( + + Delete files + + } + > +

+ This data file has an API data set linked to it. + Please remove the API data set before deleting. +

+

+ ( + releaseApiDataSetDetailsRoute.path, + { + publicationId, + releaseId, + dataSetId: dataFile.publicApiDataSetId, + }, + )} + > + Go to API data set + +

+
+ ) : ( + onDeleteFile(dataFile)} + variant="warning" + > + Delete files + + )} + )} -
-
- + {dataFile.permissions.canCancelImport && ( + + )} + + + + ))} + + ); }; diff --git a/src/explore-education-statistics-admin/src/pages/release/data/components/ReleaseDataUploadsSection.tsx b/src/explore-education-statistics-admin/src/pages/release/data/components/ReleaseDataUploadsSection.tsx index 2366e31b6c1..f3c2542968a 100644 --- a/src/explore-education-statistics-admin/src/pages/release/data/components/ReleaseDataUploadsSection.tsx +++ b/src/explore-education-statistics-admin/src/pages/release/data/components/ReleaseDataUploadsSection.tsx @@ -9,10 +9,12 @@ import releaseDataFileService, { DataFileImportStatus, DeleteDataFilePlan, } from '@admin/services/releaseDataFileService'; +import Button from '@common/components/Button'; import InsetText from '@common/components/InsetText'; import LoadingSpinner from '@common/components/LoadingSpinner'; import ModalConfirm from '@common/components/ModalConfirm'; import WarningMessage from '@common/components/WarningMessage'; +import useToggle from '@common/hooks/useToggle'; import logger from '@common/services/logger'; import { useQuery } from '@tanstack/react-query'; import React, { useCallback, useEffect, useState } from 'react'; @@ -40,6 +42,7 @@ const ReleaseDataUploadsSection = ({ const [deleteDataFile, setDeleteDataFile] = useState(); const [dataFiles, setDataFiles] = useState([]); const [bulkUploadPlan, setBulkUploadPlan] = useState(); + const [isReordering, toggleReordering] = useToggle(false); const { data: initialDataFiles, @@ -226,14 +229,34 @@ const ReleaseDataUploadsSection = ({ {dataFiles.length > 0 ? ( - + <> +

Uploaded data files

+ { + setDataFiles( + await releaseDataFileService.updateDataFilesOrder( + releaseId, + nextDataFiles.map(file => file.id), + ), + ); + toggleReordering.off(); + }} + onStatusChange={handleStatusChange} + onDeleteFile={handleDeleteFile} + publicationId={publicationId} + releaseId={releaseId} + /> + + {isReordering ? undefined : ( + + )} + ) : ( No data files have been uploaded. )} From 85840e234a59f0ecf6d0704ce061630c7381c7a5 Mon Sep 17 00:00:00 2001 From: Stuart Bennett Date: Fri, 20 Dec 2024 13:38:25 +0000 Subject: [PATCH 3/3] EES-5544 update integration tests --- .../data/components/DataFilesTable.tsx | 8 +- .../ReleaseDataUploadsSection.test.tsx | 219 +++++++----------- 2 files changed, 94 insertions(+), 133 deletions(-) diff --git a/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx index a0112653c55..1c6e35a5477 100644 --- a/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx +++ b/src/explore-education-statistics-admin/src/pages/release/data/components/DataFilesTable.tsx @@ -96,11 +96,11 @@ const DataFilesTable = ({ {dataFiles.map(dataFile => ( - {dataFile.title} - + {dataFile.title} + {dataFile.fileSize.size.toLocaleString()} {dataFile.fileSize.unit} - + - + { 'release-1', ); - expect(screen.getAllByTestId('accordionSection')).toHaveLength(2); + expect(screen.getAllByRole('row')).toHaveLength(3); }); - const sections = screen.getAllByTestId('accordionSection'); - const section1 = within(sections[0]); + const fileTableRows = screen.getAllByRole('row'); + const fileTableRow1 = within(fileTableRows[1]); - expect( - section1.getByRole('button', { name: /Test data 1/ }), - ).toBeInTheDocument(); - - expect(section1.getByTestId('Subject title')).toHaveTextContent( + expect(fileTableRow1.getByTestId('Subject title')).toHaveTextContent( 'Test data 1', ); - expect(section1.getByTestId('Data file')).toHaveTextContent('data-1.csv'); - expect(section1.getByTestId('Metadata file')).toHaveTextContent( - 'data-1.meta.csv', - ); - expect(section1.getByTestId('Data file size')).toHaveTextContent('50 Kb'); - expect(section1.getByTestId('Number of rows')).toHaveTextContent('100'); - expect(section1.getByTestId('Status')).toHaveTextContent('Complete'); - expect(section1.getByTestId('Uploaded by')).toHaveTextContent( - 'user1@test.com', + expect(fileTableRow1.getByTestId('Data file size')).toHaveTextContent( + '50 Kb', ); - expect(section1.getByTestId('Date uploaded')).toHaveTextContent( - '12 June 2020 12:00', - ); - - const section2 = within(sections[1]); + expect(fileTableRow1.getByTestId('Status')).toHaveTextContent('Complete'); - expect( - section2.getByRole('button', { name: /Test data 2/ }), - ).toBeInTheDocument(); + const fileTableRow2 = within(fileTableRows[2]); - expect(section2.getByTestId('Subject title')).toHaveTextContent( + expect(fileTableRow2.getByTestId('Subject title')).toHaveTextContent( 'Test data 2', ); - expect(section2.getByTestId('Data file')).toHaveTextContent('data-2.csv'); - expect(section2.getByTestId('Metadata file')).toHaveTextContent( - 'data-2.meta.csv', - ); - expect(section2.getByTestId('Data file size')).toHaveTextContent('100 Kb'); - expect(section2.getByTestId('Number of rows')).toHaveTextContent('200'); - expect(section2.getByTestId('Status')).toHaveTextContent('Complete'); - expect(section2.getByTestId('Uploaded by')).toHaveTextContent( - 'user2@test.com', - ); - expect(section2.getByTestId('Date uploaded')).toHaveTextContent( - '1 July 2020 12:00', - ); + expect(fileTableRow2.getByTestId('Status')).toHaveTextContent('Complete'); }); test("renders data file details with status of 'Replacement in progress' if being replaced", async () => { @@ -222,16 +193,16 @@ describe('ReleaseDataUploadsSection', () => { 'release-1', ); - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1); + expect(screen.getAllByRole('row')).toHaveLength(2); }); - const section1 = getAccordionSection(0); + const fileTableRow1 = getTableRow(1); - expect( - section1.getByRole('button', { name: /Test data 1/ }), - ).toBeInTheDocument(); + expect(fileTableRow1.getByTestId('Subject title')).toHaveTextContent( + 'Test data 1', + ); - expect(section1.getByTestId('Status')).toHaveTextContent( + expect(fileTableRow1.getByTestId('Status')).toHaveTextContent( 'Data replacement in progress', ); }); @@ -281,21 +252,21 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(2); + expect(screen.getAllByRole('row')).toHaveLength(3); }); - const sections = screen.getAllByTestId('accordionSection'); + const fileTableRows = screen.getAllByRole('row'); - const section1 = within(sections[0]); - expect(section1.getByTestId('Status')).toHaveTextContent('Queued'); + const fileTableRow1 = within(fileTableRows[1]); + expect(fileTableRow1.getByTestId('Status')).toHaveTextContent('Queued'); expect( - section1.queryByRole('button', { name: 'Delete files' }), + fileTableRow1.queryByRole('button', { name: 'Delete files' }), ).not.toBeInTheDocument(); - const section2 = within(sections[1]); - expect(section2.getByTestId('Status')).toHaveTextContent('Complete'); + const fileTableRow2 = within(fileTableRows[2]); + expect(fileTableRow2.getByTestId('Status')).toHaveTextContent('Complete'); expect( - section2.getByRole('button', { name: 'Delete files' }), + fileTableRow2.getByRole('button', { name: 'Delete files' }), ).toBeInTheDocument(); }); @@ -339,19 +310,19 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(2); + expect(screen.getAllByRole('row')).toHaveLength(3); }); - const sections = screen.getAllByTestId('accordionSection'); + const fileTableRows = screen.getAllByRole('row'); expect( - within(sections[1]).getByRole('button', { + within(fileTableRows[2]).getByRole('button', { name: 'Delete files', }), ).toBeInTheDocument(); await user.click( - within(sections[1]).getByRole('button', { + within(fileTableRows[2]).getByRole('button', { name: 'Delete files', }), ); @@ -423,19 +394,19 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(2); + expect(screen.getAllByRole('row')).toHaveLength(3); }); - const sections = screen.getAllByTestId('accordionSection'); + const fileTableRows = screen.getAllByRole('row'); expect( - within(sections[1]).getByRole('button', { + within(fileTableRows[2]).getByRole('button', { name: 'Delete files', }), ).toBeInTheDocument(); await user.click( - within(sections[1]).getByRole('button', { + within(fileTableRows[2]).getByRole('button', { name: 'Delete files', }), ); @@ -453,14 +424,12 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1); + expect(screen.getAllByRole('row')).toHaveLength(2); }); - expect( - within(screen.getByTestId('accordionSection')).getByRole('button', { - name: /Test data 1/, - }), - ).toBeInTheDocument(); + expect(getTableRow(1).getByTestId('Subject title')).toHaveTextContent( + 'Test data 1', + ); }); test('does not allow deleting files when linked to an API data set', async () => { @@ -482,13 +451,13 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1); + expect(screen.getAllByRole('row')).toHaveLength(2); }); - const sections = screen.getAllByTestId('accordionSection'); + const fileTableRows = screen.getAllByRole('row'); await user.click( - within(sections[0]).getByRole('button', { + within(fileTableRows[1]).getByRole('button', { name: 'Delete files', }), ); @@ -535,22 +504,21 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(2); + expect(screen.getAllByRole('row')).toHaveLength(3); }); - const sections = screen.getAllByTestId('accordionSection'); - expect(sections).toHaveLength(2); + const fileTableRows = screen.getAllByRole('row'); - const section1 = within(sections[0]); - expect(section1.getByTestId('Status')).toHaveTextContent('Queued'); + const fileTableRow1 = within(fileTableRows[1]); + expect(fileTableRow1.getByTestId('Status')).toHaveTextContent('Queued'); expect( - section1.queryByRole('link', { name: 'Replace data' }), + fileTableRow1.queryByRole('link', { name: 'Replace data' }), ).not.toBeInTheDocument(); - const section2 = within(sections[1]); - expect(section2.getByTestId('Status')).toHaveTextContent('Complete'); + const fileTableRow2 = within(fileTableRows[2]); + expect(fileTableRow2.getByTestId('Status')).toHaveTextContent('Complete'); expect( - section2.getByRole('link', { name: 'Replace data' }), + fileTableRow2.getByRole('link', { name: 'Replace data' }), ).toBeInTheDocument(); }); @@ -574,14 +542,14 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(2); + expect(screen.getAllByRole('row')).toHaveLength(3); }); - const sections = screen.getAllByTestId('accordionSection'); + const fileTableRows = screen.getAllByRole('row'); - const section2 = within(sections[1]); + const fileTableRow2 = within(fileTableRows[2]); expect( - section2.getByRole('link', { name: 'Replace data' }), + fileTableRow2.getByRole('link', { name: 'Replace data' }), ).toHaveAttribute( 'href', '/publication/publication-1/release/release-1/data/data-2/replace', @@ -607,13 +575,13 @@ describe('ReleaseDataUploadsSection', () => { ); await waitFor(() => { - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1); + expect(screen.getAllByRole('row')).toHaveLength(2); }); - const sections = screen.getAllByTestId('accordionSection'); + const fileTableRows = screen.getAllByRole('row'); await user.click( - within(sections[0]).getByRole('button', { name: 'Replace data' }), + within(fileTableRows[1]).getByRole('button', { name: 'Replace data' }), ); await waitFor(() => { @@ -994,7 +962,8 @@ describe('ReleaseDataUploadsSection', () => { }); }); - test('updates the number of rows after uploading CSV file when status changes', async () => { + test('updates the file size after uploading CSV file when status changes', async () => { + // we don't display rows :/ releaseDataFileService.uploadDataFiles.mockResolvedValue( testUploadedDataFile, ); @@ -1061,8 +1030,8 @@ describe('ReleaseDataUploadsSection', () => { ); }); - const sections = screen.getAllByTestId('accordionSection'); - const section3 = within(sections[2]); + const fileTableRows = screen.getAllByRole('row'); + const fileTableRow3 = within(fileTableRows[3]); await waitFor(() => expect( @@ -1070,11 +1039,13 @@ describe('ReleaseDataUploadsSection', () => { ).toHaveBeenCalledWith('release-1', testUploadedDataFile2), ); await waitFor(() => { - expect(section3.getByTestId('Number of rows')).toHaveTextContent('100'); + expect(fileTableRow3.getByTestId('Data file size')).toHaveTextContent( + '150 Kb', + ); }); }); - test('updates the number of rows after uploading ZIP file when status changes', async () => { + test('updates the file size after uploading ZIP file when status changes', async () => { releaseDataFileService.uploadZipDataFile.mockResolvedValue({ ...testUploadedZipFile, }); @@ -1132,8 +1103,8 @@ describe('ReleaseDataUploadsSection', () => { ), ); - const sections = screen.getAllByTestId('accordionSection'); - const section3 = within(sections[2]); + const fileTableRows = screen.getAllByRole('row'); + const fileTableRow3 = within(fileTableRows[3]); await waitFor(() => expect( @@ -1141,7 +1112,9 @@ describe('ReleaseDataUploadsSection', () => { ).toHaveBeenCalledWith('release-1', testUploadedDataFile2), ); await waitFor(() => { - expect(section3.getByTestId('Number of rows')).toHaveTextContent('100'); + expect(fileTableRow3.getByTestId('Data file size')).toHaveTextContent( + '150 Kb', + ); }); }); @@ -1169,14 +1142,12 @@ describe('ReleaseDataUploadsSection', () => { , ); - await waitFor(() => - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1), - ); + await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(2)); - const section = getAccordionSection(0); + const fileTableRow = getTableRow(1); expect( - section.getByRole('button', { name: 'Cancel' }), + fileTableRow.getByRole('button', { name: 'Cancel' }), ).toBeInTheDocument(); }); @@ -1203,14 +1174,12 @@ describe('ReleaseDataUploadsSection', () => { , ); - await waitFor(() => - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1), - ); + await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(2)); - const section = getAccordionSection(0); + const fileTableRow = getTableRow(1); expect( - section.queryByRole('button', { name: 'Cancel' }), + fileTableRow.queryByRole('button', { name: 'Cancel' }), ).not.toBeInTheDocument(); }); }); @@ -1238,13 +1207,11 @@ describe('ReleaseDataUploadsSection', () => { , ); - await waitFor(() => - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1), - ); + await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(2)); - const section = getAccordionSection(0); + const fileTableRow = getTableRow(1); - await user.click(section.getByRole('button', { name: 'Cancel' })); + await user.click(fileTableRow.getByRole('button', { name: 'Cancel' })); await waitFor(() => { expect( @@ -1286,13 +1253,11 @@ describe('ReleaseDataUploadsSection', () => { , ); - await waitFor(() => - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1), - ); + await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(2)); - const section = getAccordionSection(0); + const fileTableRow = getTableRow(1); - await user.click(section.getByRole('button', { name: 'Cancel' })); + await user.click(fileTableRow.getByRole('button', { name: 'Cancel' })); await waitFor(() => { expect( @@ -1318,7 +1283,7 @@ describe('ReleaseDataUploadsSection', () => { expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); expect( - section.queryByRole('button', { name: 'Cancel' }), + fileTableRow.queryByRole('button', { name: 'Cancel' }), ).not.toBeInTheDocument(); }); @@ -1337,13 +1302,11 @@ describe('ReleaseDataUploadsSection', () => { , ); - await waitFor(() => - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1), - ); + await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(2)); - const section = getAccordionSection(0); + const fileTableRow = getTableRow(1); - await user.click(section.getByRole('button', { name: 'Cancel' })); + await user.click(fileTableRow.getByRole('button', { name: 'Cancel' })); await waitFor(() => { expect( @@ -1364,7 +1327,7 @@ describe('ReleaseDataUploadsSection', () => { expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); expect( - section.getByRole('button', { name: 'Cancel' }), + fileTableRow.getByRole('button', { name: 'Cancel' }), ).toBeInTheDocument(); }); @@ -1385,13 +1348,11 @@ describe('ReleaseDataUploadsSection', () => { , ); - await waitFor(() => - expect(screen.getAllByTestId('accordionSection')).toHaveLength(1), - ); + await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(2)); - const section = getAccordionSection(0); + const fileTableRow = getTableRow(1); - await user.click(section.getByRole('button', { name: 'Cancel' })); + await user.click(fileTableRow.getByRole('button', { name: 'Cancel' })); await waitFor(() => { expect( @@ -1418,14 +1379,14 @@ describe('ReleaseDataUploadsSection', () => { expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); expect( - section.queryByRole('button', { name: 'Cancel' }), + fileTableRow.queryByRole('button', { name: 'Cancel' }), ).not.toBeInTheDocument(); expect(screen.getByText('Cancellation failed')).toBeInTheDocument(); }); }); - function getAccordionSection(index: number) { - return within(screen.getAllByTestId('accordionSection')[index]); + function getTableRow(index: number) { + return within(screen.getAllByRole('row')[index]); } });