Skip to content

Commit

Permalink
feat: updateFileMetadata use case
Browse files Browse the repository at this point in the history
  • Loading branch information
ChengShi-1 committed Jan 31, 2025
1 parent c789d0f commit 81255e0
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 3 deletions.
7 changes: 7 additions & 0 deletions src/files/domain/dtos/UpdateFileMetadataDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface UpdateFileMetadataDTO {
description?: string
prevFreeform?: string
categories?: string[]
dataFileTags?: string[]
restrict?: boolean
}
6 changes: 6 additions & 0 deletions src/files/domain/repositories/IFilesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FileModel } from '../models/FileModel'
import { Dataset } from '../../../datasets'
import { FileUploadDestination } from '../models/FileUploadDestination'
import { UploadedFileDTO } from '../dtos/UploadedFileDTO'
import { UpdateFileMetadataDTO } from '../dtos/UpdateFileMetadataDTO'

export interface IFilesRepository {
getDatasetFiles(
Expand Down Expand Up @@ -59,4 +60,9 @@ export interface IFilesRepository {
datasetId: number | string,
uploadedFileDTOs: UploadedFileDTO[]
): Promise<undefined>

updateFileMetadata(
fileId: number | string,
updateFileMetadataDTO: UpdateFileMetadataDTO
): Promise<void>
}
25 changes: 25 additions & 0 deletions src/files/domain/useCases/UpdateFileMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IFilesRepository } from '../repositories/IFilesRepository'
import { UpdateFileMetadataDTO } from '../dtos/UpdateFileMetadataDTO'

export class UpdateFileMetadata implements UseCase<void> {
private filesRepository: IFilesRepository

constructor(filesRepository: IFilesRepository) {
this.filesRepository = filesRepository
}

/**
* Updates the metadata for a particular File.
*
* @param {number | string} [fileId] - The file identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @param {UpdateFileMetadataDTO} [updateFileMetadataDTO] - The DTO containing the metadata updates.
* @returns {Promise<void>}
*/
async execute(
fileId: number | string,
updateFileMetadataDTO: UpdateFileMetadataDTO
): Promise<void> {
await this.filesRepository.updateFileMetadata(fileId, updateFileMetadataDTO)
}
}
6 changes: 5 additions & 1 deletion src/files/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { GetFileAndDataset } from './domain/useCases/GetFileAndDataset'
import { UploadFile } from './domain/useCases/UploadFile'
import { DirectUploadClient } from './infra/clients/DirectUploadClient'
import { AddUploadedFilesToDataset } from './domain/useCases/AddUploadedFilesToDataset'
import { UpdateFileMetadata } from './domain/useCases/UpdateFileMetadata'

const filesRepository = new FilesRepository()
const directUploadClient = new DirectUploadClient(filesRepository)
Expand All @@ -26,6 +27,7 @@ const getFileAndDataset = new GetFileAndDataset(filesRepository)
const getFileCitation = new GetFileCitation(filesRepository)
const uploadFile = new UploadFile(directUploadClient)
const addUploadedFilesToDataset = new AddUploadedFilesToDataset(filesRepository)
const updateFileMetadata = new UpdateFileMetadata(filesRepository)

export {
getDatasetFiles,
Expand All @@ -38,7 +40,8 @@ export {
getFileAndDataset,
getFileCitation,
uploadFile,
addUploadedFilesToDataset
addUploadedFilesToDataset,
updateFileMetadata
}

export { FileModel as File, FileEmbargo, FileChecksum } from './domain/models/FileModel'
Expand Down Expand Up @@ -68,3 +71,4 @@ export { FileDownloadSizeMode } from './domain/models/FileDownloadSizeMode'
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'
20 changes: 20 additions & 0 deletions src/files/infra/repositories/FilesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Dataset } from '../../../datasets'
import { FileUploadDestination } from '../../domain/models/FileUploadDestination'
import { transformUploadDestinationsResponseToUploadDestination } from './transformers/fileUploadDestinationsTransformers'
import { UploadedFileDTO } from '../../domain/dtos/UploadedFileDTO'
import { UpdateFileMetadataDTO } from '../../domain/dtos/UpdateFileMetadataDTO'
import { ApiConstants } from '../../../core/infra/repositories/ApiConstants'

export interface GetFilesQueryParams {
Expand Down Expand Up @@ -293,4 +294,23 @@ export class FilesRepository extends ApiRepository implements IFilesRepository {
queryParams.searchText = fileSearchCriteria.searchText
}
}

