Skip to content

Commit faf2b42

Browse files
committed
fix: add a test of using pId
2 parents 8428aae + 57409da commit faf2b42

12 files changed

Lines changed: 170 additions & 38 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
99
### Added
1010

1111
- Files: Added `getFileCitationByFormat` use case, repository method, and `FileCitationFormat` enum to support Dataverse file citation exports in `EndNote`, `RIS`, `BibTeX`, `CSL`, and `Internal` formats.
12+
- Collections: Added `allowedDatasetTypes` field to the [Collection](./src/collections/domain/models/Collection.ts) model. This field is optional and only populated the feature is enabled on the installation and configured on the collection.
13+
- Collections: Added theme information when retrieving a collection using `getCollection`.
1214

1315
### Changed
1416

docs/useCases.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,20 @@ The `collectionIdOrAlias` is a generic collection identifier, which can be eithe
198198

199199
If no collection identifier is specified, the default collection identifier; `:root` will be used. If you want to search for a different collection, you must add the collection identifier as a parameter in the use case call.
200200

201+
##### Collection Allowed Dataset Types
202+
203+
Collections can optionally restrict which [DatasetType](../src/datasets/domain/models/DatasetType.ts) objects can be created within them. The `allowedDatasetTypes` field contains an array of dataset types allowed on the collection when configured. If not configured on the collection, this field will be `undefined`.
204+
205+
```typescript
206+
getCollection.execute('myCollection').then((collection: Collection) => {
207+
if (collection.allowedDatasetTypes) {
208+
collection.allowedDatasetTypes.forEach((datasetType) => {
209+
console.log(`Allowed type: ${datasetType.displayName}`)
210+
})
211+
}
212+
})
213+
```
214+
201215
#### Get Collection Storage Driver
202216

203217
Returns a [StorageDriver](../src/core/domain/models/StorageDriver.ts) instance describing the collection's assigned storage driver.

src/collections/domain/models/Collection.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { DvObjectOwnerNode } from '../../../core'
22
import { CollectionContact } from './CollectionContact'
33
import { CollectionType } from './CollectionType'
4+
import { DatasetType } from '../../../datasets'
45

