diff --git a/src/app/core/shared/search/search-configuration.service.ts b/src/app/core/shared/search/search-configuration.service.ts index 03e46cac65..40bb8aebcd 100644 --- a/src/app/core/shared/search/search-configuration.service.ts +++ b/src/app/core/shared/search/search-configuration.service.ts @@ -20,7 +20,7 @@ import { RouteService } from '../../services/route.service'; import { getAllSucceededRemoteDataPayload, getFirstSucceededRemoteData } from '../operators'; import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; -import { SearchConfig, SortOption } from './search-filters/search-config.model'; +import { SearchConfig, SortConfig } from './search-filters/search-config.model'; import { SearchService } from './search.service'; import { PaginationService } from '../../pagination/pagination.service'; @@ -204,7 +204,7 @@ export class SearchConfigurationService implements OnDestroy { * @param searchConfig The SearchConfig object */ getConfigurationSortOptions(searchConfig: SearchConfig): SortOptions[] { - return searchConfig.sortOptions.map((entry: SortOption) => ({ + return searchConfig.sortOptions.map((entry: SortConfig) => ({ field: entry.name, direction: entry.sortOrder.toLowerCase() === SortDirection.ASC.toLowerCase() ? SortDirection.ASC : SortDirection.DESC })); diff --git a/src/app/core/shared/search/search-filters/search-config.model.ts b/src/app/core/shared/search/search-filters/search-config.model.ts index 725761fe7b..e789de0f80 100644 --- a/src/app/core/shared/search/search-filters/search-config.model.ts +++ b/src/app/core/shared/search/search-filters/search-config.model.ts @@ -29,7 +29,7 @@ export class SearchConfig implements CacheableObject { * The configured sort options. */ @autoserialize - sortOptions: SortOption[]; + sortOptions: SortConfig[]; /** * The object type. @@ -63,7 +63,7 @@ export interface FilterConfig { /** * Interface to model sort option's configuration. */ -export interface SortOption { +export interface SortConfig { name: string; sortOrder: string; } diff --git a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts index a75a0feae2..a9fd11b9ee 100644 --- a/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts +++ b/src/app/item-page/simple/related-entities/related-entities-search/related-entities-search.component.spec.ts @@ -38,10 +38,4 @@ describe('RelatedEntitiesSearchComponent', () => { expect(comp.fixedFilter).toEqual(mockFilter); }); - it('should create a configuration$', () => { - comp.configuration$.subscribe((configuration) => { - expect(configuration).toEqual(mockConfiguration); - }); - }); - }); diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts index b4926d7b92..dc971bc3af 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts @@ -10,6 +10,7 @@ import { RoleServiceMock } from '../shared/mocks/role-service.mock'; import { cold, hot } from 'jasmine-marbles'; import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; +import { Context } from '../core/shared/context.model'; describe('MyDSpaceConfigurationService', () => { let service: MyDSpaceConfigurationService; @@ -241,11 +242,13 @@ describe('MyDSpaceConfigurationService', () => { b: [ { value: MyDSpaceConfigurationValueType.Workspace, - label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}` + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}`, + context: Context.Workspace }, { value: MyDSpaceConfigurationValueType.Workflow, - label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}` + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}`, + context: Context.Workflow } ] })); diff --git a/src/app/my-dspace-page/my-dspace-page.component.spec.ts b/src/app/my-dspace-page/my-dspace-page.component.spec.ts index 6d8bfc274c..34bf20d462 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.spec.ts +++ b/src/app/my-dspace-page/my-dspace-page.component.spec.ts @@ -1,213 +1,88 @@ -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ActivatedRoute } from '@angular/router'; -import { By } from '@angular/platform-browser'; import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap'; -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { Store } from '@ngrx/store'; +import { of as observableOf } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { cold } from 'jasmine-marbles'; -import { of as observableOf } from 'rxjs'; -import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { CommunityDataService } from '../core/data/community-data.service'; -import { HostWindowService } from '../shared/host-window.service'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { MyDSpacePageComponent, SEARCH_CONFIG_SERVICE } from './my-dspace-page.component'; -import { RouteService } from '../core/services/route.service'; -import { routeServiceStub } from '../shared/testing/route-service.stub'; -import { SearchConfigurationServiceStub } from '../shared/testing/search-configuration-service.stub'; import { SearchService } from '../core/shared/search/search.service'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; -import { PaginatedSearchOptions } from '../shared/search/models/paginated-search-options.model'; -import { SidebarService } from '../shared/sidebar/sidebar.service'; -import { SearchFilterService } from '../core/shared/search/search-filter.service'; -import { RoleDirective } from '../shared/roles/role.directive'; -import { RoleService } from '../core/roles/role.service'; -import { RoleServiceMock } from '../shared/mocks/role-service.mock'; -import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; -import { SidebarServiceStub } from '../shared/testing/sidebar-service.stub'; +import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; +import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type'; +import { Context } from '../core/shared/context.model'; +import SpyObj = jasmine.SpyObj; describe('MyDSpacePageComponent', () => { let comp: MyDSpacePageComponent; let fixture: ComponentFixture; - let searchServiceObject: SearchService; - let searchConfigurationServiceObject: SearchConfigurationService; - const store: Store = jasmine.createSpyObj('store', { - /* tslint:disable:no-empty */ - dispatch: {}, - /* tslint:enable:no-empty */ - select: observableOf(true) + + const searchServiceStub: SpyObj = jasmine.createSpyObj('SearchService', { + setServiceOptions: jasmine.createSpy('setServiceOptions') }); - const pagination: PaginationComponentOptions = new PaginationComponentOptions(); - pagination.id = 'mydspace-results-pagination'; - pagination.currentPage = 1; - pagination.pageSize = 10; - const sortOption = { name: 'score', sortOrder: 'DESC', metadata: null }; - const sort: SortOptions = new SortOptions('score', SortDirection.DESC); - const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']); - const searchServiceStub = jasmine.createSpyObj('SearchService', { - search: mockResults, - getEndpoint: observableOf('discover/search/objects'), - getSearchLink: '/mydspace', - getScopes: observableOf(['test-scope']), - setServiceOptions: {}, - getSearchConfigurationFor: createSuccessfulRemoteDataObject$({ sortOptions: [sortOption]}) + + const myDSpaceConfigurationServiceStub: SpyObj = jasmine.createSpyObj('MyDSpaceConfigurationService', { + getAvailableConfigurationOptions: jasmine.createSpy('getAvailableConfigurationOptions') }); - const configurationParam = 'default'; - const queryParam = 'test query'; - const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; - const paginatedSearchOptions = new PaginatedSearchOptions({ - configuration: configurationParam, - query: queryParam, - scope: scopeParam, - pagination, - sort - }); - const activatedRouteStub = { - snapshot: { - queryParamMap: new Map([ - ['query', queryParam], - ['scope', scopeParam] - ]) + + const configurationList = [ + { + value: MyDSpaceConfigurationValueType.Workspace, + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}`, + context: Context.Workspace }, - queryParams: observableOf({ - query: queryParam, - scope: scopeParam - }) - }; + { + value: MyDSpaceConfigurationValueType.Workflow, + label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}`, + context: Context.Workflow + } + ]; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule], - declarations: [MyDSpacePageComponent, RoleDirective], + declarations: [MyDSpacePageComponent], providers: [ { provide: SearchService, useValue: searchServiceStub }, - { - provide: CommunityDataService, - useValue: jasmine.createSpyObj('communityService', ['findById', 'findAll']) - }, - { provide: ActivatedRoute, useValue: activatedRouteStub }, - { provide: RouteService, useValue: routeServiceStub }, - { - provide: Store, useValue: store - }, - { - provide: HostWindowService, useValue: jasmine.createSpyObj('hostWindowService', - { - isXs: observableOf(true), - isSm: observableOf(false), - isXsOrSm: observableOf(true) - }) - }, - { - provide: SidebarService, - useValue: SidebarServiceStub - }, - { - provide: SearchFilterService, - useValue: {} - }, { - provide: SEARCH_CONFIG_SERVICE, - useValue: new SearchConfigurationServiceStub() - }, - { - provide: RoleService, - useValue: new RoleServiceMock() - }, + { provide: MyDSpaceConfigurationService, useValue: myDSpaceConfigurationServiceStub }, ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(MyDSpacePageComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } + set: { + providers: [ + { + provide: SEARCH_CONFIG_SERVICE, + useValue: myDSpaceConfigurationServiceStub + } + ] + } }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(MyDSpacePageComponent); comp = fixture.componentInstance; // SearchPageComponent test instance + myDSpaceConfigurationServiceStub.getAvailableConfigurationOptions.and.returnValue(observableOf(configurationList)); + fixture.detectChanges(); - searchServiceObject = (comp as any).service; - searchConfigurationServiceObject = (comp as any).searchConfigService; + }); afterEach(() => { comp = null; - searchServiceObject = null; - searchConfigurationServiceObject = null; }); - it('should get the scope and query from the route parameters', () => { + it('should init properly context and configuration', fakeAsync(() => { - searchConfigurationServiceObject.paginatedSearchOptions.next(paginatedSearchOptions); - expect(comp.searchOptions$).toBeObservable(cold('b', { - b: paginatedSearchOptions + expect(comp.configurationList$).toBeObservable(cold('(a|)', { + a: configurationList })); - }); + flush(); + expect(comp.configuration).toBe(MyDSpaceConfigurationValueType.Workspace); + expect(comp.context).toBe(Context.Workspace); + })); - describe('when the open sidebar button is clicked in mobile view', () => { - - beforeEach(() => { - spyOn(comp, 'openSidebar'); - const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar')); - openSidebarButton.triggerEventHandler('click', null); - }); - - it('should trigger the openSidebar function', () => { - expect(comp.openSidebar).toHaveBeenCalled(); - }); - - }); - - describe('when sidebarCollapsed is true in mobile view', () => { - let menu: HTMLElement; - - beforeEach(() => { - menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement; - comp.isSidebarCollapsed = () => observableOf(true); - fixture.detectChanges(); - }); - - it('should close the sidebar', () => { - expect(menu.classList).not.toContain('active'); - }); - - }); - - describe('when sidebarCollapsed is false in mobile view', () => { - let menu: HTMLElement; - - beforeEach(() => { - menu = fixture.debugElement.query(By.css('#search-sidebar-sm')).nativeElement; - comp.isSidebarCollapsed = () => observableOf(false); - fixture.detectChanges(); - }); - - it('should open the menu', () => { - expect(menu.classList).toContain('active'); - }); - - }); - - describe('when stable', () => { - - beforeEach(() => { - fixture.detectChanges(); - }); - - it('should have initialized the sortOptions$ observable', (done) => { - - comp.sortOptions$.subscribe((sortOptions) => { - - expect(sortOptions.length).toEqual(2); - expect(sortOptions[0]).toEqual(new SortOptions('score', SortDirection.ASC)); - expect(sortOptions[1]).toEqual(new SortOptions('score', SortDirection.DESC)); - done(); - }); - - }); - - }); }); diff --git a/src/app/my-dspace-page/my-dspace-page.component.ts b/src/app/my-dspace-page/my-dspace-page.component.ts index 4fbebcd6a7..121d417bf1 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.ts +++ b/src/app/my-dspace-page/my-dspace-page.component.ts @@ -1,11 +1,8 @@ import { ChangeDetectionStrategy, Component, Inject, InjectionToken, OnInit } from '@angular/core'; -import { Observable, Subject } from 'rxjs'; +import { Observable } from 'rxjs'; import { take } from 'rxjs/operators'; -import { pushInOut } from '../shared/animations/push'; -import { HostWindowService } from '../shared/host-window.service'; import { SearchService } from '../core/shared/search/search.service'; -import { SidebarService } from '../shared/sidebar/sidebar.service'; import { MyDSpaceResponseParsingService } from '../core/data/mydspace-response-parsing.service'; import { SearchConfigurationOption } from '../shared/search/search-switch-configuration/search-configuration-option.model'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; @@ -25,7 +22,6 @@ export const SEARCH_CONFIG_SERVICE: InjectionToken = styleUrls: ['./my-dspace-page.component.scss'], templateUrl: './my-dspace-page.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - animations: [pushInOut], providers: [ { provide: SEARCH_CONFIG_SERVICE, @@ -55,15 +51,7 @@ export class MyDSpacePageComponent implements OnInit { */ viewModeList = [ViewMode.ListElement, ViewMode.DetailedListElement]; - - /** - * Emit an event every time search sidebars must refresh their contents. - */ - refreshFilters: Subject = new Subject(); - constructor(private service: SearchService, - private sidebarService: SidebarService, - private windowService: HostWindowService, @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: MyDSpaceConfigurationService) { this.service.setServiceOptions(MyDSpaceResponseParsingService, MyDSpaceRequest); } diff --git a/src/app/search-navbar/search-navbar.component.spec.ts b/src/app/search-navbar/search-navbar.component.spec.ts index ba08c7ca75..fbdcdc951c 100644 --- a/src/app/search-navbar/search-navbar.component.spec.ts +++ b/src/app/search-navbar/search-navbar.component.spec.ts @@ -2,18 +2,14 @@ import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angul import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { Router } from '@angular/router'; +import { NavigationExtras, Router } from '@angular/router'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { SearchService } from '../core/shared/search/search.service'; import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { SearchNavbarComponent } from './search-navbar.component'; -import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { of as observableOf } from 'rxjs'; -import { PaginationService } from '../core/pagination/pagination.service'; -import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; +import { RouterTestingModule } from '@angular/router/testing'; describe('SearchNavbarComponent', () => { let component: SearchNavbarComponent; @@ -41,6 +37,7 @@ describe('SearchNavbarComponent', () => { FormsModule, ReactiveFormsModule, BrowserAnimationsModule, + RouterTestingModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, @@ -49,10 +46,7 @@ describe('SearchNavbarComponent', () => { })], declarations: [SearchNavbarComponent], providers: [ - { provide: SearchService, useValue: mockSearchService }, - { provide: PaginationService, useValue: paginationService }, - { provide: Router, useValue: routerStub }, - { provide: SearchConfigurationService, useValue: {paginationID: 'page-id'} } + { provide: SearchService, useValue: mockSearchService } ] }) .compileComponents(); @@ -61,8 +55,8 @@ describe('SearchNavbarComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(SearchNavbarComponent); component = fixture.componentInstance; + router = TestBed.inject(Router); fixture.detectChanges(); - router = (component as any).router; }); it('should create', () => { @@ -73,7 +67,7 @@ describe('SearchNavbarComponent', () => { beforeEach(fakeAsync(() => { spyOn(component, 'expand').and.callThrough(); spyOn(component, 'onSubmit').and.callThrough(); - spyOn(router, 'navigate').and.callThrough(); + spyOn(router, 'navigate'); const searchIcon = fixture.debugElement.query(By.css('#search-navbar-container form .submit-icon')); searchIcon.triggerEventHandler('click', { preventDefault: () => {/**/ @@ -99,8 +93,9 @@ describe('SearchNavbarComponent', () => { fixture.detectChanges(); })); it('to search page with empty query', () => { + const extras: NavigationExtras = {queryParams: { query: '' }, queryParamsHandling: 'merge'}; expect(component.onSubmit).toHaveBeenCalledWith({ query: '' }); - expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); + expect(router.navigate).toHaveBeenCalledWith(['search'], extras); }); }); }); @@ -123,8 +118,10 @@ describe('SearchNavbarComponent', () => { fixture.detectChanges(); })); it('to search page with query', async () => { + const extras: NavigationExtras = { queryParams: { query: 'test' }, queryParamsHandling: 'merge'}; expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' }); - expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); + + expect(router.navigate).toHaveBeenCalledWith(['search'], extras); }); }); }); diff --git a/src/app/search-navbar/search-navbar.component.ts b/src/app/search-navbar/search-navbar.component.ts index 26849adf6d..ccdaa27861 100644 --- a/src/app/search-navbar/search-navbar.component.ts +++ b/src/app/search-navbar/search-navbar.component.ts @@ -62,8 +62,9 @@ export class SearchNavbarComponent { onSubmit(data: any) { this.collapse(); const queryParams = Object.assign({}, data); - const linkToNavigateTo = this.searchService.getSearchLink().split('/'); + const linkToNavigateTo = [this.searchService.getSearchLink().replace('/', '')]; this.searchForm.reset(); + this.router.navigate(linkToNavigateTo, { queryParams: queryParams, queryParamsHandling: 'merge' diff --git a/src/app/shared/search/search.component.spec.ts b/src/app/shared/search/search.component.spec.ts index bfa4931670..25b0814579 100644 --- a/src/app/shared/search/search.component.spec.ts +++ b/src/app/shared/search/search.component.spec.ts @@ -1,11 +1,11 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { cold } from 'jasmine-marbles'; -import { of as observableOf } from 'rxjs'; +import { BehaviorSubject, of as observableOf } from 'rxjs'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { HostWindowService } from '../host-window.service'; @@ -21,11 +21,10 @@ import { SearchFilterService } from '../../core/shared/search/search-filter.serv import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component'; import { RouteService } from '../../core/services/route.service'; -import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { PaginatedSearchOptions } from './models/paginated-search-options.model'; import { SidebarServiceStub } from '../testing/sidebar-service.stub'; -import { SearchConfig } from '../../core/shared/search/search-filters/search-config.model'; -import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { SearchConfig, SortConfig } from '../../core/shared/search/search-filters/search-config.model'; let comp: SearchComponent; let fixture: ComponentFixture; @@ -37,23 +36,29 @@ const store: Store = jasmine.createSpyObj('store', { /* tslint:enable:no-empty */ select: observableOf(true) }); -const sortOptionsList = [ +const sortConfigList: SortConfig[] = [ + { name: 'score', sortOrder: SortDirection.DESC }, + { name: 'dc.title', sortOrder: SortDirection.ASC }, + { name: 'dc.title', sortOrder: SortDirection.DESC } +]; +const sortOptionsList: SortOptions[] = [ new SortOptions('score', SortDirection.DESC), new SortOptions('dc.title', SortDirection.ASC), new SortOptions('dc.title', SortDirection.DESC) ]; const searchConfig = Object.assign(new SearchConfig(), { - sortOptions: sortOptionsList + sortOptions: sortConfigList }); +const paginationId = 'search-test-page-id'; const pagination: PaginationComponentOptions = new PaginationComponentOptions(); -pagination.id = 'search-results-pagination'; +pagination.id = paginationId; pagination.currentPage = 1; pagination.pageSize = 10; -const sortOption = { name: 'score', sortOrder: 'DESC', metadata: null }; + const sort: SortOptions = new SortOptions('score', SortDirection.DESC); -const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']); +const mockResults$ = createSuccessfulRemoteDataObject$(['test', 'data']); const searchServiceStub = jasmine.createSpyObj('SearchService', { - search: mockResults, + search: mockResults$, getSearchLink: '/search', getScopes: observableOf(['test-scope']), getSearchConfigurationFor: createSuccessfulRemoteDataObject$(searchConfig) @@ -62,6 +67,11 @@ const configurationParam = 'default'; const queryParam = 'test query'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; const fixedFilter = 'fixed filter'; + +const defaultSearchOptions = new PaginatedSearchOptions({ pagination }); + +const paginatedSearchOptions$ = new BehaviorSubject(defaultSearchOptions); + const paginatedSearchOptions = new PaginatedSearchOptions({ configuration: configurationParam, query: queryParam, @@ -97,12 +107,14 @@ const routeServiceStub = { const searchConfigurationServiceStub = jasmine.createSpyObj('SearchConfigurationService', { + getConfigurationSortOptions: jasmine.createSpy('getConfigurationSortOptions'), getConfigurationSearchConfig: jasmine.createSpy('getConfigurationSearchConfig'), getCurrentConfiguration: jasmine.createSpy('getCurrentConfiguration'), getCurrentScope: jasmine.createSpy('getCurrentScope'), + getCurrentSort: jasmine.createSpy('getCurrentSort'), updateFixedFilter: jasmine.createSpy('updateFixedFilter'), setPaginationId: jasmine.createSpy('setPaginationId') -}); +}, ['paginatedSearchOptions']); export function configureSearchComponentTestingModule(compType, additionalDeclarations: any[] = []) { TestBed.configureTestingModule({ @@ -146,7 +158,7 @@ export function configureSearchComponentTestingModule(compType, additionalDeclar }).compileComponents(); } -fdescribe('SearchComponent', () => { +describe('SearchComponent', () => { beforeEach(waitForAsync(() => { configureSearchComponentTestingModule(SearchComponent); })); @@ -155,17 +167,25 @@ fdescribe('SearchComponent', () => { fixture = TestBed.createComponent(SearchComponent); comp = fixture.componentInstance; // SearchComponent test instance comp.inPlaceSearch = false; + comp.paginationId = paginationId; - // searchConfigurationServiceStub.paginatedSearchOptions.and.returnValue(observableOf(paginatedSearchOptions)); searchConfigurationServiceStub.getConfigurationSearchConfig.and.returnValue(observableOf(searchConfig)); + searchConfigurationServiceStub.getConfigurationSortOptions.and.returnValue(sortOptionsList); searchConfigurationServiceStub.getCurrentConfiguration.and.returnValue(observableOf('default')); searchConfigurationServiceStub.getCurrentScope.and.returnValue(observableOf('test-id')); + searchConfigurationServiceStub.getCurrentSort.and.returnValue(observableOf(sortOptionsList[0])); + searchConfigurationServiceStub.setPaginationId.and.callFake((pageId) => { + paginatedSearchOptions$.next(Object.assign(paginatedSearchOptions$.value, { + pagination: Object.assign(new PaginationComponentOptions(), { + id: pageId + }) + })); + }); + spyOn((comp as any), 'getSearchOptions').and.returnValue(paginatedSearchOptions$.asObservable()); - searchServiceObject = TestBed.inject(SearchService); + searchServiceObject = TestBed.inject(SearchService); searchConfigurationServiceObject = TestBed.inject(SEARCH_CONFIG_SERVICE); - searchConfigurationServiceObject.paginatedSearchOptions = new BehaviorSubject(paginatedSearchOptions); - fixture.detectChanges(); }); afterEach(() => { @@ -174,45 +194,52 @@ fdescribe('SearchComponent', () => { searchConfigurationServiceObject = null; }); - it('should get the scope and query from the route parameters', () => { + it('should init search parameters properly and call retrieveSearchResults', fakeAsync(() => { + spyOn((comp as any), 'retrieveSearchResults').and.callThrough(); + fixture.detectChanges(); + flush(); - expect(comp.searchOptions$).toBeObservable(cold('b', { - b: paginatedSearchOptions + const expectedSearchOptions = Object.assign(paginatedSearchOptions$.value, { + configuration: 'default', + sort: sortOptionsList[0] + }); + expect(comp.currentConfiguration$).toBeObservable(cold('b', { + b: 'default' })); + expect(comp.currentSortOptions$).toBeObservable(cold('b', { + b: sortOptionsList[0] + })); + expect(comp.sortOptionsList$).toBeObservable(cold('b', { + b: sortOptionsList + })); + expect(comp.searchOptions$).toBeObservable(cold('b', { + b: expectedSearchOptions + })); + expect((comp as any).retrieveSearchResults).toHaveBeenCalledWith(expectedSearchOptions); + })); - }); + it('should retrieve SearchResults', fakeAsync(() => { + fixture.detectChanges(); + flush(); + const expectedResults = createSuccessfulRemoteDataObject(['test', 'data']); + expect(comp.resultsRD$).toBeObservable(cold('b', { + b: expectedResults + })); + })); - xdescribe('when the open sidebar button is clicked in mobile view', () => { + describe('when the open sidebar button is clicked in mobile view', () => { - beforeEach(() => { + beforeEach(fakeAsync(() => { spyOn(comp, 'openSidebar'); + fixture.detectChanges(); + flush(); const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar')); openSidebarButton.triggerEventHandler('click', null); - }); + })); it('should trigger the openSidebar function', () => { expect(comp.openSidebar).toHaveBeenCalled(); }); }); - - describe('when stable', () => { - - beforeEach(() => { - fixture.detectChanges(); - }); - - it('should have initialized the sortOptions$ observable', (done) => { - - comp.sortOptionsList$.subscribe((sortOptions) => { - - expect(sortOptions.length).toEqual(2); - expect(sortOptions[0]).toEqual(new SortOptions('score', SortDirection.ASC)); - expect(sortOptions[1]).toEqual(new SortOptions('score', SortDirection.DESC)); - done(); - }); - - }); - - }); }); diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index 2f18507652..a27f9ff0da 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -204,6 +204,7 @@ export class SearchComponent implements OnInit { return searchOptions.pagination.id === this.paginationId; }) ).subscribe(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => { + // Build the PaginatedSearchOptions object const combinedOptions = Object.assign({}, searchOptions, { @@ -211,7 +212,6 @@ export class SearchComponent implements OnInit { sort: sortOption || searchOptions.sort }); const newSearchOptions = new PaginatedSearchOptions(combinedOptions); - // Initialize variables this.currentConfiguration$.next(configuration); this.currentSortOptions$.next(newSearchOptions.sort); @@ -277,7 +277,6 @@ export class SearchComponent implements OnInit { followLink('thumbnail', { isOptional: true }) ).pipe(getFirstCompletedRemoteData()) .subscribe((results: RemoteData>) => { - console.log('results ', results); this.resultsRD$.next(results); }); }