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 new file mode 100644 index 0000000000..fd52d8eb62 --- /dev/null +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -0,0 +1,45 @@ +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +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 { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { SearchFacetFilterComponent } from './search-facet-filter.component'; +import { SearchFilterService } from '../search-filter.service'; +import { Router } from '@angular/router'; + +describe('SearchFacetFilterComponent', () => { + let comp: SearchFacetFilterComponent; + let fixture: ComponentFixture; + const filterService: Store = jasmine.createSpyObj('filterService', { + isFilterActiveWithValue: (paramName: string, filterValue: string) => true, + getQueryParamsWith: (paramName: string, filterValue: string) => '', + getQueryParamsWithout: (paramName: string, filterValue: string) => '', + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule], + declarations: [SearchFacetFilterComponent], + providers: [ + { + provide: Router, useValue: {} + }, + { + provide: SearchFilterService, + useValue: filterService + }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(SearchFacetFilterComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchFacetFilterComponent); + comp = fixture.componentInstance; // SearchPageComponent test instance + fixture.detectChanges(); + }); + +}); 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 159eecf698..ccdab52c57 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 @@ -18,7 +18,7 @@ import { isNotEmpty } from '../../../../shared/empty.util'; templateUrl: './search-facet-filter.component.html', }) -export class SidebarFacetFilterComponent implements OnInit { +export class SearchFacetFilterComponent implements OnInit { @Input() filterValues: FacetValue[]; @Input() filterConfig: SearchFilterConfig; @Input() selectedValues: string[]; diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts new file mode 100644 index 0000000000..0a5ac667c0 --- /dev/null +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.spec.ts @@ -0,0 +1,113 @@ +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; + +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 { Observable } from 'rxjs/Observable'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { SearchFilterService } from './search-filter.service'; +import { SearchService } from '../../search-service/search.service'; +import { SearchFilterComponent } from './search-filter.component'; +import { SearchFilterConfig } from '../../search-service/search-filter-config.model'; +import { FilterType } from '../../search-service/filter-type.model'; + +describe('SearchFilterComponent', () => { + let comp: SearchFilterComponent; + let fixture: ComponentFixture; + const filterName = 'test name' + const mockFilterConfig: SearchFilterConfig = Object.assign(new SearchFilterConfig(), { + name: filterName, + type: FilterType.text, + hasFacets: false, + isOpenByDefault: false + }); + const mockFilterService = { + /* tslint:disable:no-empty */ + toggle: (filter) => { + }, + collapse: (filter) => { + }, + expand: (filter) => { + }, + initialCollapse: (filter) => { + }, + initialExpand: (filter) => { + }, + getSelectedValuesForFilter: (filter) => { + }, + isFilterActive: (filter) => { + return Observable.of(true) + }, + isCollapsed: (filter) => { + return Observable.of(true) + } + /* tslint:enable:no-empty */ + + }; + let filterService; + const mockResults = Observable.of(['test', 'data']); + const searchServiceStub = { + getFacetValuesFor: (filter) => mockResults + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule], + declarations: [SearchFilterComponent], + providers: [ + { provide: SearchService, useValue: searchServiceStub }, + { + provide: SearchFilterService, + useValue: mockFilterService + }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(SearchFilterComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchFilterComponent); + comp = fixture.componentInstance; // SearchPageComponent test instance + comp.filter = mockFilterConfig; + fixture.detectChanges(); + filterService = (comp as any).filterService; + }); + + describe('when the toggle method is triggered', () => { + beforeEach(() => { + spyOn(filterService, 'toggle'); + comp.toggle(); + }); + + it('should call toggle with the correct filter configuration name', () => { + expect(filterService.toggle).toHaveBeenCalledWith(mockFilterConfig.name) + }); + }); + + describe('when the initialCollapse method is triggered', () => { + beforeEach(() => { + spyOn(filterService, 'initialCollapse'); + comp.initialCollapse(); + }); + + it('should call initialCollapse with the correct filter configuration name', () => { + expect(filterService.initialCollapse).toHaveBeenCalledWith(mockFilterConfig.name) + }); + }); + + describe('when the initialExpand method is triggered', () => { + beforeEach(() => { + spyOn(filterService, 'initialExpand'); + comp.initialExpand(); + }); + + it('should call initialCollapse with the correct filter configuration name', () => { + expect(filterService.initialExpand).toHaveBeenCalledWith(mockFilterConfig.name) + }); + }); + + +}); diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts index 57bff9af27..08d72da984 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.ts @@ -22,7 +22,7 @@ import { first } from 'rxjs/operator/first'; animations: [slide], }) -export class SidebarFilterComponent implements OnInit { +export class SearchFilterComponent implements OnInit { @Input() filter: SearchFilterConfig; filterValues: Observable>; 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 0e90f3242a..3db6b9721f 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 @@ -1,4 +1,3 @@ -import { async, TestBed } from '@angular/core/testing'; import { Observable } from 'rxjs/Observable'; import { SearchFilterService } from './search-filter.service'; import { Store } from '@ngrx/store'; @@ -22,7 +21,7 @@ describe('SearchFilterService', () => { select: Observable.of(true) }); const routeService = new RouteService(null); - const searchService = new SearchService(null, null, null) + const searchService = new SearchService(null, null, null, null) beforeEach(() => { service = new SearchFilterService(store, routeService, searchService); 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 c06c35b372..808ce3be67 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -16,7 +16,7 @@ import { Observable } from 'rxjs/Observable'; templateUrl: './search-filters.component.html', }) -export class SidebarFiltersComponent { +export class SearchFiltersComponent { filters: Observable>; constructor(private searchService: SearchService) { this.filters = searchService.getConfig(); diff --git a/src/app/+search-page/search-page.component.ts b/src/app/+search-page/search-page.component.ts index ee80bb7c56..153402d11f 100644 --- a/src/app/+search-page/search-page.component.ts +++ b/src/app/+search-page/search-page.component.ts @@ -1,13 +1,11 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs/Observable'; -import { SortOptions } from '../core/cache/models/sort-options.model'; import { CommunityDataService } from '../core/data/community-data.service'; import { RemoteData } from '../core/data/remote-data'; import { Community } from '../core/shared/community.model'; import { DSpaceObject } from '../core/shared/dspace-object.model'; import { isNotEmpty } from '../shared/empty.util'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { SearchOptions } from './search-options.model'; import { SearchResult } from './search-result.model'; import { SearchService } from './search-service/search.service'; diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index e940e4975d..6519d1e92a 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -13,9 +13,9 @@ import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; import { SearchSidebarEffects } from './search-sidebar/search-sidebar.effects'; import { SearchSettingsComponent } from './search-settings/search-settings.component'; import { EffectsModule } from '@ngrx/effects'; -import { SidebarFiltersComponent } from './search-filters/search-filters.component'; -import { SidebarFilterComponent } from './search-filters/search-filter/search-filter.component'; -import { SidebarFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component'; +import { SearchFiltersComponent } from './search-filters/search-filters.component'; +import { SearchFilterComponent } from './search-filters/search-filter/search-filter.component'; +import { SearchFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component'; import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; const effects = [ @@ -37,9 +37,9 @@ const effects = [ ItemSearchResultListElementComponent, CollectionSearchResultListElementComponent, CommunitySearchResultListElementComponent, - SidebarFiltersComponent, - SidebarFilterComponent, - SidebarFacetFilterComponent + SearchFiltersComponent, + SearchFilterComponent, + SearchFacetFilterComponent ], providers: [ SearchService, 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 f2564eed27..65af3231f9 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -7,6 +7,7 @@ import { Component } from '@angular/core'; import { SearchService } from './search.service'; import { ItemDataService } from './../../core/data/item-data.service'; import { ViewMode } from '../../+search-page/search-options.model'; +import { RouteService } from '../../shared/route.service'; @Component({ template: '' }) class DummyComponent { } @@ -27,6 +28,7 @@ describe('SearchService', () => { ], providers: [ { provide: ItemDataService, useValue: {} }, + { provide: RouteService, 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 453174d86a..4b5ba7b702 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -231,9 +231,9 @@ export class SearchService implements OnDestroy { } getViewMode(): Observable { - return this.routeService.getQueryParameterValue('view').map((value) => { - if (hasValue(value)) { - return value as ViewMode; + return this.route.queryParams.map((params) => { + if (isNotEmpty(params.view) && hasValue(params.view)) { + return params.view; } else { return ViewMode.List; } diff --git a/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts b/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts index 693ba0be5d..146b1fdcdb 100644 --- a/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts +++ b/src/app/+search-page/search-sidebar/search-sidebar.effects.spec.ts @@ -9,6 +9,7 @@ import { SearchSidebarEffects } from './search-sidebar.effects'; describe('SearchSidebarEffects', () => { let sidebarEffects: SearchSidebarEffects; let actions: Observable; + const dummyURL = 'http://f4fb15e2-1bd3-4e63-8d0d-486ad8bc714a'; beforeEach(() => { TestBed.configureTestingModule({ @@ -24,13 +25,12 @@ describe('SearchSidebarEffects', () => { describe('routeChange$', () => { - it('should return a COLLAPSE action in response to an UPDATE_LOCATION action', () => { - actions = hot('--a-', { a: { type: fromRouter.ROUTER_NAVIGATION } }); + it('should return a COLLAPSE action in response to an UPDATE_LOCATION action to a new route', () => { + actions = hot('--a-', { a: { type: fromRouter.ROUTER_NAVIGATION, payload: {routerState: {url: dummyURL}} } }); const expected = cold('--b-', { b: new SearchSidebarCollapseAction() }); expect(sidebarEffects.routeChange$).toBeObservable(expected); }); - }); }); diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts b/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts index a8486d011d..541b1ed4c3 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts @@ -1,4 +1,3 @@ -import { DebugElement } from '@angular/core'; import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @@ -6,12 +5,12 @@ import { MockTranslateLoader } from '../mocks/mock-translate-loader'; import { RouterTestingModule } from '@angular/router/testing'; import { Component } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; import { SearchService } from '../../+search-page/search-service/search.service'; import { ItemDataService } from './../../core/data/item-data.service'; import { ViewModeSwitchComponent } from './view-mode-switch.component'; import { ViewMode } from '../../+search-page/search-options.model'; +import { RouteService } from '../route.service'; @Component({ template: '' }) class DummyComponent { } @@ -42,6 +41,7 @@ describe('ViewModeSwitchComponent', () => { ], providers: [ { provide: ItemDataService, useValue: {} }, + { provide: RouteService, useValue: {} }, SearchService ], }).compileComponents();