Skip to content

Commit 1b9b826

Browse files
committed
feat: update delete dataset
1 parent b56897f commit 1b9b826

File tree

8 files changed

+213
-1
lines changed

8 files changed

+213
-1
lines changed

docs/useCases.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ The different use cases currently available in the package are classified below,
3939
- [Update a Dataset](#update-a-dataset)
4040
- [Publish a Dataset](#publish-a-dataset)
4141
- [Deaccession a Dataset](#deaccession-a-dataset)
42+
- [Delete a Dataset](#delete-a-dataset)
4243
- [Files](#Files)
4344
- [Files read use cases](#files-read-use-cases)
4445
- [Get a File](#get-a-file)
@@ -837,6 +838,28 @@ The `version` parameter should be a string or a [DatasetNotNumberedVersion](../s
837838

838839
You cannot deaccession a dataset more than once. If you call this endpoint twice for the same dataset version, you will get a not found error on the second call, since the dataset you are looking for will no longer be published since it is already deaccessioned.
839840

841+
#### Delete a Dataset
842+
843+
Delete a Dataset, given its identifier.
844+
845+
##### Example call:
846+
847+
```typescript
848+
import { deleteDataset } from '@iqss/dataverse-client-javascript'
849+
850+
/* ... */
851+
852+
const datasetId = 1
853+
854+
deletedataset.execute(datasetId)
855+
856+
/* ... */
857+
```
858+
859+
_See [use case](../src/datasets/domain/useCases/DeleteDataset.ts) implementation_.
860+
861+
The `datasetId` parameter is a number for numeric identifiers or string for persistent identifiers.
862+
840863
#### Get Download Count of a Dataset
841864

842865
Total number of downloads requested for a dataset, given a dataset numeric identifier,

src/datasets/domain/repositories/IDatasetsRepository.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,5 @@ export interface IDatasetsRepository {
6060
includeMDC?: boolean
6161
): Promise<DatasetDownloadCount>
6262
getDatasetVersionsSummaries(datasetId: number | string): Promise<DatasetVersionSummaryInfo[]>
63+
deleteDataset(datasetId: number | string): Promise<void>
6364
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { IDatasetsRepository } from '../repositories/IDatasetsRepository'
3+
4+
export class DeleteDataset implements UseCase<void> {
5+
private datasetsRepository: IDatasetsRepository
6+
7+
constructor(datasetsRepository: IDatasetsRepository) {
8+
this.datasetsRepository = datasetsRepository
9+
}
10+
11+
/**
12+
* Delete a Dataset
13+
*
14+
* @param {number | string} [datasetId] - The dataset identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
15+
*/
16+
async execute(datasetId: number | string): Promise<void> {
17+
return this.datasetsRepository.deleteDataset(datasetId)
18+
}
19+
}

src/datasets/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { GetDatasetVersionDiff } from './domain/useCases/GetDatasetVersionDiff'
1919
import { DeaccessionDataset } from './domain/useCases/DeaccessionDataset'
2020
import { GetDatasetDownloadCount } from './domain/useCases/GetDatasetDownloadCount'
2121
import { GetDatasetVersionsSummaries } from './domain/useCases/GetDatasetVersionsSummaries'
22+
import { DeleteDataset } from './domain/useCases/DeleteDataset'
2223

2324
const datasetsRepository = new DatasetsRepository()
2425

@@ -52,6 +53,7 @@ const updateDataset = new UpdateDataset(
5253
const deaccessionDataset = new DeaccessionDataset(datasetsRepository)
5354
const getDatasetDownloadCount = new GetDatasetDownloadCount(datasetsRepository)
5455
const getDatasetVersionsSummaries = new GetDatasetVersionsSummaries(datasetsRepository)
56+
const deleteDataset = new DeleteDataset(datasetsRepository)
5557

5658
export {
5759
getDataset,
@@ -68,7 +70,8 @@ export {
6870
updateDataset,
6971
deaccessionDataset,
7072
getDatasetDownloadCount,
71-
getDatasetVersionsSummaries
73+
getDatasetVersionsSummaries,
74+
deleteDataset
7275
}
7376
export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion'
7477
export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions'

src/datasets/infra/repositories/DatasetsRepository.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,12 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
277277
throw error
278278
})
279279
}
280+
281+
public async deleteDataset(datasetId: string | number): Promise<void> {
282+
return this.doDelete(this.buildApiEndpoint(this.datasetsResourceName, undefined, datasetId))
283+
.then(() => undefined)
284+
.catch((error) => {
285+
throw error
286+
})
287+
}
280288
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import {
2+
createDataset,
3+
publishDataset,
4+
VersionUpdateType,
5+
deleteDataset
6+
} from '../../../src/datasets'
7+
import { ApiConfig, WriteError } from '../../../src'
8+
import { TestConstants } from '../../testHelpers/TestConstants'
9+
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
10+
import { waitForNoLocks } from '../../testHelpers/datasets/datasetHelper'
11+
12+
const testDataset = {
13+
license: {
14+
name: 'CC0 1.0',
15+
uri: 'http://creativecommons.org/publicdomain/zero/1.0',
16+
iconUri: 'https://licensebuttons.net/p/zero/1.0/88x31.png'
17+
},
18+
metadataBlockValues: [
19+
{
20+
name: 'citation',
21+
fields: {
22+
title: 'Dataset created using the createDataset use case',
23+
author: [
24+
{
25+
authorName: 'Admin, Dataverse',
26+
authorAffiliation: 'Dataverse.org'
27+
},
28+
{
29+
authorName: 'Owner, Dataverse',
30+
authorAffiliation: 'Dataversedemo.org'
31+
}
32+
],
33+
datasetContact: [
34+
{
35+
datasetContactEmail: '[email protected]',
36+
datasetContactName: 'Finch, Fiona'
37+
}
38+
],
39+
dsDescription: [
40+
{
41+
dsDescriptionValue: 'This is the description of the dataset.'
42+
}
43+
],
44+
subject: ['Medicine, Health and Life Sciences']
45+
}
46+
}
47+
]
48+
}
49+
50+
describe('execute', () => {
51+
beforeEach(async () => {
52+
ApiConfig.init(
53+
TestConstants.TEST_API_URL,
54+
DataverseApiAuthMechanism.API_KEY,
55+
process.env.TEST_API_KEY
56+
)
57+
})
58+
59+
test('should delete a dataset when it is published successfully', async () => {
60+
const createdDatasetIdentifiers = await createDataset.execute(testDataset)
61+
62+
const response = await publishDataset.execute(
63+
createdDatasetIdentifiers.persistentId,
64+
VersionUpdateType.MAJOR
65+
)
66+
67+
await waitForNoLocks(createdDatasetIdentifiers.numericId, 10)
68+
69+
expect(response).toBeUndefined()
70+
71+
const actual = await deleteDataset.execute(createdDatasetIdentifiers.numericId)
72+
73+
expect(actual).toBeUndefined()
74+
})
75+
76+
test('should delete a dataset when it is not published successfully', async () => {
77+
const createdDatasetIdentifiers = await createDataset.execute(testDataset)
78+
79+
const actual = await deleteDataset.execute(createdDatasetIdentifiers.numericId)
80+
81+
expect(actual).toBeUndefined()
82+
})
83+
84+
test('should throw an error when the dataset id is incorrect', async () => {
85+
await expect(deleteDataset.execute(1111)).rejects.toBeInstanceOf(WriteError)
86+
})
87+
})

test/integration/datasets/DatasetsRepository.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,4 +1336,52 @@ describe('DatasetsRepository', () => {
13361336
)
13371337
})
13381338
})
1339+
1340+
describe('deleteDataset', () => {
1341+
test('should delete a draft dataset', async () => {
1342+
const testDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
1343+
1344+
await waitForNoLocks(testDatasetIds.numericId, 10)
1345+
1346+
const actual = await sut.deleteDataset(testDatasetIds.numericId)
1347+
1348+
expect(actual).toBeUndefined()
1349+
1350+
const expectedError = new ReadError(
1351+
`[404] Dataset with ID ${testDatasetIds.numericId} not found.`
1352+
)
1353+
1354+
await expect(
1355+
sut.getDataset(testDatasetIds.numericId, DatasetNotNumberedVersion.LATEST, false, false)
1356+
).rejects.toThrow(expectedError)
1357+
})
1358+
1359+
test('should delete a published dataset', async () => {
1360+
const testDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
1361+
1362+
await publishDatasetViaApi(testDatasetIds.numericId)
1363+
1364+
await waitForNoLocks(testDatasetIds.numericId, 10)
1365+
1366+
const actual = await sut.deleteDataset(testDatasetIds.numericId)
1367+
1368+
expect(actual).toBeUndefined()
1369+
1370+
const expectedError = new ReadError(
1371+
`[404] Dataset with ID ${testDatasetIds.numericId} not found.`
1372+
)
1373+
1374+
await expect(
1375+
sut.getDataset(testDatasetIds.numericId, DatasetNotNumberedVersion.LATEST, false, false)
1376+
).rejects.toThrow(expectedError)
1377+
})
1378+
1379+
test('should return error when dataset does not exist', async () => {
1380+
const expectedError = new WriteError(
1381+
`[404] Dataset with ID ${nonExistentTestDatasetId} not found.`
1382+
)
1383+
1384+
await expect(sut.deleteDataset(nonExistentTestDatasetId)).rejects.toThrow(expectedError)
1385+
})
1386+
})
13391387
})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { DeleteDataset } from '../../../src/datasets/domain/useCases/DeleteDataset'
2+
import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'
3+
import { WriteError } from '../../../src'
4+
5+
describe('execute', () => {
6+
test('should return undefined on delete success', async () => {
7+
const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository
8+
datasetsRepositoryStub.deleteDataset = jest.fn().mockResolvedValue(undefined)
9+
const sut = new DeleteDataset(datasetsRepositoryStub)
10+
11+
const actual = await sut.execute(1)
12+
expect(actual).toEqual(undefined)
13+
})
14+
15+
test('should return error result on delete error', async () => {
16+
const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository
17+
datasetsRepositoryStub.deleteDataset = jest.fn().mockRejectedValue(new WriteError())
18+
const sut = new DeleteDataset(datasetsRepositoryStub)
19+
20+
const nonExistentDatasetId = 111
21+
await expect(sut.execute(nonExistentDatasetId)).rejects.toThrow(WriteError)
22+
})
23+
})

0 commit comments

Comments
 (0)