Skip to content

Commit 449bcd2

Browse files
authored
Merge pull request #286 from IQSS/284-implement-use-case-for-deleting-a-draft-dataset
Implement use case to Delete dataset
2 parents b56897f + 663cc75 commit 449bcd2

File tree

8 files changed

+174
-1
lines changed

8 files changed

+174
-1
lines changed

docs/useCases.md

Lines changed: 25 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 Draft Dataset](#delete-a-draft-dataset)
4243
- [Files](#Files)
4344
- [Files read use cases](#files-read-use-cases)
4445
- [Get a File](#get-a-file)
@@ -837,6 +838,30 @@ 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 Draft Dataset
842+
843+
Delete a Draft Dataset, given its identifier.
844+
845+
##### Example call:
846+
847+
```typescript
848+
import { deleteDatasetDraft } from '@iqss/dataverse-client-javascript'
849+
850+
/* ... */
851+
852+
const datasetId = 1
853+
854+
deleteDatasetDraft.execute(datasetId)
855+
856+
/* ... */
857+
```
858+
859+
_See [use case](../src/datasets/domain/useCases/DeleteDatasetDraft.ts) implementation_.
860+
861+
The `datasetId` parameter is a number for numeric identifiers or string for persistent identifiers.
862+
863+
If you try to delete a dataset without draft version, you will get a not found error.
864+
840865
#### Get Download Count of a Dataset
841866

842867
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+
deleteDatasetDraft(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 DeleteDatasetDraft implements UseCase<void> {
5+
private datasetsRepository: IDatasetsRepository
6+
7+
constructor(datasetsRepository: IDatasetsRepository) {
8+
this.datasetsRepository = datasetsRepository
9+
}
10+
11+
/**
12+
* Delete a Draft 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.deleteDatasetDraft(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 { DeleteDatasetDraft } from './domain/useCases/DeleteDatasetDraft'
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 deleteDatasetDraft = new DeleteDatasetDraft(datasetsRepository)
5557

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

src/datasets/infra/repositories/DatasetsRepository.ts

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

test/integration/datasets/DatasetsRepository.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,4 +1336,32 @@ describe('DatasetsRepository', () => {
13361336
)
13371337
})
13381338
})
1339+
1340+
describe('deleteDatasetDraft', () => {
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.deleteDatasetDraft(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 return error when dataset does not exist', async () => {
1360+
const expectedError = new WriteError(
1361+
`[404] Dataset with ID ${nonExistentTestDatasetId} not found.`
1362+
)
1363+
1364+
await expect(sut.deleteDatasetDraft(nonExistentTestDatasetId)).rejects.toThrow(expectedError)
1365+
})
1366+
})
13391367
})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { DeleteDatasetDraft } from '../../../src/datasets/domain/useCases/DeleteDatasetDraft'
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.deleteDatasetDraft = jest.fn().mockResolvedValue(undefined)
9+
const sut = new DeleteDatasetDraft(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.deleteDatasetDraft = jest.fn().mockRejectedValue(new WriteError())
18+
const sut = new DeleteDatasetDraft(datasetsRepositoryStub)
19+
20+
const nonExistentDatasetId = 111
21+
await expect(sut.execute(nonExistentDatasetId)).rejects.toThrow(WriteError)
22+
})
23+
})

0 commit comments

Comments
 (0)