Added tests and comments

This commit is contained in:
Giuseppe Digilio
2019-04-02 16:25:50 +02:00
parent 16b8e91585
commit 49aee1898b
8 changed files with 290 additions and 22 deletions

View File

@@ -10,12 +10,20 @@ import { Metadata } from '../../../core/shared/metadata.utils';
selector: 'ds-my-dspace-result-detail-element', selector: 'ds-my-dspace-result-detail-element',
template: `` template: ``
}) })
export class MyDSpaceResultDetailElementComponent<T extends MyDSpaceResult<K>, K extends DSpaceObject> extends AbstractListableElementComponent<T> { export class MyDSpaceResultDetailElementComponent<T extends MyDSpaceResult<K>, K extends DSpaceObject> extends AbstractListableElementComponent<T> {
/**
* The result element object
*/
dso: K; dso: K;
public constructor(@Inject('objectElementProvider') public gridable: ListableObject) { /**
super(gridable); * Initialize instance variables
*
* @param {ListableObject} detailable
*/
public constructor(@Inject('objectElementProvider') public detailable: ListableObject) {
super(detailable);
this.dso = this.object.dspaceObject; this.dso = this.object.dspaceObject;
} }

View File

@@ -0,0 +1,181 @@
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ObjectDetailComponent } from './object-detail.component';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { MockTranslateLoader } from '../mocks/mock-translate-loader';
import { RemoteData } from '../../core/data/remote-data';
import { PaginatedList } from '../../core/data/paginated-list';
import { PageInfo } from '../../core/shared/page-info.model';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
describe('ObjectDetailComponent', () => {
let comp: ObjectDetailComponent;
let fixture: ComponentFixture<ObjectDetailComponent>;
const testEvent = {test: 'test'};
const testObjects = [
{ one: 1 },
{ two: 2 },
{ three: 3 },
{ four: 4 },
{ five: 5 },
{ six: 6 },
{ seven: 7 },
{ eight: 8 },
{ nine: 9 },
{ ten: 10 }
];
const pageInfo = Object.assign(new PageInfo(), {elementsPerPage: 1, totalElements: 10, totalPages: 10, currentPage: 1})
const mockRD = new RemoteData(false, false, true, null, new PaginatedList(pageInfo, testObjects));
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: MockTranslateLoader
}
})
],
declarations: [ObjectDetailComponent],
schemas: [NO_ERRORS_SCHEMA]
}).overrideComponent(ObjectDetailComponent, {
set: { changeDetection: ChangeDetectionStrategy.Default }
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ObjectDetailComponent);
comp = fixture.componentInstance; // SearchPageComponent test instance
comp.objects = mockRD;
fixture.detectChanges();
});
describe('when the pageChange output on the pagination is triggered', () => {
beforeEach(() => {
spyOn(comp, 'onPageChange');
const paginationEl = fixture.debugElement.query(By.css('ds-pagination'));
paginationEl.triggerEventHandler('pageChange', testEvent);
});
it('should call onPageChange on the component', () => {
expect(comp.onPageChange).toHaveBeenCalledWith(testEvent);
});
});
describe('when the pageSizeChange output on the pagination is triggered', () => {
beforeEach(() => {
spyOn(comp, 'onPageSizeChange');
const paginationEl = fixture.debugElement.query(By.css('ds-pagination'));
paginationEl.triggerEventHandler('pageSizeChange', testEvent);
});
it('should call onPageSizeChange on the component', () => {
expect(comp.onPageSizeChange).toHaveBeenCalledWith(testEvent);
});
});
describe('when the sortDirectionChange output on the pagination is triggered', () => {
beforeEach(() => {
spyOn(comp, 'onSortDirectionChange');
const paginationEl = fixture.debugElement.query(By.css('ds-pagination'));
paginationEl.triggerEventHandler('sortDirectionChange', testEvent);
});
it('should call onSortDirectionChange on the component', () => {
expect(comp.onSortDirectionChange).toHaveBeenCalledWith(testEvent);
});
});
describe('when the sortFieldChange output on the pagination is triggered', () => {
beforeEach(() => {
spyOn(comp, 'onSortFieldChange');
const paginationEl = fixture.debugElement.query(By.css('ds-pagination'));
paginationEl.triggerEventHandler('sortFieldChange', testEvent);
});
it('should call onSortFieldChange on the component', () => {
expect(comp.onSortFieldChange).toHaveBeenCalledWith(testEvent);
});
});
describe('when the paginationChange output on the pagination is triggered', () => {
beforeEach(() => {
spyOn(comp, 'onPaginationChange');
const paginationEl = fixture.debugElement.query(By.css('ds-pagination'));
paginationEl.triggerEventHandler('paginationChange', testEvent);
});
it('should call onPaginationChange on the component', () => {
expect(comp.onPaginationChange).toHaveBeenCalledWith(testEvent);
});
});
describe('when onPageChange is triggered with an event', () => {
beforeEach(() => {
spyOn(comp.pageChange, 'emit');
comp.onPageChange(testEvent);
});
it('should emit the value from the pageChange EventEmitter', fakeAsync(() => {
tick(1);
expect(comp.pageChange.emit).toHaveBeenCalled();
expect(comp.pageChange.emit).toHaveBeenCalledWith(testEvent);
}));
});
describe('when onPageSizeChange is triggered with an event', () => {
beforeEach(() => {
spyOn(comp.pageSizeChange, 'emit');
comp.onPageSizeChange(testEvent);
});
it('should emit the value from the pageSizeChange EventEmitter', fakeAsync(() => {
tick(1);
expect(comp.pageSizeChange.emit).toHaveBeenCalled();
expect(comp.pageSizeChange.emit).toHaveBeenCalledWith(testEvent);
}));
});
describe('when onSortDirectionChange is triggered with an event', () => {
beforeEach(() => {
spyOn(comp.sortDirectionChange, 'emit');
comp.onSortDirectionChange(testEvent);
});
it('should emit the value from the sortDirectionChange EventEmitter', fakeAsync(() => {
tick(1);
expect(comp.sortDirectionChange.emit).toHaveBeenCalled();
expect(comp.sortDirectionChange.emit).toHaveBeenCalledWith(testEvent);
}));
});
describe('when onSortFieldChange is triggered with an event', () => {
beforeEach(() => {
spyOn(comp.sortFieldChange, 'emit');
comp.onSortFieldChange(testEvent);
});
it('should emit the value from the sortFieldChange EventEmitter', fakeAsync(() => {
tick(1);
expect(comp.sortFieldChange.emit).toHaveBeenCalled();
expect(comp.sortFieldChange.emit).toHaveBeenCalledWith(testEvent);
}));
});
describe('when onPaginationChange is triggered with an event', () => {
beforeEach(() => {
spyOn(comp.paginationChange, 'emit');
comp.onPaginationChange(testEvent);
});
it('should emit the value from the paginationChange EventEmitter', fakeAsync(() => {
tick(1);
expect(comp.paginationChange.emit).toHaveBeenCalled();
expect(comp.paginationChange.emit).toHaveBeenCalledWith(testEvent);
}));
});
});

