[CST-4633] fix tests

This commit is contained in:
Giuseppe Digilio
2021-12-19 17:36:03 +01:00
parent f43317c2ee
commit c9b48ccb65
10 changed files with 140 additions and 256 deletions

View File

@@ -20,7 +20,7 @@ import { RouteService } from '../../services/route.service';
import { getAllSucceededRemoteDataPayload, getFirstSucceededRemoteData } from '../operators'; import { getAllSucceededRemoteDataPayload, getFirstSucceededRemoteData } from '../operators';
import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; 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 { SearchService } from './search.service';
import { PaginationService } from '../../pagination/pagination.service'; import { PaginationService } from '../../pagination/pagination.service';
@@ -204,7 +204,7 @@ export class SearchConfigurationService implements OnDestroy {
* @param searchConfig The SearchConfig object * @param searchConfig The SearchConfig object
*/ */
getConfigurationSortOptions(searchConfig: SearchConfig): SortOptions[] { getConfigurationSortOptions(searchConfig: SearchConfig): SortOptions[] {
return searchConfig.sortOptions.map((entry: SortOption) => ({ return searchConfig.sortOptions.map((entry: SortConfig) => ({
field: entry.name, field: entry.name,
direction: entry.sortOrder.toLowerCase() === SortDirection.ASC.toLowerCase() ? SortDirection.ASC : SortDirection.DESC direction: entry.sortOrder.toLowerCase() === SortDirection.ASC.toLowerCase() ? SortDirection.ASC : SortDirection.DESC
})); }));

View File

@@ -29,7 +29,7 @@ export class SearchConfig implements CacheableObject {
* The configured sort options. * The configured sort options.
*/ */
@autoserialize @autoserialize
sortOptions: SortOption[]; sortOptions: SortConfig[];
/** /**
* The object type. * The object type.
@@ -63,7 +63,7 @@ export interface FilterConfig {
/** /**
* Interface to model sort option's configuration. * Interface to model sort option's configuration.
*/ */
export interface SortOption { export interface SortConfig {
name: string; name: string;
sortOrder: string; sortOrder: string;
} }

View File

@@ -38,10 +38,4 @@ describe('RelatedEntitiesSearchComponent', () => {
expect(comp.fixedFilter).toEqual(mockFilter); expect(comp.fixedFilter).toEqual(mockFilter);
}); });
it('should create a configuration$', () => {
comp.configuration$.subscribe((configuration) => {
expect(configuration).toEqual(mockConfiguration);
});
});
}); });

View File

@@ -10,6 +10,7 @@ import { RoleServiceMock } from '../shared/mocks/role-service.mock';
import { cold, hot } from 'jasmine-marbles'; import { cold, hot } from 'jasmine-marbles';
import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type'; import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type';
import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub';
import { Context } from '../core/shared/context.model';
describe('MyDSpaceConfigurationService', () => { describe('MyDSpaceConfigurationService', () => {
let service: MyDSpaceConfigurationService; let service: MyDSpaceConfigurationService;
@@ -241,11 +242,13 @@ describe('MyDSpaceConfigurationService', () => {
b: [ b: [
{ {
value: MyDSpaceConfigurationValueType.Workspace, value: MyDSpaceConfigurationValueType.Workspace,
label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}` label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}`,
context: Context.Workspace
}, },
{ {
value: MyDSpaceConfigurationValueType.Workflow, value: MyDSpaceConfigurationValueType.Workflow,
label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}` label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}`,
context: Context.Workflow
} }
] ]
})); }));

View File

