diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts new file mode 100644 index 0000000000..8377afe92e --- /dev/null +++ b/src/app/core/data/data.service.spec.ts @@ -0,0 +1,133 @@ +import { DataService } from './data.service'; +import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { ResponseCacheService } from '../cache/response-cache.service'; +import { RequestService } from './request.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { CoreState } from '../core.reducers'; +import { Store } from '@ngrx/store'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { Observable } from 'rxjs/Observable'; +import { FindAllOptions } from './request.models'; +import { SortOptions, SortDirection } from '../cache/models/sort-options.model'; + +const LINK_NAME = 'test' + +// tslint:disable:max-classes-per-file +class NormalizedTestObject extends NormalizedObject { +} + +class TestService extends DataService { + constructor( + protected responseCache: ResponseCacheService, + protected requestService: RequestService, + protected rdbService: RemoteDataBuildService, + protected store: Store, + protected linkPath: string, + protected halService: HALEndpointService + ) { + super(); + } + + public getScopedEndpoint(scope: string): Observable { + throw new Error('getScopedEndpoint is abstract in DataService'); + } + +} + +describe('DataService', () => { + let service: TestService; + let options: FindAllOptions; + const responseCache = {} as ResponseCacheService; + const requestService = {} as RequestService; + const halService = {} as HALEndpointService; + const rdbService = {} as RemoteDataBuildService; + const store = {} as Store; + const endpoint = 'https://rest.api/core'; + + function initTestService(): TestService { + return new TestService( + responseCache, + requestService, + rdbService, + store, + LINK_NAME, + halService + ); + } + + service = initTestService(); + + describe('getFindAllHref', () => { + + it('should return an observable with the endpoint', () => { + options = {}; + + (service as any).getFindAllHref(endpoint).subscribe((value) => { + expect(value).toBe(endpoint); + } + ); + }); + + // getScopedEndpoint is not implemented in abstract DataService + it('should throw error if scopeID provided in options', () => { + options = { scopeID: 'somevalue' }; + + expect(() => { (service as any).getFindAllHref(endpoint, options) }) + .toThrowError('getScopedEndpoint is abstract in DataService'); + }); + + it('should include page in href if currentPage provided in options', () => { + options = { currentPage: 2 }; + const expected = `${endpoint}?page=${options.currentPage - 1}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include size in href if elementsPerPage provided in options', () => { + options = { elementsPerPage: 5 }; + const expected = `${endpoint}?size=${options.elementsPerPage}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include sort href if SortOptions provided in options', () => { + const sortOptions = new SortOptions('field1', SortDirection.ASC); + options = { sort: sortOptions}; + const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include startsWith in href if startsWith provided in options', () => { + options = { startsWith: 'ab' }; + const expected = `${endpoint}?startsWith=${options.startsWith}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }); + + it('should include all provided options in href', () => { + const sortOptions = new SortOptions('field1', SortDirection.DESC) + options = { + currentPage: 6, + elementsPerPage: 10, + sort: sortOptions, + startsWith: 'ab' + } + const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` + + `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`; + + (service as any).getFindAllHref(endpoint, options).subscribe((value) => { + expect(value).toBe(expected); + }); + }) + }); + +}); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index f532ff05ba..06e7f25926 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -45,6 +45,10 @@ export abstract class DataService args.push(`sort=${options.sort.field},${options.sort.direction}`); } + if (hasValue(options.startsWith)) { + args.push(`startsWith=${options.startsWith}`); + } + if (isNotEmpty(args)) { return result.map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString()); } else { diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 7015b0b0f1..ce45d5b41c 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -141,6 +141,7 @@ export class FindAllOptions { elementsPerPage?: number; currentPage?: number; sort?: SortOptions; + startsWith?: string; } export class FindAllRequest extends GetRequest { diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts index d52036b5dc..59df86fdff 100644 --- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts +++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts @@ -1,5 +1,6 @@ import { Component, Inject } from '@angular/core'; import { ListableObject } from '../listable-object.model'; +import { hasValue } from '../../../empty.util'; @Component({ selector: 'ds-abstract-object-element', @@ -10,4 +11,8 @@ export class AbstractListableElementComponent { public constructor(@Inject('objectElementProvider') public listableObject: ListableObject) { this.object = listableObject as T; } + + hasValue(data) { + return hasValue(data); + } } diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html index cc2f2efdb1..5100b984e0 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html @@ -10,7 +10,7 @@ {{authorMd.value}} ; - {{object.findMetadata("dc.date.issued")}} + {{object.findMetadata("dc.date.issued")}}

{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}

diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html index 1cf14587ad..1e4f6f3c64 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html @@ -13,7 +13,7 @@

- {{dso.findMetadata("dc.date.issued")}} + {{dso.findMetadata("dc.date.issued")}} , diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index e6217eb0bb..5ab9f472b4 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -3,7 +3,7 @@ import { Component, Inject } from '@angular/core'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { Metadatum } from '../../../core/shared/metadatum.model'; -import { isEmpty, hasNoValue } from '../../empty.util'; +import { isEmpty, hasNoValue, hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { TruncatableService } from '../../truncatable/truncatable.service'; @@ -60,4 +60,5 @@ export class SearchResultGridElementComponent, K exten isCollapsed(): Observable { return this.truncatableService.isCollapsed(this.dso.id); } + } diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.html b/src/app/shared/object-list/item-list-element/item-list-element.component.html index b4259c25c2..1e4a944ffa 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.html @@ -9,8 +9,8 @@ ; - ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}}) + ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}})

{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }} diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html index 2b90269693..584d476e73 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html @@ -6,7 +6,7 @@ ()