View File

@@ -24,17 +24,44 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o
templateUrl: './object-detail.component.html', templateUrl: './object-detail.component.html',
animations: [fadeIn] animations: [fadeIn]
}) })
export class ObjectDetailComponent { export class ObjectDetailComponent {
/**
* Pagination options object
*/
@Input() config: PaginationComponentOptions; @Input() config: PaginationComponentOptions;
/**
* Sort options object
*/
@Input() sortConfig: SortOptions; @Input() sortConfig: SortOptions;
@Input() hideGear = false;
/**
* A boolean representing if to hide gear pagination icon
*/
@Input() hideGear = true;
/**
* A boolean representing if to hide pagination when there is only a page
*/
@Input() hidePagerWhenSinglePage = true; @Input() hidePagerWhenSinglePage = true;
/**
* The list of objects to paginate
*/
private _objects: RemoteData<PaginatedList<ListableObject>>; private _objects: RemoteData<PaginatedList<ListableObject>>;
/**
* Setter for _objects property
* @param objects
*/
@Input() set objects(objects: RemoteData<PaginatedList<ListableObject>>) { @Input() set objects(objects: RemoteData<PaginatedList<ListableObject>>) {
this._objects = objects; this._objects = objects;
} }
/**
* Getter for _objects property
*/
get objects() { get objects() {
return this._objects; return this._objects;
} }
@@ -69,6 +96,10 @@ export class ObjectDetailComponent {
*/ */
@Output() sortDirectionChange: EventEmitter<SortDirection> = new EventEmitter<SortDirection>(); @Output() sortDirectionChange: EventEmitter<SortDirection> = new EventEmitter<SortDirection>();
/**
* An event fired when the pagination is changed.
* Event's payload equals to the newly selected sort direction.
*/
@Output() paginationChange: EventEmitter<SortDirection> = new EventEmitter<any>(); @Output() paginationChange: EventEmitter<SortDirection> = new EventEmitter<any>();
/** /**
@@ -76,23 +107,38 @@ export class ObjectDetailComponent {
* Event's payload equals to the newly selected sort field. * Event's payload equals to the newly selected sort field.
*/ */
@Output() sortFieldChange: EventEmitter<string> = new EventEmitter<string>(); @Output() sortFieldChange: EventEmitter<string> = new EventEmitter<string>();
data: any = {};
/**
* Emit pageChange event
*/
onPageChange(event) { onPageChange(event) {
this.pageChange.emit(event); this.pageChange.emit(event);
} }
/**
* Emit pageSizeChange event
*/
onPageSizeChange(event) { onPageSizeChange(event) {
this.pageSizeChange.emit(event); this.pageSizeChange.emit(event);
} }
/**
* Emit sortDirectionChange event
*/
onSortDirectionChange(event) { onSortDirectionChange(event) {
this.sortDirectionChange.emit(event); this.sortDirectionChange.emit(event);
} }
/**
* Emit sortFieldChange event
*/
onSortFieldChange(event) { onSortFieldChange(event) {
this.sortFieldChange.emit(event); this.sortFieldChange.emit(event);
} }
/**
* Emit paginationChange event
*/
onPaginationChange(event) { onPaginationChange(event) {
this.paginationChange.emit(event); this.paginationChange.emit(event);
} }

View File

@@ -1,16 +1,15 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import { RouterStub } from '../../testing/router-stub'; import { RouterStub } from '../../testing/router-stub';
import { WrapperDetailElementComponent } from './wrapper-detail-element.component';
import { WrapperGridElementComponent } from '../../object-grid/wrapper-grid-element/wrapper-grid-element.component'; let wrapperDetailElementComponent: WrapperDetailElementComponent;
let fixture: ComponentFixture<WrapperDetailElementComponent>;
let wrapperGridElementComponent: WrapperGridElementComponent;
let fixture: ComponentFixture<WrapperGridElementComponent>;
const queryParam = 'test query'; const queryParam = 'test query';
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f';
const activatedRouteStub = { const activatedRouteStub = {
@@ -20,14 +19,14 @@ const activatedRouteStub = {
}) })
}; };
describe('WrapperGridElementComponent', () => { describe('WrapperDetailElementComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ WrapperGridElementComponent ], declarations: [ WrapperDetailElementComponent ],
providers: [ providers: [
{ provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: ActivatedRoute, useValue: activatedRouteStub },
{ provide: Router, useClass: RouterStub }, { provide: Router, useClass: RouterStub },
{ provide: 'objectElementProvider', useFactory: (wrapperGridElementComponent)} { provide: 'objectElementProvider', useFactory: (WrapperDetailElementComponent)}
], ],
schemas: [ NO_ERRORS_SCHEMA ] schemas: [ NO_ERRORS_SCHEMA ]
@@ -35,12 +34,11 @@ describe('WrapperGridElementComponent', () => {
})); }));
beforeEach(async(() => { beforeEach(async(() => {
fixture = TestBed.createComponent(WrapperGridElementComponent); fixture = TestBed.createComponent(WrapperDetailElementComponent);
wrapperGridElementComponent = fixture.componentInstance; wrapperDetailElementComponent = fixture.componentInstance;
})); }));
it('should show the wrapper element containing the cards',() => { it('should show the wrapper element containing the detail object',() => {
expect(fixture.debugElement.query(By.css('ds-collection-grid-element'))).toBeDefined(); expect(fixture.debugElement.query(By.css('ds-workspaceitem-my-dspace-result-detail-element'))).toBeDefined();
}) })
}); });

