Skip to content
25 changes: 25 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The different use cases currently available in the package are classified below,
- [List All Datasets](#list-all-datasets)
- [Get Dataset Versions Summaries](#get-dataset-versions-summaries)
- [Get Dataset Linked Collections](#get-dataset-linked-collections)
- [Get Dataset Available Categories](#get-dataset-available-categories)
- [Datasets write use cases](#datasets-write-use-cases)
- [Create a Dataset](#create-a-dataset)
- [Update a Dataset](#update-a-dataset)
Expand Down Expand Up @@ -64,6 +65,8 @@ The different use cases currently available in the package are classified below,
- [Replace a File](#replace-a-file)
- [Restrict or Unrestrict a File](#restrict-or-unrestrict-a-file)
- [Update File Metadata](#update-file-metadata)
- [Update File Categories](#update-file-categories)
- [Update File Tabular Tags](#update-file-tabular-tags)
- [Metadata Blocks](#metadata-blocks)
- [Metadata Blocks read use cases](#metadata-blocks-read-use-cases)
- [Get All Facetable Metadata Fields](#get-all-facetable-metadata-fields)
Expand Down Expand Up @@ -1080,6 +1083,28 @@ The `includeMDC` parameter is optional.
- If MDC isn't enabled, the download count will return a total count, without `MDCStartDate`.
- If MDC is enabled but the `includeMDC` is false, the count will be limited to the time before `MDCStartDate`

#### Get Dataset Available Categories

Returns a list of available file categories that may be applied to the files of a given dataset.

###### Example call:

```typescript
import { getDatasetAvailableCategories } from '@iqss/dataverse-client-javascript'

/* ... */

const datasetId = 1

getDatasetAvailableCategories.execute(datasetId).then((categories: String[]) => {
/* ... */
})
```

_See [use case](../src/datasets/domain/useCases/GetDatasetAvailableCategories.ts) implementation_.

The `datasetId` parameter is a number for numeric identifiers or string for persistent identifiers.

## Files

### Files read use cases
Expand Down
1 change: 1 addition & 0 deletions src/datasets/domain/repositories/IDatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface IDatasetsRepository {
linkDataset(datasetId: number, collectionAlias: string): Promise<void>
unlinkDataset(datasetId: number, collectionAlias: string): Promise<void>
getDatasetLinkedCollections(datasetId: number | string): Promise<DatasetLinkedCollection[]>
getDatasetAvailableCategories(datasetId: number | string): Promise<string[]>
getDatasetCitationInOtherFormats(
datasetId: number | string,
datasetVersionId: string,
Expand Down
20 changes: 20 additions & 0 deletions src/datasets/domain/useCases/GetDatasetAvailableCategories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IDatasetsRepository } from '../repositories/IDatasetsRepository'

export class GetDatasetAvailableCategories implements UseCase<string[]> {
private readonly datasetsRepository: IDatasetsRepository

constructor(datasetsRepository: IDatasetsRepository) {
this.datasetsRepository = datasetsRepository
}

/**
* Retrieves the available file categories for a dataset.
*
* @param {number | string} [datasetId] - Persistent dataset identifier
* @returns {Promise<string[]>} - List of available file categories
*/
async execute(datasetId: number | string): Promise<string[]> {
return this.datasetsRepository.getDatasetAvailableCategories(datasetId)
}
}
3 changes: 3 additions & 0 deletions src/datasets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { DeleteDatasetDraft } from './domain/useCases/DeleteDatasetDraft'
import { LinkDataset } from './domain/useCases/LinkDataset'
import { UnlinkDataset } from './domain/useCases/UnlinkDataset'
import { GetDatasetLinkedCollections } from './domain/useCases/GetDatasetLinkedCollections'
import { GetDatasetAvailableCategories } from './domain/useCases/GetDatasetAvailableCategories'
import { GetDatasetCitationInOtherFormats } from './domain/useCases/GetDatasetCitationInOtherFormats'

const datasetsRepository = new DatasetsRepository()
Expand Down Expand Up @@ -61,6 +62,7 @@ const deleteDatasetDraft = new DeleteDatasetDraft(datasetsRepository)
const linkDataset = new LinkDataset(datasetsRepository)
const unlinkDataset = new UnlinkDataset(datasetsRepository)
const getDatasetLinkedCollections = new GetDatasetLinkedCollections(datasetsRepository)
const getDatasetAvailableCategories = new GetDatasetAvailableCategories(datasetsRepository)
const getDatasetCitationInOtherFormats = new GetDatasetCitationInOtherFormats(datasetsRepository)

export {
Expand All @@ -83,6 +85,7 @@ export {
linkDataset,
unlinkDataset,
getDatasetLinkedCollections,
getDatasetAvailableCategories,
getDatasetCitationInOtherFormats
}
export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion'
Expand Down
11 changes: 11 additions & 0 deletions src/datasets/infra/repositories/DatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,4 +346,15 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
throw error
})
}

public async getDatasetAvailableCategories(datasetId: number | string): Promise<string[]> {
return this.doGet(
this.buildApiEndpoint(this.datasetsResourceName, 'availableFileCategories', datasetId),
true
)
.then((response) => response.data.data as string[])
.catch((error) => {
throw error
})
}
}
2 changes: 1 addition & 1 deletion src/files/domain/useCases/UpdateFileCategories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class UpdateFileCategories implements UseCase<void> {

/**
* Updates the categories for a particular File.
* More detailed information about updating a file's categories behavior can be found in https://guides.dataverse.org/en/latest/api/native-api.html#updating-file-metadata
* More detailed information about updating a file's categories behavior can be found in https://guides.dataverse.org/en/latest/api/native-api.html#updating-file-metadata-categories
*
* @param {number | string} [fileId] - The file identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @param {string[]} [categories] - The categories to be added to the file.
Expand Down
2 changes: 1 addition & 1 deletion src/files/domain/useCases/UpdateFileTabularTags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class UpdateFileTabularTags implements UseCase<void> {

/**
* Updates the tabular tabular Tags for a particular File.
* More detailed information about updating a file's tabularTags behavior can be found in https://guides.dataverse.org/en/latest/api/native-api.html#updating-file-metadata
* More detailed information about updating a file's tabularTags behavior can be found in https://guides.dataverse.org/en/latest/api/native-api.html#updating-file-tabular-tags
*
* @param {number | string} [fileId] - The file identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @param {string[]} [tabularTags] - The tabular tags to be added to the file.
Expand Down
37 changes: 37 additions & 0 deletions test/functional/datasets/GetDatasetAvailableCategories.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ApiConfig, createDataset, getDatasetAvailableCategories, ReadError } from '../../../src'
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
import { deleteUnpublishedDatasetViaApi } from '../../testHelpers/datasets/datasetHelper'
import { CreatedDatasetIdentifiers } from '../../../src/datasets/domain/models/CreatedDatasetIdentifiers'
import { TestConstants } from '../../testHelpers/TestConstants'

describe('execute', () => {
let createdDatasetIdentifiers: CreatedDatasetIdentifiers
beforeEach(async () => {
ApiConfig.init(
TestConstants.TEST_API_URL,
DataverseApiAuthMechanism.API_KEY,
process.env.TEST_API_KEY
)
createdDatasetIdentifiers = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
})

afterEach(async () => {
deleteUnpublishedDatasetViaApi(createdDatasetIdentifiers.numericId)
})

it('should return categories array when a dataset has files categories', async () => {
const defaultCategories = ['Code', 'Data', 'Documentation']
const categoriesList = await getDatasetAvailableCategories.execute(
createdDatasetIdentifiers.numericId
)
expect(categoriesList.sort()).toEqual(defaultCategories.sort())
})

it('should return error when dataset does not exist', async () => {
const nonExistentDatasetId = 99999

await expect(
getDatasetAvailableCategories.execute(nonExistentDatasetId)
).rejects.toBeInstanceOf(ReadError)
})
})
40 changes: 40 additions & 0 deletions test/integration/datasets/DatasetsRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@
])
})
// TODO: add this test when https://github.com/IQSS/dataverse-client-javascript/issues/343 is fixed
test.skip('should throw error if trying to update an outdated internal version dataset', async () => {

Check warning on line 1066 in test/integration/datasets/DatasetsRepository.test.ts

View workflow job for this annotation

GitHub Actions / lint

Disabled test
const testDataset = {
metadataBlockValues: [
{
Expand Down Expand Up @@ -1609,4 +1609,44 @@
await expect(sut.getDatasetLinkedCollections(nonExistentTestDatasetId)).rejects.toThrow()
})
})

describe('getDatasetAvailableCategories', () => {
let testDatasetIds: CreatedDatasetIdentifiers

beforeAll(async () => {
testDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
})

afterAll(async () => {
await deletePublishedDatasetViaApi(testDatasetIds.persistentId)
})

test('should get available categories', async () => {
const fileMetadata = {
description: 'test description',
directoryLabel: 'directoryLabel',
categories: ['category1', 'category2', 'Documentation', 'Data', 'Code']
}

await uploadFileViaApi(testDatasetIds.numericId, testTextFile1Name, fileMetadata)

const actual = await sut.getDatasetAvailableCategories(testDatasetIds.numericId)
expect(actual.sort()).toEqual(fileMetadata.categories.sort())
})

test('should get available categorie if dataset id is persistent id', async () => {
const fileMetadata = {
description: 'test description',
directoryLabel: 'directoryLabel',
categories: ['category1', 'category2', 'Documentation', 'Data', 'Code']
}

const actual = await sut.getDatasetAvailableCategories(testDatasetIds.persistentId)
expect(actual.sort()).toEqual(fileMetadata.categories.sort())
})

test('should return error when dataset does not exist', async () => {
await expect(sut.getDatasetAvailableCategories(nonExistentTestDatasetId)).rejects.toThrow()
})
})
})