Skip to content

Commit 5ec471f

Browse files
committed
Added: GetCollectionFacets use case
1 parent c43f17c commit 5ec471f

File tree

8 files changed

+178
-2
lines changed

8 files changed

+178
-2
lines changed

src/collections/domain/repositories/ICollectionsRepository.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export interface ICollectionsRepository {
77
collectionDTO: CollectionDTO,
88
parentCollectionId: number | string
99
): Promise<number>
10+
getCollectionFacets(collectionIdOrAlias: number | string): Promise<string[]>
1011
}
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,22 @@
1-
// TODO
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { ICollectionsRepository } from '../repositories/ICollectionsRepository'
3+
import { ROOT_COLLECTION_ALIAS } from '../models/Collection'
4+
5+
export class GetCollectionFacets implements UseCase<string[]> {
6+
private collectionsRepository: ICollectionsRepository
7+
8+
constructor(collectionsRepository: ICollectionsRepository) {
9+
this.collectionsRepository = collectionsRepository
10+
}
11+
12+
/**
13+
* Returns the names of the configured collection facets, given a collection identifier or alias.
14+
*
15+
* @param {number | string} [collectionIdOrAlias = 'root'] - A generic collection identifier, which can be either a string (for queries by CollectionAlias), or a number (for queries by CollectionId)
16+
* If this parameter is not set, the default value is: 'root'
17+
* @returns {Promise<Collection>}
18+
*/
19+
async execute(collectionIdOrAlias: number | string = ROOT_COLLECTION_ALIAS): Promise<string[]> {
20+
return await this.collectionsRepository.getCollectionFacets(collectionIdOrAlias)
21+
}
22+
}

src/collections/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { CreateCollection } from './domain/useCases/CreateCollection'
22
import { GetCollection } from './domain/useCases/GetCollection'
3+
import { GetCollectionFacets } from './domain/useCases/GetCollectionFacets'
34

45
import { CollectionsRepository } from './infra/repositories/CollectionsRepository'
56

67
const collectionsRepository = new CollectionsRepository()
78

89
const getCollection = new GetCollection(collectionsRepository)
910
const createCollection = new CreateCollection(collectionsRepository)
11+
const getCollectionFacets = new GetCollectionFacets(collectionsRepository)
1012

11-
export { getCollection, createCollection }
13+
export { getCollection, createCollection, getCollectionFacets }
1214
export { Collection } from './domain/models/Collection'
1315
export { CollectionDTO, DatasetFieldTypeInputLevelDTO } from './domain/dtos/CollectionDTO'

src/collections/infra/repositories/CollectionsRepository.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,12 @@ export class CollectionsRepository extends ApiRepository implements ICollections
8080
throw error
8181
})
8282
}
83+
84+
public async getCollectionFacets(collectionIdOrAlias: string | number): Promise<string[]> {
85+
return this.doGet(`/${this.collectionsResourceName}/${collectionIdOrAlias}/facets`, true)
86+
.then((response) => response.data.data)
87+
.catch((error) => {
88+
throw error
89+
})
90+
}
8391
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { ApiConfig, ReadError, getCollectionFacets } from '../../../src'
2+
import { TestConstants } from '../../testHelpers/TestConstants'
3+
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
4+
import { ROOT_COLLECTION_ALIAS } from '../../../src/collections/domain/models/Collection'
5+
6+
describe('execute', () => {
7+
beforeEach(async () => {
8+
ApiConfig.init(
9+
TestConstants.TEST_API_URL,
10+
DataverseApiAuthMechanism.API_KEY,
11+
process.env.TEST_API_KEY
12+
)
13+
})
14+
15+
test('should return facets when a valid collection alias is provided', async () => {
16+
let actual: string[] = []
17+
try {
18+
actual = await getCollectionFacets.execute(ROOT_COLLECTION_ALIAS)
19+
} catch (error) {
20+
throw new Error('Facets should be retrieved')
21+
} finally {
22+
expect(actual).toContain('authorName')
23+
expect(actual).toContain('subject')
24+
expect(actual).toContain('keywordValue')
25+
expect(actual).toContain('dateOfDeposit')
26+
}
27+
})
28+
29+
test('should throw an error when collection does not exist', async () => {
30+
expect.assertions(2)
31+
let readError: ReadError
32+
try {
33+
await getCollectionFacets.execute(TestConstants.TEST_DUMMY_COLLECTION_ID)
34+
throw new Error('Use case should throw an error')
35+
} catch (error) {
36+
readError = error
37+
} finally {
38+
expect(readError).toBeInstanceOf(ReadError)
39+
expect(readError.message).toEqual(
40+
`There was an error when reading the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'`
41+
)
42+
}
43+
})
44+
})

