From a2321274220ac5553d7e5d80d86bbc70261a0e96 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Wed, 4 Apr 2018 14:25:57 +0200 Subject: [PATCH 01/10] fixed some tests --- .../search-facet-filter.component.spec.ts | 99 +++++++------------ .../search-facet-filter.component.ts | 2 +- .../search-filter.service.spec.ts | 2 +- .../search-filters.component.html | 2 +- .../search-filters.component.ts | 9 +- .../search-page.component.spec.ts | 5 + .../search-service/search.service.spec.ts | 17 ++-- .../search-service/search.service.ts | 17 ---- src/app/core/browse/browse.service.spec.ts | 12 +-- src/app/core/config/config.service.spec.ts | 13 ++- src/app/core/data/comcol-data.service.spec.ts | 30 ++---- src/app/core/data/item-data.service.spec.ts | 25 +---- .../core/metadata/metadata.service.spec.ts | 3 +- .../core/shared/hal-endpoint.service.spec.ts | 23 ++--- src/app/core/shared/hal-endpoint.service.ts | 7 +- src/app/shared/route.service.spec.ts | 50 ++++------ .../testing/hal-endpoint-service-stub.ts | 11 +++ src/app/shared/testing/search-service-stub.ts | 10 +- src/tsconfig.test.json | 2 +- 19 files changed, 128 insertions(+), 211 deletions(-) create mode 100644 src/app/shared/testing/hal-endpoint-service-stub.ts diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index bf069eee60..e629925e28 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -10,6 +10,10 @@ import { FilterType } from '../../../search-service/filter-type.model'; import { FacetValue } from '../../../search-service/facet-value.model'; import { FormsModule } from '@angular/forms'; import { Observable } from 'rxjs/Observable'; +import { SearchService } from '../../../search-service/search.service'; +import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { PaginatedList } from '../../../../core/data/paginated-list'; describe('SearchFacetFilterComponent', () => { let comp: SearchFacetFilterComponent; @@ -40,29 +44,31 @@ describe('SearchFacetFilterComponent', () => { search: '' } ]; + + const searchLink = '/search'; + const selectedValues = [value1, value2]; let filterService; - const page = Observable.of(0) + const page = Observable.of(0); beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, FormsModule], declarations: [SearchFacetFilterComponent], providers: [ + { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { - provide: SearchFilterService, - useValue: { - isFilterActiveWithValue: (paramName: string, filterValue: string) => true, - getQueryParamsWith: (paramName: string, filterValue: string) => '', - getQueryParamsWithout: (paramName: string, filterValue: string) => '', - getPage: (paramName: string) => page, - /* tslint:disable:no-empty */ - incrementPage: (filterName: string) => { - }, - resetPage: (filterName: string) => { - }, - /* tslint:enable:no-empty */ - searchLink: '/search', - } - }, + provide: SearchFilterService, useValue: { + isFilterActiveWithValue: (paramName: string, filterValue: string) => true, + getPage: (paramName: string) => page, + /* tslint:disable:no-empty */ + incrementPage: (filterName: string) => { + }, + resetPage: (filterName: string) => { + }, + getSearchOptions: () => Observable.of({}), + + /* tslint:enable:no-empty */ + } + } ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(SearchFacetFilterComponent, { @@ -74,7 +80,8 @@ describe('SearchFacetFilterComponent', () => { fixture = TestBed.createComponent(SearchFacetFilterComponent); comp = fixture.componentInstance; // SearchPageComponent test instance comp.filterConfig = mockFilterConfig; - comp.filterValues = values; + comp.filterValues = [Observable.of(new RemoteData(false, false, true, null, new PaginatedList(null, values)))]; + comp.selectedValues = selectedValues; filterService = (comp as any).filterService; fixture.detectChanges(); }); @@ -97,64 +104,24 @@ describe('SearchFacetFilterComponent', () => { }); it('should return the value of the searchLink variable in the filter service', () => { - expect(link).toEqual(filterService.searchLink); + expect(link).toEqual(searchLink); }); }); - describe('when the getQueryParamsWith method is called wih a value', () => { - beforeEach(() => { - spyOn(filterService, 'getQueryParamsWith'); - comp.getQueryParamsWith(values[1].value); - }); - - it('should call getQueryParamsWith on the filterService with the correct filter parameter name and the passed value', () => { - expect(filterService.getQueryParamsWith).toHaveBeenCalledWith(mockFilterConfig, values[1].value) + describe('when the getAddParams method is called wih a value', () => { + it('should return the selectedValueq list with the new parameter value', () => { + const result = comp.getAddParams(value3); + expect(result).toEqual({[mockFilterConfig.paramName]: [value1, value2, value3]}); }); }); - describe('when the getQueryParamsWithout method is called wih a value', () => { - beforeEach(() => { - spyOn(filterService, 'getQueryParamsWithout'); - comp.getQueryParamsWithout(values[1].value); - }); - - it('should call getQueryParamsWithout on the filterService with the correct filter parameter name and the passed value', () => { - expect(filterService.getQueryParamsWithout).toHaveBeenCalledWith(mockFilterConfig, values[1].value) + describe('when the getRemoveParams method is called wih a value', () => { + it('should return the selectedValueq list with the parameter value left out', () => { + const result = comp.getRemoveParams(value1); + expect(result).toEqual({[mockFilterConfig.paramName]: [value2]}); }); }); - describe('when the facetCount method is triggered when there are less items than the amount of pages should display', () => { - let count: Observable; - beforeEach(() => { - comp.currentPage = Observable.of(3); - // 2 x 3 = 6, there are only 3 values - count = comp.facetCount; - }); - - it('should return the correct number of items shown (this equals the total amount of values for this filter)', () => { - const sub = count.subscribe((c) => expect(c).toBe(values.length)); - sub.unsubscribe(); - }); - }); - - describe('when the facetCount method is triggered when there are more items than the amount of pages should display', () => { - let count: Observable; - beforeEach(() => { - comp.currentPage = Observable.of(1); - // 2 x 1 = 2, there are more than 2 (3) items - count = comp.facetCount; - }); - - it('should return the correct number of items shown (this equals the page count x page size)', () => { - const sub = count.subscribe((c) => { - const subsub = comp.currentPage.subscribe((currentPage) => { - expect(c).toBe(currentPage * mockFilterConfig.pageSize); - }); - subsub.unsubscribe() - }); - sub.unsubscribe(); - }); - }); describe('when the showMore method is called', () => { beforeEach(() => { diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index c7941ec5dc..60b7b13b0d 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -102,7 +102,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { isLastPage(): Observable { return Observable.of(false); - // return this.filterValues.flatMap((map) => map.pop().map((rd: RemoteData>) => rd.payload.currentPage >= rd.payload.totalPages)); + // return this.filterValues$.flatMap((map) => map.pop().map((rd: RemoteData>) => rd.payload.currentPage >= rd.payload.totalPages)); } getRemoveParams(value: string) { diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts index 853f8b0f68..0ab1e4319d 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts @@ -50,7 +50,7 @@ describe('SearchFilterService', () => { }; beforeEach(() => { - service = new SearchFilterService(store, routeServiceStub, searchServiceStub); + service = new SearchFilterService(store, routeServiceStub); }); describe('when the initialCollapse method is triggered', () => { diff --git a/src/app/+search-page/search-filters/search-filters.component.html b/src/app/+search-page/search-filters/search-filters.component.html index 09782b68d4..566450b7f5 100644 --- a/src/app/+search-page/search-filters/search-filters.component.html +++ b/src/app/+search-page/search-filters/search-filters.component.html @@ -4,4 +4,4 @@ -{{"search.filters.reset" | translate}} \ No newline at end of file +{{"search.filters.reset" | translate}} \ No newline at end of file diff --git a/src/app/+search-page/search-filters/search-filters.component.ts b/src/app/+search-page/search-filters/search-filters.component.ts index 808ce3be67..517b2e1e59 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -3,6 +3,7 @@ import { SearchService } from '../search-service/search.service'; import { RemoteData } from '../../core/data/remote-data'; import { SearchFilterConfig } from '../search-service/search-filter-config.model'; import { Observable } from 'rxjs/Observable'; +import { SearchFilterService } from './search-filter/search-filter.service'; /** * This component renders a simple item page. @@ -18,12 +19,10 @@ import { Observable } from 'rxjs/Observable'; export class SearchFiltersComponent { filters: Observable>; - constructor(private searchService: SearchService) { + clearParams; + constructor(private searchService: SearchService, private filterService: SearchFilterService) { this.filters = searchService.getConfig(); - } - - getClearFiltersQueryParams(): any { - return this.searchService.getClearFiltersQueryParams(); + this.clearParams = filterService.getCurrentFilters().map((filters) => {Object.keys(filters).forEach((f) => filters[f] = null); return filters;}); } getSearchLink() { diff --git a/src/app/+search-page/search-page.component.spec.ts b/src/app/+search-page/search-page.component.spec.ts index d72610695d..8cd041eabb 100644 --- a/src/app/+search-page/search-page.component.spec.ts +++ b/src/app/+search-page/search-page.component.spec.ts @@ -17,6 +17,7 @@ import { ActivatedRoute } from '@angular/router'; import { By } from '@angular/platform-browser'; import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; +import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; describe('SearchPageComponent', () => { let comp: SearchPageComponent; @@ -89,6 +90,10 @@ describe('SearchPageComponent', () => { provide: SearchSidebarService, useValue: sidebarService }, + { + provide: SearchFilterService, + useValue: {} + }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(SearchPageComponent, { diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index f8a1d73ae1..5f9f67390b 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -15,6 +15,7 @@ import { RequestService } from '../../core/data/request.service'; import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { RouterStub } from '../../shared/testing/router-stub'; +import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; @Component({ template: '' }) class DummyComponent { @@ -37,14 +38,12 @@ describe('SearchService', () => { DummyComponent ], providers: [ - { provide: ItemDataService, useValue: {} }, - { provide: RouteService, useValue: {} }, + { provide: Router, useValue: router }, + { provide: ActivatedRoute, useValue: route }, { provide: ResponseCacheService, useValue: {} }, { provide: RequestService, useValue: {} }, - { provide: ActivatedRoute, useValue: route }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: GLOBAL_CONFIG, useValue: {} }, - { provide: Router, useValue: router }, + { provide: HALEndpointService, useValue: {} }, SearchService ], }); @@ -73,14 +72,12 @@ describe('SearchService', () => { DummyComponent ], providers: [ - { provide: ItemDataService, useValue: {} }, - { provide: RouteService, useValue: {} }, + { provide: Router, useValue: router }, + { provide: ActivatedRoute, useValue: route }, { provide: ResponseCacheService, useValue: {} }, { provide: RequestService, useValue: {} }, - { provide: ActivatedRoute, useValue: route }, { provide: RemoteDataBuildService, useValue: {} }, - { provide: GLOBAL_CONFIG, useValue: {} }, - { provide: Router, useValue: router }, + { provide: HALEndpointService, useValue: {} }, SearchService ], }); diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 2ef69e8578..134ae657a1 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -23,7 +23,6 @@ import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; -import { RouteService } from '../../shared/route.service'; import { NormalizedSearchResult } from '../normalized-search-result.model'; import { SearchOptions } from '../search-options.model'; import { SearchResult } from '../search-result.model'; @@ -37,7 +36,6 @@ import { getSearchResultFor } from './search-result-element-decorator'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { FacetValueResponseParsingService } from '../../core/data/facet-value-response-parsing.service'; import { FacetConfigResponseParsingService } from '../../core/data/facet-config-response-parsing.service'; -import { SearchFilterService } from '../search-filters/search-filter/search-filter.service'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; @Injectable() @@ -206,7 +204,6 @@ export class SearchService implements OnDestroy { } getFacetValuesFor(filterConfig: SearchFilterConfig, valuePage: number, searchOptions?: SearchOptions): Observable>> { - console.log('facetvalues'); const requestObs = this.halService.getEndpoint(this.facetValueLinkPathPrefix + filterConfig.name).pipe( map((url: string) => { const args: string[] = [`page=${valuePage - 1}`, `size=${filterConfig.pageSize}`]; @@ -268,20 +265,6 @@ export class SearchService implements OnDestroy { this.router.navigate([this.uiSearchRoute], navigationExtras); } - getClearFiltersQueryParams(): any { - const params = {}; - this.sub = this.route.queryParamMap - .subscribe((pmap) => { - pmap.keys - .filter((key) => this.config - .findIndex((conf: SearchFilterConfig) => conf.paramName === key) < 0) - .forEach((key) => { - params[key] = pmap.get(key); - }) - }); - return params; - } - getSearchLink() { return this.uiSearchRoute; } diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index 2385948b2f..2e9163fbac 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -3,11 +3,11 @@ import { getMockResponseCacheService } from '../../shared/mocks/mock-response-ca import { BrowseService } from './browse.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { RequestService } from '../data/request.service'; -import { GlobalConfig } from '../../../config'; import { hot, cold, getTestScheduler } from 'jasmine-marbles'; import { BrowseDefinition } from '../shared/browse-definition.model'; import { BrowseEndpointRequest } from '../data/request.models'; import { TestScheduler } from 'rxjs/Rx'; +import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; describe('BrowseService', () => { let scheduler: TestScheduler; @@ -15,8 +15,8 @@ describe('BrowseService', () => { let responseCache: ResponseCacheService; let requestService: RequestService; - const envConfig = {} as GlobalConfig; const browsesEndpointURL = 'https://rest.api/browses'; + const halService: any = new HALEndpointServiceStub(browsesEndpointURL); const browseDefinitions = [ Object.assign(new BrowseDefinition(), { metadataBrowse: false, @@ -91,7 +91,7 @@ describe('BrowseService', () => { return new BrowseService( responseCache, requestService, - envConfig + halService ); } @@ -106,7 +106,7 @@ describe('BrowseService', () => { responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); service = initTestService(); - spyOn(service, 'getEndpoint').and + spyOn(halService, 'getEndpoint').and .returnValue(hot('--a-', { a: browsesEndpointURL })); }); @@ -171,7 +171,7 @@ describe('BrowseService', () => { responseCache = initMockResponseCacheService(true); requestService = getMockRequestService(); service = initTestService(); - spyOn(service, 'getEndpoint').and + spyOn(halService, 'getEndpoint').and .returnValue(hot('----')); const metadatumKey = 'dc.date.issued'; @@ -188,7 +188,7 @@ describe('BrowseService', () => { responseCache = initMockResponseCacheService(false); requestService = getMockRequestService(); service = initTestService(); - spyOn(service, 'getEndpoint').and + spyOn(halService, 'getEndpoint').and .returnValue(hot('--a-', { a: browsesEndpointURL })); const metadatumKey = 'dc.date.issued'; diff --git a/src/app/core/config/config.service.spec.ts b/src/app/core/config/config.service.spec.ts index 3cdb22948f..4b05d5c929 100644 --- a/src/app/core/config/config.service.spec.ts +++ b/src/app/core/config/config.service.spec.ts @@ -1,11 +1,12 @@ import { cold, getTestScheduler, hot } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/Rx'; -import { GlobalConfig } from '../../../config'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { ConfigService } from './config.service'; import { RequestService } from '../data/request.service'; import { ConfigRequest, FindAllOptions } from '../data/request.models'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; const LINK_NAME = 'test'; const BROWSE = 'search/findByCollection'; @@ -17,8 +18,7 @@ class TestService extends ConfigService { constructor( protected responseCache: ResponseCacheService, protected requestService: RequestService, - protected EnvConfig: GlobalConfig - ) { + protected halService: HALEndpointService) { super(); } } @@ -28,8 +28,8 @@ describe('ConfigService', () => { let service: TestService; let responseCache: ResponseCacheService; let requestService: RequestService; + let halService: any; - const envConfig = {} as GlobalConfig; const findOptions: FindAllOptions = new FindAllOptions(); const scopeName = 'traditional'; @@ -51,7 +51,7 @@ describe('ConfigService', () => { return new TestService( responseCache, requestService, - envConfig + halService ); } @@ -60,8 +60,7 @@ describe('ConfigService', () => { requestService = getMockRequestService(); service = initTestService(); scheduler = getTestScheduler(); - spyOn(service, 'getEndpoint').and - .returnValue(hot('--a-', { a: serviceEndpoint })); + halService = new HALEndpointServiceStub(configEndpoint); }); describe('getConfigByHref', () => { diff --git a/src/app/core/data/comcol-data.service.spec.ts b/src/app/core/data/comcol-data.service.spec.ts index cf43482ba5..b5727fb22f 100644 --- a/src/app/core/data/comcol-data.service.spec.ts +++ b/src/app/core/data/comcol-data.service.spec.ts @@ -13,6 +13,7 @@ import { CommunityDataService } from './community-data.service'; import { FindByIDRequest } from './request.models'; import { RequestService } from './request.service'; import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; const LINK_NAME = 'test'; @@ -21,7 +22,6 @@ class NormalizedTestObject extends NormalizedObject { } class TestService extends ComColDataService { - protected linkPath = LINK_NAME; constructor( protected responseCache: ResponseCacheService, @@ -30,7 +30,9 @@ class TestService extends ComColDataService { protected store: Store, protected EnvConfig: GlobalConfig, protected cds: CommunityDataService, - protected objectCache: ObjectCacheService + protected objectCache: ObjectCacheService, + protected halService: HALEndpointService, + protected linkPath: string ) { super(); } @@ -44,6 +46,7 @@ describe('ComColDataService', () => { let requestService: RequestService; let cds: CommunityDataService; let objectCache: ObjectCacheService; + const halService: any = {}; const rdbService = {} as RemoteDataBuildService; const store = {} as Store; @@ -90,7 +93,9 @@ describe('ComColDataService', () => { store, EnvConfig, cds, - objectCache + objectCache, + halService, + LINK_NAME ); } @@ -154,24 +159,5 @@ describe('ComColDataService', () => { }); }); - describe('if the scope is not specified', () => { - beforeEach(() => { - cds = initMockCommunityDataService(); - requestService = getMockRequestService(); - objectCache = initMockObjectCacheService(); - responseCache = initMockResponseCacheService(true); - service = initTestService(); - }); - - it('should return this.getEndpoint()', () => { - spyOn(service, 'getEndpoint').and.returnValue(cold('--e-', { e: serviceEndpoint })); - - const result = service.getScopedEndpoint(undefined); - const expected = cold('--f-', { f: serviceEndpoint }); - - expect(result).toBeObservable(expected); - }); - }); - }); }); diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 7d610bfaae..4d0dc8aec3 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -1,24 +1,23 @@ import { Store } from '@ngrx/store'; import { cold, getTestScheduler } from 'jasmine-marbles'; import { TestScheduler } from 'rxjs/Rx'; -import { GlobalConfig } from '../../../config/global-config.interface'; import { BrowseService } from '../browse/browse.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { ResponseCacheService } from '../cache/response-cache.service'; import { CoreState } from '../core.reducers'; import { ItemDataService } from './item-data.service'; import { RequestService } from './request.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; describe('ItemDataService', () => { let scheduler: TestScheduler; let service: ItemDataService; let bs: BrowseService; - const requestService = {} as RequestService; const responseCache = {} as ResponseCacheService; const rdbService = {} as RemoteDataBuildService; const store = {} as Store; - const EnvConfig = {} as GlobalConfig; + const halEndpointService = {} as HALEndpointService; const scopeID = '4af28e99-6a9c-4036-a199-e1b587046d39'; const browsesEndpoint = 'https://rest.api/discover/browses'; @@ -42,8 +41,8 @@ describe('ItemDataService', () => { requestService, rdbService, store, - EnvConfig, - bs + bs, + halEndpointService ); } @@ -74,21 +73,5 @@ describe('ItemDataService', () => { expect(result).toBeObservable(expected); }); }); - - describe('if the scope is not specified', () => { - beforeEach(() => { - bs = initMockBrowseService(true); - service = initTestService(); - spyOn(service, 'getEndpoint').and.returnValue(cold('--b-', { b: serviceEndpoint })) - }); - - it('should return this.getEndpoint()', () => { - const result = service.getScopedEndpoint(undefined); - const expected = cold('--c-', { c: serviceEndpoint }); - - expect(result).toBeObservable(expected); - }); - }); - }); }); diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index 4182587cc7..f8f36a358e 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -33,7 +33,7 @@ import { Item } from '../../core/shared/item.model'; import { MockItem } from '../../shared/mocks/mock-item'; import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader'; import { BrowseService } from '../browse/browse.service'; -import { PageInfo } from '../shared/page-info.model'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; /* tslint:disable:max-classes-per-file */ @Component({ @@ -114,6 +114,7 @@ describe('MetadataService', () => { { provide: RequestService, useValue: requestService }, { provide: RemoteDataBuildService, useValue: remoteDataBuildService }, { provide: GLOBAL_CONFIG, useValue: ENV_CONFIG }, + { provide: HALEndpointService, useValue: {}}, Meta, Title, ItemDataService, diff --git a/src/app/core/shared/hal-endpoint.service.spec.ts b/src/app/core/shared/hal-endpoint.service.spec.ts index 7c73e15fab..479e15b52a 100644 --- a/src/app/core/shared/hal-endpoint.service.spec.ts +++ b/src/app/core/shared/hal-endpoint.service.spec.ts @@ -15,15 +15,15 @@ describe('HALEndpointService', () => { const endpointMap = { test: 'https://rest.api/test', }; + const linkPath = 'test'; /* tslint:disable:no-shadowed-variable */ class TestService extends HALEndpointService { - protected linkPath = 'test'; - constructor(protected responseCache: ResponseCacheService, - protected requestService: RequestService, - protected EnvConfig: GlobalConfig) { - super(); + constructor(private responseCache: ResponseCacheService, + private requestService: RequestService, + private EnvConfig: GlobalConfig) { + super(responseCache, requestService, EnvConfig); } } @@ -83,17 +83,16 @@ describe('HALEndpointService', () => { it('should return the endpoint URL for the service\'s linkPath', () => { spyOn(service as any, 'getEndpointAt').and .returnValue(hot('a-', { a: 'https://rest.api/test' })); - const result = service.getEndpoint(); + const result = service.getEndpoint(linkPath); const expected = cold('b-', { b: endpointMap.test }); expect(result).toBeObservable(expected); }); it('should return undefined for a linkPath that isn\'t in the endpoint map', () => { - (service as any).linkPath = 'unknown'; spyOn(service as any, 'getEndpointAt').and .returnValue(hot('a-', { a: undefined })); - const result = service.getEndpoint(); + const result = service.getEndpoint('unknown'); const expected = cold('b-', { b: undefined }); expect(result).toBeObservable(expected); }); @@ -113,7 +112,7 @@ describe('HALEndpointService', () => { spyOn(service as any, 'getRootEndpointMap').and .returnValue(hot('----')); - const result = service.isEnabledOnRestApi(); + const result = service.isEnabledOnRestApi(linkPath); const expected = cold('b---', { b: undefined }); expect(result).toBeObservable(expected); }); @@ -121,8 +120,7 @@ describe('HALEndpointService', () => { it('should return true if the service\'s linkPath is in the endpoint map', () => { spyOn(service as any, 'getRootEndpointMap').and .returnValue(hot('--a-', { a: endpointMap })); - - const result = service.isEnabledOnRestApi(); + const result = service.isEnabledOnRestApi(linkPath); const expected = cold('b-c-', { b: undefined, c: true }); expect(result).toBeObservable(expected); }); @@ -131,8 +129,7 @@ describe('HALEndpointService', () => { spyOn(service as any, 'getRootEndpointMap').and .returnValue(hot('--a-', { a: endpointMap })); - (service as any).linkPath = 'unknown'; - const result = service.isEnabledOnRestApi(); + const result = service.isEnabledOnRestApi('unknown'); const expected = cold('b-c-', { b: undefined, c: false }); expect(result).toBeObservable(expected); }); diff --git a/src/app/core/shared/hal-endpoint.service.ts b/src/app/core/shared/hal-endpoint.service.ts index c81c3c792d..3bedeb9915 100644 --- a/src/app/core/shared/hal-endpoint.service.ts +++ b/src/app/core/shared/hal-endpoint.service.ts @@ -14,12 +14,9 @@ import { GLOBAL_CONFIG } from '../../../config'; @Injectable() export class HALEndpointService { - protected linkPath: string; - constructor(private responseCache: ResponseCacheService, private requestService: RequestService, @Inject(GLOBAL_CONFIG) private EnvConfig: GlobalConfig) { - } protected getRootHref(): string { @@ -41,9 +38,7 @@ export class HALEndpointService { } public getEndpoint(linkPath: string): Observable { - const test = this.getEndpointAt(...linkPath.split('/')); - // test.subscribe((test) => console.log(linkPath, test)); - return test; + return this.getEndpointAt(...linkPath.split('/')); } private getEndpointAt(...path: string[]): Observable { diff --git a/src/app/shared/route.service.spec.ts b/src/app/shared/route.service.spec.ts index 00b7d78be6..b134771b3e 100644 --- a/src/app/shared/route.service.spec.ts +++ b/src/app/shared/route.service.spec.ts @@ -67,50 +67,36 @@ describe('RouteService', () => { }); }); - describe('addQueryParameterValue', () => { - it('should return a list of values that contains the added value when a new value is added and the parameter did not exist yet', () => { - service.resolveRouteWithParameterValue(nonExistingParamName, nonExistingParamValue).subscribe((params) => { - expect(params[nonExistingParamName]).toContain(nonExistingParamValue); + describe('getQueryParameterValues', () => { + it('should return a list of values when the parameter exists', () => { + service.getQueryParameterValues(paramName2).subscribe((params) => { + expect(params).toEqual([paramValue2a, paramValue2b]); }); }); - it('should return a list of values that contains the existing values and the added value when a new value is added and the parameter already has values', () => { - service.resolveRouteWithParameterValue(paramName1, nonExistingParamValue).subscribe((params) => { - const values = params[paramName1]; - expect(values).toContain(paramValue1); - expect(values).toContain(nonExistingParamValue); + + it('should return an empty array when the parameter does not exists', () => { + service.getQueryParameterValues(nonExistingParamName).subscribe((params) => { + expect(params).toEqual([]); }); }); }); - describe('removeQueryParameterValue', () => { - it('should return a list of values that does not contain the removed value when the parameter value exists', () => { - service.resolveRouteWithoutParameterValue(paramName2, paramValue2a).subscribe((params) => { - const values = params[paramName2]; - expect(values).toContain(paramValue2b); - expect(values).not.toContain(paramValue2a); + describe('getQueryParameterValue', () => { + it('should return a single value when the parameter exists', () => { + service.getQueryParameterValue(paramName1).subscribe((params) => { + expect(params).toEqual(paramValue1); }); }); - it('should return a list of values that does contain all existing values when the removed parameter does not exist', () => { - service.resolveRouteWithoutParameterValue(paramName2, nonExistingParamValue).subscribe((params) => { - const values = params[paramName2]; - expect(values).toContain(paramValue2a); - expect(values).toContain(paramValue2b); + it('should return only the first value when the parameter exists', () => { + service.getQueryParameterValue(paramName2).subscribe((params) => { + expect(params).toEqual(paramValue2a); }); }); - }); - describe('getWithoutParameter', () => { - it('should return a list of values that does not contain any values for the parameter anymore when the parameter exists', () => { - service.resolveRouteWithoutParameter(paramName2).subscribe((params) => { - const values = params[paramName2]; - expect(values).toEqual({}); - }); - }); - it('should return a list of values that does not contain any values for the parameter when the parameter does not exist', () => { - service.resolveRouteWithoutParameter(nonExistingParamName).subscribe((params) => { - const values = params[nonExistingParamName]; - expect(values).toEqual({}); + it('should return undefined when the parameter exists', () => { + service.getQueryParameterValue(nonExistingParamName).subscribe((params) => { + expect(params).toBeNull(); }); }); }); diff --git a/src/app/shared/testing/hal-endpoint-service-stub.ts b/src/app/shared/testing/hal-endpoint-service-stub.ts new file mode 100644 index 0000000000..e7dbe8bea1 --- /dev/null +++ b/src/app/shared/testing/hal-endpoint-service-stub.ts @@ -0,0 +1,11 @@ +import { Observable } from 'rxjs/Observable'; +import { ViewMode } from '../../+search-page/search-options.model'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; + +export class HALEndpointServiceStub { + + constructor(private url: string) {}; + getEndpoint(path: string) { + return Observable.of(this.url + '/' + path); + } +} diff --git a/src/app/shared/testing/search-service-stub.ts b/src/app/shared/testing/search-service-stub.ts index 23b2004827..7ad0d871ce 100644 --- a/src/app/shared/testing/search-service-stub.ts +++ b/src/app/shared/testing/search-service-stub.ts @@ -9,7 +9,7 @@ export class SearchServiceStub { viewMode = this.subject.asObservable(); - constructor() { + constructor(private searchLink: string = '/search') { this.setViewMode(ViewMode.List); } @@ -21,6 +21,10 @@ export class SearchServiceStub { this.testViewMode = viewMode; } + getFacetValuesFor() { + return null; + } + get testViewMode(): ViewMode { return this._viewMode; } @@ -29,4 +33,8 @@ export class SearchServiceStub { this._viewMode = viewMode; this.subject.next(viewMode); } + + getSearchLink() { + return this.searchLink; + } } diff --git a/src/tsconfig.test.json b/src/tsconfig.test.json index 079eabc561..712ad1ab1c 100644 --- a/src/tsconfig.test.json +++ b/src/tsconfig.test.json @@ -1,4 +1,4 @@ -yarn add{ +{ "extends": "../tsconfig.json", "compilerOptions": { "sourceMap": true From 79caf1533c3e90a31ab8b15b360187f4df359dc9 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Thu, 5 Apr 2018 08:49:36 +0200 Subject: [PATCH 02/10] fixes for existing tested --- .../search-facet-filter.component.html | 4 +- .../search-filter.service.spec.ts | 32 ------- .../search-filters.component.spec.ts | 16 ++-- .../+search-page/search-page.component.html | 18 ++-- .../search-page.component.spec.ts | 85 +++++-------------- src/app/+search-page/search-page.component.ts | 43 +++------- .../core/shared/hal-endpoint.service.spec.ts | 18 +--- .../search-form/search-form.component.spec.ts | 2 +- .../search-form/search-form.component.ts | 6 +- 9 files changed, 56 insertions(+), 168 deletions(-) diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html index aa71c5c24c..8687aeb25b 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html @@ -32,7 +32,7 @@ [action]="getCurrentUrl()"> + [placeholder]="'search.filters.filter.' + filterConfig.name + '.placeholder'| translate" [ngModelOptions]="{standalone: true}"/> - \ No newline at end of file + diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts index 0ab1e4319d..26eb961c53 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.spec.ts @@ -159,28 +159,6 @@ describe('SearchFilterService', () => { }); }); - describe('when the getQueryParamsWithout method is called', () => { - beforeEach(() => { - spyOn(routeServiceStub, 'removeQueryParameterValue'); - service.getQueryParamsWithout(mockFilterConfig, value1); - }); - - it('should call removeQueryParameterValue on the route service with the same parameters', () => { - expect(routeServiceStub.removeQueryParameterValue).toHaveBeenCalledWith(mockFilterConfig.paramName, value1); - }); - }); - - describe('when the getQueryParamsWith method is called', () => { - beforeEach(() => { - spyOn(routeServiceStub, 'addQueryParameterValue'); - service.getQueryParamsWith(mockFilterConfig, value1); - }); - - it('should call addQueryParameterValue on the route service with the same parameters', () => { - expect(routeServiceStub.addQueryParameterValue).toHaveBeenCalledWith(mockFilterConfig.paramName, value1); - }); - }); - describe('when the getSelectedValuesForFilter method is called', () => { beforeEach(() => { spyOn(routeServiceStub, 'getQueryParameterValues'); @@ -192,14 +170,4 @@ describe('SearchFilterService', () => { }); }); - describe('when the uiSearchRoute method is called', () => { - let link: string; - beforeEach(() => { - link = service.searchLink; - }); - - it('should return the value of uiSearchRoute in the search service', () => { - expect(link).toEqual(searchServiceStub.uiSearchRoute); - }); - }); }); diff --git a/src/app/+search-page/search-filters/search-filters.component.spec.ts b/src/app/+search-page/search-filters/search-filters.component.spec.ts index 0bdee94634..64c2ea5332 100644 --- a/src/app/+search-page/search-filters/search-filters.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filters.component.spec.ts @@ -4,6 +4,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { SearchFilterService } from './search-filter/search-filter.service'; import { SearchFiltersComponent } from './search-filters.component'; import { SearchService } from '../search-service/search.service'; import { Observable } from 'rxjs/Observable'; @@ -22,6 +23,9 @@ describe('SearchFiltersComponent', () => { } /* tslint:enable:no-empty */ }; + const searchFilterServiceStub = jasmine.createSpyObj('SearchFilterService', { + getCurrentFilters: Observable.of({}) + }); beforeEach(async(() => { TestBed.configureTestingModule({ @@ -29,6 +33,7 @@ describe('SearchFiltersComponent', () => { declarations: [SearchFiltersComponent], providers: [ { provide: SearchService, useValue: searchServiceStub }, + { provide: SearchFilterService, useValue: searchFilterServiceStub }, ], schemas: [NO_ERRORS_SCHEMA] @@ -44,17 +49,6 @@ describe('SearchFiltersComponent', () => { searchService = (comp as any).searchService; }); - describe('when the getClearFiltersQueryParams method is called', () => { - beforeEach(() => { - spyOn(searchService, 'getClearFiltersQueryParams'); - comp.getClearFiltersQueryParams(); - }); - - it('should call getClearFiltersQueryParams on the searchService', () => { - expect(searchService.getClearFiltersQueryParams).toHaveBeenCalled() - }); - }); - describe('when the getSearchLink method is called', () => { beforeEach(() => { spyOn(searchService, 'getSearchLink'); diff --git a/src/app/+search-page/search-page.component.html b/src/app/+search-page/search-page.component.html index 81f0c78527..c50bb30696 100644 --- a/src/app/+search-page/search-page.component.html +++ b/src/app/+search-page/search-page.component.html @@ -1,22 +1,22 @@
- + [resultCount]="(resultsRD$ | async)?.pageInfo?.totalElements">
+ [scopes]="(scopeListRD$ | async)?.payload?.page">
- @@ -29,8 +29,8 @@ | translate}}
- +
diff --git a/src/app/+search-page/search-page.component.spec.ts b/src/app/+search-page/search-page.component.spec.ts index 8cd041eabb..cc53e18871 100644 --- a/src/app/+search-page/search-page.component.spec.ts +++ b/src/app/+search-page/search-page.component.spec.ts @@ -4,12 +4,14 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; +import { cold, hot } from 'jasmine-marbles'; import { Observable } from 'rxjs/Observable'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CommunityDataService } from '../core/data/community-data.service'; import { Community } from '../core/shared/community.model'; import { HostWindowService } from '../shared/host-window.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; +import { PaginatedSearchOptions } from './paginated-search-options.model'; import { SearchPageComponent } from './search-page.component'; import { SearchService } from './search-service/search.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -35,12 +37,17 @@ describe('SearchPageComponent', () => { pagination.pageSize = 10; const sort: SortOptions = new SortOptions(); const mockResults = Observable.of(['test', 'data']); - const searchServiceStub = { - searchOptions:{ pagination: pagination, sort: sort }, - search: () => mockResults - }; + const searchServiceStub = jasmine.createSpyObj('SearchService', { + search: mockResults + }); const queryParam = 'test query'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; + const paginatedSearchOptions = { + query: queryParam, + scope: scopeParam, + pagination, + sort + }; const activatedRouteStub = { queryParams: Observable.of({ query: queryParam, @@ -51,20 +58,8 @@ describe('SearchPageComponent', () => { isCollapsed: Observable.of(true), collapse: () => this.isCollapsed = Observable.of(true), expand: () => this.isCollapsed = Observable.of(false) - } - - const mockCommunityList = []; - const communityDataServiceStub = { - findAll: () => Observable.of(mockCommunityList), - findById: () => Observable.of(new Community()) }; - class RouterStub { - navigateByUrl(url: string) { - return url; - } - } - beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule.forRoot()], @@ -92,7 +87,11 @@ describe('SearchPageComponent', () => { }, { provide: SearchFilterService, - useValue: {} + useValue: jasmine.createSpyObj('SearchFilterService', { + getPaginatedSearchOptions: hot('a', { + a: paginatedSearchOptions + }) + }) }, ], schemas: [NO_ERRORS_SCHEMA] @@ -108,54 +107,10 @@ describe('SearchPageComponent', () => { searchServiceObject = (comp as any).service; }); - it('should set the scope and query based on the route parameters', () => { - expect(comp.query).toBe(queryParam); - expect((comp as any).scope).toBe(scopeParam); - }); - - describe('when update search results is called', () => { - let paginationUpdate; - let sortUpdate; - beforeEach(() => { - paginationUpdate = Object.assign( - {}, - new PaginationComponentOptions(), - { - currentPage: 5, - pageSize: 15 - } - ); - sortUpdate = Object.assign({}, - new SortOptions(), - { - direction: SortDirection.Ascending, - field: 'test-field' - } - ); - }); - - it('should call the search function of the search service with the right parameters', () => { - spyOn(searchServiceObject, 'search').and.callThrough(); - - (comp as any).updateSearchResults({ - pagination: pagination, - sort: sort - }); - - expect(searchServiceObject.search).toHaveBeenCalledWith(queryParam, scopeParam, { - pagination: pagination, - sort: sort - }); - }); - - it('should update the results', () => { - spyOn(searchServiceObject, 'search').and.callThrough(); - - (comp as any).updateSearchResults({}); - - expect(comp.resultsRDObs as any).toBe(mockResults); - }); - + it('should get the scope and query from the route parameters', () => { + expect(comp.searchOptions$).toBeObservable(cold('b', { + b: paginatedSearchOptions + })); }); describe('when the closeSidebar event is emitted clicked in mobile view', () => { diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index 57fb02b730..2a903f884a 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs/Observable'; +import { flatMap, } from 'rxjs/operators'; import { SortOptions } from '../core/cache/models/sort-options.model'; import { CommunityDataService } from '../core/data/community-data.service'; import { PaginatedList } from '../core/data/paginated-list'; @@ -8,14 +8,12 @@ import { RemoteData } from '../core/data/remote-data'; import { Community } from '../core/shared/community.model'; import { DSpaceObject } from '../core/shared/dspace-object.model'; import { pushInOut } from '../shared/animations/push'; -import { isNotEmpty } from '../shared/empty.util'; import { HostWindowService } from '../shared/host-window.service'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { SearchOptions, ViewMode } from './search-options.model'; +import { PaginatedSearchOptions } from './paginated-search-options.model'; +import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; import { SearchResult } from './search-result.model'; import { SearchService } from './search-service/search.service'; import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; -import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; /** * This component renders a simple item page. @@ -30,19 +28,14 @@ import { SearchFilterService } from './search-filters/search-filter/search-filte changeDetection: ChangeDetectionStrategy.OnPush, animations: [pushInOut] }) -export class SearchPageComponent implements OnInit, OnDestroy { +export class SearchPageComponent implements OnInit { - private sub; - private scope: string; - - query: string; - scopeObjectRDObs: Observable>; - resultsRDObs: Observable>>>; + resultsRD$: Observable>>>; currentParams = {}; - searchOptions: SearchOptions; + searchOptions$: Observable; sortConfig: SortOptions; - scopeListRDObs: Observable>>; - isMobileView: Observable; + scopeListRD$: Observable>>; + isMobileView$: Observable; pageSize; pageSizeOptions; defaults = { @@ -58,27 +51,19 @@ export class SearchPageComponent implements OnInit, OnDestroy { private sidebarService: SearchSidebarService, private windowService: HostWindowService, private filterService: SearchFilterService) { - this.isMobileView = Observable.combineLatest( + this.isMobileView$ = Observable.combineLatest( this.windowService.isXs(), this.windowService.isSm(), ((isXs, isSm) => isXs || isSm) ); - this.scopeListRDObs = communityService.findAll(); + this.scopeListRD$ = communityService.findAll(); } ngOnInit(): void { - this.sub = this.filterService.getPaginatedSearchOptions(this.defaults).subscribe((options) => { - this.updateSearchResults(options); - }); - } - - private updateSearchResults(searchOptions) { - this.resultsRDObs = this.service.search(searchOptions); - this.searchOptions = searchOptions; - } - - ngOnDestroy() { - this.sub.unsubscribe(); + this.searchOptions$ = this.filterService.getPaginatedSearchOptions(this.defaults); + this.resultsRD$ = this.searchOptions$.pipe( + flatMap((searchOptions) => this.service.search(searchOptions)) + ); } public closeSidebar(): void { diff --git a/src/app/core/shared/hal-endpoint.service.spec.ts b/src/app/core/shared/hal-endpoint.service.spec.ts index 479e15b52a..0c2afe938b 100644 --- a/src/app/core/shared/hal-endpoint.service.spec.ts +++ b/src/app/core/shared/hal-endpoint.service.spec.ts @@ -17,18 +17,6 @@ describe('HALEndpointService', () => { }; const linkPath = 'test'; - /* tslint:disable:no-shadowed-variable */ - class TestService extends HALEndpointService { - - constructor(private responseCache: ResponseCacheService, - private requestService: RequestService, - private EnvConfig: GlobalConfig) { - super(responseCache, requestService, EnvConfig); - } - } - - /* tslint:enable:no-shadowed-variable */ - describe('getRootEndpointMap', () => { beforeEach(() => { responseCache = jasmine.createSpyObj('responseCache', { @@ -45,7 +33,7 @@ describe('HALEndpointService', () => { rest: { baseUrl: 'https://rest.api/' } } as any; - service = new TestService( + service = new HALEndpointService( responseCache, requestService, envConfig @@ -73,7 +61,7 @@ describe('HALEndpointService', () => { rest: { baseUrl: 'https://rest.api/' } } as any; - service = new TestService( + service = new HALEndpointService( responseCache, requestService, envConfig @@ -100,7 +88,7 @@ describe('HALEndpointService', () => { describe('isEnabledOnRestApi', () => { beforeEach(() => { - service = new TestService( + service = new HALEndpointService( responseCache, requestService, envConfig diff --git a/src/app/shared/search-form/search-form.component.spec.ts b/src/app/shared/search-form/search-form.component.spec.ts index ee1a8cd8f5..d148429b01 100644 --- a/src/app/shared/search-form/search-form.component.spec.ts +++ b/src/app/shared/search-form/search-form.component.spec.ts @@ -69,7 +69,7 @@ describe('SearchFormComponent', () => { fixture.detectChanges(); const testCommunity = objects[1]; - comp.scope = testCommunity; + comp.scope = testCommunity.id; fixture.detectChanges(); tick(); diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index fb3c6ba5a2..478df3bb65 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -22,10 +22,8 @@ export class SearchFormComponent { @Input() scopes: DSpaceObject[]; @Input() - set scope(dso: DSpaceObject) { - if (hasValue(dso)) { - this.selectedId = dso.id; - } + set scope(id: string) { + this.selectedId = id; } constructor(private router: Router) { From 6133bc5068a37a8d3f0bd16c22b35ecca5cb63c1 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Thu, 5 Apr 2018 09:51:46 +0200 Subject: [PATCH 03/10] fixed tslint error --- .../search-facet-filter/search-facet-filter.component.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index e629925e28..c3dcff8368 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -122,7 +122,6 @@ describe('SearchFacetFilterComponent', () => { }); }); - describe('when the showMore method is called', () => { beforeEach(() => { spyOn(filterService, 'incrementPage'); From d5114a87dab77fd8aec872ca684ed38b06362439 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Thu, 5 Apr 2018 15:54:51 +0200 Subject: [PATCH 04/10] search page fix --- .../search-filters/search-filter/search-filter.service.ts | 4 ++-- src/app/+search-page/search-page.component.ts | 3 ++- src/app/+search-page/search-service/search.service.ts | 2 +- src/app/shared/pagination/pagination.component.ts | 3 ++- src/app/shared/search-form/search-form.component.html | 2 +- src/app/shared/search-form/search-form.component.ts | 7 ------- 6 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts index 9c5e406a78..1ba8182d33 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.service.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.service.ts @@ -79,13 +79,13 @@ export class SearchFilterService { this.getCurrentQuery(), this.getCurrentFilters(), (pagination, sort, view, scope, query, filters) => { - return Object.assign(new SearchOptions(), + return Object.assign(new PaginatedSearchOptions(), defaults, { pagination: pagination, sort: sort, view: view, - scope: scope, + scope: scope || defaults.scope, query: query, filters: filters }) diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index 2a903f884a..c9efc65676 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -43,7 +43,8 @@ export class SearchPageComponent implements OnInit { id: 'search-results-pagination', pageSize: 10 }, - query: '' + query: '', + scope: '' }; constructor(private service: SearchService, diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 134ae657a1..42f527a411 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -99,7 +99,7 @@ export class SearchService implements OnDestroy { const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe( map((url: string) => { if (hasValue(searchOptions)) { - url = searchOptions.toRestUrl(url); + url = (searchOptions as PaginatedSearchOptions).toRestUrl(url); } const request = new GetRequest(this.requestService.generateRequestId(), url); return Object.assign(request, { diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 2fa70ddd18..6ab0e2a567 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -336,7 +336,8 @@ export class PaginationComponent implements OnDestroy, OnInit { */ private updateRoute(params: {}) { this.router.navigate([], { - queryParams: Object.assign({}, this.currentQueryParams, params) + queryParams: Object.assign({}, this.currentQueryParams, params), + queryParamsHandling: 'merge' }); } diff --git a/src/app/shared/search-form/search-form.component.html b/src/app/shared/search-form/search-form.component.html index a4e8cddc1e..8bca5aabeb 100644 --- a/src/app/shared/search-form/search-form.component.html +++ b/src/app/shared/search-form/search-form.component.html @@ -1,6 +1,6 @@
- diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index 478df3bb65..49f825e28c 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -50,11 +50,4 @@ export class SearchFormComponent { return isNotEmpty(object); } - byId(id1: string, id2: string) { - if (isEmpty(id1) && isEmpty(id2)) { - return true; - } - return id1 === id2; - } - } From e6b4381f4573c954fbe09c95059203718d46ea9a Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Thu, 5 Apr 2018 16:34:49 +0200 Subject: [PATCH 05/10] fixed pagination test --- src/app/shared/pagination/pagination.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index b108074893..ad05f0cdfe 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -271,7 +271,7 @@ describe('Pagination component', () => { changePage(testFixture, 3); tick(); - expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 3, pageSize: 10, sortDirection: 'ASC', sortField: 'dc.title' } }); + expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 3, pageSize: 10, sortDirection: 'ASC', sortField: 'dc.title' }, queryParamsHandling: 'merge' }); })); @@ -282,7 +282,7 @@ describe('Pagination component', () => { changePageSize(testFixture, '20'); tick(); - expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 1, pageSize: 20, sortDirection: 'ASC', sortField: 'dc.title' } }); + expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 1, pageSize: 20, sortDirection: 'ASC', sortField: 'dc.title' } , queryParamsHandling: 'merge' }); })); it('should set correct values', fakeAsync(() => { From 7caff8ca8ae9149a65658d512f5f56a24a931f77 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Mon, 9 Apr 2018 11:34:34 +0200 Subject: [PATCH 06/10] added missing tests for the search-facet-filter component --- .../search-facet-filter.component.spec.ts | 96 +++++++++++++++++-- .../search-facet-filter.component.ts | 11 ++- src/app/shared/testing/router-stub.ts | 4 + 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index c3dcff8368..25a6d90c17 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -14,6 +14,10 @@ import { SearchService } from '../../../search-service/search.service'; import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; import { RemoteData } from '../../../../core/data/remote-data'; import { PaginatedList } from '../../../../core/data/paginated-list'; +import { SearchOptions } from '../../../search-options.model'; +import { RouterStub } from '../../../../shared/testing/router-stub'; +import { Router } from '@angular/router'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; describe('SearchFacetFilterComponent', () => { let comp: SearchFacetFilterComponent; @@ -48,13 +52,18 @@ describe('SearchFacetFilterComponent', () => { const searchLink = '/search'; const selectedValues = [value1, value2]; let filterService; + let searchService; + let router; const page = Observable.of(0); + + const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(null, values))); beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, FormsModule], + imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], declarations: [SearchFacetFilterComponent], providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, + { provide: Router, useValue: new RouterStub() }, { provide: SearchFilterService, useValue: { isFilterActiveWithValue: (paramName: string, filterValue: string) => true, @@ -65,7 +74,6 @@ describe('SearchFacetFilterComponent', () => { resetPage: (filterName: string) => { }, getSearchOptions: () => Observable.of({}), - /* tslint:enable:no-empty */ } } @@ -80,9 +88,13 @@ describe('SearchFacetFilterComponent', () => { fixture = TestBed.createComponent(SearchFacetFilterComponent); comp = fixture.componentInstance; // SearchPageComponent test instance comp.filterConfig = mockFilterConfig; - comp.filterValues = [Observable.of(new RemoteData(false, false, true, null, new PaginatedList(null, values)))]; + comp.filterValues = [mockValues]; + comp.filterValues$ = new BehaviorSubject(comp.filterValues); comp.selectedValues = selectedValues; filterService = (comp as any).filterService; + searchService = (comp as any).searchService; + spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues); + router = (comp as any).router; fixture.detectChanges(); }); @@ -111,14 +123,14 @@ describe('SearchFacetFilterComponent', () => { describe('when the getAddParams method is called wih a value', () => { it('should return the selectedValueq list with the new parameter value', () => { const result = comp.getAddParams(value3); - expect(result).toEqual({[mockFilterConfig.paramName]: [value1, value2, value3]}); + expect(result).toEqual({ [mockFilterConfig.paramName]: [value1, value2, value3] }); }); }); describe('when the getRemoveParams method is called wih a value', () => { it('should return the selectedValueq list with the parameter value left out', () => { const result = comp.getRemoveParams(value1); - expect(result).toEqual({[mockFilterConfig.paramName]: [value2]}); + expect(result).toEqual({ [mockFilterConfig.paramName]: [value2] }); }); }); @@ -140,7 +152,7 @@ describe('SearchFacetFilterComponent', () => { }); it('should call resetPage on the filterService with the correct filter parameter name', () => { - expect(filterService.resetPage).toHaveBeenCalledWith(mockFilterConfig.name) + expect(filterService.resetPage).toHaveBeenCalledWith(mockFilterConfig.name); }); }); @@ -154,4 +166,76 @@ describe('SearchFacetFilterComponent', () => { expect(filterService.getPage).toHaveBeenCalledWith(mockFilterConfig.name) }); }); + + describe('when the getCurrentUrl method is called', () => { + const url = 'test.url/test' + beforeEach(() => { + router.navigateByUrl(url); + }); + + it('should call getPage on the filterService with the correct filter parameter name', () => { + expect(router.url).toEqual(url); + }); + }); + + describe('when the onSubmit method is called with data', () => { + const searchUrl = '/search/path'; + const testValue = 'test'; + const data = { [mockFilterConfig.paramName]: testValue }; + beforeEach(() => { + spyOn(comp, 'getSearchLink').and.returnValue(searchUrl); + comp.onSubmit(data); + }); + + it('should call navigate on the router with the right searchlink and parameters', () => { + expect(router.navigate).toHaveBeenCalledWith([searchUrl], { + queryParams: { [mockFilterConfig.paramName]: [...selectedValues, testValue] }, + queryParamsHandling: 'merge' + }); + }); + }); + + describe('when updateFilterValueList is called', () => { + const cPage = 10; + const searchOptions = new SearchOptions(); + beforeEach(() => { + // spyOn(searchService, 'getFacetValuesFor'); Already spied upon + comp.currentPage = Observable.of(cPage); + comp.updateFilterValueList(searchOptions); + }); + + it('should call getFacetValuesFor on the searchService with the correct parameters', () => { + expect(searchService.getFacetValuesFor).toHaveBeenCalledWith(mockFilterConfig, cPage, searchOptions); + }); + }); + + describe('when updateFilterValueList is called and pageChange is set to true', () => { + const searchOptions = new SearchOptions(); + beforeEach(() => { + comp.pageChange = true; + spyOn(comp, 'showFirstPageOnly'); + comp.updateFilterValueList(searchOptions); + }); + + it('should not call showFirstPageOnly on the component', () => { + expect(comp.showFirstPageOnly).not.toHaveBeenCalled(); + }); + + it('should set pageChange to false', () => { + expect(comp.pageChange).toBeFalsy(); + }); + }); + + describe('when updateFilterValueList is called and pageChange is set to false', () => { + const searchOptions = new SearchOptions(); + beforeEach(() => { + comp.pageChange = false; + spyOn(comp, 'showFirstPageOnly'); + comp.updateFilterValueList(searchOptions); + }); + + it('should call showFirstPageOnly on the component', () => { + expect(comp.showFirstPageOnly).toHaveBeenCalled(); + }); + }); }); diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 60b7b13b0d..04258fbd35 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -57,7 +57,6 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { this.filterValues = [...this.filterValues, newValues$]; this.filterValues$.next(this.filterValues); }); - // this.filterValues.subscribe((c) => c.map((a) => a.subscribe((b) => console.log(b)))); } isChecked(value: FacetValue): Observable { @@ -101,8 +100,14 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { } isLastPage(): Observable { - return Observable.of(false); - // return this.filterValues$.flatMap((map) => map.pop().map((rd: RemoteData>) => rd.payload.currentPage >= rd.payload.totalPages)); + return this.filterValues$.flatMap((map) => { + + if (isNotEmpty(map)) { + return map.pop().map((rd: RemoteData>) => rd.payload.currentPage >= rd.payload.totalPages); + } else { + return false; + } + }); } getRemoveParams(value: string) { diff --git a/src/app/shared/testing/router-stub.ts b/src/app/shared/testing/router-stub.ts index 6a560d9574..ca4f7642b8 100644 --- a/src/app/shared/testing/router-stub.ts +++ b/src/app/shared/testing/router-stub.ts @@ -1,4 +1,8 @@ export class RouterStub { + url: string; //noinspection TypeScriptUnresolvedFunction navigate = jasmine.createSpy('navigate'); + navigateByUrl(url): void { + this.url = url; + } } From c9e7cdcf9a20399a549242f18584a6ce0ae2db0e Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Mon, 9 Apr 2018 16:29:12 +0200 Subject: [PATCH 07/10] added search service test --- .../search-service/search.service.spec.ts | 138 +++++++++++++++++- .../search-service/search.service.ts | 2 +- src/app/shared/mocks/mock-request.service.ts | 4 +- .../mocks/mock-response-cache.service.ts | 12 +- 4 files changed, 143 insertions(+), 13 deletions(-) diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index 5f9f67390b..ef6efe3deb 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -16,6 +16,22 @@ import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { RouterStub } from '../../shared/testing/router-stub'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; +import { Observable } from 'rxjs/Observable'; +import { PaginatedSearchOptions } from '../paginated-search-options.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { SearchResult } from '../search-result.model'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; +import { RequestEntry } from '../../core/data/request.reducer'; +import { getMockRequestService } from '../../shared/mocks/mock-request.service'; +import { getMockResponseCacheService } from '../../shared/mocks/mock-response-cache.service'; +import { + FacetConfigSuccessResponse, RestResponse, + SearchSuccessResponse +} from '../../core/cache/response-cache.models'; +import { SearchQueryResponse } from './search-query-response.model'; +import { SearchFilterConfig } from './search-filter-config.model'; @Component({ template: '' }) class DummyComponent { @@ -40,8 +56,8 @@ describe('SearchService', () => { providers: [ { provide: Router, useValue: router }, { provide: ActivatedRoute, useValue: route }, - { provide: ResponseCacheService, useValue: {} }, - { provide: RequestService, useValue: {} }, + { provide: ResponseCacheService, useValue: getMockResponseCacheService() }, + { provide: RequestService, useValue: getMockRequestService() }, { provide: RemoteDataBuildService, useValue: {} }, { provide: HALEndpointService, useValue: {} }, SearchService @@ -60,6 +76,26 @@ describe('SearchService', () => { let searchService: SearchService; const router = new RouterStub(); const route = new ActivatedRouteStub(); + + const halService = { + /* tslint:disable:no-empty */ + getEndpoint: () => {} + /* tslint:enable:no-empty */ + + }; + + const remoteDataBuildService = { + toRemoteDataObservable: (requestEntryObs: Observable, responseCacheObs: Observable, payloadObs: Observable) => { + return Observable.combineLatest(requestEntryObs, + responseCacheObs, payloadObs, (req, res, pay) => { + return { req, res, pay }; + }); + }, + aggregate: (input: Array>>): Observable> => { + return Observable.of(new RemoteData(false, false, true, null, [])); + } + }; + beforeEach(() => { TestBed.configureTestingModule({ imports: [ @@ -74,10 +110,10 @@ describe('SearchService', () => { providers: [ { provide: Router, useValue: router }, { provide: ActivatedRoute, useValue: route }, - { provide: ResponseCacheService, useValue: {} }, - { provide: RequestService, useValue: {} }, - { provide: RemoteDataBuildService, useValue: {} }, - { provide: HALEndpointService, useValue: {} }, + { provide: ResponseCacheService, useValue: getMockResponseCacheService() }, + { provide: RequestService, useValue: getMockRequestService() }, + { provide: RemoteDataBuildService, useValue: remoteDataBuildService }, + { provide: HALEndpointService, useValue: halService }, SearchService ], }); @@ -113,5 +149,95 @@ describe('SearchService', () => { searchService.getViewMode().subscribe((mode) => viewMode = mode); expect(viewMode).toEqual(ViewMode.Grid); }); + + describe('when search is called', () => { + const endPoint = 'http://endpoint.com/test/test'; + const searchOptions = new PaginatedSearchOptions(); + const queryResponse = Object.assign(new SearchQueryResponse(), { objects: [] }); + const response = new SearchSuccessResponse(queryResponse, '200'); + const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + beforeEach(() => { + spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); + (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + /* tslint:disable:no-empty */ + searchService.search(searchOptions).subscribe((t) => {}); // subscribe to make sure all methods are called + /* tslint:enable:no-empty */ + }); + + it('should call getEndpoint on the halService', () => { + expect((searchService as any).halService.getEndpoint).toHaveBeenCalled(); + }); + + it('should send out the request on the request service', () => { + expect((searchService as any).requestService.configure).toHaveBeenCalled(); + }); + + it('should call getByHref on the request service with the correct request url', () => { + expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(endPoint); + }); + it('should call get on the request service with the correct request url', () => { + expect((searchService as any).responseCache.get).toHaveBeenCalledWith(endPoint); + }); + }); + + describe('when getConfig is called without a scope', () => { + const endPoint = 'http://endpoint.com/test/config'; + const filterConfig = [new SearchFilterConfig()]; + const response = new FacetConfigSuccessResponse(filterConfig, '200'); + const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + beforeEach(() => { + spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); + (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + /* tslint:disable:no-empty */ + searchService.getConfig(null).subscribe((t) => {}); // subscribe to make sure all methods are called + /* tslint:enable:no-empty */ + }); + + it('should call getEndpoint on the halService', () => { + expect((searchService as any).halService.getEndpoint).toHaveBeenCalled(); + }); + + it('should send out the request on the request service', () => { + expect((searchService as any).requestService.configure).toHaveBeenCalled(); + }); + + it('should call getByHref on the request service with the correct request url', () => { + expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(endPoint); + }); + it('should call get on the request service with the correct request url', () => { + expect((searchService as any).responseCache.get).toHaveBeenCalledWith(endPoint); + }); + }); + + describe('when getConfig is called with a scope', () => { + const endPoint = 'http://endpoint.com/test/config'; + const scope = 'test'; + const requestUrl = endPoint + '?scope=' + scope; + const filterConfig = [new SearchFilterConfig()]; + const response = new FacetConfigSuccessResponse(filterConfig, '200'); + const responseEntry = Object.assign(new ResponseCacheEntry(), { response: response }); + beforeEach(() => { + spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); + (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); + /* tslint:disable:no-empty */ + searchService.getConfig(scope).subscribe((t) => {}); // subscribe to make sure all methods are called + /* tslint:enable:no-empty */ + }); + + it('should call getEndpoint on the halService', () => { + expect((searchService as any).halService.getEndpoint).toHaveBeenCalled(); + }); + + it('should send out the request on the request service', () => { + expect((searchService as any).requestService.configure).toHaveBeenCalled(); + }); + + it('should call getByHref on the request service with the correct request url', () => { + expect((searchService as any).requestService.getByHref).toHaveBeenCalledWith(requestUrl); + }); + it('should call get on the request service with the correct request url', () => { + expect((searchService as any).responseCache.get).toHaveBeenCalledWith(requestUrl); + }); + }); }); }); diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 42f527a411..6b1034fa33 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -96,6 +96,7 @@ export class SearchService implements OnDestroy { } search(searchOptions?: PaginatedSearchOptions): Observable>>> { + // this.halService.getEndpoint(this.searchLinkPath).subscribe((t) => console.log(t)); const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe( map((url: string) => { if (hasValue(searchOptions)) { @@ -110,7 +111,6 @@ export class SearchService implements OnDestroy { }), tap((request: RestRequest) => this.requestService.configure(request)), ); - const requestEntryObs = requestObs.pipe( flatMap((request: RestRequest) => this.requestService.getByHref(request.href)) ); diff --git a/src/app/shared/mocks/mock-request.service.ts b/src/app/shared/mocks/mock-request.service.ts index ed8ffa028d..02d3e54282 100644 --- a/src/app/shared/mocks/mock-request.service.ts +++ b/src/app/shared/mocks/mock-request.service.ts @@ -1,8 +1,10 @@ import { RequestService } from '../../core/data/request.service'; +import { RequestEntry } from '../../core/data/request.reducer'; export function getMockRequestService(): RequestService { return jasmine.createSpyObj('requestService', { configure: () => false, - generateRequestId: () => 'clients/b186e8ce-e99c-4183-bc9a-42b4821bdb78' + generateRequestId: () => 'clients/b186e8ce-e99c-4183-bc9a-42b4821bdb78', + getByHref: (uuid: string) => new RequestEntry() }); } diff --git a/src/app/shared/mocks/mock-response-cache.service.ts b/src/app/shared/mocks/mock-response-cache.service.ts index 95b4e7aca0..ad1457c3eb 100644 --- a/src/app/shared/mocks/mock-response-cache.service.ts +++ b/src/app/shared/mocks/mock-response-cache.service.ts @@ -1,10 +1,12 @@ import { ResponseCacheService } from '../../core/cache/response-cache.service'; +import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; +import { RestResponse } from '../../core/cache/response-cache.models'; export function getMockResponseCacheService(): ResponseCacheService { - return jasmine.createSpyObj('ResponseCacheService', [ - 'add', - 'get', - 'has', - ]); + return jasmine.createSpyObj('ResponseCacheService', { + add: (key: string, response: RestResponse, msToLive: number) => new ResponseCacheEntry(), + get: (key: string) => new ResponseCacheEntry(), + has: (key: string) => false, + }); } From e56ea2aff894ea21537d66340b74b8a7b6a59787 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Fri, 13 Apr 2018 15:18:35 +0200 Subject: [PATCH 08/10] Applied feedback and other fixes --- resources/i18n/en.json | 3 +- .../search-facet-filter.component.html | 2 +- .../search-facet-filter.component.spec.ts | 7 +-- .../search-facet-filter.component.ts | 19 ++----- .../+search-page/search-page.component.html | 4 +- src/app/+search-page/search-page.component.ts | 2 + .../search-results.component.html | 5 +- .../search-results.component.ts | 3 +- .../search-service/search.service.spec.ts | 16 ++++-- .../search-service/search.service.ts | 54 +++++-------------- .../builders/remote-data-build.service.ts | 7 ++- .../data/base-response-parsing.service.ts | 5 +- .../data/config-response-parsing.service.ts | 2 +- .../core/data/dso-response-parsing.service.ts | 2 +- ...acet-value-map-response-parsing.service.ts | 2 +- .../facet-value-response-parsing.service.ts | 6 +-- src/app/core/data/paginated-list.ts | 36 ++++++++++++- .../data/search-response-parsing.service.ts | 2 +- src/app/core/shared/page-info.model.ts | 11 ++++ src/app/shared/testing/router-stub.ts | 2 + 20 files changed, 107 insertions(+), 83 deletions(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 68dfcbe147..5c750b2397 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -80,7 +80,8 @@ "search_dspace": "Search DSpace" }, "results": { - "head": "Search Results" + "head": "Search Results", + "no-results": "There were no results for this search" }, "sidebar": { "close": "Back to results", diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html index 8687aeb25b..074c5700d7 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.html @@ -20,7 +20,7 @@
- {{"search.filters.filter.show-more" | translate}} { let comp: SearchFacetFilterComponent; @@ -56,7 +57,7 @@ describe('SearchFacetFilterComponent', () => { let router; const page = Observable.of(0); - const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(null, values))); + const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); beforeEach(async(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -121,14 +122,14 @@ describe('SearchFacetFilterComponent', () => { }); describe('when the getAddParams method is called wih a value', () => { - it('should return the selectedValueq list with the new parameter value', () => { + it('should return the selectedValue list with the new parameter value', () => { const result = comp.getAddParams(value3); expect(result).toEqual({ [mockFilterConfig.paramName]: [value1, value2, value3] }); }); }); describe('when the getRemoveParams method is called wih a value', () => { - it('should return the selectedValueq list with the parameter value left out', () => { + it('should return the selectedValue list with the parameter value left out', () => { const result = comp.getRemoveParams(value1); expect(result).toEqual({ [mockFilterConfig.paramName]: [value2] }); }); diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts index 04258fbd35..bf78bbe5ec 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.ts @@ -4,7 +4,7 @@ import { SearchFilterConfig } from '../../../search-service/search-filter-config import { Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { SearchFilterService } from '../search-filter.service'; -import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; +import { hasNoValue, hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { RemoteData } from '../../../../core/data/remote-data'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { SearchService } from '../../../search-service/search.service'; @@ -30,6 +30,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { filterValues: Array>>> = []; filterValues$: BehaviorSubject = new BehaviorSubject(this.filterValues); currentPage: Observable; + isLastPage$: BehaviorSubject = new BehaviorSubject(false); filter: string; pageChange = false; sub: Subscription; @@ -50,12 +51,12 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { this.pageChange = false; this.unsubscribe(); - this.sub = this.currentPage.distinctUntilChanged().map((page) => { return this.searchService.getFacetValuesFor(this.filterConfig, page, options); }).subscribe((newValues$) => { this.filterValues = [...this.filterValues, newValues$]; this.filterValues$.next(this.filterValues); + newValues$.first().subscribe((rd) => this.isLastPage$.next(hasNoValue(rd.payload.next))); }); } @@ -98,18 +99,6 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { hasValue(o: any): boolean { return hasValue(o); } - - isLastPage(): Observable { - return this.filterValues$.flatMap((map) => { - - if (isNotEmpty(map)) { - return map.pop().map((rd: RemoteData>) => rd.payload.currentPage >= rd.payload.totalPages); - } else { - return false; - } - }); - } - getRemoveParams(value: string) { return { [this.filterConfig.paramName]: this.selectedValues.filter((v) => v !== value) }; } @@ -123,7 +112,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy { } unsubscribe(): void { - if (this.sub !== undefined) { + if (hasValue(this.sub)) { this.sub.unsubscribe(); } } diff --git a/src/app/+search-page/search-page.component.html b/src/app/+search-page/search-page.component.html index c50bb30696..d53e4776b1 100644 --- a/src/app/+search-page/search-page.component.html +++ b/src/app/+search-page/search-page.component.html @@ -36,6 +36,4 @@
- - - + \ No newline at end of file diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index c9efc65676..03f664de59 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -65,6 +65,8 @@ export class SearchPageComponent implements OnInit { this.resultsRD$ = this.searchOptions$.pipe( flatMap((searchOptions) => this.service.search(searchOptions)) ); + this.resultsRD$.subscribe((t) => console.log(t)); + } public closeSidebar(): void { diff --git a/src/app/+search-page/search-results/search-results.component.html b/src/app/+search-page/search-results/search-results.component.html index 7d7c169380..ec103e8957 100644 --- a/src/app/+search-page/search-results/search-results.component.html +++ b/src/app/+search-page/search-results/search-results.component.html @@ -1,10 +1,11 @@ +

{{ 'search.results.head' | translate }}

-

{{ 'search.results.head' | translate }}

- + + \ No newline at end of file diff --git a/src/app/+search-page/search-results/search-results.component.ts b/src/app/+search-page/search-results/search-results.component.ts index 4b3fec4565..14ccb5d541 100644 --- a/src/app/+search-page/search-results/search-results.component.ts +++ b/src/app/+search-page/search-results/search-results.component.ts @@ -5,6 +5,7 @@ import { fadeIn, fadeInOut } from '../../shared/animations/fade'; import { SearchOptions, ViewMode } from '../search-options.model'; import { SortOptions } from '../../core/cache/models/sort-options.model'; import { SearchResult } from '../search-result.model'; +import { PaginatedList } from '../../core/data/paginated-list'; /** * This component renders a simple item page. @@ -20,7 +21,7 @@ import { SearchResult } from '../search-result.model'; ] }) export class SearchResultsComponent { - @Input() searchResults: RemoteData>>; + @Input() searchResults: RemoteData>>; @Input() searchConfig: SearchOptions; @Input() sortConfig: SortOptions; @Input() viewMode: ViewMode; diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index ef6efe3deb..4b558f8726 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -10,7 +10,7 @@ import { ViewMode } from '../../+search-page/search-options.model'; import { RouteService } from '../../shared/route.service'; import { GLOBAL_CONFIG } from '../../../config'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, UrlTree } from '@angular/router'; import { RequestService } from '../../core/data/request.service'; import { ResponseCacheService } from '../../core/cache/response-cache.service'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; @@ -79,7 +79,8 @@ describe('SearchService', () => { const halService = { /* tslint:disable:no-empty */ - getEndpoint: () => {} + getEndpoint: () => { + } /* tslint:enable:no-empty */ }; @@ -118,6 +119,8 @@ describe('SearchService', () => { ], }); searchService = TestBed.get(SearchService); + const urlTree = Object.assign(new UrlTree(), { root: { children: { primary: 'search' } } }); + router.parseUrl.and.returnValue(urlTree); }); it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => { @@ -160,7 +163,8 @@ describe('SearchService', () => { spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); /* tslint:disable:no-empty */ - searchService.search(searchOptions).subscribe((t) => {}); // subscribe to make sure all methods are called + searchService.search(searchOptions).subscribe((t) => { + }); // subscribe to make sure all methods are called /* tslint:enable:no-empty */ }); @@ -189,7 +193,8 @@ describe('SearchService', () => { spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); /* tslint:disable:no-empty */ - searchService.getConfig(null).subscribe((t) => {}); // subscribe to make sure all methods are called + searchService.getConfig(null).subscribe((t) => { + }); // subscribe to make sure all methods are called /* tslint:enable:no-empty */ }); @@ -220,7 +225,8 @@ describe('SearchService', () => { spyOn((searchService as any).halService, 'getEndpoint').and.returnValue(Observable.of(endPoint)); (searchService as any).responseCache.get.and.returnValue(Observable.of(responseEntry)); /* tslint:disable:no-empty */ - searchService.getConfig(scope).subscribe((t) => {}); // subscribe to make sure all methods are called + searchService.getConfig(scope).subscribe((t) => { + }); // subscribe to make sure all methods are called /* tslint:enable:no-empty */ }); diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 6b1034fa33..ec4ccc9742 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -1,5 +1,8 @@ import { Injectable, OnDestroy } from '@angular/core'; -import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; +import { + ActivatedRoute, NavigationExtras, PRIMARY_OUTLET, Router, + UrlSegmentGroup +} from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { flatMap, map, tap } from 'rxjs/operators'; import { ViewMode } from '../../+search-page/search-options.model'; @@ -21,13 +24,12 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { URLCombiner } from '../../core/url-combiner/url-combiner'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { NormalizedSearchResult } from '../normalized-search-result.model'; import { SearchOptions } from '../search-options.model'; import { SearchResult } from '../search-result.model'; import { FacetValue } from './facet-value.model'; -import { FilterType } from './filter-type.model'; import { SearchFilterConfig } from './search-filter-config.model'; import { SearchResponseParsingService } from '../../core/data/search-response-parsing.service'; import { SearchQueryResponse } from './search-query-response.model'; @@ -37,48 +39,16 @@ import { ListableObject } from '../../shared/object-collection/shared/listable-o import { FacetValueResponseParsingService } from '../../core/data/facet-value-response-parsing.service'; import { FacetConfigResponseParsingService } from '../../core/data/facet-config-response-parsing.service'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; +import { observable } from 'rxjs/symbol/observable'; @Injectable() export class SearchService implements OnDestroy { private searchLinkPath = 'discover/search/objects'; - private facetValueLinkPath = 'discover/search/facets'; private facetValueLinkPathPrefix = 'discover/facets/'; private facetConfigLinkPath = 'discover/facets'; private sub; - uiSearchRoute = '/search'; - config: SearchFilterConfig[] = [ - // Object.assign(new SearchFilterConfig(), - // { - // name: 'scope', - // type: FilterType.hierarchical, - // hasFacets: true, - // isOpenByDefault: true - // }), - Object.assign(new SearchFilterConfig(), - { - name: 'author', - type: FilterType.text, - hasFacets: true, - isOpenByDefault: false - }), - Object.assign(new SearchFilterConfig(), - { - name: 'dateIssued', - type: FilterType.date, - hasFacets: true, - isOpenByDefault: false - }), - Object.assign(new SearchFilterConfig(), - { - name: 'subject', - type: FilterType.text, - hasFacets: false, - isOpenByDefault: false - }) - ]; - // searchOptions: BehaviorSubject; searchOptions: SearchOptions; constructor(private router: Router, @@ -96,7 +66,6 @@ export class SearchService implements OnDestroy { } search(searchOptions?: PaginatedSearchOptions): Observable>>> { - // this.halService.getEndpoint(this.searchLinkPath).subscribe((t) => console.log(t)); const requestObs = this.halService.getEndpoint(this.searchLinkPath).pipe( map((url: string) => { if (hasValue(searchOptions)) { @@ -136,7 +105,8 @@ export class SearchService implements OnDestroy { ); // Create search results again with the correct dso objects linked to each result - const tDomainListObs: Observable>> = Observable.combineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData) => { + const tDomainListObs = Observable.combineLatest(sqrObs, dsoObs, (sqr: SearchQueryResponse, dsos: RemoteData) => { + return sqr.objects.map((object: NormalizedSearchResult, index: number) => { let co = DSpaceObject; if (dsos.payload[index]) { @@ -150,7 +120,7 @@ export class SearchService implements OnDestroy { } }); }); - + const pageInfoObs: Observable = responseCacheObs.pipe( map((entry: ResponseCacheEntry) => entry.response), map((response: FacetValueSuccessResponse) => response.pageInfo) @@ -262,11 +232,13 @@ export class SearchService implements OnDestroy { queryParamsHandling: 'merge' }; - this.router.navigate([this.uiSearchRoute], navigationExtras); + this.router.navigate([this.getSearchLink()], navigationExtras); } getSearchLink() { - return this.uiSearchRoute; + const urlTree = this.router.parseUrl(this.router.url); + const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET]; + return '/' + g.toString(); } ngOnDestroy(): void { diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index af2c80c9aa..ece80cf4ca 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -4,7 +4,7 @@ import { map, tap } from 'rxjs/operators'; import { NormalizedSearchResult } from '../../../+search-page/normalized-search-result.model'; import { SearchResult } from '../../../+search-page/search-result.model'; import { SearchQueryResponse } from '../../../+search-page/search-service/search-query-response.model'; -import { hasValue, isNotEmpty } from '../../../shared/empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; import { RemoteDataError } from '../../data/remote-data-error'; @@ -200,6 +200,11 @@ export class RemoteDataBuildService { } aggregate(input: Array>>): Observable> { + + if (isEmpty(input)) { + return Observable.of(new RemoteData(false, false, true, null, [])); + } + return Observable.combineLatest( ...input, (...arr: Array>) => { diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index 9d6a5851e5..bde0857946 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -117,8 +117,9 @@ export abstract class BaseResponseParsingService { this.objectCache.add(co, this.EnvConfig.cache.msToLive, requestHref); } - processPageInfo(pageObj: any): PageInfo { - if (isNotEmpty(pageObj)) { + processPageInfo(payload: any): PageInfo { + if (isNotEmpty(payload.page)) { + const pageObj = Object.assign({}, payload.page, {_links: payload._links}); const pageInfoObject = new DSpaceRESTv2Serializer(PageInfo).deserialize(pageObj); if (pageInfoObject.currentPage >= 0) { Object.assign(pageInfoObject, { currentPage: pageInfoObject.currentPage + 1 }); diff --git a/src/app/core/data/config-response-parsing.service.ts b/src/app/core/data/config-response-parsing.service.ts index 69be4bbc02..033c9ddc68 100644 --- a/src/app/core/data/config-response-parsing.service.ts +++ b/src/app/core/data/config-response-parsing.service.ts @@ -29,7 +29,7 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') { const configDefinition = this.process(data.payload, request.href); - return new ConfigSuccessResponse(configDefinition[Object.keys(configDefinition)[0]], data.statusCode, this.processPageInfo(data.payload.page)); + return new ConfigSuccessResponse(configDefinition[Object.keys(configDefinition)[0]], data.statusCode, this.processPageInfo(data.payload)); } else { return new ErrorResponse( Object.assign( diff --git a/src/app/core/data/dso-response-parsing.service.ts b/src/app/core/data/dso-response-parsing.service.ts index 11590d0431..9651eb3157 100644 --- a/src/app/core/data/dso-response-parsing.service.ts +++ b/src/app/core/data/dso-response-parsing.service.ts @@ -28,7 +28,7 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const processRequestDTO = this.process(data.payload, request.href); const selfLinks = this.flattenSingleKeyObject(processRequestDTO).map((no) => no.self); - return new DSOSuccessResponse(selfLinks, data.statusCode, this.processPageInfo(data.payload.page)) + return new DSOSuccessResponse(selfLinks, data.statusCode, this.processPageInfo(data.payload)) } } diff --git a/src/app/core/data/facet-value-map-response-parsing.service.ts b/src/app/core/data/facet-value-map-response-parsing.service.ts index dfd72c0cc5..8588e4aa0b 100644 --- a/src/app/core/data/facet-value-map-response-parsing.service.ts +++ b/src/app/core/data/facet-value-map-response-parsing.service.ts @@ -37,7 +37,7 @@ export class FacetValueMapResponseParsingService extends BaseResponseParsingServ payload._embedded.facets.map((facet) => { const values = facet._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); const facetValues = serializer.deserializeArray(values); - const valuesResponse = new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload.page)); + const valuesResponse = new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload)); facetMap[facet.name] = valuesResponse; }); diff --git a/src/app/core/data/facet-value-response-parsing.service.ts b/src/app/core/data/facet-value-response-parsing.service.ts index 17f0730566..bc3f4e5368 100644 --- a/src/app/core/data/facet-value-response-parsing.service.ts +++ b/src/app/core/data/facet-value-response-parsing.service.ts @@ -30,9 +30,9 @@ export class FacetValueResponseParsingService extends BaseResponseParsingService const payload = data.payload; const serializer = new DSpaceRESTv2Serializer(FacetValue); - const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); + // const values = payload._embedded.values.map((value) => {value.search = value._links.search.href; return value;}); - const facetValues = serializer.deserializeArray(values); - return new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload.page)); + const facetValues = serializer.deserializeArray(payload._embedded.values); + return new FacetValueSuccessResponse(facetValues, data.statusCode, this.processPageInfo(data.payload)); } } diff --git a/src/app/core/data/paginated-list.ts b/src/app/core/data/paginated-list.ts index 7e4a57f84e..fe095ecc45 100644 --- a/src/app/core/data/paginated-list.ts +++ b/src/app/core/data/paginated-list.ts @@ -45,10 +45,44 @@ export class PaginatedList { return this.pageInfo.currentPage; } return 1; - } set currentPage(value: number) { this.pageInfo.currentPage = value; } + + get first(): string { + return this.pageInfo.first; + } + + set first(first: string) { + this.pageInfo.first = first; + } + + get prev(): string { + return this.pageInfo.prev; + } + set prev(prev: string) { + this.pageInfo.prev = prev; + } + + get next(): string { + return this.pageInfo.next; + } + + set next(next: string) { + this.pageInfo.next = next; + } + + get last(): string { + return this.pageInfo.last; + } + + set last(last: string) { + this.pageInfo.last = last; + } + + + + } diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index 927c5ff010..707875911d 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -56,6 +56,6 @@ export class SearchResponseParsingService implements ResponseParsingService { })); payload.objects = objects; const deserialized = new DSpaceRESTv2Serializer(SearchQueryResponse).deserialize(payload); - return new SearchSuccessResponse(deserialized, data.statusCode, this.dsoParser.processPageInfo(data.payload.page)); + return new SearchSuccessResponse(deserialized, data.statusCode, this.dsoParser.processPageInfo(data.payload)); } } diff --git a/src/app/core/shared/page-info.model.ts b/src/app/core/shared/page-info.model.ts index 0cb5cac5b1..ba2af24dce 100644 --- a/src/app/core/shared/page-info.model.ts +++ b/src/app/core/shared/page-info.model.ts @@ -28,4 +28,15 @@ export class PageInfo { @autoserializeAs(Number, 'number') currentPage: number; + @autoserialize + last: string; + + @autoserialize + next: string; + + @autoserialize + prev: string; + + @autoserialize + first: string; } diff --git a/src/app/shared/testing/router-stub.ts b/src/app/shared/testing/router-stub.ts index ca4f7642b8..31c09c41e3 100644 --- a/src/app/shared/testing/router-stub.ts +++ b/src/app/shared/testing/router-stub.ts @@ -1,7 +1,9 @@ + export class RouterStub { url: string; //noinspection TypeScriptUnresolvedFunction navigate = jasmine.createSpy('navigate'); + parseUrl = jasmine.createSpy('parseUrl'); navigateByUrl(url): void { this.url = url; } From 790ca4bc79f1ac8a2718cd90b2b23ebff5d0c5dc Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Fri, 13 Apr 2018 15:31:26 +0200 Subject: [PATCH 09/10] Fixed TSLint errors --- src/app/+search-page/search-service/search.service.ts | 2 +- src/app/core/data/paginated-list.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index ec4ccc9742..25b8c0b23e 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -120,7 +120,7 @@ export class SearchService implements OnDestroy { } }); }); - + const pageInfoObs: Observable = responseCacheObs.pipe( map((entry: ResponseCacheEntry) => entry.response), map((response: FacetValueSuccessResponse) => response.pageInfo) diff --git a/src/app/core/data/paginated-list.ts b/src/app/core/data/paginated-list.ts index fe095ecc45..21cc13f3fa 100644 --- a/src/app/core/data/paginated-list.ts +++ b/src/app/core/data/paginated-list.ts @@ -81,8 +81,4 @@ export class PaginatedList { set last(last: string) { this.pageInfo.last = last; } - - - - } From 60366e3eecec3f4a7d334050582072a9eb0d5061 Mon Sep 17 00:00:00 2001 From: Lotte Hofstede Date: Fri, 13 Apr 2018 15:35:26 +0200 Subject: [PATCH 10/10] removed log --- src/app/+search-page/search-page.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index 03f664de59..c9efc65676 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -65,8 +65,6 @@ export class SearchPageComponent implements OnInit { this.resultsRD$ = this.searchOptions$.pipe( flatMap((searchOptions) => this.service.search(searchOptions)) ); - this.resultsRD$.subscribe((t) => console.log(t)); - } public closeSidebar(): void {