diff --git a/CHANGELOG.md b/CHANGELOG.md index 906a6918..e56fe504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel ### Changed +- Add pagination query parameters to Dataset Version Summeries and File Version Summaries use cases + ### Fixed ### Removed diff --git a/docs/useCases.md b/docs/useCases.md index 5ec382c6..b55157b8 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -872,7 +872,7 @@ The `DatasetPreviewSubset`returned instance contains a property called `totalDat #### Get Dataset Versions Summaries -Returns an array of [DatasetVersionSummaryInfo](../src/datasets/domain/models/DatasetVersionSummaryInfo.ts) that contains information about what changed in every specific version. +Returns the total count of versions and an array of [DatasetVersionSummaryInfo](../src/datasets/domain/models/DatasetVersionSummaryInfo.ts) that contains information about what changed in every specific version. ##### Example call: @@ -885,7 +885,7 @@ const datasetId = 'doi:10.77777/FK2/AAAAAA' getDatasetVersionsSummaries .execute(datasetId) - .then((datasetVersionsSummaries: DatasetVersionSummaryInfo[]) => { + .then((datasetVersionsSummaries: DatasetVersionSummarySubset) => { /* ... */ }) @@ -894,7 +894,9 @@ getDatasetVersionsSummaries _See [use case](../src/datasets/domain/useCases/GetDatasetVersionsSummaries.ts) implementation_. -The `datasetId` parameter can be a string, for persistent identifiers, or a number, for numeric identifiers. +- The `datasetId` parameter can be a string, for persistent identifiers, or a number, for numeric identifiers. +- **limit**: (number) Limit for pagination. +- **offset**: (number) Offset for pagination. #### Get Dataset Linked Collections @@ -2000,7 +2002,7 @@ The `fileId` parameter can be a string, for persistent identifiers, or a number, #### Get File Version Summaries -Get the file versions summaries, return a list of summaries for each version +Get the file versions summaries, return a total count of versions and a list of summaries for each version ##### Example call: @@ -2011,7 +2013,7 @@ import { getFileVersionSummaries } from '@iqss/dataverse-client-javascript' const fileId = 1 -getFileVersionSummaries.execute(fileId).then((fileVersionSummaries: fileVersionSummaryInfo[]) => { +getFileVersionSummaries.execute(fileId).then((fileVersionSummaries: fileVersionSummarySubset) => { /* ... */ }) @@ -2020,6 +2022,9 @@ getFileVersionSummaries.execute(fileId).then((fileVersionSummaries: fileVersionS _See [use case](../src/files/domain/useCases/GetFileVersionSummaries.ts) implementation_. +- **limit**: (number) Limit for pagination. +- **offset**: (number) Offset for pagination. + ## Metadata Blocks ### Metadata Blocks read use cases diff --git a/src/datasets/domain/models/DatasetVersionSummaryInfo.ts b/src/datasets/domain/models/DatasetVersionSummaryInfo.ts index 782a2e0f..c012a4b6 100644 --- a/src/datasets/domain/models/DatasetVersionSummaryInfo.ts +++ b/src/datasets/domain/models/DatasetVersionSummaryInfo.ts @@ -6,6 +6,11 @@ export interface DatasetVersionSummaryInfo { publishedOn?: string } +export interface DatasetVersionSummarySubset { + summaries: DatasetVersionSummaryInfo[] + totalCount: number +} + export type DatasetVersionSummary = { [key: string]: | SummaryUpdates diff --git a/src/datasets/domain/repositories/IDatasetsRepository.ts b/src/datasets/domain/repositories/IDatasetsRepository.ts index 91674966..8521d813 100644 --- a/src/datasets/domain/repositories/IDatasetsRepository.ts +++ b/src/datasets/domain/repositories/IDatasetsRepository.ts @@ -8,7 +8,7 @@ import { DatasetDeaccessionDTO } from '../dtos/DatasetDeaccessionDTO' import { MetadataBlock } from '../../../metadataBlocks' import { DatasetVersionDiff } from '../models/DatasetVersionDiff' import { DatasetDownloadCount } from '../models/DatasetDownloadCount' -import { DatasetVersionSummaryInfo } from '../models/DatasetVersionSummaryInfo' +import { DatasetVersionSummarySubset } from '../models/DatasetVersionSummaryInfo' import { DatasetLinkedCollection } from '../models/DatasetLinkedCollection' import { CitationFormat } from '../models/CitationFormat' import { FormattedCitation } from '../models/FormattedCitation' @@ -66,7 +66,11 @@ export interface IDatasetsRepository { datasetId: number | string, includeMDC?: boolean ): Promise - getDatasetVersionsSummaries(datasetId: number | string): Promise + getDatasetVersionsSummaries( + datasetId: number | string, + limit?: number, + offset?: number + ): Promise deleteDatasetDraft(datasetId: number | string): Promise linkDataset(datasetId: number | string, collectionIdOrAlias: number | string): Promise unlinkDataset(datasetId: number | string, collectionIdOrAlias: number | string): Promise diff --git a/src/datasets/domain/useCases/GetDatasetVersionsSummaries.ts b/src/datasets/domain/useCases/GetDatasetVersionsSummaries.ts index 24458b00..d5ea8834 100644 --- a/src/datasets/domain/useCases/GetDatasetVersionsSummaries.ts +++ b/src/datasets/domain/useCases/GetDatasetVersionsSummaries.ts @@ -1,8 +1,8 @@ import { UseCase } from '../../../core/domain/useCases/UseCase' -import { DatasetVersionSummaryInfo } from '../models/DatasetVersionSummaryInfo' +import { DatasetVersionSummarySubset } from '../models/DatasetVersionSummaryInfo' import { IDatasetsRepository } from '../repositories/IDatasetsRepository' -export class GetDatasetVersionsSummaries implements UseCase { +export class GetDatasetVersionsSummaries implements UseCase { private datasetsRepository: IDatasetsRepository constructor(datasetsRepository: IDatasetsRepository) { @@ -14,9 +14,15 @@ export class GetDatasetVersionsSummaries implements UseCase} - An array of DatasetVersionSummaryInfo. + * @param {number} [limit] - Limit for pagination (optional). + * @param {number} [offset] - Offset for pagination (optional). + * @returns {Promise} - A DatasetVersionSummarySubset containing the summaries and total count. */ - async execute(datasetId: number | string): Promise { - return await this.datasetsRepository.getDatasetVersionsSummaries(datasetId) + async execute( + datasetId: number | string, + limit?: number, + offset?: number + ): Promise { + return await this.datasetsRepository.getDatasetVersionsSummaries(datasetId, limit, offset) } } diff --git a/src/datasets/index.ts b/src/datasets/index.ts index 1bd1de0e..6fcc3963 100644 --- a/src/datasets/index.ts +++ b/src/datasets/index.ts @@ -141,7 +141,8 @@ export { CreatedDatasetIdentifiers } from './domain/models/CreatedDatasetIdentif export { VersionUpdateType } from './domain/models/Dataset' export { DatasetVersionSummaryInfo, - DatasetVersionSummaryStringValues + DatasetVersionSummaryStringValues, + DatasetVersionSummarySubset } from './domain/models/DatasetVersionSummaryInfo' export { DatasetLinkedCollection } from './domain/models/DatasetLinkedCollection' export { DatasetType } from './domain/models/DatasetType' diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts index f75bf1c0..08d950d2 100644 --- a/src/datasets/infra/repositories/DatasetsRepository.ts +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -20,7 +20,7 @@ import { transformDatasetPreviewsResponseToDatasetPreviewSubset } from './transf import { DatasetVersionDiff } from '../../domain/models/DatasetVersionDiff' import { transformDatasetVersionDiffResponseToDatasetVersionDiff } from './transformers/datasetVersionDiffTransformers' import { DatasetDownloadCount } from '../../domain/models/DatasetDownloadCount' -import { DatasetVersionSummaryInfo } from '../../domain/models/DatasetVersionSummaryInfo' +import { DatasetVersionSummarySubset } from '../../domain/models/DatasetVersionSummaryInfo' import { DatasetLinkedCollection } from '../../domain/models/DatasetLinkedCollection' import { CitationFormat } from '../../domain/models/CitationFormat' import { transformDatasetLinkedCollectionsResponseToDatasetLinkedCollection } from './transformers/datasetLinkedCollectionsTransformers' @@ -306,13 +306,29 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi } public async getDatasetVersionsSummaries( - datasetId: string | number - ): Promise { + datasetId: string | number, + limit?: number, + offset?: number + ): Promise { + const queryParams = new URLSearchParams() + + if (limit) { + queryParams.set('limit', limit.toString()) + } + + if (offset) { + queryParams.set('offset', offset.toString()) + } + return this.doGet( this.buildApiEndpoint(this.datasetsResourceName, 'versions/compareSummary', datasetId), - true + true, + queryParams ) - .then((response) => response.data.data) + .then((response) => ({ + summaries: response.data.data, + totalCount: response.data.totalCount + })) .catch((error) => { throw error }) diff --git a/src/files/domain/models/FileVersionSummaryInfo.ts b/src/files/domain/models/FileVersionSummaryInfo.ts index 2ee0a7ba..3cf95315 100644 --- a/src/files/domain/models/FileVersionSummaryInfo.ts +++ b/src/files/domain/models/FileVersionSummaryInfo.ts @@ -11,6 +11,11 @@ export interface FileVersionSummaryInfo { versionNote?: string } +export interface FileVersionSummarySubset { + summaries: FileVersionSummaryInfo[] + totalCount: number +} + export type FileDifferenceSummary = { file?: FileChangeType fileAccess?: 'Restricted' | 'Unrestricted' diff --git a/src/files/domain/repositories/IFilesRepository.ts b/src/files/domain/repositories/IFilesRepository.ts index 9256d92d..4890a38b 100644 --- a/src/files/domain/repositories/IFilesRepository.ts +++ b/src/files/domain/repositories/IFilesRepository.ts @@ -10,7 +10,7 @@ import { FileUploadDestination } from '../models/FileUploadDestination' import { UploadedFileDTO } from '../dtos/UploadedFileDTO' import { UpdateFileMetadataDTO } from '../dtos/UpdateFileMetadataDTO' import { RestrictFileDTO } from '../dtos/RestrictFileDTO' -import { FileVersionSummaryInfo } from '../models/FileVersionSummaryInfo' +import { FileVersionSummarySubset } from '../models/FileVersionSummaryInfo' export interface IFilesRepository { getDatasetFiles( @@ -88,7 +88,11 @@ export interface IFilesRepository { replace?: boolean ): Promise - getFileVersionSummaries(fileId: number | string): Promise + getFileVersionSummaries( + fileId: number | string, + limit?: number, + offset?: number + ): Promise isFileDeleted(fileId: number | string): Promise } diff --git a/src/files/domain/useCases/GetFileVersionSummaries.ts b/src/files/domain/useCases/GetFileVersionSummaries.ts index c8bafb50..c46b14db 100644 --- a/src/files/domain/useCases/GetFileVersionSummaries.ts +++ b/src/files/domain/useCases/GetFileVersionSummaries.ts @@ -1,8 +1,8 @@ import { UseCase } from '../../../core/domain/useCases/UseCase' -import { FileVersionSummaryInfo } from '../models/FileVersionSummaryInfo' +import { FileVersionSummarySubset } from '../models/FileVersionSummaryInfo' import { IFilesRepository } from '../repositories/IFilesRepository' -export class GetFileVersionSummaries implements UseCase { +export class GetFileVersionSummaries implements UseCase { private filesRepository: IFilesRepository constructor(filesRepository: IFilesRepository) { @@ -13,9 +13,15 @@ export class GetFileVersionSummaries implements UseCase} - An array of FileVersionSummaryInfo. + * @param {number} [limit] - Limit for pagination (optional). + * @param {number} [offset] - Offset for pagination (optional). + * @returns {Promise} - A FileVersionSummarySubset containing the summaries and total count. */ - async execute(fileId: number | string): Promise { - return await this.filesRepository.getFileVersionSummaries(fileId) + async execute( + fileId: number | string, + limit?: number, + offset?: number + ): Promise { + return await this.filesRepository.getFileVersionSummaries(fileId, limit, offset) } } diff --git a/src/files/index.ts b/src/files/index.ts index b13bfc53..a9d38386 100644 --- a/src/files/index.ts +++ b/src/files/index.ts @@ -93,3 +93,10 @@ export { FilesSubset } from './domain/models/FilesSubset' export { FilePreview, FilePreviewChecksum } from './domain/models/FilePreview' export { UploadedFileDTO } from './domain/dtos/UploadedFileDTO' export { UpdateFileMetadataDTO } from './domain/dtos/UpdateFileMetadataDTO' +export { + FileVersionSummaryInfo, + FileDifferenceSummary, + FileChangeType, + FileMetadataChange, + FileVersionSummarySubset +} from './domain/models/FileVersionSummaryInfo' diff --git a/src/files/infra/repositories/FilesRepository.ts b/src/files/infra/repositories/FilesRepository.ts index 3d24edaf..00b70ba8 100644 --- a/src/files/infra/repositories/FilesRepository.ts +++ b/src/files/infra/repositories/FilesRepository.ts @@ -22,7 +22,7 @@ import { UploadedFileDTO } from '../../domain/dtos/UploadedFileDTO' import { UpdateFileMetadataDTO } from '../../domain/dtos/UpdateFileMetadataDTO' import { ApiConstants } from '../../../core/infra/repositories/ApiConstants' import { RestrictFileDTO } from '../../domain/dtos/RestrictFileDTO' -import { FileVersionSummaryInfo } from '../../domain/models/FileVersionSummaryInfo' +import { FileVersionSummarySubset } from '../../domain/models/FileVersionSummaryInfo' import { transformFileVersionSummaryInfoResponseToFileVersionSummaryInfo } from './transformers/fileVersionSummaryInfoTransformers' export interface GetFilesQueryParams { @@ -423,10 +423,25 @@ export class FilesRepository extends ApiRepository implements IFilesRepository { }) } - public async getFileVersionSummaries(fileId: number | string): Promise { + public async getFileVersionSummaries( + fileId: number | string, + limit?: number, + offset?: number + ): Promise { + const queryParams = new URLSearchParams() + + if (limit) { + queryParams.set('limit', limit.toString()) + } + + if (offset) { + queryParams.set('offset', offset.toString()) + } + return this.doGet( this.buildApiEndpoint(this.filesResourceName, 'versionDifferences', fileId), - true + true, + queryParams ) .then((response) => transformFileVersionSummaryInfoResponseToFileVersionSummaryInfo(response)) .catch((error) => { diff --git a/src/files/infra/repositories/transformers/fileVersionSummaryInfoTransformers.ts b/src/files/infra/repositories/transformers/fileVersionSummaryInfoTransformers.ts index 46eb4049..dd62262d 100644 --- a/src/files/infra/repositories/transformers/fileVersionSummaryInfoTransformers.ts +++ b/src/files/infra/repositories/transformers/fileVersionSummaryInfoTransformers.ts @@ -2,7 +2,8 @@ import { AxiosResponse } from 'axios' import { FileVersionSummaryInfo, FileMetadataChange, - FileDifferenceSummary + FileDifferenceSummary, + FileVersionSummarySubset } from '../../../domain/models/FileVersionSummaryInfo' import { DatasetVersionState } from '../../../../datasets/domain/models/Dataset' @@ -29,10 +30,11 @@ export interface FileVersionSummaryInfoPayload { export const transformFileVersionSummaryInfoResponseToFileVersionSummaryInfo = ( response: AxiosResponse -): FileVersionSummaryInfo[] => { +): FileVersionSummarySubset => { const payload = response.data.data + const totalCount = response.data.totalCount - return payload.map((item: FileVersionSummaryInfoPayload): FileVersionSummaryInfo => { + const summaries = payload.map((item: FileVersionSummaryInfoPayload): FileVersionSummaryInfo => { const summary = item.fileDifferenceSummary || {} const fileDifferenceSummary: FileDifferenceSummary = { @@ -54,4 +56,9 @@ export const transformFileVersionSummaryInfoResponseToFileVersionSummaryInfo = ( versionNote: item.versionNote } }) + + return { + summaries, + totalCount + } } diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts index 7abde006..5513314f 100644 --- a/test/integration/datasets/DatasetsRepository.test.ts +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -1307,9 +1307,10 @@ describe('DatasetsRepository', () => { const actual = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) - expect(actual.length).toBeGreaterThan(0) - expect(actual[0].versionNumber).toBe('DRAFT') - expect(actual[0].summary).toBe(DatasetVersionSummaryStringValues.firstDraft) + expect(actual.summaries.length).toBeGreaterThan(0) + expect(actual.totalCount).toBeGreaterThan(0) + expect(actual.summaries[0].versionNumber).toBe('DRAFT') + expect(actual.summaries[0].summary).toBe(DatasetVersionSummaryStringValues.firstDraft) await deleteUnpublishedDatasetViaApi(testDatasetIds.numericId) }) @@ -1325,9 +1326,10 @@ describe('DatasetsRepository', () => { const actual = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) - expect(actual.length).toBeGreaterThan(0) - expect(actual[0].versionNumber).toBe('1.0') - expect(actual[0].summary).toBe(DatasetVersionSummaryStringValues.firstPublished) + expect(actual.summaries.length).toBeGreaterThan(0) + expect(actual.totalCount).toBeGreaterThan(0) + expect(actual.summaries[0].versionNumber).toBe('1.0') + expect(actual.summaries[0].summary).toBe(DatasetVersionSummaryStringValues.firstPublished) await deletePublishedDatasetViaApi(testDatasetIds.persistentId) }) @@ -1348,9 +1350,10 @@ describe('DatasetsRepository', () => { const actual = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) - expect(actual.length).toBeGreaterThan(0) - expect(actual[0].versionNumber).toBe('1.0') - expect(actual[0].summary).toStrictEqual(deaccessionReason) + expect(actual.summaries.length).toBeGreaterThan(0) + expect(actual.totalCount).toBeGreaterThan(0) + expect(actual.summaries[0].versionNumber).toBe('1.0') + expect(actual.summaries[0].summary).toStrictEqual(deaccessionReason) await deletePublishedDatasetViaApi(testDatasetIds.persistentId) }) @@ -1387,9 +1390,10 @@ describe('DatasetsRepository', () => { const actual = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) - expect(actual.length).toEqual(2) - expect(actual[0].versionNumber).toBe('DRAFT') - expect(actual[0].summary).toMatchObject({ + expect(actual.summaries.length).toEqual(2) + expect(actual.totalCount).toEqual(2) + expect(actual.summaries[0].versionNumber).toBe('DRAFT') + expect(actual.summaries[0].summary).toMatchObject({ 'Citation Metadata': { Title: { added: 0, @@ -1407,8 +1411,8 @@ describe('DatasetsRepository', () => { termsAccessChanged: false }) - expect(actual[1].versionNumber).toBe('1.0') - expect(actual[1].summary).toBe(DatasetVersionSummaryStringValues.firstPublished) + expect(actual.summaries[1].versionNumber).toBe('1.0') + expect(actual.summaries[1].summary).toBe(DatasetVersionSummaryStringValues.firstPublished) await deletePublishedDatasetViaApi(testDatasetIds.persistentId) }) @@ -1454,10 +1458,11 @@ describe('DatasetsRepository', () => { const actual = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) - expect(actual.length).toEqual(2) + expect(actual.summaries.length).toEqual(2) + expect(actual.totalCount).toEqual(2) - expect(actual[0].versionNumber).toBe('DRAFT') - expect(actual[0].summary).toMatchObject({ + expect(actual.summaries[0].versionNumber).toBe('DRAFT') + expect(actual.summaries[0].summary).toMatchObject({ files: { added: 1, removed: 0, @@ -1467,8 +1472,8 @@ describe('DatasetsRepository', () => { }, termsAccessChanged: false }) - expect(actual[1].versionNumber).toBe('1.0') - expect(actual[1].summary).toBe(DatasetVersionSummaryStringValues.firstPublished) + expect(actual.summaries[1].versionNumber).toBe('1.0') + expect(actual.summaries[1].summary).toBe(DatasetVersionSummaryStringValues.firstPublished) await deletePublishedDatasetViaApi(testDatasetIds.persistentId) }) @@ -1482,6 +1487,72 @@ describe('DatasetsRepository', () => { expectedError ) }) + + test('should return dataset versions summaries with pagination', async () => { + const testDatasetIds = await createDataset.execute( + TestConstants.TEST_NEW_DATASET_DTO, + testDatasetVersionsCollectionAlias + ) + + await publishDataset.execute(testDatasetIds.numericId, VersionUpdateType.MAJOR) + await waitForNoLocks(testDatasetIds.numericId, 10) + + const metadataBlocksRepository = new MetadataBlocksRepository() + const citationMetadataBlock = await metadataBlocksRepository.getMetadataBlockByName( + 'citation' + ) + + for (let i = 1; i <= 21; i++) { + await sut.updateDataset( + testDatasetIds.numericId, + { + metadataBlockValues: [ + { + name: 'citation', + fields: { + title: `Updated Dataset Title - Version ${i}` + } + } + ] + }, + [citationMetadataBlock] + ) + + await publishDataset.execute(testDatasetIds.numericId, VersionUpdateType.MINOR) + await waitForNoLocks(testDatasetIds.numericId, 10) + } + + const summaries = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) + console.log('summaries', summaries) + + const firstPage = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId, 5, 0) + + expect(firstPage.summaries.length).toBe(5) + expect(firstPage.totalCount).toBe(22) + expect(firstPage.summaries[0].versionNumber).toBe('1.21') + expect(firstPage.summaries[4].versionNumber).toBe('1.17') + + // Test pagination with limit=5, offset=5 (second page) + const secondPage = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId, 5, 5) + expect(secondPage.summaries.length).toBe(5) + expect(secondPage.totalCount).toBe(22) + expect(secondPage.summaries[0].versionNumber).toBe('1.16') + expect(secondPage.summaries[4].versionNumber).toBe('1.12') + + // Test pagination with limit=5, offset=10 (third page) + const thirdPage = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId, 5, 10) + expect(thirdPage.summaries.length).toBe(5) + expect(thirdPage.totalCount).toBe(22) + expect(thirdPage.summaries[0].versionNumber).toBe('1.11') + expect(thirdPage.summaries[4].versionNumber).toBe('1.7') + + // Test that all versions are returned without pagination + const allVersions = await sut.getDatasetVersionsSummaries(testDatasetIds.numericId) + expect(allVersions.summaries.length).toBe(22) // 1 initial + 21 updates + expect(allVersions.totalCount).toBe(22) + + await deletePublishedDatasetViaApi(testDatasetIds.persistentId) + }, 180000) }) describe('getDatasetDownloadCount', () => { diff --git a/test/integration/files/FilesRepository.test.ts b/test/integration/files/FilesRepository.test.ts index c20fd0c4..6e0c9bbc 100644 --- a/test/integration/files/FilesRepository.test.ts +++ b/test/integration/files/FilesRepository.test.ts @@ -925,11 +925,14 @@ describe('FilesRepository', () => { contributors: 'Dataverse Admin', datafileId: testFile.id, persistentId: testFile.persistentId, + publishedDate: '', + versionNote: undefined, fileDifferenceSummary: { file: 'Added' } } - expect(actual).toHaveLength(1) - expect(actual[0]).toEqual(fileSummmaries) + expect(actual.summaries).toHaveLength(1) + expect(actual.totalCount).toBe(1) + expect(actual.summaries[0]).toEqual(fileSummmaries) deleteUnpublishedDatasetViaApi(fileTestDatasetIds.numericId) }) @@ -953,7 +956,7 @@ describe('FilesRepository', () => { const publishedFileVersionSummmaries: FileVersionSummaryInfo = { datasetVersion: '1.0', - publishedDate: publishedFileVersionSummariesActual[0].publishedDate, + publishedDate: publishedFileVersionSummariesActual.summaries[0].publishedDate, versionState: DatasetVersionState.RELEASED, contributors: 'Dataverse Admin', datafileId: testFile.id, @@ -961,8 +964,11 @@ describe('FilesRepository', () => { fileDifferenceSummary: { file: 'Added' } } - expect(publishedFileVersionSummariesActual).toHaveLength(1) - expect(publishedFileVersionSummariesActual[0]).toEqual(publishedFileVersionSummmaries) + expect(publishedFileVersionSummariesActual.summaries).toHaveLength(1) + expect(publishedFileVersionSummariesActual.totalCount).toBe(1) + expect(publishedFileVersionSummariesActual.summaries[0]).toEqual( + publishedFileVersionSummmaries + ) await deaccessionDatasetViaApi(fileTestDatasetIds.numericId, '1.0').catch(() => { throw new Error('Error while deaccessioning test Dataset') @@ -972,7 +978,7 @@ describe('FilesRepository', () => { const fileSummmaries: FileVersionSummaryInfo = { datasetVersion: '1.0', - publishedDate: publishedFileVersionSummariesActual[0].publishedDate, + publishedDate: publishedFileVersionSummariesActual.summaries[0].publishedDate, versionState: DatasetVersionState.DEACCESSIONED, contributors: 'Dataverse Admin', datafileId: testFile.id, @@ -983,8 +989,9 @@ describe('FilesRepository', () => { } } - expect(actual).toHaveLength(1) - expect(actual[0]).toEqual(fileSummmaries) + expect(actual.summaries).toHaveLength(1) + expect(actual.totalCount).toBe(1) + expect(actual.summaries[0]).toEqual(fileSummmaries) deletePublishedDatasetViaApi(fileTestDatasetIds.persistentId) }) @@ -1006,7 +1013,8 @@ describe('FilesRepository', () => { const testFile = datasetFiles.files[0] const actual = await sut.getFileVersionSummaries(testFile.id) - expect(actual).toHaveLength(1) + expect(actual.summaries).toHaveLength(1) + expect(actual.totalCount).toBe(1) await sut.updateFileMetadata(testFile.id, { description: 'My description test.', @@ -1022,7 +1030,7 @@ describe('FilesRepository', () => { contributors: 'Dataverse Admin', datafileId: testFile.id, persistentId: testFile.persistentId, - publishedDate: actual[0].publishedDate, + publishedDate: '', versionNote: undefined, fileDifferenceSummary: { fileMetadata: [ @@ -1042,11 +1050,68 @@ describe('FilesRepository', () => { } } - expect(updatedFileVersionSummariesActual).toHaveLength(2) - expect(updatedFileVersionSummariesActual[0]).toEqual(updatedFileVersionSummaries) + expect(updatedFileVersionSummariesActual.summaries).toHaveLength(2) + expect(updatedFileVersionSummariesActual.totalCount).toBe(2) + expect(updatedFileVersionSummariesActual.summaries[0]).toEqual(updatedFileVersionSummaries) deletePublishedDatasetViaApi(fileTestDatasetIds.persistentId) }) + test('should return file version summaries with pagination', async () => { + // Create a new dataset and upload a file + const paginationTestDatasetIds = await createDataset.execute( + TestConstants.TEST_NEW_DATASET_DTO + ) + await uploadFileViaApi(paginationTestDatasetIds.numericId, testTextFile1Name) + + // Publish initial version (creates version 1.0) + await publishDatasetViaApi(paginationTestDatasetIds.numericId) + await waitForNoLocks(paginationTestDatasetIds.numericId, 10) + + // Get the file ID + const datasetFiles = await sut.getDatasetFiles( + paginationTestDatasetIds.numericId, + latestDatasetVersionId, + false, + FileOrderCriteria.NAME_AZ + ) + const paginationTestFile = datasetFiles.files[0] + + for (let i = 1; i <= 21; i++) { + await sut.updateFileMetadata(paginationTestFile.id, { + description: `File description update ${i}`, + label: `updated-file-${i}.txt` + }) + + await publishDatasetViaApi(paginationTestDatasetIds.numericId) + await waitForNoLocks(paginationTestDatasetIds.numericId, 10) + } + + const firstPage = await sut.getFileVersionSummaries(paginationTestFile.id, 5, 0) + + expect(firstPage.summaries.length).toBe(5) + expect(firstPage.totalCount).toBe(22) + expect(firstPage.summaries[0].datasetVersion).toBe('22.0') + expect(firstPage.summaries[4].datasetVersion).toBe('18.0') + + const secondPage = await sut.getFileVersionSummaries(paginationTestFile.id, 5, 5) + expect(secondPage.summaries.length).toBe(5) + expect(secondPage.totalCount).toBe(22) + expect(secondPage.summaries[0].datasetVersion).toBe('17.0') + expect(secondPage.summaries[4].datasetVersion).toBe('13.0') + + const thirdPage = await sut.getFileVersionSummaries(paginationTestFile.id, 5, 10) + expect(thirdPage.summaries.length).toBe(5) + expect(thirdPage.totalCount).toBe(22) + expect(thirdPage.summaries[0].datasetVersion).toBe('12.0') + expect(thirdPage.summaries[4].datasetVersion).toBe('8.0') + + const allVersions = await sut.getFileVersionSummaries(paginationTestFile.id) + expect(allVersions.summaries.length).toBe(22) + expect(allVersions.totalCount).toBe(22) + + await deletePublishedDatasetViaApi(paginationTestDatasetIds.persistentId) + }, 180000) + test('should return error when file does not exist', async () => { const expectedError = new ReadError(`[404] File with ID ${nonExistentFiledId} not found.`) diff --git a/test/integration/notifications/NotificationsRepository.test.ts b/test/integration/notifications/NotificationsRepository.test.ts index 5333e48d..78d692f5 100644 --- a/test/integration/notifications/NotificationsRepository.test.ts +++ b/test/integration/notifications/NotificationsRepository.test.ts @@ -54,10 +54,11 @@ describe('NotificationsRepository', () => { expect(publishedNotification).toHaveProperty('sentTimestamp') expect(publishedNotification?.subjectText).toContain( - 'Dataset created using the createDataset use case' + `Dataset "${TestConstants.TEST_NEW_DATASET_DTO.metadataBlockValues[0].fields.title}" has been published` ) + expect(publishedNotification?.messageText).toContain( - 'Your dataset named Dataset created using the createDataset use case' + `Your dataset named ${TestConstants.TEST_NEW_DATASET_DTO.metadataBlockValues[0].fields.title}` ) }) diff --git a/test/unit/datasets/DatasetsRepository.test.ts b/test/unit/datasets/DatasetsRepository.test.ts index fe53ed49..b87e05de 100644 --- a/test/unit/datasets/DatasetsRepository.test.ts +++ b/test/unit/datasets/DatasetsRepository.test.ts @@ -12,7 +12,11 @@ import { createUpdateDatasetRequestPayload } from '../../testHelpers/datasets/datasetHelper' import { TestConstants } from '../../testHelpers/TestConstants' -import { DatasetNotNumberedVersion, DatasetPreviewSubset } from '../../../src/datasets' +import { + DatasetNotNumberedVersion, + DatasetPreviewSubset, + DatasetVersionSummarySubset +} from '../../../src/datasets' import { createDatasetUserPermissionsModel } from '../../testHelpers/datasets/datasetUserPermissionsHelper' import { createDatasetLockModel, @@ -1050,12 +1054,16 @@ describe('DatasetsRepository', () => { }) describe('getDatasetVersionSummaries', () => { - const testDatasetVersionSummaries = createDatasetVersionSummaryModel() + const testDatasetVersionSummariesSubset: DatasetVersionSummarySubset = { + summaries: [createDatasetVersionSummaryModel()], + totalCount: 1 + } const testDatasetVersionSummariesResponse = { data: { status: 'OK', - data: [testDatasetVersionSummaries] + data: testDatasetVersionSummariesSubset.summaries, + totalCount: testDatasetVersionSummariesSubset.totalCount } } @@ -1068,22 +1076,37 @@ describe('DatasetsRepository', () => { // API Key auth let actual = await sut.getDatasetVersionsSummaries(testDatasetModel.id) - expect(axios.get).toHaveBeenCalledWith( + const expectedRequestParams = new URLSearchParams() + + const expectedRequestConfigApiKey = { + params: expectedRequestParams, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers + } + + expect(axios.get).toHaveBeenNthCalledWith( + 1, expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY + expectedRequestConfigApiKey ) - expect(actual).toStrictEqual([testDatasetVersionSummaries]) + expect(actual).toStrictEqual(testDatasetVersionSummariesSubset) // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE) actual = await sut.getDatasetVersionsSummaries(testDatasetModel.id) - expect(axios.get).toHaveBeenCalledWith( + const expectedRequestConfigSessionCookie = { + params: expectedRequestParams, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.headers, + withCredentials: true + } + + expect(axios.get).toHaveBeenNthCalledWith( + 2, expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE + expectedRequestConfigSessionCookie ) - expect(actual).toStrictEqual([testDatasetVersionSummaries]) + expect(actual).toStrictEqual(testDatasetVersionSummariesSubset) }) test('should return error result on error response', async () => { @@ -1092,10 +1115,14 @@ describe('DatasetsRepository', () => { let error = undefined as unknown as ReadError await sut.getDatasetVersionsSummaries(testDatasetModel.id).catch((e) => (error = e)) - expect(axios.get).toHaveBeenCalledWith( - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY - ) + const expectedRequestParams = new URLSearchParams() + + const expectedRequestConfigApiKey = { + params: expectedRequestParams, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers + } + + expect(axios.get).toHaveBeenCalledWith(expectedApiEndpoint, expectedRequestConfigApiKey) expect(error).toBeInstanceOf(ReadError) }) }) @@ -1109,22 +1136,37 @@ describe('DatasetsRepository', () => { // API Key auth let actual = await sut.getDatasetVersionsSummaries(TestConstants.TEST_DUMMY_PERSISTENT_ID) - expect(axios.get).toHaveBeenCalledWith( + const expectedRequestParams = new URLSearchParams() + + const expectedRequestConfigApiKey = { + params: expectedRequestParams, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers + } + + expect(axios.get).toHaveBeenNthCalledWith( + 1, expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY + expectedRequestConfigApiKey ) - expect(actual).toStrictEqual([testDatasetVersionSummaries]) + expect(actual).toStrictEqual(testDatasetVersionSummariesSubset) // Session cookie auth ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE) actual = await sut.getDatasetVersionsSummaries(TestConstants.TEST_DUMMY_PERSISTENT_ID) - expect(axios.get).toHaveBeenCalledWith( + const expectedRequestConfigSessionCookie = { + params: expectedRequestParams, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE.headers, + withCredentials: true + } + + expect(axios.get).toHaveBeenNthCalledWith( + 2, expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE + expectedRequestConfigSessionCookie ) - expect(actual).toStrictEqual([testDatasetVersionSummaries]) + expect(actual).toStrictEqual(testDatasetVersionSummariesSubset) }) test('should return error result on error response', async () => { @@ -1135,10 +1177,14 @@ describe('DatasetsRepository', () => { .getDatasetVersionsSummaries(TestConstants.TEST_DUMMY_PERSISTENT_ID) .catch((e) => (error = e)) - expect(axios.get).toHaveBeenCalledWith( - expectedApiEndpoint, - TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY - ) + const expectedRequestParams = new URLSearchParams() + + const expectedRequestConfigApiKey = { + params: expectedRequestParams, + headers: TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY.headers + } + + expect(axios.get).toHaveBeenCalledWith(expectedApiEndpoint, expectedRequestConfigApiKey) expect(error).toBeInstanceOf(ReadError) }) }) diff --git a/test/unit/datasets/GetDatasetVersionsSummaries.test.ts b/test/unit/datasets/GetDatasetVersionsSummaries.test.ts index 184ec648..82850a28 100644 --- a/test/unit/datasets/GetDatasetVersionsSummaries.test.ts +++ b/test/unit/datasets/GetDatasetVersionsSummaries.test.ts @@ -2,22 +2,30 @@ import { ReadError } from '../../../src/core/domain/repositories/ReadError' import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository' import { createDatasetVersionSummaryModel } from '../../testHelpers/datasets/datasetVersionsSummariesHelper' import { GetDatasetVersionsSummaries } from '../../../src/datasets/domain/useCases/GetDatasetVersionsSummaries' +import { DatasetVersionSummarySubset } from '../../../src/datasets/domain/models/DatasetVersionSummaryInfo' const testDatasetId = 1 describe('execute', () => { test('should return dataset versions summaries on repository success', async () => { - const testDatasetVersionsSummaries = [createDatasetVersionSummaryModel()] + const testDatasetVersionsSummariesSubset: DatasetVersionSummarySubset = { + summaries: [createDatasetVersionSummaryModel()], + totalCount: 1 + } const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository datasetsRepositoryStub.getDatasetVersionsSummaries = jest .fn() - .mockResolvedValue(testDatasetVersionsSummaries) + .mockResolvedValue(testDatasetVersionsSummariesSubset) const sut = new GetDatasetVersionsSummaries(datasetsRepositoryStub) const actual = await sut.execute(testDatasetId) - expect(actual).toEqual(testDatasetVersionsSummaries) - expect(datasetsRepositoryStub.getDatasetVersionsSummaries).toHaveBeenCalledWith(testDatasetId) + expect(actual).toEqual(testDatasetVersionsSummariesSubset) + expect(datasetsRepositoryStub.getDatasetVersionsSummaries).toHaveBeenCalledWith( + testDatasetId, + undefined, + undefined + ) }) test('should return error result on repository error', async () => { diff --git a/test/unit/files/GetFileVersionSummaries.test.ts b/test/unit/files/GetFileVersionSummaries.test.ts index d8352603..f2f29ab9 100644 --- a/test/unit/files/GetFileVersionSummaries.test.ts +++ b/test/unit/files/GetFileVersionSummaries.test.ts @@ -1,32 +1,37 @@ import { IFilesRepository } from '../../../src/files/domain/repositories/IFilesRepository' import { ReadError } from '../../../src' import { GetFileVersionSummaries } from '../../../src/files/domain/useCases/GetFileVersionSummaries' -import { FileVersionSummaryInfo } from '../../../src/files/domain/models/FileVersionSummaryInfo' +import { FileVersionSummarySubset } from '../../../src/files/domain/models/FileVersionSummaryInfo' describe('execute', () => { test('should return file on repository success when passing numeric id', async () => { const filesRepositoryStub: IFilesRepository = {} as IFilesRepository - const fileVersionSummaries: FileVersionSummaryInfo[] = [ - { - datasetVersion: '1.0', - contributors: 'John Doe', - publishedDate: '2023-01-01', - fileDifferenceSummary: { - fileMetadata: [ - { - name: 'file.txt', - action: 'Added' - } - ] - }, - datafileId: 1 - } - ] - filesRepositoryStub.getFileVersionSummaries = jest.fn().mockResolvedValue(fileVersionSummaries) + const fileVersionSummariesSubset: FileVersionSummarySubset = { + summaries: [ + { + datasetVersion: '1.0', + contributors: 'John Doe', + publishedDate: '2023-01-01', + fileDifferenceSummary: { + fileMetadata: [ + { + name: 'file.txt', + action: 'Added' + } + ] + }, + datafileId: 1 + } + ], + totalCount: 1 + } + filesRepositoryStub.getFileVersionSummaries = jest + .fn() + .mockResolvedValue(fileVersionSummariesSubset) const sut = new GetFileVersionSummaries(filesRepositoryStub) const actualFileVersionSummaries = await sut.execute(1) - expect(actualFileVersionSummaries).toEqual(fileVersionSummaries) + expect(actualFileVersionSummaries).toEqual(fileVersionSummariesSubset) }) test('should return error result on repository error', async () => {