diff --git a/src/app/shared/browse-most-elements/browse-most-elements.component.spec.ts b/src/app/shared/browse-most-elements/browse-most-elements.component.spec.ts index c03816da90f..95fad5f05b7 100644 --- a/src/app/shared/browse-most-elements/browse-most-elements.component.spec.ts +++ b/src/app/shared/browse-most-elements/browse-most-elements.component.spec.ts @@ -1,224 +1,141 @@ -// // Load the implementations that should be tested -// import { ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -// import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync, } from '@angular/core/testing'; -// -// import { Chips } from './models/chips.model'; -// import { UploaderService } from '../uploader/uploader.service'; -// import { BrowseMostElements } from './chips.component'; -// import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -// import { By } from '@angular/platform-browser'; -// import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model'; -// import { createTestComponent } from '../testing/utils.test'; -// import { AuthorityConfidenceStateDirective } from '../authority-confidence/authority-confidence-state.directive'; -// import { TranslateModule } from '@ngx-translate/core'; -// import { ConfidenceType } from '../../core/shared/confidence-type'; -// import { SortablejsModule } from 'ngx-sortablejs'; -// import { environment } from '../../../environments/environment'; -// -// describe('ChipsComponent test suite', () => { -// -// let testComp: TestComponent; -// let chipsComp: BrowseMostElements; -// let testFixture: ComponentFixture; -// let chipsFixture: ComponentFixture; -// let html; -// let chips: Chips; -// -// // waitForAsync beforeEach -// beforeEach(waitForAsync(() => { -// -// TestBed.configureTestingModule({ -// imports: [ -// NgbModule, -// SortablejsModule.forRoot({ animation: 150 }), -// TranslateModule.forRoot() -// ], -// declarations: [ -// BrowseMostElements, -// TestComponent, -// AuthorityConfidenceStateDirective -// ], // declare the test component -// providers: [ -// ChangeDetectorRef, -// BrowseMostElements, -// UploaderService -// ], -// schemas: [CUSTOM_ELEMENTS_SCHEMA] -// }); -// -// })); -// -// describe('', () => { -// // synchronous beforeEach -// beforeEach(() => { -// html = ` -// `; -// -// testFixture = createTestComponent(html, TestComponent) as ComponentFixture; -// testComp = testFixture.componentInstance; -// }); -// -// it('should create Chips Component', inject([BrowseMostElements], (app: BrowseMostElements) => { -// expect(app).toBeDefined(); -// })); -// }); -// -// describe('when has items as string', () => { -// beforeEach(() => { -// chips = new Chips(['a', 'b', 'c']); -// chipsFixture = TestBed.createComponent(BrowseMostElements); -// chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance -// chipsComp.chips = chips; -// chipsFixture.detectChanges(); -// }); -// -// afterEach(() => { -// chipsFixture.destroy(); -// chipsComp = null; -// }); -// -// it('should emit when a chip item is removed', fakeAsync(() => { -// -// spyOn(chipsComp.chips, 'remove'); -// -// const item = chipsComp.chips.getChipByIndex(1); -// -// chipsComp.removeChips(new Event('click'), 1); -// chipsFixture.detectChanges(); -// tick(); -// -// expect(chipsComp.chips.remove).toHaveBeenCalledWith(item); -// })); -// -// it('should save chips item index when drag and drop start', fakeAsync(() => { -// const de = chipsFixture.debugElement.query(By.css('li.nav-item')); -// -// de.triggerEventHandler('dragstart', null); -// -// expect(chipsComp.dragged).toBe(0); -// })); -// -// it('should update chips item order when drag and drop end', fakeAsync(() => { -// spyOn(chipsComp.chips, 'updateOrder'); -// const de = chipsFixture.debugElement.query(By.css('li.nav-item')); -// -// de.triggerEventHandler('dragend', null); -// -// expect(chipsComp.dragged).toBe(-1); -// expect(chipsComp.chips.updateOrder).toHaveBeenCalled(); -// })); -// }); -// -// describe('when has items as object', () => { -// beforeEach(() => { -// const item = { -// mainField: new FormFieldMetadataValueObject('main test', null, 'test001', 'main test', 0, ConfidenceType.CF_ACCEPTED), -// relatedField: new FormFieldMetadataValueObject('related test', null, 'test002', 'related test', 0, ConfidenceType.CF_ACCEPTED), -// otherRelatedField: new FormFieldMetadataValueObject('other related test') -// }; -// -// chips = new Chips([item], 'display', 'mainField', environment.submission.icons.metadata); -// chipsFixture = TestBed.createComponent(BrowseMostElements); -// chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance -// chipsComp.showIcons = true; -// chipsComp.chips = chips; -// chipsFixture.detectChanges(); -// }); -// -// it('should show icon for every field that has a configured icon', () => { -// const de = chipsFixture.debugElement.query(By.css('li.nav-item')); -// const icons = de.queryAll(By.css('i.fas')); -// -// expect(icons.length).toBe(4); -// -// }); -// -// it('should show tooltip on mouse over an icon', () => { -// const de = chipsFixture.debugElement.query(By.css('li.nav-item')); -// const icons = de.queryAll(By.css('i.fas')); -// -// icons[0].triggerEventHandler('mouseover', null); -// -// expect(chipsComp.tipText).toEqual(['main test']); -// }); -// }); -// -// describe('hasWillBeGenerated', () => { -// beforeEach(() => { -// chips = new Chips([]); -// chipsFixture = TestBed.createComponent(BrowseMostElements); -// chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance -// chipsComp.chips = chips; -// chipsFixture.detectChanges(); -// }); -// -// it('should return true if authority starts with will be generated and false otherwise', () => { -// const metadata = 'dc.title'; -// let chip; -// chip = { item: { 'dc.title': { authority: 'will be generated::'}}} as any; -// expect(chipsComp.hasWillBeGenerated(chip, metadata)).toEqual(true); -// -// chip = { item: { 'dc.title': { authority: ''}}} as any; -// expect(chipsComp.hasWillBeGenerated(chip, metadata)).toEqual(false); -// }); -// -// }); -// -// describe('hasWillBeReferenced', () => { -// beforeEach(() => { -// chips = new Chips([]); -// chipsFixture = TestBed.createComponent(BrowseMostElements); -// chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance -// chipsComp.chips = chips; -// chipsFixture.detectChanges(); -// }); -// -// it('should return true if authority starts with will be referenced and false otherwise', () => { -// const metadata = 'dc.title'; -// let chip; -// chip = { item: { 'dc.title': { authority: 'will be referenced::'}}} as any; -// expect(chipsComp.hasWillBeReferenced(chip, metadata)).toEqual(true); -// -// chip = { item: { 'dc.title': { authority: ''}}} as any; -// expect(chipsComp.hasWillBeReferenced(chip, metadata)).toEqual(false); -// }); -// -// }); -// -// describe('getWillBeReferencedContent', () => { -// beforeEach(() => { -// chips = new Chips([]); -// chipsFixture = TestBed.createComponent(BrowseMostElements); -// chipsComp = chipsFixture.componentInstance; // TruncatableComponent test instance -// chipsComp.chips = chips; -// chipsFixture.detectChanges(); -// }); -// -// it('should return the value of the reference if present, null otherwise', () => { -// const metadata = 'dc.title'; -// let chip; -// chip = { item: { 'dc.title': { authority: 'will be referenced::ORCID::0000'}}} as any; -// expect(chipsComp.getWillBeReferencedContent(chip, metadata)).toEqual('ORCID::0000'); -// -// chip = { item: { 'dc.title': { authority: ''}}} as any; -// expect(chipsComp.getWillBeReferencedContent(chip, metadata)).toEqual(null); -// }); -// -// }); -// -// }); -// -// // declare a test component -// @Component({ -// selector: 'ds-test-cmp', -// template: `` -// }) -// class TestComponent { -// -// public chips = new Chips(['a', 'b', 'c']); -// public editable = true; -// } +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { BrowseMostElementsComponent } from './browse-most-elements.component'; +import { SearchService } from '../../core/shared/search/search.service'; +import { of } from 'rxjs'; +import { PaginatedSearchOptions } from '../search/models/paginated-search-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { APP_CONFIG } from '../../../config/app-config.interface'; +import { ItemSearchResult } from '../object-collection/shared/item-search-result.model'; +import { Item } from '../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; +import { buildPaginatedList } from '../../core/data/paginated-list.model'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { followLink } from '../utils/follow-link-config.model'; + +describe('BrowseMostElementsComponent', () => { + let component: BrowseMostElementsComponent; + let fixture: ComponentFixture; + + + const mockResultObject: ItemSearchResult = new ItemSearchResult(); + mockResultObject.hitHighlights = {}; + + mockResultObject.indexableObject = Object.assign(new Item(), { + bundles: of({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } + }); + const mockResponse = createSuccessfulRemoteDataObject(buildPaginatedList(new PageInfo(), [mockResultObject])); + + const mockSearchService = { + search: jasmine.createSpy('search').and.returnValue(of(mockResponse)), // Replace with your desired response + }; + + const mockConfig = { + browseBy: { + showThumbnails: true + } + }; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [BrowseMostElementsComponent], + providers: [ + { provide: APP_CONFIG, useValue: mockConfig }, + { provide: SearchService, useValue: mockSearchService }, + { provide: ChangeDetectorRef, useValue: {} }, + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], // Ignore unknown Angular elements + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BrowseMostElementsComponent); + component = fixture.componentInstance; + component.paginatedSearchOptions = new PaginatedSearchOptions({ + configuration: 'test', + pagination: Object.assign(new PaginationComponentOptions(), { + id: 'search-object-pagination', + pageSize: 5, + currentPage: 1 + }), + sort: new SortOptions('dc.title', SortDirection.ASC) + }); + }); + + it('should create', () => { + component.showThumbnails = true; + fixture.detectChanges(); + expect(component).toBeTruthy(); + }); + + it('should call searchService.search on ngOnInit with followLinks', () => { + component.showThumbnails = true; + fixture.detectChanges(); + + expect(mockSearchService.search).toHaveBeenCalledWith( + component.paginatedSearchOptions, + null, + true, + true, + followLink('thumbnail') + ); + }); + + it('should call searchService.search on ngOnInit with followLinks', () => { + component.showThumbnails = undefined; + fixture.detectChanges(); + + expect(mockSearchService.search).toHaveBeenCalledWith( + component.paginatedSearchOptions, + null, + true, + true, + followLink('thumbnail') + ); + }); + + it('should call searchService.search on ngOnInit without followLinks', () => { + component.showThumbnails = false; + fixture.detectChanges(); + + expect(mockSearchService.search).toHaveBeenCalledWith( + component.paginatedSearchOptions, + null, + true, + true + ); + }); + + it('should update searchResults after searchService response', () => { + component.ngOnInit(); + + expect(component.searchResults).toEqual(mockResponse); + }); +}); diff --git a/src/app/shared/browse-most-elements/browse-most-elements.component.ts b/src/app/shared/browse-most-elements/browse-most-elements.component.ts index 407cd912ae8..63af28ad53c 100644 --- a/src/app/shared/browse-most-elements/browse-most-elements.component.ts +++ b/src/app/shared/browse-most-elements/browse-most-elements.component.ts @@ -1,4 +1,5 @@ -import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, Inject, Input, OnInit } from '@angular/core'; + import { SearchService } from '../../core/shared/search/search.service'; import { PaginatedSearchOptions } from '../search/models/paginated-search-options.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; @@ -7,11 +8,13 @@ import { Context } from '../../core/shared/context.model'; import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { followLink } from '../utils/follow-link-config.model'; +import { APP_CONFIG, AppConfig } from '../../../config/app-config.interface'; @Component({ selector: 'ds-browse-most-elements', styleUrls: ['./browse-most-elements.component.scss'], - templateUrl: './browse-most-elements.component.html', + templateUrl: './browse-most-elements.component.html' }) export class BrowseMostElementsComponent implements OnInit { @@ -32,11 +35,17 @@ export class BrowseMostElementsComponent implements OnInit { searchResults: RemoteData>>; - constructor(private searchService: SearchService, private cdr: ChangeDetectorRef) { /* */ } + constructor( + @Inject(APP_CONFIG) protected appConfig: AppConfig, + private searchService: SearchService, + private cdr: ChangeDetectorRef) { - ngOnInit() { + } - this.searchService.search(this.paginatedSearchOptions).pipe( + ngOnInit() { + const showThumbnails = this.showThumbnails ?? this.appConfig.browseBy.showThumbnails; + const followLinks = showThumbnails ? [followLink('thumbnail')] : []; + this.searchService.search(this.paginatedSearchOptions, null, true, true, ...followLinks).pipe( getFirstCompletedRemoteData(), ).subscribe((response: RemoteData>>) => { this.searchResults = response as any; diff --git a/src/app/shared/utils/safe-url-pipe.ts b/src/app/shared/utils/safe-url-pipe.ts index 3f35ed92627..c3b8db62ce1 100644 --- a/src/app/shared/utils/safe-url-pipe.ts +++ b/src/app/shared/utils/safe-url-pipe.ts @@ -10,6 +10,6 @@ import { DomSanitizer } from '@angular/platform-browser'; export class SafeUrlPipe implements PipeTransform { constructor(private domSanitizer: DomSanitizer) { } transform(url) { - return this.domSanitizer.bypassSecurityTrustResourceUrl(url); + return url == null ? null : this.domSanitizer.bypassSecurityTrustResourceUrl(url); } }