test/integration/collections/CollectionsRepository.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,24 @@ describe('CollectionsRepository', () => {
122122
).rejects.toThrow(expectedError)
123123
})
124124
})
125+
126+
describe('getCollectionFacets', () => {
127+
test('should return collection facets given a valid collection alias', async () => {
128+
const actual = await sut.getCollectionFacets(testCollectionAlias)
129+
expect(actual).toContain('authorName')
130+
expect(actual).toContain('subject')
131+
expect(actual).toContain('keywordValue')
132+
expect(actual).toContain('dateOfDeposit')
133+
})
134+
135+
test('should return error when collection does not exist', async () => {
136+
const expectedError = new ReadError(
137+
`[404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ALIAS}'`
138+
)
139+
140+
await expect(
141+
sut.getCollectionFacets(TestConstants.TEST_DUMMY_COLLECTION_ALIAS)
142+
).rejects.toThrow(expectedError)
143+
})
144+
})
125145
})

test/unit/collections/CollectionsRepository.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,60 @@ describe('CollectionsRepository', () => {
172172
expect(error).toBeInstanceOf(Error)
173173
})
174174
})
175+
176+
describe('getCollectionFacets', () => {
177+
const testFacetsSuccessfulResponse = {
178+
data: {
179+
status: 'OK',
180+
data: ['authorName', 'subject', 'keywordValue', 'dateOfDeposit']
181+
}
182+
}
183+
184+
describe('by numeric id', () => {
185+
test('should return facets when providing a valid id', async () => {
186+
jest.spyOn(axios, 'get').mockResolvedValue(testFacetsSuccessfulResponse)
187+
const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/dataverses/${testCollectionModel.id}/facets`
188+
189+
// API Key auth
190+
let actual = await sut.getCollectionFacets(testCollectionModel.id)
191+
192+
expect(axios.get).toHaveBeenCalledWith(
193+
expectedApiEndpoint,
194+
TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY
195+
)
196+
expect(actual).toContain('authorName')
197+
expect(actual).toContain('subject')
198+
expect(actual).toContain('keywordValue')
199+
expect(actual).toContain('dateOfDeposit')
200+
201+
// Session cookie auth
202+
ApiConfig.init(TestConstants.TEST_API_URL, DataverseApiAuthMechanism.SESSION_COOKIE)
203+
204+
actual = await sut.getCollectionFacets(testCollectionModel.id)
205+
206+
expect(axios.get).toHaveBeenCalledWith(
207+
expectedApiEndpoint,
208+
TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_SESSION_COOKIE
209+
)
210+
expect(actual).toContain('authorName')
211+
expect(actual).toContain('subject')
212+
expect(actual).toContain('keywordValue')
213+
expect(actual).toContain('dateOfDeposit')
214+
})
215+
216+
test('should return error on repository read error', async () => {
217+
jest.spyOn(axios, 'get').mockRejectedValue(TestConstants.TEST_ERROR_RESPONSE)
218+
const expectedApiEndpoint = `${TestConstants.TEST_API_URL}/dataverses/${testCollectionModel.id}/facets`
219+
let error = undefined as unknown as ReadError
220+
221+
await sut.getCollectionFacets(testCollectionModel.id).catch((e) => (error = e))
222+
223+
expect(axios.get).toHaveBeenCalledWith(
224+
expectedApiEndpoint,
225+
TestConstants.TEST_EXPECTED_AUTHENTICATED_REQUEST_CONFIG_API_KEY
226+
)
227+
expect(error).toBeInstanceOf(Error)
228+
})
229+
})
230+
})
175231
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { GetCollectionFacets } from '../../../src/collections/domain/useCases/GetCollectionFacets'
2+
import { ICollectionsRepository } from '../../../src/collections/domain/repositories/ICollectionsRepository'
3+
import { ReadError } from '../../../src'
4+
5+
describe('execute', () => {
6+
test('should return collection facets on repository success', async () => {
7+
const testFacets = ['test1', 'test2']
8+
const collectionRepositoryStub: ICollectionsRepository = {} as ICollectionsRepository
9+
collectionRepositoryStub.getCollectionFacets = jest.fn().mockResolvedValue(testFacets)
10+
const testGetCollection = new GetCollectionFacets(collectionRepositoryStub)
11+
12+
const actual = await testGetCollection.execute(1)
13+
14+
expect(actual).toEqual(testFacets)
15+
})
16+
17+
test('should return error result on repository error', async () => {
18+
const collectionRepositoryStub: ICollectionsRepository = {} as ICollectionsRepository
19+
collectionRepositoryStub.getCollectionFacets = jest.fn().mockRejectedValue(new ReadError())
20+
const testGetCollection = new GetCollectionFacets(collectionRepositoryStub)
21+
22+
await expect(testGetCollection.execute(1)).rejects.toThrow(ReadError)
23+
})
24+
})

0 commit comments

Comments
 (0)