@@ -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 { 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 { 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 { RouterTestingModule } from '@angular/router/testing';
import { Store } from '@ngrx/store'; import { of as observableOf } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles'; 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 { 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 { SearchService } from '../core/shared/search/search.service';
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { MyDSpaceConfigurationService } from './my-dspace-configuration.service';
import { PaginatedSearchOptions } from '../shared/search/models/paginated-search-options.model'; import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type';
import { SidebarService } from '../shared/sidebar/sidebar.service'; import { Context } from '../core/shared/context.model';
import { SearchFilterService } from '../core/shared/search/search-filter.service'; import SpyObj = jasmine.SpyObj;
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';
describe('MyDSpacePageComponent', () => { describe('MyDSpacePageComponent', () => {
let comp: MyDSpacePageComponent; let comp: MyDSpacePageComponent;
let fixture: ComponentFixture<MyDSpacePageComponent>; let fixture: ComponentFixture<MyDSpacePageComponent>;
let searchServiceObject: SearchService;
let searchConfigurationServiceObject: SearchConfigurationService; const searchServiceStub: SpyObj<SearchService> = jasmine.createSpyObj('SearchService', {
const store: Store<MyDSpacePageComponent> = jasmine.createSpyObj('store', { setServiceOptions: jasmine.createSpy('setServiceOptions')
/* tslint:disable:no-empty */
dispatch: {},
/* tslint:enable:no-empty */
select: observableOf(true)
}); });
const pagination: PaginationComponentOptions = new PaginationComponentOptions();
pagination.id = 'mydspace-results-pagination'; const myDSpaceConfigurationServiceStub: SpyObj<MyDSpaceConfigurationService> = jasmine.createSpyObj('MyDSpaceConfigurationService', {
pagination.currentPage = 1; getAvailableConfigurationOptions: jasmine.createSpy('getAvailableConfigurationOptions')
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 configurationParam = 'default';
const queryParam = 'test query'; const configurationList = [
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; {
const paginatedSearchOptions = new PaginatedSearchOptions({ value: MyDSpaceConfigurationValueType.Workspace,
configuration: configurationParam, label: `mydspace.show.${MyDSpaceConfigurationValueType.Workspace}`,
query: queryParam, context: Context.Workspace
scope: scopeParam,
pagination,
sort
});
const activatedRouteStub = {
snapshot: {
queryParamMap: new Map([
['query', queryParam],
['scope', scopeParam]
])
}, },
queryParams: observableOf({ {
query: queryParam, value: MyDSpaceConfigurationValueType.Workflow,
scope: scopeParam label: `mydspace.show.${MyDSpaceConfigurationValueType.Workflow}`,
}) context: Context.Workflow
}; }
];
beforeEach(waitForAsync(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule, NgbCollapseModule],
declarations: [MyDSpacePageComponent, RoleDirective], declarations: [MyDSpacePageComponent],
providers: [ providers: [
{ provide: SearchService, useValue: searchServiceStub }, { provide: SearchService, useValue: searchServiceStub },
{ { provide: MyDSpaceConfigurationService, useValue: myDSpaceConfigurationServiceStub },
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()
},
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}).overrideComponent(MyDSpacePageComponent, { }).overrideComponent(MyDSpacePageComponent, {
set: { changeDetection: ChangeDetectionStrategy.Default } set: {
providers: [
{
provide: SEARCH_CONFIG_SERVICE,
useValue: myDSpaceConfigurationServiceStub
}
]
}
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(MyDSpacePageComponent); fixture = TestBed.createComponent(MyDSpacePageComponent);
comp = fixture.componentInstance; // SearchPageComponent test instance comp = fixture.componentInstance; // SearchPageComponent test instance
myDSpaceConfigurationServiceStub.getAvailableConfigurationOptions.and.returnValue(observableOf(configurationList));
fixture.detectChanges(); fixture.detectChanges();
searchServiceObject = (comp as any).service;
searchConfigurationServiceObject = (comp as any).searchConfigService;
}); });
afterEach(() => { afterEach(() => {
comp = null; 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.configurationList$).toBeObservable(cold('(a|)', {
expect(comp.searchOptions$).toBeObservable(cold('b', { a: configurationList
b: paginatedSearchOptions
})); }));
}); 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();
});
});
});
}); });

View File