56
export interface Collection {
67
id: number
@@ -13,9 +14,22 @@ export interface Collection {
1314
inputLevels?: CollectionInputLevel[]
1415
type: CollectionType
1516
contacts?: CollectionContact[]
17+
allowedDatasetTypes?: DatasetType[]
1618
isMetadataBlockRoot: boolean
1719
isFacetRoot: boolean
1820
childCount: number
21+
theme?: CollectionTheme
22+
}
23+
24+
export interface CollectionTheme {
25+
id: number
26+
logo?: string
27+
tagline?: string
28+
linkUrl?: string
29+
linkColor?: string
30+
textColor?: string
31+
backgroundColor?: string
32+
logoBackgroundColor?: string
1933
}
2034

2135
export interface CollectionInputLevel {

src/collections/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export {
7070
deleteCollectionStorageDriver,
7171
getAllowedCollectionStorageDrivers
7272
}
73-
export { Collection, CollectionInputLevel } from './domain/models/Collection'
73+
export { Collection, CollectionInputLevel, CollectionTheme } from './domain/models/Collection'
7474
export { CollectionFacet } from './domain/models/CollectionFacet'
7575
export { CollectionUserPermissions } from './domain/models/CollectionUserPermissions'
7676
export { CollectionDTO, CollectionInputLevelDTO } from './domain/dtos/CollectionDTO'

src/collections/infra/repositories/transformers/CollectionPayload.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,23 @@ export interface CollectionPayload {
1010
isPartOf: OwnerNodePayload
1111
inputLevels?: CollectionInputLevelPayload[]
1212
dataverseContacts?: CollectionContactPayload[]
13+
allowedDatasetTypes?: AllowedDatasetTypePayload[]
1314
dataverseType: string
1415
isMetadataBlockRoot: boolean
1516
isFacetRoot: boolean
1617
childCount: number
18+
theme?: CollectionThemePayload
19+
}
20+
21+
export interface CollectionThemePayload {
22+
id: number
23+
logo?: string
24+
tagline?: string
25+
linkUrl?: string
26+
linkColor?: string
27+
textColor?: string
28+
backgroundColor?: string
29+
logoBackgroundColor?: string
1730
}
1831

1932
export interface CollectionInputLevelPayload {
@@ -26,3 +39,10 @@ export interface CollectionContactPayload {
2639
contactEmail: string
2740
displayOrder: number
2841
}
42+
43+
export interface AllowedDatasetTypePayload {
44+
id: number
45+
name: string
46+
displayName: string
47+
description?: string
48+
}

src/collections/infra/repositories/transformers/collectionTransformers.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { AxiosResponse } from 'axios'
33
import {
44
CollectionContactPayload,
55
CollectionInputLevelPayload,
6-
CollectionPayload
6+
CollectionPayload,
7+
AllowedDatasetTypePayload
78
} from './CollectionPayload'
89
import { transformPayloadToOwnerNode } from '../../../../core/infra/repositories/transformers/dvObjectOwnerNodeTransformer'
910
import { CollectionFacet } from '../../../domain/models/CollectionFacet'
@@ -13,7 +14,7 @@ import {
1314
CollectionItemSubset,
1415
CountPerObjectType
1516
} from '../../../domain/models/CollectionItemSubset'
16-
import { DatasetPreview } from '../../../../datasets'
17+
import { DatasetPreview, DatasetType } from '../../../../datasets'
1718
import { FilePreview } from '../../../../files'
1819
import { DatasetPreviewPayload } from '../../../../datasets/infra/repositories/transformers/DatasetPreviewPayload'
1920
import { FilePreviewPayload } from '../../../../files/infra/repositories/transformers/FilePreviewPayload'
@@ -74,6 +75,9 @@ const transformPayloadToCollection = (collectionPayload: CollectionPayload): Col
7475
isFacetRoot: collectionPayload.isFacetRoot,
7576
description: collectionPayload.description,
7677
childCount: collectionPayload.childCount,
78+
...(collectionPayload.theme && {
79+
theme: collectionPayload.theme
80+
}),
7781
...(collectionPayload.isPartOf && {
7882
isPartOf: transformPayloadToOwnerNode(collectionPayload.isPartOf)
7983
}),
@@ -82,6 +86,11 @@ const transformPayloadToCollection = (collectionPayload: CollectionPayload): Col
8286
}),
8387
...(collectionPayload.dataverseContacts && {
8488
contacts: transformContactsPayloadToContacts(collectionPayload.dataverseContacts)
89+
}),
90+
...(collectionPayload.allowedDatasetTypes && {
91+
allowedDatasetTypes: transformAllowedDatasetTypesPayloadToAllowedDatasetTypes(
92+
collectionPayload.allowedDatasetTypes
93+
)
8594
})
8695
}
8796
return collectionModel
@@ -252,3 +261,14 @@ const transformContactsPayloadToContacts = (
252261
displayOrder: contactPayload.displayOrder
253262
}))
254263
}
264+
265+
const transformAllowedDatasetTypesPayloadToAllowedDatasetTypes = (
266+
allowedDatasetTypesPayload: AllowedDatasetTypePayload[]
267+
): DatasetType[] => {
268+
return allowedDatasetTypesPayload.map((allowedDatasetType) => ({
269+
id: allowedDatasetType.id,
270+
name: allowedDatasetType.name,
271+
displayName: allowedDatasetType.displayName,
272+
description: allowedDatasetType.description
273+
}))
274+
}

test/functional/datasets/GetDatasetAvailableDatasetTypes.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,17 @@ describe('getDatasetAvailableDatasetTypes', () => {
1414

1515
test('should return available dataset types', async () => {
1616
const actualDatasetTypes: DatasetType[] = await getDatasetAvailableDatasetTypes.execute()
17-
const expectedDatasetTypes = [
18-
{
19-
id: 1,
20-
name: 'dataset',
21-
linkedMetadataBlocks: [],
22-
availableLicenses: [],
23-
description:
24-
'A study, experiment, set of observations, or publication. A dataset can comprise a single file or multiple files.',
25-
displayName: 'Dataset'
26-
}
27-
]
28-
expect(actualDatasetTypes).toEqual(expectedDatasetTypes)
17+
const expectedDatasetType = {
18+
id: 1,
19+
name: 'dataset',
20+
linkedMetadataBlocks: [],
21+
availableLicenses: [],
22+
description:
23+
'A study, experiment, set of observations, or publication. A dataset can comprise a single file or multiple files.',
24+
displayName: 'Dataset'
25+
}
26+
27+
expect(actualDatasetTypes).toContainEqual(expectedDatasetType)
2928
})
3029
})
3130
})