View File

@@ -5,18 +5,37 @@ import { GenericConstructor } from '../../../core/shared/generic-constructor';
import { rendersDSOType } from '../../object-collection/shared/dso-element-decorator'; import { rendersDSOType } from '../../object-collection/shared/dso-element-decorator';
import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { ListableObject } from '../../object-collection/shared/listable-object.model';
/**
* This component renders a wrapper for an object in the detail view.
*/
@Component({ @Component({
selector: 'ds-wrapper-detail-element', selector: 'ds-wrapper-detail-element',
styleUrls: ['./wrapper-detail-element.component.scss'], styleUrls: ['./wrapper-detail-element.component.scss'],
templateUrl: './wrapper-detail-element.component.html' templateUrl: './wrapper-detail-element.component.html'
}) })
export class WrapperDetailElementComponent implements OnInit { export class WrapperDetailElementComponent implements OnInit {
/**
* The listable object.
*/
@Input() object: ListableObject; @Input() object: ListableObject;
/**
* The instance of the injector.
*/
objectInjector: Injector; objectInjector: Injector;
/**
* Initialize instance variables
*
* @param {Injector} injector
*/
constructor(private injector: Injector) { constructor(private injector: Injector) {
} }
/**
* Initialize injector
*/
ngOnInit(): void { ngOnInit(): void {
this.objectInjector = Injector.create({ this.objectInjector = Injector.create({
providers: [{ provide: 'objectElementProvider', useFactory: () => (this.object), deps:[] }], providers: [{ provide: 'objectElementProvider', useFactory: () => (this.object), deps:[] }],
@@ -25,6 +44,9 @@ export class WrapperDetailElementComponent implements OnInit {
} }
/**
* Return class name for the object to inject
*/
getDetailElement(): string { getDetailElement(): string {
const f: GenericConstructor<ListableObject> = this.object.constructor as GenericConstructor<ListableObject>; const f: GenericConstructor<ListableObject> = this.object.constructor as GenericConstructor<ListableObject>;
return rendersDSOType(f, ViewMode.Detail); return rendersDSOType(f, ViewMode.Detail);

View File

@@ -10,11 +10,24 @@ import { Metadata } from '../../../core/shared/metadata.utils';
selector: 'ds-my-dspace-result-list-element', selector: 'ds-my-dspace-result-list-element',
template: `` template: ``
}) })
export class MyDSpaceResultListElementComponent<T extends MyDSpaceResult<K>, K extends DSpaceObject> extends AbstractListableElementComponent<T> { export class MyDSpaceResultListElementComponent<T extends MyDSpaceResult<K>, K extends DSpaceObject> extends AbstractListableElementComponent<T> {
/**
* The result element object
*/
dso: K; dso: K;
/**
* The array index of the result element
*/
dsoIndex: number; dsoIndex: number;
/**
* Initialize instance variables
*
* @param {ListableObject} listable
* @param {number} index
*/
public constructor(@Inject('objectElementProvider') public listable: ListableObject, public constructor(@Inject('objectElementProvider') public listable: ListableObject,
@Inject('indexElementProvider') public index: number) { @Inject('indexElementProvider') public index: number) {
super(listable); super(listable);

View File

@@ -6,7 +6,7 @@ import { By } from '@angular/platform-browser';
describe('ObjectListComponent', () => { describe('ObjectListComponent', () => {
let comp: ObjectListComponent; let comp: ObjectListComponent;
let fixture: ComponentFixture<ObjectListComponent>; let fixture: ComponentFixture<ObjectListComponent>;
const testEvent = {test: 'test'} const testEvent = {test: 'test'};
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({

View File

@@ -79,7 +79,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
@Output() sortFieldChange: EventEmitter<string> = new EventEmitter<string>(); @Output() sortFieldChange: EventEmitter<string> = new EventEmitter<string>();
/** /**
* An event fired when the sort field is changed. * An event fired when the pagination is changed.
* Event's payload equals to the newly selected sort field. * Event's payload equals to the newly selected sort field.
*/ */
@Output() paginationChange: EventEmitter<any> = new EventEmitter<any>(); @Output() paginationChange: EventEmitter<any> = new EventEmitter<any>();