fixed collection dropdown component after angular 10 upgrade

This commit is contained in:
Giuseppe Digilio
2020-12-01 15:22:58 +01:00
parent 5b5d2031d5
commit ef0c574473
2 changed files with 96 additions and 102 deletions

View File

@@ -1,22 +1,22 @@
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ChangeDetectorRef, ElementRef, NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { getTestScheduler } from 'jasmine-marbles';
import { TestScheduler } from 'rxjs/testing';
import { of as observableOf } from 'rxjs';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { CollectionDropdownComponent } from './collection-dropdown.component'; import { CollectionDropdownComponent } from './collection-dropdown.component';
import { FollowLinkConfig } from '../utils/follow-link-config.model'; import { RemoteData } from '../../core/data/remote-data';
import { Observable, of } from 'rxjs'; import { PaginatedList } from '../../core/data/paginated-list';
import { RemoteData } from 'src/app/core/data/remote-data'; import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { PaginatedList } from 'src/app/core/data/paginated-list'; import { PageInfo } from '../../core/shared/page-info.model';
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
import { PageInfo } from 'src/app/core/shared/page-info.model';
import { Collection } from '../../core/shared/collection.model'; import { Collection } from '../../core/shared/collection.model';
import { NO_ERRORS_SCHEMA, ChangeDetectorRef, ElementRef } from '@angular/core'; import { CollectionDataService } from '../../core/data/collection-data.service';
import { CollectionDataService } from 'src/app/core/data/collection-data.service';
import { FindListOptions } from 'src/app/core/data/request.models';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateLoaderMock } from '../mocks/translate-loader.mock'; import { TranslateLoaderMock } from '../mocks/translate-loader.mock';
import { TestScheduler } from 'rxjs/testing'; import { Community } from '../../core/shared/community.model';
import { By } from '@angular/platform-browser'; import { MockElementRef } from '../testing/element-ref.mock';
import { Community } from 'src/app/core/shared/community.model';
const community: Community = Object.assign(new Community(), { const community: Community = Object.assign(new Community(), {
id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88',
@@ -34,7 +34,7 @@ const collections: Collection[] = [
language: 'en_US', language: 'en_US',
value: 'Community 1-Collection 1' value: 'Community 1-Collection 1'
}], }],
parentCommunity: of( parentCommunity: observableOf(
new RemoteData(false, false, true, undefined, community, 200) new RemoteData(false, false, true, undefined, community, 200)
) )
}), }),
@@ -47,7 +47,7 @@ const collections: Collection[] = [
language: 'en_US', language: 'en_US',
value: 'Community 1-Collection 2' value: 'Community 1-Collection 2'
}], }],
parentCommunity: of( parentCommunity: observableOf(
new RemoteData(false, false, true, undefined, community, 200) new RemoteData(false, false, true, undefined, community, 200)
) )
}), }),
@@ -60,7 +60,7 @@ const collections: Collection[] = [
language: 'en_US', language: 'en_US',
value: 'Community 1-Collection 3' value: 'Community 1-Collection 3'
}], }],
parentCommunity: of( parentCommunity: observableOf(
new RemoteData(false, false, true, undefined, community, 200) new RemoteData(false, false, true, undefined, community, 200)
) )
}), }),
@@ -73,7 +73,7 @@ const collections: Collection[] = [
language: 'en_US', language: 'en_US',
value: 'Community 1-Collection 4' value: 'Community 1-Collection 4'
}], }],
parentCommunity: of( parentCommunity: observableOf(
new RemoteData(false, false, true, undefined, community, 200) new RemoteData(false, false, true, undefined, community, 200)
) )
}), }),
@@ -86,44 +86,40 @@ const collections: Collection[] = [
language: 'en_US', language: 'en_US',
value: 'Community 1-Collection 5' value: 'Community 1-Collection 5'
}], }],
parentCommunity: of( parentCommunity: observableOf(
new RemoteData(false, false, true, undefined, community, 200) new RemoteData(false, false, true, undefined, community, 200)
) )
}) })
]; ];
const listElementMock = { const listElementMock = {
communities: [ communities: [
{ {
id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88', id: 'ce64f48e-2c9b-411a-ac36-ee429c0e6a88',
name: 'Community 1' name: 'Community 1'
}
],
collection: {
id: 'e9dbf393-7127-415f-8919-55be34a6e9ed',
uuid: 'e9dbf393-7127-415f-8919-55be34a6e9ed',
name: 'Collection 3'
} }
}; ],
collection: {
// tslint:disable-next-line: max-classes-per-file id: 'e9dbf393-7127-415f-8919-55be34a6e9ed',
class CollectionDataServiceMock { uuid: 'e9dbf393-7127-415f-8919-55be34a6e9ed',
getAuthorizedCollection(query: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<Collection>>): Observable<RemoteData<PaginatedList<Collection>>> { name: 'Collection 3'
return of(
createSuccessfulRemoteDataObject(
new PaginatedList(new PageInfo(), collections)
)
);
} }
} };
describe('CollectionDropdownComponent', () => { describe('CollectionDropdownComponent', () => {
let component: CollectionDropdownComponent; let component: CollectionDropdownComponent;
let componentAsAny: any;
let fixture: ComponentFixture<CollectionDropdownComponent>; let fixture: ComponentFixture<CollectionDropdownComponent>;
let scheduler: TestScheduler; let scheduler: TestScheduler;
const searchedCollection = 'TEXT';
beforeEach(async(() => { const collectionDataServiceMock: any = jasmine.createSpyObj('CollectionDataService', {
getAuthorizedCollection: jasmine.createSpy('getAuthorizedCollection')
});
const paginatedCollection = new PaginatedList(new PageInfo(), collections);
const paginatedCollectionRD$ = createSuccessfulRemoteDataObject$(paginatedCollection);
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
TranslateModule.forRoot({ TranslateModule.forRoot({
@@ -133,11 +129,11 @@ describe('CollectionDropdownComponent', () => {
} }
}) })
], ],
declarations: [ CollectionDropdownComponent ], declarations: [CollectionDropdownComponent],
providers: [ providers: [
{provide: CollectionDataService, useClass: CollectionDataServiceMock}, { provide: CollectionDataService, useValue: collectionDataServiceMock },
{provide: ChangeDetectorRef, useValue: {}}, { provide: ElementRef, useClass: MockElementRef },
{provide: ElementRef, userValue: {}} ChangeDetectorRef
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}) })
@@ -148,39 +144,39 @@ describe('CollectionDropdownComponent', () => {
scheduler = getTestScheduler(); scheduler = getTestScheduler();
fixture = TestBed.createComponent(CollectionDropdownComponent); fixture = TestBed.createComponent(CollectionDropdownComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); componentAsAny = component;
componentAsAny.collectionDataService.getAuthorizedCollection.and.returnValue(paginatedCollectionRD$);
}); });
it('should populate collections list with five items', () => { it('should init component with collection list', () => {
spyOn(component.subs, 'push');
spyOn(component, 'resetPagination');
spyOn(component, 'populateCollectionList').and.callThrough();
scheduler.schedule(() => fixture.detectChanges());
scheduler.flush();
const elements = fixture.debugElement.queryAll(By.css('.collection-item')); const elements = fixture.debugElement.queryAll(By.css('.collection-item'));
expect(elements.length).toEqual(5); expect(elements.length).toEqual(5);
expect(component.subs.push).toHaveBeenCalled();
expect(component.resetPagination).toHaveBeenCalled();
expect(component.populateCollectionList).toHaveBeenCalled();
expect((component as any).collectionDataService.getAuthorizedCollection).toHaveBeenCalled();
}); });
it('should trigger onSelect method when select a new collection from list', fakeAsync(() => { it('should trigger onSelect method when select a new collection from list', () => {
spyOn(component, 'onSelect'); scheduler.schedule(() => fixture.detectChanges());
scheduler.flush();
spyOn(component, 'onSelect').and.callThrough();
const collectionItem = fixture.debugElement.query(By.css('.collection-item:nth-child(2)')); const collectionItem = fixture.debugElement.query(By.css('.collection-item:nth-child(2)'));
collectionItem.triggerEventHandler('click', null); collectionItem.triggerEventHandler('click', null);
fixture.detectChanges();
tick();
fixture.whenStable().then(() => {
expect(component.onSelect).toHaveBeenCalled();
});
}));
it('should init component with collection list', fakeAsync(() => { scheduler.schedule(() => fixture.detectChanges());
spyOn(component.subs, 'push').and.callThrough(); scheduler.flush();
spyOn(component, 'resetPagination').and.callThrough();
spyOn(component, 'populateCollectionList').and.callThrough();
component.ngOnInit();
tick();
fixture.detectChanges();
fixture.whenStable().then(() => { expect(component.onSelect).toHaveBeenCalled();
expect(component.subs.push).toHaveBeenCalled(); });
expect(component.resetPagination).toHaveBeenCalled();
expect(component.populateCollectionList).toHaveBeenCalled();
});
}));
it('should emit collectionChange event when selecting a new collection', () => { it('should emit collectionChange event when selecting a new collection', () => {
spyOn(component.selectionChange, 'emit').and.callThrough(); spyOn(component.selectionChange, 'emit').and.callThrough();
@@ -191,36 +187,23 @@ describe('CollectionDropdownComponent', () => {
expect(component.selectionChange.emit).toHaveBeenCalledWith(listElementMock as any); expect(component.selectionChange.emit).toHaveBeenCalledWith(listElementMock as any);
}); });
it('should reset collections list after reset of searchField', fakeAsync(() => { it('should reset collections list after reset of searchField', () => {
spyOn(component.subs, 'push').and.callThrough(); spyOn(component.subs, 'push').and.callThrough();
spyOn(component, 'reset').and.callThrough();
spyOn(component.searchField, 'setValue').and.callThrough(); spyOn(component.searchField, 'setValue').and.callThrough();
spyOn(component, 'resetPagination').and.callThrough(); spyOn(component, 'resetPagination').and.callThrough();
spyOn(component, 'populateCollectionList').and.callThrough(); spyOn(component, 'populateCollectionList').and.callThrough();
component.reset(); scheduler.schedule(() => fixture.detectChanges());
const input = fixture.debugElement.query(By.css('input.form-control')); scheduler.flush();
const el = input.nativeElement;
el.value = searchedCollection;
el.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick(500);
fixture.whenStable().then(() => { scheduler.schedule(() => component.reset());
expect(component.reset).toHaveBeenCalled(); scheduler.flush();
expect(component.searchField.setValue).toHaveBeenCalledWith('');
expect(component.resetPagination).toHaveBeenCalled();
expect(component.currentQuery).toEqual('');
expect(component.populateCollectionList).toHaveBeenCalledWith(component.currentQuery, component.currentPage);
expect(component.searchListCollection).toEqual(collections as any);
expect(component.subs.push).toHaveBeenCalled();
});
}));
it('should reset searchField when dropdown menu has been closed', () => { expect(component.searchField.setValue).toHaveBeenCalledWith('');
spyOn(component.searchField, 'setValue').and.callThrough(); expect(component.resetPagination).toHaveBeenCalled();
component.reset(); expect(component.currentQuery).toEqual('');
expect(component.populateCollectionList).toHaveBeenCalledWith(component.currentQuery, component.currentPage);
expect(component.searchField.setValue).toHaveBeenCalled(); expect(component.searchListCollection.length).toEqual(5);
expect(component.subs.push).toHaveBeenCalled();
}); });
it('should change loader status', () => { it('should change loader status', () => {

View File

@@ -1,13 +1,24 @@
import { Component, OnInit, HostListener, ChangeDetectorRef, OnDestroy, Output, EventEmitter, ElementRef } from '@angular/core'; import {
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostListener,
OnDestroy,
OnInit,
Output
} from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Observable, Subscription, BehaviorSubject } from 'rxjs';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, mergeMap, reduce, startWith, switchMap } from 'rxjs/operators';
import { hasValue } from '../empty.util'; import { hasValue } from '../empty.util';
import { map, mergeMap, startWith, debounceTime, distinctUntilChanged, switchMap, reduce } from 'rxjs/operators'; import { RemoteData } from '../../core/data/remote-data';
import { RemoteData } from 'src/app/core/data/remote-data'; import { FindListOptions } from '../../core/data/request.models';
import { FindListOptions } from 'src/app/core/data/request.models'; import { PaginatedList } from '../../core/data/paginated-list';
import { PaginatedList } from 'src/app/core/data/paginated-list'; import { Community } from '../../core/shared/community.model';
import { Community } from 'src/app/core/shared/community.model'; import { CollectionDataService } from '../../core/data/collection-data.service';
import { CollectionDataService } from 'src/app/core/data/collection-data.service';
import { Collection } from '../../core/shared/collection.model'; import { Collection } from '../../core/shared/collection.model';
import { followLink } from '../utils/follow-link-config.model'; import { followLink } from '../utils/follow-link-config.model';
import { getFirstSucceededRemoteDataPayload, getSucceededRemoteWithNotEmptyData } from '../../core/shared/operators'; import { getFirstSucceededRemoteDataPayload, getSucceededRemoteWithNotEmptyData } from '../../core/shared/operators';