) {
diff --git a/src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.module.scss b/src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.module.scss
new file mode 100644
index 000000000..fdac01057
--- /dev/null
+++ b/src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.module.scss
@@ -0,0 +1,12 @@
+@import "node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module";
+
+.container {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ background-color: $dv-warning-box-color;
+}
+
+.message {
+ margin-left: 0.75rem;
+}
\ No newline at end of file
diff --git a/src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.tsx b/src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.tsx
new file mode 100644
index 000000000..51bc69772
--- /dev/null
+++ b/src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.tsx
@@ -0,0 +1,51 @@
+import { createRowSelection, RowSelection } from '../useFilesTable'
+import { Button } from '@iqss/dataverse-design-system'
+import { useTranslation } from 'react-i18next'
+import styles from './RowSelectionMessage.module.scss'
+
+interface RowSelectionMessageProps {
+ selectedFilesCount: number
+ totalFilesCount: number
+ setRowSelection: (rowSelection: RowSelection) => void
+}
+
+const MINIMUM_SELECTED_FILES_TO_SHOW_MESSAGE = 0
+const MINIMUM_FILES_TO_SHOW_MESSAGE = 10
+
+export function RowSelectionMessage({
+ selectedFilesCount,
+ totalFilesCount,
+ setRowSelection
+}: RowSelectionMessageProps) {
+ const { t } = useTranslation('files')
+ const showMessage =
+ totalFilesCount > MINIMUM_FILES_TO_SHOW_MESSAGE &&
+ selectedFilesCount > MINIMUM_SELECTED_FILES_TO_SHOW_MESSAGE
+ const selectAllRowsHandler = () => {
+ const rowSelectionAll = createRowSelection(totalFilesCount)
+ setRowSelection(rowSelectionAll)
+ }
+ const clearSelectionHandler = () => {
+ const rowSelectionNone = createRowSelection(0)
+ setRowSelection(rowSelectionNone)
+ }
+
+ if (!showMessage) {
+ return <>>
+ }
+ return (
+
+
+ {t('table.rowSelection.filesSelected', { count: selectedFilesCount })}
+
+ {selectedFilesCount < totalFilesCount && (
+
+ )}
+
+
+ )
+}
diff --git a/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx b/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx
index faf246b67..40e7e11c3 100644
--- a/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx
+++ b/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx
@@ -8,6 +8,10 @@ import {
} from '@tanstack/react-table'
import { columns } from './FilesTableColumnsDefinition'
+export interface RowSelection {
+ [key: string]: boolean
+}
+
export function useFilesTable(files: File[]) {
const [rowSelection, setRowSelection] = useState({})
@@ -25,5 +29,15 @@ export function useFilesTable(files: File[]) {
debugTable: true
})
- return { table }
+ return { table, rowSelection, setRowSelection }
+}
+
+export function createRowSelection(numberOfRows: number) {
+ const rowSelection: Record = {}
+
+ for (let i = 0; i < numberOfRows; i++) {
+ rowSelection[i as unknown as string] = true
+ }
+
+ return rowSelection
}
diff --git a/src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage.tsx b/src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage.tsx
new file mode 100644
index 000000000..a066dba7a
--- /dev/null
+++ b/src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage.tsx
@@ -0,0 +1,73 @@
+import { useTranslation } from 'react-i18next'
+import styles from './ZipLimitMessage.module.scss'
+import { File, FileSizeUnit } from '../../../../../files/domain/models/File'
+import { useSettings } from '../../../../settings/SettingsContext'
+import { SettingName } from '../../../../../settings/domain/models/Setting'
+import { ZipDownloadLimit } from '../../../../../settings/domain/models/ZipDownloadLimit'
+import { useEffect, useState } from 'react'
+
+interface ZipDownloadLimitMessageProps {
+ selectedFiles: File[]
+}
+
+const MINIMUM_FILES_TO_SHOW_MESSAGE = 1
+
+export function ZipDownloadLimitMessage({ selectedFiles }: ZipDownloadLimitMessageProps) {
+ const { t } = useTranslation('files')
+ const { getSettingByName } = useSettings()
+ const [zipDownloadLimitInBytes, setZipDownloadLimitInBytes] = useState()
+ const selectionTotalSizeInBytes = getFilesTotalSizeInBytes(selectedFiles)
+
+ useEffect(() => {
+ getSettingByName(SettingName.ZIP_DOWNLOAD_LIMIT)
+ .then((zipDownloadLimit) => {
+ setZipDownloadLimitInBytes(zipDownloadLimit.value.toBytes())
+ })
+ .catch((error) => {
+ console.error(error)
+ })
+ }, [getSettingByName])
+
+ const showMessage =
+ zipDownloadLimitInBytes &&
+ selectedFiles.length > MINIMUM_FILES_TO_SHOW_MESSAGE &&
+ selectionTotalSizeInBytes > zipDownloadLimitInBytes
+
+ if (!showMessage) {
+ return <>>
+ }
+ return (
+
+
+ {t('table.zipDownloadExceedsLimit', {
+ selectionTotalSize: bytesToHumanReadable(selectionTotalSizeInBytes),
+ zipDownloadSizeLimit: bytesToHumanReadable(zipDownloadLimitInBytes)
+ })}
+
+
+ )
+}
+
+function getFilesTotalSizeInBytes(files: File[]) {
+ return files.map((file) => file.size).reduce((bytes, size) => bytes + size.toBytes(), 0)
+}
+
+function bytesToHumanReadable(bytes: number) {
+ const units = [
+ FileSizeUnit.BYTES,
+ FileSizeUnit.KILOBYTES,
+ FileSizeUnit.MEGABYTES,
+ FileSizeUnit.GIGABYTES,
+ FileSizeUnit.TERABYTES,
+ FileSizeUnit.PETABYTES
+ ]
+ const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024))
+ const unit = units[unitIndex]
+
+ if (unit == undefined) {
+ return 'more than 1024.0 PB'
+ }
+
+ const value = bytes / Math.pow(1024, unitIndex)
+ return `${value.toFixed(1)} ${unit}`
+}
diff --git a/src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipLimitMessage.module.scss b/src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipLimitMessage.module.scss
new file mode 100644
index 000000000..fdac01057
--- /dev/null
+++ b/src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipLimitMessage.module.scss
@@ -0,0 +1,12 @@
+@import "node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module";
+
+.container {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ background-color: $dv-warning-box-color;
+}
+
+.message {
+ margin-left: 0.75rem;
+}
\ No newline at end of file
diff --git a/src/sections/settings/SettingsContext.ts b/src/sections/settings/SettingsContext.ts
new file mode 100644
index 000000000..71654be11
--- /dev/null
+++ b/src/sections/settings/SettingsContext.ts
@@ -0,0 +1,11 @@
+import { createContext, useContext } from 'react'
+import { Setting, SettingName } from '../../settings/domain/models/Setting'
+
+interface SettingsContextProps {
+ getSettingByName: (name: SettingName) => Promise>
+}
+
+export const SettingsContext = createContext({
+ getSettingByName: () => Promise.reject('Not implemented')
+})
+export const useSettings = () => useContext(SettingsContext)
diff --git a/src/sections/settings/SettingsProvider.tsx b/src/sections/settings/SettingsProvider.tsx
new file mode 100644
index 000000000..f0489039f
--- /dev/null
+++ b/src/sections/settings/SettingsProvider.tsx
@@ -0,0 +1,34 @@
+import { PropsWithChildren, useState } from 'react'
+import { SettingsContext } from './SettingsContext'
+import { Setting, SettingName } from '../../settings/domain/models/Setting'
+import { SettingRepository } from '../../settings/domain/repositories/SettingRepository'
+
+interface SettingsProviderProps {
+ repository: SettingRepository
+}
+
+export function SettingsProvider({
+ repository,
+ children
+}: PropsWithChildren) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const [settings, setSettings] = useState[]>([])
+
+ function getSettingByName(name: SettingName): Promise> {
+ const setting = settings.find((setting) => setting.name === name)
+ if (setting) {
+ return Promise.resolve(setting as Setting)
+ }
+
+ return repository.getByName(name).then((setting) => {
+ setSettings((settings) => [...settings, setting])
+ return setting
+ })
+ }
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/src/settings/domain/models/Setting.ts b/src/settings/domain/models/Setting.ts
new file mode 100644
index 000000000..857b29a50
--- /dev/null
+++ b/src/settings/domain/models/Setting.ts
@@ -0,0 +1,8 @@
+export enum SettingName {
+ ZIP_DOWNLOAD_LIMIT = 'ZIP_DOWNLOAD_LIMIT'
+}
+
+export interface Setting {
+ name: SettingName
+ value: T
+}
diff --git a/src/settings/domain/models/ZipDownloadLimit.ts b/src/settings/domain/models/ZipDownloadLimit.ts
new file mode 100644
index 000000000..d6a6b415e
--- /dev/null
+++ b/src/settings/domain/models/ZipDownloadLimit.ts
@@ -0,0 +1,3 @@
+import { FileSize } from '../../../files/domain/models/File'
+
+export class ZipDownloadLimit extends FileSize {}
diff --git a/src/settings/domain/repositories/SettingRepository.ts b/src/settings/domain/repositories/SettingRepository.ts
new file mode 100644
index 000000000..5e9912689
--- /dev/null
+++ b/src/settings/domain/repositories/SettingRepository.ts
@@ -0,0 +1,5 @@
+import { Setting, SettingName } from '../models/Setting'
+
+export interface SettingRepository {
+ getByName: (name: SettingName) => Promise>
+}
diff --git a/src/settings/domain/useCases/getByName.ts b/src/settings/domain/useCases/getByName.ts
new file mode 100644
index 000000000..8923c36ca
--- /dev/null
+++ b/src/settings/domain/useCases/getByName.ts
@@ -0,0 +1,11 @@
+import { SettingRepository } from '../repositories/SettingRepository'
+import { Setting, SettingName } from '../models/Setting'
+
+export async function getByName(
+ settingRepository: SettingRepository,
+ name: SettingName
+): Promise> {
+ return settingRepository.getByName(name).catch((error: Error) => {
+ throw new Error(error.message)
+ })
+}
diff --git a/src/settings/infrastructure/SettingJSDataverseRepository.ts b/src/settings/infrastructure/SettingJSDataverseRepository.ts
new file mode 100644
index 000000000..03deebe37
--- /dev/null
+++ b/src/settings/infrastructure/SettingJSDataverseRepository.ts
@@ -0,0 +1,19 @@
+import { SettingRepository } from '../domain/repositories/SettingRepository'
+import { Setting, SettingName } from '../domain/models/Setting'
+import { ZipDownloadLimit } from '../domain/models/ZipDownloadLimit'
+import { FileSizeUnit } from '../../files/domain/models/File'
+
+export class SettingJSDataverseRepository implements SettingRepository {
+ // eslint-disable-next-line unused-imports/no-unused-vars
+ getByName(name: SettingName): Promise> {
+ // TODO - implement using js-dataverse
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({
+ name: SettingName.ZIP_DOWNLOAD_LIMIT,
+ value: new ZipDownloadLimit(500, FileSizeUnit.BYTES)
+ } as Setting)
+ }, 1000)
+ })
+ }
+}
diff --git a/src/stories/WithSettings.tsx b/src/stories/WithSettings.tsx
new file mode 100644
index 000000000..def130b42
--- /dev/null
+++ b/src/stories/WithSettings.tsx
@@ -0,0 +1,20 @@
+import { StoryFn } from '@storybook/react'
+import { SettingsContext } from '../sections/settings/SettingsContext'
+import { Setting, SettingName } from '../settings/domain/models/Setting'
+import { SettingMother } from '../../tests/component/settings/domain/models/SettingMother'
+import { ZipDownloadLimit } from '../settings/domain/models/ZipDownloadLimit'
+import { FileSizeUnit } from '../files/domain/models/File'
+
+const zipDownloadLimitMock = new ZipDownloadLimit(500, FileSizeUnit.BYTES)
+export const WithSettings = (Story: StoryFn) => {
+ // eslint-disable-next-line unused-imports/no-unused-vars
+ function getSettingByName(name: SettingName): Promise> {
+ return Promise.resolve(SettingMother.createZipDownloadLimit(zipDownloadLimitMock) as Setting)
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/src/stories/dataset/Dataset.stories.tsx b/src/stories/dataset/Dataset.stories.tsx
index b8749a94e..f66457c54 100644
--- a/src/stories/dataset/Dataset.stories.tsx
+++ b/src/stories/dataset/Dataset.stories.tsx
@@ -9,11 +9,12 @@ import { DatasetMockNoDataRepository } from './DatasetMockNoDataRepository'
import { FileMockRepository } from '../files/FileMockRepository'
import { WithCitationMetadataBlockInfo } from './WithCitationMetadataBlockInfo'
import { FileMockNoDataRepository } from '../files/FileMockNoDataRepository'
+import { WithSettings } from '../WithSettings'
const meta: Meta = {
title: 'Pages/Dataset',
component: Dataset,
- decorators: [WithI18next, WithCitationMetadataBlockInfo],
+ decorators: [WithI18next, WithCitationMetadataBlockInfo, WithSettings],
parameters: {
// Sets the delay for all stories.
chromatic: { delay: 15000, pauseAnimationAtEnd: true }
diff --git a/src/stories/dataset/dataset-files/DatasetFiles.stories.tsx b/src/stories/dataset/dataset-files/DatasetFiles.stories.tsx
index a401a8e4a..dec369520 100644
--- a/src/stories/dataset/dataset-files/DatasetFiles.stories.tsx
+++ b/src/stories/dataset/dataset-files/DatasetFiles.stories.tsx
@@ -5,12 +5,13 @@ import { DatasetMockData } from '../DatasetMockData'
import { FileMockRepository } from '../../files/FileMockRepository'
import { FileMockLoadingRepository } from '../../files/FileMockLoadingRepository'
import { FileMockNoDataRepository } from '../../files/FileMockNoDataRepository'
+import { WithSettings } from '../../WithSettings'
import { FileMockNoFiltersRepository } from '../../files/FileMockNoFiltersRepository'
const meta: Meta = {
title: 'Sections/Dataset Page/DatasetFiles',
component: DatasetFiles,
- decorators: [WithI18next]
+ decorators: [WithI18next, WithSettings]
}
export default meta
diff --git a/src/stories/files/FileMockLoadingRepository.ts b/src/stories/files/FileMockLoadingRepository.ts
index 65a5fa7d1..86fb02192 100644
--- a/src/stories/files/FileMockLoadingRepository.ts
+++ b/src/stories/files/FileMockLoadingRepository.ts
@@ -11,13 +11,13 @@ export class FileMockLoadingRepository implements FileRepository {
}, 0)
})
}
- // eslint-disable-next-line unused-imports/no-unused-vars
getCountInfoByDatasetPersistentId(
+ // eslint-disable-next-line unused-imports/no-unused-vars
persistentId: string,
+ // eslint-disable-next-line unused-imports/no-unused-vars
version?: string
): Promise {
- // TODO - implement using js-dataverse
- return new Promise((resolve) => {
+ return new Promise(() => {
setTimeout(() => {
// Do nothing
}, 1000)
diff --git a/src/stories/files/FileMockNoDataRepository.ts b/src/stories/files/FileMockNoDataRepository.ts
index bdc5c0fa1..60cead095 100644
--- a/src/stories/files/FileMockNoDataRepository.ts
+++ b/src/stories/files/FileMockNoDataRepository.ts
@@ -12,12 +12,12 @@ export class FileMockNoDataRepository implements FileRepository {
}, 1000)
})
}
- // eslint-disable-next-line unused-imports/no-unused-vars
getCountInfoByDatasetPersistentId(
+ // eslint-disable-next-line unused-imports/no-unused-vars
persistentId: string,
+ // eslint-disable-next-line unused-imports/no-unused-vars
version?: string
): Promise {
- // TODO - implement using js-dataverse
return new Promise((resolve) => {
setTimeout(() => {
resolve(FilesCountInfoMother.createEmpty())
diff --git a/src/stories/files/FileMockNoFiltersRepository.ts b/src/stories/files/FileMockNoFiltersRepository.ts
index 7ab2aebe1..345f1e6de 100644
--- a/src/stories/files/FileMockNoFiltersRepository.ts
+++ b/src/stories/files/FileMockNoFiltersRepository.ts
@@ -13,12 +13,12 @@ export class FileMockNoFiltersRepository implements FileRepository {
}, 1000)
})
}
- // eslint-disable-next-line unused-imports/no-unused-vars
getCountInfoByDatasetPersistentId(
+ // eslint-disable-next-line unused-imports/no-unused-vars
persistentId: string,
+ // eslint-disable-next-line unused-imports/no-unused-vars
version?: string
): Promise {
- // TODO - implement using js-dataverse
return new Promise((resolve) => {
setTimeout(() => {
resolve(FilesCountInfoMother.createOnlyTotal())
diff --git a/src/stories/files/FileMockRepository.ts b/src/stories/files/FileMockRepository.ts
index 4c4e8904b..df1224a35 100644
--- a/src/stories/files/FileMockRepository.ts
+++ b/src/stories/files/FileMockRepository.ts
@@ -13,15 +13,15 @@ export class FileMockRepository implements FileRepository {
}, 1000)
})
}
- // eslint-disable-next-line unused-imports/no-unused-vars
getCountInfoByDatasetPersistentId(
+ // eslint-disable-next-line unused-imports/no-unused-vars
persistentId: string,
+ // eslint-disable-next-line unused-imports/no-unused-vars
version?: string
): Promise {
- // TODO - implement using js-dataverse
return new Promise((resolve) => {
setTimeout(() => {
- resolve(FilesCountInfoMother.create())
+ resolve(FilesCountInfoMother.create({ total: 200 }))
}, 1000)
})
}
diff --git a/tests/component/sections/dataset/dataset-files/DatasetFiles.spec.tsx b/tests/component/sections/dataset/dataset-files/DatasetFiles.spec.tsx
index 3d7af822d..701030599 100644
--- a/tests/component/sections/dataset/dataset-files/DatasetFiles.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/DatasetFiles.spec.tsx
@@ -3,6 +3,11 @@ import { DatasetFiles } from '../../../../../src/sections/dataset/dataset-files/
import { FileRepository } from '../../../../../src/files/domain/repositories/FileRepository'
import { FileCriteria, FileSortByOption } from '../../../../../src/files/domain/models/FileCriteria'
import { FilesCountInfoMother } from '../../../files/domain/models/FilesCountInfoMother'
+import { FileSize, FileSizeUnit } from '../../../../../src/files/domain/models/File'
+import { ZipDownloadLimit } from '../../../../../src/settings/domain/models/ZipDownloadLimit'
+import { SettingMother } from '../../../settings/domain/models/SettingMother'
+import { SettingsContext } from '../../../../../src/sections/settings/SettingsContext'
+import styles from '../../../../../src/sections/dataset/dataset-files/files-table/FilesTable.module.scss'
const testFiles = FileMother.createMany(200)
const datasetPersistentId = 'test-dataset-persistent-id'
@@ -77,9 +82,9 @@ describe('DatasetFiles', () => {
)
cy.findByRole('button', { name: /Sort/ }).should('not.exist')
- cy.findByRole('button', { name: 'Filter Type: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Type: All' }).should('not.exist')
cy.findByRole('button', { name: 'Access: All' }).should('not.exist')
- cy.findByRole('button', { name: 'Filter Tag: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Tags: All' }).should('not.exist')
cy.findByText('There are no files in this dataset.').should('exist')
})
@@ -117,6 +122,106 @@ describe('DatasetFiles', () => {
new FileCriteria().withSortBy(FileSortByOption.NAME_AZ)
)
- cy.findByRole('button', { name: 'Filter Type: All' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: All' }).should('exist')
+ })
+
+ it('calls the useFiles hook with the correct parameters when searchText criteria changes', () => {
+ cy.customMount(
+
+ )
+
+ cy.findByLabelText('Search').type('test{enter}')
+ cy.wrap(fileRepository.getAllByDatasetPersistentId).should(
+ 'be.calledWith',
+ datasetPersistentId,
+ datasetVersion,
+ new FileCriteria().withSearchText('test')
+ )
+ })
+
+ it("selects all rows when the 'Select all' button is clicked", () => {
+ cy.customMount(
+
+ )
+
+ cy.get('table > tbody > tr:nth-child(2) > td:nth-child(1) > input[type=checkbox]').click()
+
+ cy.findByRole('button', { name: 'Select all 200 files in this dataset.' }).click()
+
+ cy.findByText('200 files are currently selected.').should('exist')
+
+ cy.findByRole('button', { name: 'Select all 200 files in this dataset.' }).should('not.exist')
+ })
+
+ it('clears the selection when the clear selection button is clicked', () => {
+ cy.customMount(
+
+ )
+
+ cy.get('table > tbody > tr:nth-child(2) > td:nth-child(1) > input[type=checkbox]').click()
+
+ cy.findByRole('button', { name: 'Select all 200 files in this dataset.' }).click()
+
+ cy.findByText('200 files are currently selected.').should('exist')
+
+ cy.findByRole('button', { name: 'Clear selection.' }).click()
+
+ cy.findByText(/files are currently selected./).should('not.exist')
+ })
+
+ it('highlights the selected rows', () => {
+ cy.customMount(
+
+ )
+ cy.get('table > tbody > tr:nth-child(2) > td:nth-child(1) > input[type=checkbox]').click()
+
+ cy.get('table > tbody > tr:nth-child(2)').should('have.class', styles['selected-row'])
+ })
+
+ it('renders the zip download limit message when the zip download limit is reached', () => {
+ const testFiles = [
+ FileMother.create({ size: new FileSize(1024, FileSizeUnit.BYTES) }),
+ FileMother.create({ size: new FileSize(2048, FileSizeUnit.BYTES) })
+ ]
+ fileRepository.getAllByDatasetPersistentId = cy.stub().resolves(testFiles)
+ const getSettingByName = cy
+ .stub()
+ .resolves(SettingMother.createZipDownloadLimit(new ZipDownloadLimit(500, FileSizeUnit.BYTES)))
+
+ cy.customMount(
+
+
+
+ )
+
+ cy.findByText(
+ 'The overall size of the files selected (3.0 KB) for download exceeds the zip limit of 500.0 B. Please unselect some files to continue.'
+ ).should('not.exist')
+ cy.get('table > tbody > tr:nth-child(1) > td:nth-child(1) > input[type=checkbox]').click()
+ cy.get('table > tbody > tr:nth-child(2) > td:nth-child(1) > input[type=checkbox]').click()
+
+ cy.findByText(
+ 'The overall size of the files selected (3.0 KB) for download exceeds the zip limit of 500.0 B. Please unselect some files to continue.'
+ ).should('exist')
})
})
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByAccess.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByAccess.spec.tsx
similarity index 96%
rename from tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByAccess.spec.tsx
rename to tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByAccess.spec.tsx
index dacdf92c2..7c0afb6fd 100644
--- a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByAccess.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByAccess.spec.tsx
@@ -3,8 +3,8 @@ import {
FileCriteria
} from '../../../../../../src/files/domain/models/FileCriteria'
import { FilesCountInfoMother } from '../../../../files/domain/models/FilesCountInfoMother'
-import styles from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls.module.scss'
-import { FileCriteriaFilterByAccess } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByAccess'
+import styles from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.module.scss'
+import { FileCriteriaFilterByAccess } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByAccess'
const defaultCriteria = new FileCriteria()
const filesCountInfo = FilesCountInfoMother.create({
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByTag.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByTag.spec.tsx
similarity index 82%
rename from tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByTag.spec.tsx
rename to tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByTag.spec.tsx
index 49d36d2d2..d2acad803 100644
--- a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByTag.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByTag.spec.tsx
@@ -1,8 +1,8 @@
import { FileCriteria, FileTag } from '../../../../../../src/files/domain/models/FileCriteria'
import { FilesCountInfoMother } from '../../../../files/domain/models/FilesCountInfoMother'
import { FileType } from '../../../../../../src/files/domain/models/File'
-import styles from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls.module.scss'
-import { FileCriteriaFilterByTag } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByTag'
+import styles from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.module.scss'
+import { FileCriteriaFilterByTag } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByTag'
const defaultCriteria = new FileCriteria()
const filesCountInfo = FilesCountInfoMother.create({
@@ -30,7 +30,7 @@ describe('FilesCriteriaFilterByTag', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Tag: All' }).click()
+ cy.findByRole('button', { name: 'File Tags: All' }).click()
cy.findByText('All').should('exist')
cy.findByText('Document (5)').should('exist')
@@ -48,11 +48,11 @@ describe('FilesCriteriaFilterByTag', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Tag: All' }).click()
+ cy.findByRole('button', { name: 'File Tags: All' }).click()
cy.findByText('Document (5)').click()
cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withFilterByTag('document'))
- cy.findByRole('button', { name: 'Filter Tag: Document' }).click()
+ cy.findByRole('button', { name: 'File Tags: Document' }).click()
cy.findByText('Data (10)').click()
cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withFilterByTag('data'))
})
@@ -69,7 +69,7 @@ describe('FilesCriteriaFilterByTag', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Tag: Document' }).click()
+ cy.findByRole('button', { name: 'File Tags: Document' }).click()
cy.findByText('All').should('exist').click()
cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withFilterByType(undefined))
})
@@ -85,15 +85,15 @@ describe('FilesCriteriaFilterByTag', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Tag: All' }).click()
+ cy.findByRole('button', { name: 'File Tags: All' }).click()
cy.findByText('All').should('have.class', styles['selected-option'])
cy.findByRole('button', { name: 'Document (5)' }).click()
- cy.findByRole('button', { name: 'Filter Tag: Document' }).click()
+ cy.findByRole('button', { name: 'File Tags: Document' }).click()
cy.findByText('Document (5)').should('have.class', styles['selected-option'])
cy.findByRole('button', { name: 'Data (10)' }).click()
- cy.findByRole('button', { name: 'Filter Tag: Data' }).click()
+ cy.findByRole('button', { name: 'File Tags: Data' }).click()
cy.findByText('Data (10)').should('have.class', styles['selected-option'])
})
@@ -111,6 +111,6 @@ describe('FilesCriteriaFilterByTag', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Tag: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Tags: All' }).should('not.exist')
})
})
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByType.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByType.spec.tsx
similarity index 82%
rename from tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByType.spec.tsx
rename to tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByType.spec.tsx
index 2a28d5164..e6c72496f 100644
--- a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByType.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByType.spec.tsx
@@ -1,8 +1,8 @@
import { FileCriteria } from '../../../../../../src/files/domain/models/FileCriteria'
import { FilesCountInfoMother } from '../../../../files/domain/models/FilesCountInfoMother'
import { FileType } from '../../../../../../src/files/domain/models/File'
-import styles from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls.module.scss'
-import { FileCriteriaFilterByType } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilterByType'
+import styles from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.module.scss'
+import { FileCriteriaFilterByType } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilterByType'
const defaultCriteria = new FileCriteria()
const filesCountInfo = FilesCountInfoMother.create({
@@ -30,7 +30,7 @@ describe('FilesCriteriaFilterByType', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Type: All' }).click()
+ cy.findByRole('button', { name: 'File Type: All' }).click()
cy.findByText('All').should('exist')
cy.findByText('Image (5)').should('exist')
@@ -48,11 +48,11 @@ describe('FilesCriteriaFilterByType', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Type: All' }).click()
+ cy.findByRole('button', { name: 'File Type: All' }).click()
cy.findByText('Image (5)').click()
cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withFilterByType('image'))
- cy.findByRole('button', { name: 'Filter Type: Image' }).click()
+ cy.findByRole('button', { name: 'File Type: Image' }).click()
cy.findByText('Text (10)').click()
cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withFilterByType('text'))
})
@@ -69,7 +69,7 @@ describe('FilesCriteriaFilterByType', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Type: Image' }).click()
+ cy.findByRole('button', { name: 'File Type: Image' }).click()
cy.findByText('All').should('exist').click()
cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withFilterByType(undefined))
})
@@ -85,15 +85,15 @@ describe('FilesCriteriaFilterByType', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Type: All' }).click()
+ cy.findByRole('button', { name: 'File Type: All' }).click()
cy.findByText('All').should('have.class', styles['selected-option'])
cy.findByRole('button', { name: 'Image (5)' }).click()
- cy.findByRole('button', { name: 'Filter Type: Image' }).click()
+ cy.findByRole('button', { name: 'File Type: Image' }).click()
cy.findByText('Image (5)').should('have.class', styles['selected-option'])
cy.findByRole('button', { name: 'Text (10)' }).click()
- cy.findByRole('button', { name: 'Filter Type: Text' }).click()
+ cy.findByRole('button', { name: 'File Type: Text' }).click()
cy.findByText('Text (10)').should('have.class', styles['selected-option'])
})
@@ -109,6 +109,6 @@ describe('FilesCriteriaFilterByType', () => {
/>
)
- cy.findByRole('button', { name: 'Filter Type: Image' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Type: Image' }).should('not.exist')
})
})
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilters.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilters.spec.tsx
similarity index 80%
rename from tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilters.spec.tsx
rename to tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilters.spec.tsx
index 009701d05..88ec100ed 100644
--- a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilters.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilters.spec.tsx
@@ -1,5 +1,5 @@
import { FileCriteria } from '../../../../../../src/files/domain/models/FileCriteria'
-import { FileCriteriaFilters } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaFilters'
+import { FileCriteriaFilters } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaFilters'
import { FilesCountInfoMother } from '../../../../files/domain/models/FilesCountInfoMother'
import { FileType } from '../../../../../../src/files/domain/models/File'
@@ -31,9 +31,9 @@ describe('FilesCriteriaFilters', () => {
cy.findByText('Filter by').should('exist')
- cy.findByRole('button', { name: 'Filter Type: All' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: All' }).should('exist')
cy.findByRole('button', { name: 'Access: All' }).should('exist')
- cy.findByRole('button', { name: 'Filter Tag: All' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: All' }).should('exist')
})
it('does not render filters by type options when there are no filters to be applied', () => {
@@ -50,8 +50,8 @@ describe('FilesCriteriaFilters', () => {
cy.findByText('Filter by').should('not.exist')
- cy.findByRole('button', { name: 'Filter Type: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Type: All' }).should('not.exist')
cy.findByRole('button', { name: 'Access: All' }).should('not.exist')
- cy.findByRole('button', { name: 'Filter Tag: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Tags: All' }).should('not.exist')
})
})
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.spec.tsx
similarity index 61%
rename from tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls.spec.tsx
rename to tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.spec.tsx
index 32050ecb3..1ad307d6d 100644
--- a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm.spec.tsx
@@ -1,4 +1,4 @@
-import { FileCriteriaControls } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaControls'
+import { FileCriteriaForm } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaForm'
import {
FileAccessOption,
FileCriteria,
@@ -40,41 +40,66 @@ const filesCountInfo = FilesCountInfoMother.create({
}
]
})
-describe('FileCriteriaControls', () => {
+describe('FileCriteriaForm', () => {
beforeEach(() => {
onCriteriaChange = cy.stub().as('onCriteriaChange')
})
+ it('does not render the files criteria inputs when there are less than 2 files', () => {
+ cy.customMount(
+
+ )
+
+ cy.findByRole('button', { name: /Sort/ }).should('not.exist')
+ cy.findByRole('button', { name: 'File Type: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'Access: All' }).should('not.exist')
+ cy.findByRole('button', { name: 'File Tags: All' }).should('not.exist')
+ cy.findByLabelText('Search').should('not.exist')
+ })
+
it('renders the SortBy input', () => {
- const filesCountInfo = FilesCountInfoMother.createOnlyTotal()
cy.customMount(
-
)
cy.findByRole('button', { name: /Sort/ }).should('exist')
- cy.findByRole('button', { name: 'Filter Type: All' }).should('not.exist')
- cy.findByRole('button', { name: 'Access: All' }).should('not.exist')
- cy.findByRole('button', { name: 'Filter Tag: All' }).should('not.exist')
})
it('renders the Filters input', () => {
cy.customMount(
-
)
- cy.findByRole('button', { name: /Sort/ }).should('exist')
- cy.findByRole('button', { name: 'Filter Type: All' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: All' }).should('exist')
+ cy.findByRole('button', { name: 'Access: All' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: All' }).should('exist')
cy.findByText('Filter by').should('exist')
})
+ it('renders the Search input', () => {
+ cy.customMount(
+
+ )
+
+ cy.findByLabelText('Search').should('exist')
+ })
+
it('saves global criteria when the sort by option changes', () => {
const criteria = new FileCriteria()
.withFilterByTag('document')
@@ -82,7 +107,7 @@ describe('FileCriteriaControls', () => {
.withFilterByType('image')
cy.customMount(
- {
cy.findByRole('button', { name: /Sort/ }).click()
cy.findByText('Oldest').click()
- cy.findByRole('button', { name: 'Filter Type: Image' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: Image' }).should('exist')
cy.findByRole('button', { name: 'Access: Public' }).should('exist')
- cy.findByRole('button', { name: 'Filter Tag: Document' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: Document' }).should('exist')
})
it('saves global criteria when the filter by type option changes', () => {
@@ -104,19 +129,19 @@ describe('FileCriteriaControls', () => {
.withFilterByType('image')
cy.customMount(
-
)
- cy.findByRole('button', { name: 'Filter Type: Image' }).click()
+ cy.findByRole('button', { name: 'File Type: Image' }).click()
cy.findByText('Text (10)').click()
- cy.findByRole('button', { name: 'Filter Type: Text' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: Text' }).should('exist')
cy.findByRole('button', { name: 'Access: Public' }).should('exist')
- cy.findByRole('button', { name: 'Filter Tag: Document' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: Document' }).should('exist')
})
it('saves global criteria when the filter by access option changes', () => {
@@ -126,7 +151,7 @@ describe('FileCriteriaControls', () => {
.withFilterByType('image')
cy.customMount(
- {
cy.findByRole('button', { name: 'Access: Public' }).click()
cy.findByText('Restricted (10)').click()
- cy.findByRole('button', { name: 'Filter Type: Image' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: Image' }).should('exist')
cy.findByRole('button', { name: 'Access: Restricted' }).should('exist')
- cy.findByRole('button', { name: 'Filter Tag: Document' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: Document' }).should('exist')
})
it('saves global criteria when the filter by tag option changes', () => {
@@ -148,35 +173,41 @@ describe('FileCriteriaControls', () => {
.withFilterByType('image')
cy.customMount(
-
)
- cy.findByRole('button', { name: 'Filter Tag: Document' }).click()
+ cy.findByRole('button', { name: 'File Tags: Document' }).click()
cy.findByText('Data (10)').click()
- cy.findByRole('button', { name: 'Filter Type: Image' }).should('exist')
+ cy.findByRole('button', { name: 'File Type: Image' }).should('exist')
cy.findByRole('button', { name: 'Access: Public' }).should('exist')
- cy.findByRole('button', { name: 'Filter Tag: Data' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: Data' }).should('exist')
})
- it('does not render the files criteria inputs when there are less than 2 files', () => {
- const filesCountInfo = FilesCountInfoMother.create({ total: 1 })
+ it('saves global criteria when the search input changes', () => {
const criteria = new FileCriteria()
+ .withFilterByTag('document')
+ .withFilterByAccess(FileAccessOption.PUBLIC)
+ .withFilterByType('image')
+ .withSearchText('search')
+
cy.customMount(
-
)
- cy.findByRole('button', { name: /Sort/ }).should('not.exist')
- cy.findByRole('button', { name: 'Filter Type: All' }).should('not.exist')
- cy.findByRole('button', { name: 'Access: All' }).should('not.exist')
- cy.findByRole('button', { name: 'Filter Tag: All' }).should('not.exist')
+ cy.findByLabelText('Search').clear().type('new search')
+
+ cy.findByRole('button', { name: 'File Type: Image' }).should('exist')
+ cy.findByRole('button', { name: 'Access: Public' }).should('exist')
+ cy.findByRole('button', { name: 'File Tags: Document' }).should('exist')
+ cy.findByLabelText('Search').should('have.value', 'new search')
})
})
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSearchText.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSearchText.spec.tsx
new file mode 100644
index 000000000..6c023bb76
--- /dev/null
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSearchText.spec.tsx
@@ -0,0 +1,39 @@
+import { FileCriteriaSearchText } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSearchText'
+import { FileCriteria } from '../../../../../../src/files/domain/models/FileCriteria'
+
+const defaultCriteria = new FileCriteria()
+
+describe('FilesSearch', () => {
+ it('renders the search input', () => {
+ const onCriteriaChange = cy.stub().as('onCriteriaChange')
+ cy.customMount(
+
+ )
+
+ cy.findByLabelText('Search').should('exist')
+ cy.findByRole('button', { name: 'Submit search' }).should('exist')
+ })
+
+ it('calls onCriteriaChange with the searchText value on enter', () => {
+ const onCriteriaChange = cy.stub().as('onCriteriaChange')
+
+ cy.customMount(
+
+ )
+
+ cy.findByLabelText('Search').type('test{enter}')
+ cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withSearchText('test'))
+ })
+
+ it('calls onCriteriaChange with the searchText value on submit', () => {
+ const onCriteriaChange = cy.stub().as('onCriteriaChange')
+
+ cy.customMount(
+
+ )
+
+ cy.findByLabelText('Search').type('test')
+ cy.findByRole('button', { name: 'Submit search' }).click()
+ cy.wrap(onCriteriaChange).should('be.calledWith', defaultCriteria.withSearchText('test'))
+ })
+})
diff --git a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaSortBy.spec.tsx b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSortBy.spec.tsx
similarity index 96%
rename from tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaSortBy.spec.tsx
rename to tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSortBy.spec.tsx
index 9d522af56..50437e287 100644
--- a/tests/component/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaSortBy.spec.tsx
+++ b/tests/component/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSortBy.spec.tsx
@@ -1,4 +1,4 @@
-import { FileCriteriaSortBy } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-controls/FileCriteriaSortBy'
+import { FileCriteriaSortBy } from '../../../../../../src/sections/dataset/dataset-files/file-criteria-form/FileCriteriaSortBy'
import {
FileCriteria,
FileSortByOption
diff --git a/tests/component/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.spec.tsx
new file mode 100644
index 000000000..b028b50bb
--- /dev/null
+++ b/tests/component/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage.spec.tsx
@@ -0,0 +1,74 @@
+import { RowSelectionMessage } from '../../../../../../../src/sections/dataset/dataset-files/files-table/row-selection/RowSelectionMessage'
+import { createRowSelection } from '../../../../../../../src/sections/dataset/dataset-files/files-table/useFilesTable'
+
+describe('RowSelectionMessage', () => {
+ it('renders the message when there are more than 10 files and some row is selected', () => {
+ cy.customMount(
+ {}} />
+ )
+
+ cy.findByText('1 file is currently selected.')
+ cy.findByRole('button', { name: 'Select all 11 files in this dataset.' })
+ cy.findByRole('button', { name: 'Clear selection.' })
+ })
+
+ it('does not render the message when there are less than 10 files', () => {
+ cy.customMount(
+ {}} />
+ )
+
+ cy.findByText('1 file is currently selected.').should('not.exist')
+ cy.findByRole('button', { name: 'Select all 9 files in this dataset.' }).should('not.exist')
+ cy.findByRole('button', { name: 'Clear selection.' }).should('not.exist')
+ })
+
+ it('does not render the message when there are more than 10 files but no row is selected', () => {
+ cy.customMount(
+ {}} />
+ )
+
+ cy.findByText('1 file is currently selected.').should('not.exist')
+ cy.findByRole('button', { name: 'Select all 11 files in this dataset.' }).should('not.exist')
+ cy.findByRole('button', { name: 'Clear selection.' }).should('not.exist')
+ })
+
+ it('renders the plural form of the message when there is more than 1 row selected', () => {
+ cy.customMount(
+ {}} />
+ )
+
+ cy.findByText('2 files are currently selected.')
+ })
+
+ it("calls setRowSelection when the 'Select all' button is clicked", () => {
+ const setRowSelection = cy.stub().as('setRowSelection')
+
+ cy.customMount(
+
+ )
+
+ cy.findByRole('button', { name: 'Select all 11 files in this dataset.' }).click()
+
+ cy.wrap(setRowSelection).should('be.calledWith', createRowSelection(11))
+ })
+
+ it("calls setRowSelection when the 'Clear selection.' button is clicked", () => {
+ const setRowSelection = cy.stub().as('setRowSelection')
+
+ cy.customMount(
+
+ )
+
+ cy.findByRole('button', { name: 'Clear selection.' }).click()
+
+ cy.wrap(setRowSelection).should('be.calledWith', createRowSelection(0))
+ })
+})
diff --git a/tests/component/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage.spec.tsx b/tests/component/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage.spec.tsx
new file mode 100644
index 000000000..cfff711bf
--- /dev/null
+++ b/tests/component/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage.spec.tsx
@@ -0,0 +1,63 @@
+import { FileMother } from '../../../../../files/domain/models/FileMother'
+import { ZipDownloadLimitMessage } from '../../../../../../../src/sections/dataset/dataset-files/files-table/zip-download-limit-message/ZipDownloadLimitMessage'
+import { FileSize, FileSizeUnit } from '../../../../../../../src/files/domain/models/File'
+import { SettingMother } from '../../../../../settings/domain/models/SettingMother'
+import { ZipDownloadLimit } from '../../../../../../../src/settings/domain/models/ZipDownloadLimit'
+import { SettingsContext } from '../../../../../../../src/sections/settings/SettingsContext'
+
+const files = [
+ FileMother.create({ size: new FileSize(1024, FileSizeUnit.BYTES) }),
+ FileMother.create({ size: new FileSize(2048, FileSizeUnit.BYTES) })
+]
+const zipDownloadLimit = new ZipDownloadLimit(500, FileSizeUnit.BYTES)
+describe('ZipDownloadLimitMessage', () => {
+ it('should render the component with no message if conditions are not met', () => {
+ const getSettingByName = cy
+ .stub()
+ .resolves(SettingMother.createZipDownloadLimit(zipDownloadLimit))
+
+ cy.customMount(
+
+
+
+ )
+
+ cy.findByText(/The overall size of the files selected/).should('not.exist')
+ })
+
+ it('should render the component with the appropriate message if conditions are met', () => {
+ const getSettingByName = cy
+ .stub()
+ .resolves(SettingMother.createZipDownloadLimit(zipDownloadLimit))
+ cy.customMount(
+
+
+
+ )
+
+ cy.findByText(
+ 'The overall size of the files selected (3.0 KB) for download exceeds the zip limit of 500.0 B. Please unselect some files to continue.'
+ ).should('exist')
+ })
+
+ it('should show the more than 1024 PB message if the total size is too big', () => {
+ const getSettingByName = cy
+ .stub()
+ .resolves(SettingMother.createZipDownloadLimit(zipDownloadLimit))
+ const files = [
+ FileMother.create({ size: new FileSize(1000000, FileSizeUnit.PETABYTES) }),
+ FileMother.create({ size: new FileSize(1000000, FileSizeUnit.PETABYTES) })
+ ]
+ cy.customMount(
+
+
+
+ )
+
+ cy.findByText(
+ 'The overall size of the files selected (more than 1024.0 PB) for download exceeds the zip limit of 500.0 B. Please unselect some files to continue.'
+ ).should('exist')
+ })
+})
diff --git a/tests/component/settings/domain/models/SettingMother.ts b/tests/component/settings/domain/models/SettingMother.ts
new file mode 100644
index 000000000..73f9593ee
--- /dev/null
+++ b/tests/component/settings/domain/models/SettingMother.ts
@@ -0,0 +1,18 @@
+import { faker } from '@faker-js/faker'
+import { Setting, SettingName } from '../../../../../src/settings/domain/models/Setting'
+import { ZipDownloadLimit } from '../../../../../src/settings/domain/models/ZipDownloadLimit'
+import { FileSizeUnit } from '../../../../../src/files/domain/models/File'
+
+export class SettingMother {
+ static createZipDownloadLimit(value?: ZipDownloadLimit): Setting {
+ return {
+ name: SettingName.ZIP_DOWNLOAD_LIMIT,
+ value: value
+ ? value
+ : new ZipDownloadLimit(
+ faker.datatype.number(),
+ faker.helpers.arrayElement(Object.values(FileSizeUnit))
+ )
+ }
+ }
+}