@@ -1,11 +1,8 @@
import { ChangeDetectionStrategy, Component, Inject, InjectionToken, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, InjectionToken, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs'; import { Observable } from 'rxjs';
import { take } from 'rxjs/operators'; 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 { SearchService } from '../core/shared/search/search.service';
import { SidebarService } from '../shared/sidebar/sidebar.service';
import { MyDSpaceResponseParsingService } from '../core/data/mydspace-response-parsing.service'; import { MyDSpaceResponseParsingService } from '../core/data/mydspace-response-parsing.service';
import { SearchConfigurationOption } from '../shared/search/search-switch-configuration/search-configuration-option.model'; import { SearchConfigurationOption } from '../shared/search/search-switch-configuration/search-configuration-option.model';
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
@@ -25,7 +22,6 @@ export const SEARCH_CONFIG_SERVICE: InjectionToken<SearchConfigurationService> =
styleUrls: ['./my-dspace-page.component.scss'], styleUrls: ['./my-dspace-page.component.scss'],
templateUrl: './my-dspace-page.component.html', templateUrl: './my-dspace-page.component.html',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
animations: [pushInOut],
providers: [ providers: [
{ {
provide: SEARCH_CONFIG_SERVICE, provide: SEARCH_CONFIG_SERVICE,
@@ -55,15 +51,7 @@ export class MyDSpacePageComponent implements OnInit {
*/ */
viewModeList = [ViewMode.ListElement, ViewMode.DetailedListElement]; viewModeList = [ViewMode.ListElement, ViewMode.DetailedListElement];
/**
* Emit an event every time search sidebars must refresh their contents.
*/
refreshFilters: Subject<any> = new Subject<any>();
constructor(private service: SearchService, constructor(private service: SearchService,
private sidebarService: SidebarService,
private windowService: HostWindowService,
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: MyDSpaceConfigurationService) { @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: MyDSpaceConfigurationService) {
this.service.setServiceOptions(MyDSpaceResponseParsingService, MyDSpaceRequest); this.service.setServiceOptions(MyDSpaceResponseParsingService, MyDSpaceRequest);
} }

View File

@@ -2,18 +2,14 @@ import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angul
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 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 { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { SearchService } from '../core/shared/search/search.service'; import { SearchService } from '../core/shared/search/search.service';
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
import { SearchNavbarComponent } from './search-navbar.component'; 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 { PaginationServiceStub } from '../shared/testing/pagination-service.stub';
import { RouterTestingModule } from '@angular/router/testing';
describe('SearchNavbarComponent', () => { describe('SearchNavbarComponent', () => {
let component: SearchNavbarComponent; let component: SearchNavbarComponent;
@@ -41,6 +37,7 @@ describe('SearchNavbarComponent', () => {
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
BrowserAnimationsModule, BrowserAnimationsModule,
RouterTestingModule,
TranslateModule.forRoot({ TranslateModule.forRoot({
loader: { loader: {
provide: TranslateLoader, provide: TranslateLoader,
@@ -49,10 +46,7 @@ describe('SearchNavbarComponent', () => {
})], })],
declarations: [SearchNavbarComponent], declarations: [SearchNavbarComponent],
providers: [ providers: [
{ provide: SearchService, useValue: mockSearchService }, { provide: SearchService, useValue: mockSearchService }
{ provide: PaginationService, useValue: paginationService },
{ provide: Router, useValue: routerStub },
{ provide: SearchConfigurationService, useValue: {paginationID: 'page-id'} }
] ]
}) })
.compileComponents(); .compileComponents();
@@ -61,8 +55,8 @@ describe('SearchNavbarComponent', () => {
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(SearchNavbarComponent); fixture = TestBed.createComponent(SearchNavbarComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
router = TestBed.inject(Router);
fixture.detectChanges(); fixture.detectChanges();
router = (component as any).router;
}); });
it('should create', () => { it('should create', () => {
@@ -73,7 +67,7 @@ describe('SearchNavbarComponent', () => {
beforeEach(fakeAsync(() => { beforeEach(fakeAsync(() => {
spyOn(component, 'expand').and.callThrough(); spyOn(component, 'expand').and.callThrough();
spyOn(component, 'onSubmit').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')); const searchIcon = fixture.debugElement.query(By.css('#search-navbar-container form .submit-icon'));
searchIcon.triggerEventHandler('click', { searchIcon.triggerEventHandler('click', {
preventDefault: () => {/**/ preventDefault: () => {/**/
@@ -99,8 +93,9 @@ describe('SearchNavbarComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
})); }));
it('to search page with empty query', () => { it('to search page with empty query', () => {
const extras: NavigationExtras = {queryParams: { query: '' }, queryParamsHandling: 'merge'};
expect(component.onSubmit).toHaveBeenCalledWith({ query: '' }); expect(component.onSubmit).toHaveBeenCalledWith({ query: '' });
expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); expect(router.navigate).toHaveBeenCalledWith(['search'], extras);
}); });
}); });
}); });
@@ -123,8 +118,10 @@ describe('SearchNavbarComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
})); }));
it('to search page with query', async () => { it('to search page with query', async () => {
const extras: NavigationExtras = { queryParams: { query: 'test' }, queryParamsHandling: 'merge'};
expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' }); expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' });
expect(paginationService.updateRouteWithUrl).toHaveBeenCalled();
expect(router.navigate).toHaveBeenCalledWith(['search'], extras);
}); });
}); });
}); });

View File