public async updateFileMetadata(
fileId: string | number,
updateFileMetadata: UpdateFileMetadataDTO
): Promise<void> {
const formData = new FormData()
formData.append('jsonData', JSON.stringify(updateFileMetadata))

return this.doPost(
this.buildApiEndpoint(this.filesResourceName, `${fileId}/metadata`),
formData,
{},
ApiConstants.CONTENT_TYPE_MULTIPART_FORM_DATA
)
.then(() => undefined)
.catch((error) => {
throw error
})
}
}
1 change: 0 additions & 1 deletion test/functional/users/DeleteCurrentApiToken.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ describe('execute', () => {
const testApiToken = await createApiTokenViaApi('deleteCurrentApiTokenFTUser')
ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.API_KEY, testApiToken)
await deleteCurrentApiToken.execute()
// Since the token has been deleted, the next call using it should return a WriteError
await expect(deleteCurrentApiToken.execute()).rejects.toBeInstanceOf(WriteError)
})
})
46 changes: 45 additions & 1 deletion test/integration/files/FilesRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
} from '../../../src/datasets'
import { FileModel } from '../../../src/files/domain/models/FileModel'
import { FileCounts } from '../../../src/files/domain/models/FileCounts'
import { FileDownloadSizeMode } from '../../../src'
import { FileDownloadSizeMode, WriteError } from '../../../src'
import {
deaccessionDatasetViaApi,
publishDatasetViaApi,
Expand All @@ -41,6 +41,7 @@ import {
deleteCollectionViaApi,
setStorageDriverViaApi
} from '../../testHelpers/collections/collectionHelper'
import { getFileMetadata } from '../../testHelpers/files/filesHelper'

describe('FilesRepository', () => {
const sut: FilesRepository = new FilesRepository()
Expand Down Expand Up @@ -646,4 +647,47 @@ describe('FilesRepository', () => {
).rejects.toThrow(errorExpected)
})
})

describe('updateFileMetadata', () => {
test('should update file metadata when file exists', async () => {
const getDatasetFiles = await sut.getDatasetFiles(
testDatasetIds.numericId,
latestDatasetVersionId,
false,
FileOrderCriteria.NAME_AZ
)
const fileid = getDatasetFiles.files[0].id
console.log('updateFileMetadata fileid', fileid)
const testFileMetadata = {
description: 'My description bbb.',
categories: ['Data'],
restrict: false
}

const actual = await sut.updateFileMetadata(fileid, testFileMetadata)
const getFileMetadataResult = await getFileMetadata(fileid).catch(() => {
throw new Error(`Error while getting file metadata ${fileid}`)
})

await new Promise((resolve) => setTimeout(resolve, 1000))
expect(actual).toBeUndefined()
expect(getFileMetadataResult.data.description).toBe(testFileMetadata.description)
expect(getFileMetadataResult.data.categories).toEqual(testFileMetadata.categories)
expect(getFileMetadataResult.data.restricted).toBe(testFileMetadata.restrict)
})

test('should return error when file does not exist', async () => {
const nonExistentFiledId = 4000
const testFileMetadata = {
description: 'My description bbb.',
categories: ['Data'],
restrict: false
}
const errorExpected = new WriteError(`[400] Error attempting get the requested data file.`)

await expect(sut.updateFileMetadata(nonExistentFiledId, testFileMetadata)).rejects.toThrow(
errorExpected
)
})
})
})
8 changes: 8 additions & 0 deletions test/testHelpers/files/filesHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,11 @@ export const updateFileTabularTags = async (
}
)
}

export const getFileMetadata = async (fileId: number): Promise<AxiosResponse> => {
return await axios.get(`${TestConstants.TEST_API_URL}/files/${fileId}/metadata`, {
headers: {
'X-Dataverse-Key': process.env.TEST_API_KEY
}
})
}
46 changes: 46 additions & 0 deletions test/unit/files/UpdateFileMetadata.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { UpdateFileMetadata } from '../../../src/files/domain/useCases/UpdateFileMetadata'
import { IFilesRepository } from '../../../src/files/domain/repositories/IFilesRepository'
import { WriteError } from '../../../src/core/domain/repositories/WriteError'
import { createFileMetadataWithCategories } from '../../testHelpers/files/filesHelper'

describe('UpdateFileMetadata', () => {
const testFileMetadata = createFileMetadataWithCategories()
test('should updated file metadata with correct parameters and id', async () => {
const filesRepositoryStub: IFilesRepository = {} as IFilesRepository
filesRepositoryStub.updateFileMetadata = jest.fn().mockResolvedValue(testFileMetadata)

const sut = new UpdateFileMetadata(filesRepositoryStub)

await sut.execute(1, testFileMetadata)

expect(filesRepositoryStub.updateFileMetadata).toHaveBeenCalledWith(1, testFileMetadata)
expect(filesRepositoryStub.updateFileMetadata).toHaveBeenCalledTimes(1)
})

test('should return the updated file metadata with correct parameters and persisten Id', async () => {
const filesRepositoryStub: IFilesRepository = {
updateFileMetadata: jest.fn().mockResolvedValue(testFileMetadata)
} as unknown as IFilesRepository

const sut = new UpdateFileMetadata(filesRepositoryStub)

await sut.execute('doi:10.5072/FK2/HC6KTB', testFileMetadata)

expect(filesRepositoryStub.updateFileMetadata).toHaveBeenCalledWith(
'doi:10.5072/FK2/HC6KTB',
testFileMetadata
)
expect(filesRepositoryStub.updateFileMetadata).toHaveBeenCalledTimes(1)
})

test('should throw an error if the repository throws an error', async () => {
const filesRepositoryStub: IFilesRepository = {
updateFileMetadata: jest.fn().mockRejectedValue(new WriteError())
} as unknown as IFilesRepository

const sut = new UpdateFileMetadata(filesRepositoryStub)

await expect(sut.execute(1, testFileMetadata)).rejects.toThrow(WriteError)
expect(filesRepositoryStub.updateFileMetadata).toHaveBeenCalledWith(1, testFileMetadata)
})
})

0 comments on commit 81255e0

Please sign in to comment.