test/integration/collections/CollectionsRepository.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ describe('CollectionsRepository', () => {
110110
expect(actual.alias).toBe(ROOT_COLLECTION_ALIAS)
111111
expect(actual.isReleased).toBe(true)
112112
})
113+
114+
test('should return theme for root collection', async () => {
115+
const actual = await sut.getCollection()
116+
expect(actual.alias).toBe(ROOT_COLLECTION_ALIAS)
117+
// Root collection might or might not have a theme, but the property should be present if it does
118+
// and we want to ensure the transformer doesn't fail.
119+
// In a default Dataverse installation, root theme is usually undefined or has some default values.
120+
if (actual.theme) {
121+
expect(actual.theme).toHaveProperty('id')
122+
}
123+
})
113124
})
114125
describe('by string alias', () => {
115126
test('should return collection when it exists filtering by id AS (alias)', async () => {
@@ -176,6 +187,13 @@ describe('CollectionsRepository', () => {
176187
expect(actualAfterDatasetDeletion.childCount).toBe(0)
177188
await deleteCollectionViaApi(parentCollectionAlias)
178189
})
190+
191+
test('should transform allowedDatasetTypes correctly when retrieving a collection', async () => {
192+
const actual = await sut.getCollection(testCollectionAlias)
193+
expect(
194+
actual.allowedDatasetTypes === undefined || Array.isArray(actual.allowedDatasetTypes)
195+
).toBe(true)
196+
})
179197
})
180198

181199
describe('publishCollection', () => {

test/integration/files/FilesRepository.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,19 @@ describe('FilesRepository', () => {
682682
expect(citation.trimStart()).toMatch(/^@\w+\{/)
683683
})
684684

685+
test('should return BibTeX citation when file is requested by persistent id', async () => {
686+
expect(testFilePersistentId).toBeTruthy()
687+
688+
const citation = await sut.getFileCitationByFormat(
689+
testFilePersistentId,
690+
FileCitationFormat.BIBTEX
691+
)
692+
693+
expect(typeof citation).toBe('string')
694+
// BibTeX entries start with @<entry-type>{
695+
expect(citation.trimStart()).toMatch(/^@\w+\{/)
696+
})
697+
685698
test('should return CSL citation as JSON', async () => {
686699
const citation = await sut.getFileCitationByFormat(testFileId, FileCitationFormat.CSL)
687700

test/testHelpers/collections/collectionHelper.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import { Collection, CollectionFacet } from '../../../src/collections'
1+
import { Collection, CollectionFacet, CollectionTheme } from '../../../src/collections'
22
import { DvObjectType } from '../../../src'
3-
import { CollectionPayload } from '../../../src/collections/infra/repositories/transformers/CollectionPayload'
3+
import {
4+
CollectionPayload,
5+
CollectionThemePayload
6+
} from '../../../src/collections/infra/repositories/transformers/CollectionPayload'
47
import { TestConstants } from '../TestConstants'
58
import axios from 'axios'
69
import { CollectionDTO } from '../../../src/collections/domain/dtos/CollectionDTO'
@@ -22,7 +25,7 @@ const DATAVERSE_API_REQUEST_HEADERS = {
2225
headers: { 'Content-Type': 'application/json', 'X-Dataverse-Key': process.env.TEST_API_KEY }
2326
}
2427

25-
export const createCollectionModel = (): Collection => {
28+
export const createCollectionModel = (theme?: CollectionTheme): Collection => {
2629
const collectionModel: Collection = {
2730
id: COLLECTION_ID,
2831
alias: COLLECTION_ALIAS_STR,
@@ -45,14 +48,23 @@ export const createCollectionModel = (): Collection => {
4548
displayOrder: 0
4649
}
4750
],
51+
allowedDatasetTypes: [
52+
{
53+
id: 1,
54+
name: 'review',
55+
displayName: 'Review',
56+
description: 'A review of a dataset compiled by the expert community.'
57+
}
58+
],
4859
isMetadataBlockRoot: true,
4960
isFacetRoot: true,
50-
childCount: 0
61+
childCount: 0,
62+
...(theme && { theme })
5163
}
5264
return collectionModel
5365
}
5466

55-
export const createCollectionPayload = (): CollectionPayload => {
67+
export const createCollectionPayload = (theme?: CollectionThemePayload): CollectionPayload => {
5668
const collectionPayload: CollectionPayload = {
5769
id: COLLECTION_ID,
5870
alias: COLLECTION_ALIAS_STR,
@@ -75,9 +87,18 @@ export const createCollectionPayload = (): CollectionPayload => {
7587
displayOrder: 0
7688
}
7789
],
90+
allowedDatasetTypes: [
91+
{
92+
id: 1,
93+
name: 'review',
94+
displayName: 'Review',
95+
description: 'A review of a dataset compiled by the expert community.'
96+
}
97+
],
7898
isMetadataBlockRoot: true,
7999
isFacetRoot: true,
80-
childCount: 0
100+
childCount: 0,
101+
...(theme && { theme })
81102
}
82103
return collectionPayload
83104
}

0 commit comments

Comments
 (0)