@@ -62,8 +62,9 @@ export class SearchNavbarComponent {
onSubmit(data: any) { onSubmit(data: any) {
this.collapse(); this.collapse();
const queryParams = Object.assign({}, data); const queryParams = Object.assign({}, data);
const linkToNavigateTo = this.searchService.getSearchLink().split('/'); const linkToNavigateTo = [this.searchService.getSearchLink().replace('/', '')];
this.searchForm.reset(); this.searchForm.reset();
this.router.navigate(linkToNavigateTo, { this.router.navigate(linkToNavigateTo, {
queryParams: queryParams, queryParams: queryParams,
queryParamsHandling: 'merge' queryParamsHandling: 'merge'

View File

@@ -1,11 +1,11 @@
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; 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 { RouterTestingModule } from '@angular/router/testing';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles'; 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 { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
import { CommunityDataService } from '../../core/data/community-data.service'; import { CommunityDataService } from '../../core/data/community-data.service';
import { HostWindowService } from '../host-window.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 { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component'; import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component';
import { RouteService } from '../../core/services/route.service'; 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 { PaginatedSearchOptions } from './models/paginated-search-options.model';
import { SidebarServiceStub } from '../testing/sidebar-service.stub'; import { SidebarServiceStub } from '../testing/sidebar-service.stub';
import { SearchConfig } from '../../core/shared/search/search-filters/search-config.model'; import { SearchConfig, SortConfig } from '../../core/shared/search/search-filters/search-config.model';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
let comp: SearchComponent; let comp: SearchComponent;
let fixture: ComponentFixture<SearchComponent>; let fixture: ComponentFixture<SearchComponent>;
@@ -37,23 +36,29 @@ const store: Store<SearchComponent> = jasmine.createSpyObj('store', {
/* tslint:enable:no-empty */ /* tslint:enable:no-empty */
select: observableOf(true) 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('score', SortDirection.DESC),
new SortOptions('dc.title', SortDirection.ASC), new SortOptions('dc.title', SortDirection.ASC),
new SortOptions('dc.title', SortDirection.DESC) new SortOptions('dc.title', SortDirection.DESC)
]; ];
const searchConfig = Object.assign(new SearchConfig(), { const searchConfig = Object.assign(new SearchConfig(), {
sortOptions: sortOptionsList sortOptions: sortConfigList
}); });
const paginationId = 'search-test-page-id';
const pagination: PaginationComponentOptions = new PaginationComponentOptions(); const pagination: PaginationComponentOptions = new PaginationComponentOptions();
pagination.id = 'search-results-pagination'; pagination.id = paginationId;
pagination.currentPage = 1; pagination.currentPage = 1;
pagination.pageSize = 10; pagination.pageSize = 10;
const sortOption = { name: 'score', sortOrder: 'DESC', metadata: null };
const sort: SortOptions = new SortOptions('score', SortDirection.DESC); const sort: SortOptions = new SortOptions('score', SortDirection.DESC);
const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']); const mockResults$ = createSuccessfulRemoteDataObject$(['test', 'data']);
const searchServiceStub = jasmine.createSpyObj('SearchService', { const searchServiceStub = jasmine.createSpyObj('SearchService', {
search: mockResults, search: mockResults$,
getSearchLink: '/search', getSearchLink: '/search',
getScopes: observableOf(['test-scope']), getScopes: observableOf(['test-scope']),
getSearchConfigurationFor: createSuccessfulRemoteDataObject$(searchConfig) getSearchConfigurationFor: createSuccessfulRemoteDataObject$(searchConfig)
@@ -62,6 +67,11 @@ const configurationParam = 'default';
const queryParam = 'test query'; const queryParam = 'test query';
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f';
const fixedFilter = 'fixed filter'; const fixedFilter = 'fixed filter';
const defaultSearchOptions = new PaginatedSearchOptions({ pagination });
const paginatedSearchOptions$ = new BehaviorSubject(defaultSearchOptions);
const paginatedSearchOptions = new PaginatedSearchOptions({ const paginatedSearchOptions = new PaginatedSearchOptions({
configuration: configurationParam, configuration: configurationParam,
query: queryParam, query: queryParam,
@@ -97,12 +107,14 @@ const routeServiceStub = {
const searchConfigurationServiceStub = jasmine.createSpyObj('SearchConfigurationService', { const searchConfigurationServiceStub = jasmine.createSpyObj('SearchConfigurationService', {
getConfigurationSortOptions: jasmine.createSpy('getConfigurationSortOptions'),
getConfigurationSearchConfig: jasmine.createSpy('getConfigurationSearchConfig'), getConfigurationSearchConfig: jasmine.createSpy('getConfigurationSearchConfig'),
getCurrentConfiguration: jasmine.createSpy('getCurrentConfiguration'), getCurrentConfiguration: jasmine.createSpy('getCurrentConfiguration'),
getCurrentScope: jasmine.createSpy('getCurrentScope'), getCurrentScope: jasmine.createSpy('getCurrentScope'),
getCurrentSort: jasmine.createSpy('getCurrentSort'),
updateFixedFilter: jasmine.createSpy('updateFixedFilter'), updateFixedFilter: jasmine.createSpy('updateFixedFilter'),
setPaginationId: jasmine.createSpy('setPaginationId') setPaginationId: jasmine.createSpy('setPaginationId')
}); }, ['paginatedSearchOptions']);
export function configureSearchComponentTestingModule(compType, additionalDeclarations: any[] = []) { export function configureSearchComponentTestingModule(compType, additionalDeclarations: any[] = []) {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@@ -146,7 +158,7 @@ export function configureSearchComponentTestingModule(compType, additionalDeclar
}).compileComponents(); }).compileComponents();
} }
fdescribe('SearchComponent', () => { describe('SearchComponent', () => {
beforeEach(waitForAsync(() => { beforeEach(waitForAsync(() => {
configureSearchComponentTestingModule(SearchComponent); configureSearchComponentTestingModule(SearchComponent);
})); }));
@@ -155,17 +167,25 @@ fdescribe('SearchComponent', () => {
fixture = TestBed.createComponent(SearchComponent); fixture = TestBed.createComponent(SearchComponent);
comp = fixture.componentInstance; // SearchComponent test instance comp = fixture.componentInstance; // SearchComponent test instance
comp.inPlaceSearch = false; comp.inPlaceSearch = false;
comp.paginationId = paginationId;
// searchConfigurationServiceStub.paginatedSearchOptions.and.returnValue(observableOf(paginatedSearchOptions));
searchConfigurationServiceStub.getConfigurationSearchConfig.and.returnValue(observableOf(searchConfig)); searchConfigurationServiceStub.getConfigurationSearchConfig.and.returnValue(observableOf(searchConfig));
searchConfigurationServiceStub.getConfigurationSortOptions.and.returnValue(sortOptionsList);
searchConfigurationServiceStub.getCurrentConfiguration.and.returnValue(observableOf('default')); searchConfigurationServiceStub.getCurrentConfiguration.and.returnValue(observableOf('default'));
searchConfigurationServiceStub.getCurrentScope.and.returnValue(observableOf('test-id')); 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 = TestBed.inject(SEARCH_CONFIG_SERVICE);
searchConfigurationServiceObject.paginatedSearchOptions = new BehaviorSubject(paginatedSearchOptions);
fixture.detectChanges();
}); });
afterEach(() => { afterEach(() => {
@@ -174,45 +194,52 @@ fdescribe('SearchComponent', () => {
searchConfigurationServiceObject = null; 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', { const expectedSearchOptions = Object.assign(paginatedSearchOptions$.value, {
b: paginatedSearchOptions 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'); spyOn(comp, 'openSidebar');
fixture.detectChanges();
flush();
const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar')); const openSidebarButton = fixture.debugElement.query(By.css('.open-sidebar'));
openSidebarButton.triggerEventHandler('click', null); openSidebarButton.triggerEventHandler('click', null);
}); }));
it('should trigger the openSidebar function', () => { it('should trigger the openSidebar function', () => {
expect(comp.openSidebar).toHaveBeenCalled(); 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();
});
});
});
}); });

View File

@@ -204,6 +204,7 @@ export class SearchComponent implements OnInit {
return searchOptions.pagination.id === this.paginationId; return searchOptions.pagination.id === this.paginationId;
}) })
).subscribe(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => { ).subscribe(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => {
// Build the PaginatedSearchOptions object // Build the PaginatedSearchOptions object
const combinedOptions = Object.assign({}, searchOptions, const combinedOptions = Object.assign({}, searchOptions,
{ {
@@ -211,7 +212,6 @@ export class SearchComponent implements OnInit {
sort: sortOption || searchOptions.sort sort: sortOption || searchOptions.sort
}); });
const newSearchOptions = new PaginatedSearchOptions(combinedOptions); const newSearchOptions = new PaginatedSearchOptions(combinedOptions);
// Initialize variables // Initialize variables
this.currentConfiguration$.next(configuration); this.currentConfiguration$.next(configuration);
this.currentSortOptions$.next(newSearchOptions.sort); this.currentSortOptions$.next(newSearchOptions.sort);
@@ -277,7 +277,6 @@ export class SearchComponent implements OnInit {
followLink<Item>('thumbnail', { isOptional: true }) followLink<Item>('thumbnail', { isOptional: true })
).pipe(getFirstCompletedRemoteData()) ).pipe(getFirstCompletedRemoteData())
.subscribe((results: RemoteData<SearchObjects<DSpaceObject>>) => { .subscribe((results: RemoteData<SearchObjects<DSpaceObject>>) => {
console.log('results ', results);
this.resultsRD$.next(results); this.resultsRD$.next(results);
}); });
} }