diff --git a/src/app/core/data/external-source.service.spec.ts b/src/app/core/data/external-source.service.spec.ts new file mode 100644 index 0000000000..77a2a85dfd --- /dev/null +++ b/src/app/core/data/external-source.service.spec.ts @@ -0,0 +1,76 @@ +import { ExternalSourceService } from './external-source.service'; +import { createPaginatedList, createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { ExternalSourceEntry } from '../shared/external-source-entry.model'; +import { of as observableOf } from 'rxjs'; +import { GetRequest } from './request.models'; + +describe('ExternalSourceService', () => { + let service: ExternalSourceService; + + let requestService; + let rdbService; + let halService; + + const entries = [ + Object.assign(new ExternalSourceEntry(), { + id: '0001-0001-0001-0001', + display: 'John Doe', + value: 'John, Doe', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0001' + } + ] + } + }), + Object.assign(new ExternalSourceEntry(), { + id: '0001-0001-0001-0002', + display: 'Sampson Megan', + value: 'Sampson, Megan', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0002' + } + ] + } + }) + ]; + + function init() { + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: 'request-uuid', + configure: {} + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildList: createSuccessfulRemoteDataObject$(createPaginatedList(entries)) + }); + halService = jasmine.createSpyObj('halService', { + getEndpoint: observableOf('external-sources-REST-endpoint') + }); + service = new ExternalSourceService(requestService, rdbService, undefined, undefined, undefined, halService, undefined, undefined, undefined); + } + + beforeEach(() => { + init(); + }); + + describe('getExternalSourceEntries', () => { + let result; + + beforeEach(() => { + result = service.getExternalSourceEntries('test'); + }); + + it('should configure a GetRequest', () => { + expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(GetRequest)); + }); + + it('should return the entries', () => { + result.subscribe((resultRD) => { + expect(resultRD.payload.page).toBe(entries); + }); + }); + }); +}); diff --git a/src/app/core/data/lookup-relation.service.spec.ts b/src/app/core/data/lookup-relation.service.spec.ts new file mode 100644 index 0000000000..5ac29b5030 --- /dev/null +++ b/src/app/core/data/lookup-relation.service.spec.ts @@ -0,0 +1,110 @@ +import { LookupRelationService } from './lookup-relation.service'; +import { ExternalSourceService } from './external-source.service'; +import { SearchService } from '../shared/search/search.service'; +import { createPaginatedList, createSuccessfulRemoteDataObject$ } from '../../shared/testing/utils'; +import { PaginatedList } from './paginated-list'; +import { PageInfo } from '../shared/page-info.model'; +import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; +import { RelationshipOptions } from '../../shared/form/builder/models/relationship-options.model'; +import { SearchResult } from '../../shared/search/search-result.model'; +import { Item } from '../shared/item.model'; +import { skip, take } from 'rxjs/operators'; + +describe('LookupRelationService', () => { + let service: LookupRelationService; + let externalSourceService: ExternalSourceService; + let searchService: SearchService; + + const totalExternal = 8; + const optionsWithQuery = new PaginatedSearchOptions({ query: 'test-query' }); + const relationship = Object.assign(new RelationshipOptions(), { + filter: 'test-filter', + configuration: 'test-configuration' + }); + const localResults = [ + Object.assign(new SearchResult(), { + indexableObject: Object.assign(new Item(), { + uuid: 'test-item-uuid', + handle: 'test-item-handle' + }) + }) + ]; + + function init() { + externalSourceService = jasmine.createSpyObj('externalSourceService', { + getExternalSourceEntries: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: totalExternal, totalPages: totalExternal, currentPage: 1 }), [{}])) + }); + searchService = jasmine.createSpyObj('searchService', { + search: createSuccessfulRemoteDataObject$(createPaginatedList(localResults)) + }); + service = new LookupRelationService(externalSourceService, searchService); + } + + beforeEach(() => { + init(); + }); + + describe('getLocalResults', () => { + let result; + + beforeEach(() => { + result = service.getLocalResults(relationship, optionsWithQuery); + }); + + it('should return the local results', () => { + result.subscribe((resultsRD) => { + expect(resultsRD.payload.page).toBe(localResults); + }); + }); + + it('should set the searchConfig to contain a fixedFilter and configuration', () => { + expect(service.searchConfig).toEqual(Object.assign(new PaginatedSearchOptions({}), optionsWithQuery, + { fixedFilter: relationship.filter, configuration: relationship.searchConfiguration } + )); + }); + }); + + describe('getTotalLocalResults', () => { + let result; + + beforeEach(() => { + result = service.getTotalLocalResults(relationship, optionsWithQuery); + }); + + it('should start with 0', () => { + result.pipe(take(1)).subscribe((amount) => { + expect(amount).toEqual(0) + }); + }); + + it('should return the correct total amount', () => { + result.pipe(skip(1)).subscribe((amount) => { + expect(amount).toEqual(localResults.length) + }); + }); + + it('should not set searchConfig', () => { + expect(service.searchConfig).toBeUndefined(); + }); + }); + + describe('getTotalExternalResults', () => { + let result; + + beforeEach(() => { + result = service.getTotalExternalResults(relationship, optionsWithQuery); + }); + + it('should start with 0', () => { + result.pipe(take(1)).subscribe((amount) => { + expect(amount).toEqual(0) + }); + }); + + it('should return the correct total amount', () => { + result.pipe(skip(1)).subscribe((amount) => { + expect(amount).toEqual(totalExternal) + }); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.spec.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.spec.ts new file mode 100644 index 0000000000..fa153b8c5e --- /dev/null +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.spec.ts @@ -0,0 +1,47 @@ +import { ExternalSourceEntryListSubmissionElementComponent } from './external-source-entry-list-submission-element.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ExternalSourceEntry } from '../../../../../core/shared/external-source-entry.model'; +import { TranslateModule } from '@ngx-translate/core'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; + +describe('ExternalSourceEntryListSubmissionElementComponent', () => { + let component: ExternalSourceEntryListSubmissionElementComponent; + let fixture: ComponentFixture; + + const uri = 'https://orcid.org/0001-0001-0001-0001'; + const entry = Object.assign(new ExternalSourceEntry(), { + id: '0001-0001-0001-0001', + display: 'John Doe', + value: 'John, Doe', + metadata: { + 'dc.identifier.uri': [ + { + value: uri + } + ] + } + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ExternalSourceEntryListSubmissionElementComponent], + imports: [TranslateModule.forRoot()], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExternalSourceEntryListSubmissionElementComponent); + component = fixture.componentInstance; + component.object = entry; + fixture.detectChanges(); + }); + + it('should display the entry\'s display value', () => { + expect(fixture.nativeElement.textContent).toContain(entry.display); + }); + + it('should display the entry\'s uri', () => { + expect(fixture.nativeElement.textContent).toContain(uri); + }); +}); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.spec.ts index a4f77fd364..d1b289bf11 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.spec.ts @@ -13,6 +13,12 @@ import { Item } from '../../../../../core/shared/item.model'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; import { RelationshipOptions } from '../../models/relationship-options.model'; import { AddRelationshipAction, RemoveRelationshipAction } from './relationship.actions'; +import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service'; +import { PaginatedSearchOptions } from '../../../../search/paginated-search-options.model'; +import { ExternalSource } from '../../../../../core/shared/external-source.model'; +import { createPaginatedList, createSuccessfulRemoteDataObject$ } from '../../../../testing/utils'; +import { ExternalSourceService } from '../../../../../core/data/external-source.service'; +import { LookupRelationService } from '../../../../../core/data/lookup-relation.service'; describe('DsDynamicLookupRelationModalComponent', () => { let component: DsDynamicLookupRelationModalComponent; @@ -28,6 +34,24 @@ describe('DsDynamicLookupRelationModalComponent', () => { let relationship; let nameVariant; let metadataField; + let pSearchOptions; + let externalSourceService; + let lookupRelationService; + + const externalSources = [ + Object.assign(new ExternalSource(), { + id: 'orcidV2', + name: 'orcidV2', + hierarchical: false + }), + Object.assign(new ExternalSource(), { + id: 'sherpaPublisher', + name: 'sherpaPublisher', + hierarchical: false + }) + ]; + const totalLocal = 10; + const totalExternal = 8; function init() { item = Object.assign(new Item(), { uuid: '7680ca97-e2bd-4398-bfa7-139a8673dc42', metadata: {} }); @@ -41,6 +65,14 @@ describe('DsDynamicLookupRelationModalComponent', () => { relationship = { filter: 'filter', relationshipType: 'isAuthorOfPublication', nameVariants: true } as RelationshipOptions; nameVariant = 'Doe, J.'; metadataField = 'dc.contributor.author'; + pSearchOptions = new PaginatedSearchOptions({}); + externalSourceService = jasmine.createSpyObj('externalSourceService', { + findAll: createSuccessfulRemoteDataObject$(createPaginatedList(externalSources)) + }); + lookupRelationService = jasmine.createSpyObj('lookupRelationService', { + getTotalLocalResults: observableOf(totalLocal), + getTotalExternalResults: observableOf(totalExternal) + }); } beforeEach(async(() => { @@ -49,6 +81,13 @@ describe('DsDynamicLookupRelationModalComponent', () => { declarations: [DsDynamicLookupRelationModalComponent], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NgbModule.forRoot()], providers: [ + { + provide: SearchConfigurationService, useValue: { + paginatedSearchOptions: observableOf(pSearchOptions) + } + }, + { provide: ExternalSourceService, useValue: externalSourceService }, + { provide: LookupRelationService, useValue: lookupRelationService }, { provide: SelectableListService, useValue: selectableListService }, diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html index 6b66be97c4..9536d0a5cb 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html @@ -8,7 +8,7 @@

{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + externalSource.id | translate}}

- -
+
{{ 'search.results.empty' | translate }}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts new file mode 100644 index 0000000000..62327e236e --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts @@ -0,0 +1,162 @@ +import { DsDynamicLookupRelationExternalSourceTabComponent } from './dynamic-lookup-relation-external-source-tab.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { VarDirective } from '../../../../../utils/var.directive'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model'; +import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { + createFailedRemoteDataObject$, + createPaginatedList, + createPendingRemoteDataObject$, + createSuccessfulRemoteDataObject$ +} from '../../../../../testing/utils'; +import { ExternalSourceService } from '../../../../../../core/data/external-source.service'; +import { ExternalSource } from '../../../../../../core/shared/external-source.model'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { By } from '@angular/platform-browser'; +import { ExternalSourceEntry } from '../../../../../../core/shared/external-source-entry.model'; + +describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { + let component: DsDynamicLookupRelationExternalSourceTabComponent; + let fixture: ComponentFixture; + let pSearchOptions; + let externalSourceService; + + const externalSource = { + id: 'orcidV2', + name: 'orcidV2', + hierarchical: false + } as ExternalSource; + const externalEntries = [ + Object.assign({ + id: '0001-0001-0001-0001', + display: 'John Doe', + value: 'John, Doe', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0001' + } + ] + } + }), + Object.assign({ + id: '0001-0001-0001-0002', + display: 'Sampson Megan', + value: 'Sampson, Megan', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0002' + } + ] + } + }), + Object.assign({ + id: '0001-0001-0001-0003', + display: 'Edwards Anna', + value: 'Edwards, Anna', + metadata: { + 'dc.identifier.uri': [ + { + value: 'https://orcid.org/0001-0001-0001-0003' + } + ] + } + }) + ] as ExternalSourceEntry[]; + + function init() { + pSearchOptions = new PaginatedSearchOptions({ + query: 'test' + }); + externalSourceService = jasmine.createSpyObj('externalSourceService', { + getExternalSourceEntries: createSuccessfulRemoteDataObject$(createPaginatedList(externalEntries)) + }); + } + + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + declarations: [DsDynamicLookupRelationExternalSourceTabComponent, VarDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), BrowserAnimationsModule], + providers: [ + { + provide: SearchConfigurationService, useValue: { + paginatedSearchOptions: observableOf(pSearchOptions) + } + }, + { provide: ExternalSourceService, useValue: externalSourceService } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DsDynamicLookupRelationExternalSourceTabComponent); + component = fixture.componentInstance; + component.externalSource = externalSource; + fixture.detectChanges(); + }); + + describe('when the external entries finished loading successfully', () => { + it('should display a ds-viewable-collection component', () => { + const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(collection).toBeDefined(); + }); + }); + + describe('when the external entries are loading', () => { + beforeEach(() => { + component.entriesRD$ = createPendingRemoteDataObject$(undefined); + fixture.detectChanges(); + }); + + it('should not display a ds-viewable-collection component', () => { + const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(collection).toBeNull(); + }); + + it('should display a ds-loading component', () => { + const loading = fixture.debugElement.query(By.css('ds-loading')); + expect(loading).not.toBeNull(); + }); + }); + + describe('when the external entries failed loading', () => { + beforeEach(() => { + component.entriesRD$ = createFailedRemoteDataObject$(undefined); + fixture.detectChanges(); + }); + + it('should not display a ds-viewable-collection component', () => { + const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(collection).toBeNull(); + }); + + it('should display a ds-error component', () => { + const error = fixture.debugElement.query(By.css('ds-error')); + expect(error).not.toBeNull(); + }); + }); + + describe('when the external entries return an empty list', () => { + beforeEach(() => { + component.entriesRD$ = createSuccessfulRemoteDataObject$(createPaginatedList([])); + fixture.detectChanges(); + }); + + it('should not display a ds-viewable-collection component', () => { + const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(collection).toBeNull(); + }); + + it('should display a message the list is empty', () => { + const empty = fixture.debugElement.query(By.css('#empty-external-entry-list')); + expect(empty).not.toBeNull(); + }); + }); +}); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts index 241d022dc3..3d713b15fe 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.spec.ts @@ -15,6 +15,8 @@ import { createSuccessfulRemoteDataObject$ } from '../../../../../testing/utils' import { PaginatedList } from '../../../../../../core/data/paginated-list'; import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; import { Item } from '../../../../../../core/shared/item.model'; +import { ActivatedRoute } from '@angular/router'; +import { LookupRelationService } from '../../../../../../core/data/lookup-relation.service'; describe('DsDynamicLookupRelationSearchTabComponent', () => { let component: DsDynamicLookupRelationSearchTabComponent; @@ -32,6 +34,7 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { let results; let selectableListService; + let lookupRelationService; function init() { relationship = { filter: 'filter', relationshipType: 'isAuthorOfPublication', nameVariants: true } as RelationshipOptions; @@ -47,6 +50,10 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { results = new PaginatedList(undefined, [searchResult1, searchResult2, searchResult3]); selectableListService = jasmine.createSpyObj('selectableListService', ['deselect', 'select', 'deselectAll']); + lookupRelationService = jasmine.createSpyObj('lookupRelationService', { + getLocalResults: createSuccessfulRemoteDataObject$(results) + }); + lookupRelationService.searchConfig = {}; } beforeEach(async(() => { @@ -71,6 +78,8 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => { } } }, + { provide: ActivatedRoute, useValue: { snapshot: { queryParams: {} } } }, + { provide: LookupRelationService, useValue: lookupRelationService } ], schemas: [NO_ERRORS_SCHEMA] })