diff --git a/src/app/admin/admin-notify-dashboard/admin-notify-metrics/admin-notify-metrics.component.spec.ts b/src/app/admin/admin-notify-dashboard/admin-notify-metrics/admin-notify-metrics.component.spec.ts index bf3a86ec2e..57f21a4ef3 100644 --- a/src/app/admin/admin-notify-dashboard/admin-notify-metrics/admin-notify-metrics.component.spec.ts +++ b/src/app/admin/admin-notify-dashboard/admin-notify-metrics/admin-notify-metrics.component.spec.ts @@ -2,18 +2,30 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AdminNotifyMetricsComponent } from './admin-notify-metrics.component'; import { TranslateModule } from '@ngx-translate/core'; +import { Router } from '@angular/router'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { RouterStub } from '../../../shared/testing/router.stub'; describe('AdminNotifyMetricsComponent', () => { let component: AdminNotifyMetricsComponent; let fixture: ComponentFixture; + let router: RouterStub; beforeEach(async () => { + router = Object.assign(new RouterStub(), + {url : '/notify-dashboard'} + ); + + await TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], - declarations: [ AdminNotifyMetricsComponent ] + declarations: [ AdminNotifyMetricsComponent ], + providers: [{provide: Router, useValue: router}] }) .compileComponents(); + + fixture = TestBed.createComponent(AdminNotifyMetricsComponent); component = fixture.componentInstance; fixture.detectChanges(); @@ -22,4 +34,38 @@ describe('AdminNotifyMetricsComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + it('should navigate to correct url based on config', () => { + const searchConfig = 'test.involvedItems'; + const incomingConfig = 'NOTIFY.incoming.test'; + const outgoingConfig = 'NOTIFY.outgoing.test'; + const adminPath = '/admin/search'; + const routeExtras = { + queryParams: { + configuration: searchConfig, + view: ViewMode.ListElement + }, + }; + + const routeExtrasTable = { + queryParams: { + configuration: incomingConfig, + view: ViewMode.Table + }, + }; + + const routeExtrasTableOutgoing = { + queryParams: { + configuration: outgoingConfig, + view: ViewMode.Table + }, + }; + component.navigateToSelectedSearchConfig(searchConfig); + expect(router.navigate).toHaveBeenCalledWith([adminPath], routeExtras); + + component.navigateToSelectedSearchConfig(incomingConfig); + expect(router.navigate).toHaveBeenCalledWith(['/notify-dashboard/inbound'], routeExtrasTable); + + component.navigateToSelectedSearchConfig(outgoingConfig); + expect(router.navigate).toHaveBeenCalledWith(['/notify-dashboard/outbound'], routeExtrasTableOutgoing); + }); }); diff --git a/src/app/notifications/reciter-suggestions/suggestion.service.spec.ts b/src/app/notifications/reciter-suggestions/suggestion.service.spec.ts new file mode 100644 index 0000000000..1803cb948e --- /dev/null +++ b/src/app/notifications/reciter-suggestions/suggestion.service.spec.ts @@ -0,0 +1,190 @@ +import { SuggestionsService } from './suggestions.service'; +import { AuthService } from '../../core/auth/auth.service'; +import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service'; + +import { TestScheduler } from 'rxjs/testing'; +import { getTestScheduler } from 'jasmine-marbles'; +import { of as observableOf } from 'rxjs'; +import { FindListOptions } from '../../core/data/find-list-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { ResearcherProfile } from '../../core/profile/model/researcher-profile.model'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +import { mockSuggestionPublicationOne } from '../../shared/mocks/reciter-suggestion.mock'; +import { ResourceType } from '../../core/shared/resource-type'; +import { SuggestionsDataService } from '../../core/notifications/reciter-suggestions/suggestions-data.service'; +import { + SuggestionSourceDataService +} from '../../core/notifications/reciter-suggestions/source/suggestion-source-data.service'; +import { + SuggestionTargetDataService +} from '../../core/notifications/reciter-suggestions/target/suggestion-target-data.service'; +import { SuggestionTarget } from '../../core/notifications/reciter-suggestions/models/suggestion-target.model'; + + +describe('SuggestionsService test', () => { + let scheduler: TestScheduler; + let service: SuggestionsService; + let authService: AuthService; + let researcherProfileService: ResearcherProfileDataService; + let suggestionsDataService: SuggestionsDataService; + let suggestionSourceDataService: SuggestionSourceDataService; + let suggestionTargetDataService: SuggestionTargetDataService; + let translateService: any = { + instant: (str) => str, + }; + const suggestionTarget = { + id: '1234:4321', + display: 'display', + source: 'source', + total: 8, + type: new ResourceType('suggestiontarget') + }; + + const mockResercherProfile = { + id: '1234', + uuid: '1234', + visible: true + }; + + function initTestService() { + return new SuggestionsService( + authService, + researcherProfileService, + suggestionsDataService, + suggestionSourceDataService, + suggestionTargetDataService, + translateService + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + + suggestionSourceDataService = jasmine.createSpyObj('suggestionSourcesDataService', { + getSources: observableOf(null), + }); + + researcherProfileService = jasmine.createSpyObj('researcherProfileService', { + findById: createSuccessfulRemoteDataObject$(mockResercherProfile as ResearcherProfile), + findRelatedItemId: observableOf('1234'), + }); + + suggestionTargetDataService = jasmine.createSpyObj('suggestionTargetsDataService', { + getTargets: observableOf(null), + findById: observableOf(null), + }); + + suggestionsDataService = jasmine.createSpyObj('suggestionsDataService', { + searchBy: observableOf(null), + delete: observableOf(null), + deleteSuggestion: createSuccessfulRemoteDataObject$({}), + getSuggestionsByTargetAndSource : observableOf(null), + clearSuggestionRequests : null, + getTargetsByUser: observableOf(null), + }); + + service = initTestService(); + + }); + + describe('Suggestion service', () => { + it('should create', () => { + expect(service).toBeDefined(); + }); + + it('should get targets', () => { + const sortOptions = new SortOptions('display', SortDirection.ASC); + const findListOptions: FindListOptions = { + elementsPerPage: 10, + currentPage: 1, + sort: sortOptions + }; + service.getTargets('source', 10, 1); + expect(suggestionTargetDataService.getTargets).toHaveBeenCalledWith('source', findListOptions); + }); + + it('should get suggestions', () => { + const sortOptions = new SortOptions('display', SortDirection.ASC); + const findListOptions: FindListOptions = { + elementsPerPage: 10, + currentPage: 1, + sort: sortOptions + }; + service.getSuggestions('source:target', 10, 1, sortOptions); + expect(suggestionsDataService.getSuggestionsByTargetAndSource).toHaveBeenCalledWith('target', 'source', findListOptions); + }); + + it('should clear suggestions', () => { + service.clearSuggestionRequests(); + expect(suggestionsDataService.clearSuggestionRequests).toHaveBeenCalled(); + }); + + it('should delete reviewed suggestion', () => { + service.deleteReviewedSuggestion('1234'); + expect(suggestionsDataService.deleteSuggestion).toHaveBeenCalledWith('1234'); + }); + + it('should retrieve current user suggestions', () => { + service.retrieveCurrentUserSuggestions('1234'); + expect(researcherProfileService.findById).toHaveBeenCalledWith('1234'); + }); + + it('should approve and import suggestion', () => { + spyOn(service, 'resolveCollectionId'); + const workspaceitemService = {importExternalSourceEntry: (x,y) => observableOf(null)}; + service.approveAndImport(workspaceitemService as unknown as WorkspaceitemDataService, mockSuggestionPublicationOne, '1234'); + expect(service.resolveCollectionId).toHaveBeenCalled(); + }); + + it('should approve and import suggestions', () => { + spyOn(service, 'approveAndImport'); + const workspaceitemService = {importExternalSourceEntry: (x,y) => observableOf(null)}; + service.approveAndImportMultiple(workspaceitemService as unknown as WorkspaceitemDataService, [mockSuggestionPublicationOne], '1234'); + expect(service.approveAndImport).toHaveBeenCalledWith(workspaceitemService as unknown as WorkspaceitemDataService, mockSuggestionPublicationOne, '1234'); + }); + + it('should delete suggestion', () => { + spyOn(service, 'deleteReviewedSuggestion').and.returnValue(createSuccessfulRemoteDataObject$({})); + service.notMine('1234'); + expect(service.deleteReviewedSuggestion).toHaveBeenCalledWith('1234'); + }); + + it('should delete suggestions', () => { + spyOn(service, 'notMine'); + service.notMineMultiple([mockSuggestionPublicationOne]); + expect(service.notMine).toHaveBeenCalledWith(mockSuggestionPublicationOne.id); + }); + + it('should get target Uuid', () => { + expect(service.getTargetUuid(suggestionTarget as SuggestionTarget)).toBe('4321'); + expect(service.getTargetUuid({id: ''} as SuggestionTarget)).toBe(null); + }); + + it('should get suggestion interpolation', () => { + const result = service.getNotificationSuggestionInterpolation(suggestionTarget as SuggestionTarget); + expect(result.count).toEqual(suggestionTarget.total); + expect(result.source).toEqual('reciter.suggestion.source.' + suggestionTarget.source); + expect(result.type).toEqual('reciter.suggestion.type.' + suggestionTarget.source); + expect(result.suggestionId).toEqual(suggestionTarget.id); + expect(result.displayName).toEqual(suggestionTarget.display); + }); + + it('should translate suggestion type', () => { + expect(service.translateSuggestionType('source')).toEqual('reciter.suggestion.type.source'); + }); + + it('should translate suggestion source', () => { + expect(service.translateSuggestionSource('source')).toEqual('reciter.suggestion.source.source'); + }); + + it('should resolve collection id', () => { + expect(service.resolveCollectionId(mockSuggestionPublicationOne, '1234')).toEqual('1234'); + }); + + it('should check if collection is fixed', () => { + expect(service.isCollectionFixed([mockSuggestionPublicationOne])).toBeFalse(); + }); + }); +}); diff --git a/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.spec.ts b/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.spec.ts index a887482fa7..e500bbe9f3 100644 --- a/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.spec.ts +++ b/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.spec.ts @@ -1,4 +1,4 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { TabulatableObjectsLoaderComponent } from './tabulatable-objects-loader.component'; import { ThemeService } from '../../../theme-support/theme.service'; @@ -14,8 +14,13 @@ import { TabulatableResultListElementsComponent } from '../../../object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component'; import { TestType } from '../listable-object/listable-object-component-loader.component.spec'; +import { By } from '@angular/platform-browser'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; + const testType = 'TestType'; +const testContext = Context.CoarNotify; +const testViewMode = ViewMode.Table; class TestTypes extends PaginatedList { page: TestType[] = [new TestType()]; @@ -48,12 +53,55 @@ describe('TabulatableObjectsLoaderComponent', () => { fixture = TestBed.createComponent(TabulatableObjectsLoaderComponent); component = fixture.componentInstance; component.objects = new TestTypes(); - component.context = Context.Search; + component.context = Context.CoarNotify; spyOn(component, 'getComponent').and.returnValue(TabulatableResultListElementsComponent as any); + spyOn(component as any, 'connectInputsAndOutputs').and.callThrough(); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + describe('When the component is rendered', () => { + it('should call the getTabulatableObjectComponent function with the right types, view mode and context', () => { + expect(component.getComponent).toHaveBeenCalledWith([testType], testViewMode, testContext); + }); + + it('should connectInputsAndOutputs of loaded component', () => { + expect((component as any).connectInputsAndOutputs).toHaveBeenCalled(); + }); + }); + + describe('When a reloadedObject is emitted', () => { + let tabulatableComponent; + let reloadedObject: any; + + beforeEach(() => { + spyOn((component as any), 'instantiateComponent').and.returnValue(null); + spyOn((component as any).contentChange, 'emit').and.returnValue(null); + + tabulatableComponent = fixture.debugElement.query(By.css('ds-search-result-table-element')).componentInstance; + reloadedObject = 'object'; + }); + + it('should re-instantiate the listable component', fakeAsync(() => { + expect((component as any).instantiateComponent).not.toHaveBeenCalled(); + + (tabulatableComponent as any).reloadedObject.emit(reloadedObject); + tick(200); + + expect((component as any).instantiateComponent).toHaveBeenCalledWith(reloadedObject, undefined); + })); + + it('should re-emit it as a contentChange', fakeAsync(() => { + expect((component as any).contentChange.emit).not.toHaveBeenCalled(); + + (tabulatableComponent as any).reloadedObject.emit(reloadedObject); + tick(200); + + expect((component as any).contentChange.emit).toHaveBeenCalledWith(reloadedObject); + })); + + }); }); diff --git a/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.ts b/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.ts index fa57c1200d..323be3242f 100644 --- a/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.ts +++ b/src/app/shared/object-collection/shared/tabulatable-objects/tabulatable-objects-loader.component.ts @@ -39,7 +39,7 @@ export class TabulatableObjectsLoaderComponent implements OnInit, OnChanges, OnD /** - * The context of listable object + * The context of tabulatable object */ @Input() context: Context; diff --git a/src/app/shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component.ts b/src/app/shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component.ts index 94d132f822..f4b5694056 100644 --- a/src/app/shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component.ts +++ b/src/app/shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component.ts @@ -6,7 +6,7 @@ import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { SearchResult } from '../../../search/models/search-result.model'; @Component({ - selector: 'ds-search-result-list-element', + selector: 'ds-search-result-table-element', template: `` }) export class TabulatableResultListElementsComponent, K extends SearchResult> extends AbstractTabulatableElementComponent {} diff --git a/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.spec.ts b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.spec.ts new file mode 100644 index 0000000000..ecb8a2a61d --- /dev/null +++ b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.spec.ts @@ -0,0 +1,92 @@ +import { CoarNotifyConfigDataService } from './coar-notify-config-data.service'; +import { testFindAllDataImplementation } from '../../../core/data/base/find-all-data.spec'; +import { FindAllData } from '../../../core/data/base/find-all-data'; +import { cold, getTestScheduler } from 'jasmine-marbles'; +import { ObjectCacheService } from '../../../core/cache/object-cache.service'; +import { TestScheduler } from 'rxjs/testing'; +import { RequestService } from '../../../core/data/request.service'; +import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service'; +import { HALEndpointService } from '../../../core/shared/hal-endpoint.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { RequestEntry } from '../../../core/data/request-entry.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { RequestEntryState } from '../../../core/data/request-entry-state.model'; +import { RestResponse } from '../../../core/cache/response.models'; +import { of } from 'rxjs'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { testPatchDataImplementation } from '../../../core/data/base/patch-data.spec'; +import { testDeleteDataImplementation } from '../../../core/data/base/delete-data.spec'; +import { DeleteData } from '../../../core/data/base/delete-data'; +import { PatchData } from '../../../core/data/base/patch-data'; +import { CreateData } from '../../../core/data/base/create-data'; +import { testCreateDataImplementation } from '../../../core/data/base/create-data.spec'; + +describe('CoarNotifyConfigDataService test', () => { + let scheduler: TestScheduler; + let service: CoarNotifyConfigDataService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let notificationsService: NotificationsService; + let responseCacheEntry: RequestEntry; + + const endpointURL = `https://rest.api/rest/api/coar-notify`; + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + const remoteDataMocks = { + Success: new RemoteData(null, null, null, RequestEntryState.Success, null, null, 200), + }; + + function initTestService() { + return new CoarNotifyConfigDataService( + requestService, + rdbService, + objectCache, + halService, + notificationsService + ); + } + + beforeEach(() => { + scheduler = getTestScheduler(); + + objectCache = {} as ObjectCacheService; + notificationsService = {} as NotificationsService; + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: of(responseCacheEntry), + getByUUID: of(responseCacheEntry), + }); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: of(endpointURL) + }); + + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: createSuccessfulRemoteDataObject$({}, 500), + buildList: cold('a', { a: remoteDataMocks.Success }) + }); + + + service = initTestService(); + }); + + describe('composition', () => { + const initCreateService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as CreateData; + const initFindAllService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as FindAllData; + const initDeleteService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as DeleteData; + const initPatchService = () => new CoarNotifyConfigDataService(null, null, null, null, null) as unknown as PatchData; + testCreateDataImplementation(initCreateService); + testFindAllDataImplementation(initFindAllService); + testPatchDataImplementation(initPatchService); + testDeleteDataImplementation(initDeleteService); + }); + +}); diff --git a/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts index 7b8d309667..0bf5fe5359 100644 --- a/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts +++ b/src/app/submission/sections/section-coar-notify/coar-notify-config-data.service.ts @@ -25,8 +25,7 @@ import { PatchData, PatchDataImpl } from '../../../core/data/base/patch-data'; import { ChangeAnalyzer } from '../../../core/data/change-analyzer'; import { Operation } from 'fast-json-patch'; import { RestRequestMethod } from '../../../core/data/rest-request-method'; -import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; -import { hasValue } from '../../../shared/empty.util'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; /** @@ -57,8 +56,8 @@ export class CoarNotifyConfigDataService extends IdentifiableDataService> { - return this.createData.create(object); + create(object: SubmissionCoarNotifyConfig, ...params: RequestParam[]): Observable> { + return this.createData.create(object, ...params); } patch(object: SubmissionCoarNotifyConfig, operations: Operation[]): Observable> { @@ -81,6 +80,7 @@ export class CoarNotifyConfigDataService extends IdentifiableDataService> { return this.deleteData.delete(objectId, copyVirtualMetadata); } @@ -103,15 +103,6 @@ export class CoarNotifyConfigDataService extends IdentifiableDataService(requestId); } - public SubmissionCoarNotifyConfigModelWithNameExistsAndCanExecute(scriptName: string): Observable { - return this.findById(scriptName).pipe( - getFirstCompletedRemoteData(), - map((rd: RemoteData) => { - return hasValue(rd.payload); - }), - ); - } - private getInvocationFormData(files: File[]): FormData { const form: FormData = new FormData(); files.forEach((file: File) => { diff --git a/src/app/suggestions-page/suggestions-page.component.spec.ts b/src/app/suggestions-page/suggestions-page.component.spec.ts index 37d01a4adc..ab118d68f9 100644 --- a/src/app/suggestions-page/suggestions-page.component.spec.ts +++ b/src/app/suggestions-page/suggestions-page.component.spec.ts @@ -7,13 +7,8 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { of as observableOf } from 'rxjs'; import { SuggestionsPageComponent } from './suggestions-page.component'; -import { SuggestionListElementComponent } from '../notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; -import { SuggestionsService } from '../notifications/reciter-suggestions/suggestions.service'; import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; -import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model'; -import { Suggestion } from '../core/notifications/reciter-suggestions/models/suggestion.model'; import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/reciter-suggestion.mock'; -import { SuggestionEvidencesComponent } from '../notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; import { VarDirective } from '../shared/utils/var.directive'; import { ActivatedRoute, Router } from '@angular/router'; @@ -23,14 +18,23 @@ import { AuthService } from '../core/auth/auth.service'; import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub'; import { getMockTranslateService } from '../shared/mocks/translate.service.mock'; -import { SuggestionTargetsStateService } from '../notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; -import { PageInfo } from '../core/shared/page-info.model'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; import { PaginationService } from '../core/pagination/pagination.service'; +import { + SuggestionEvidencesComponent +} from '../notifications/reciter-suggestions/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; +import { + SuggestionApproveAndImport, + SuggestionListElementComponent +} from '../notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component'; +import { SuggestionsService } from '../notifications/reciter-suggestions/suggestions.service'; +import { + SuggestionTargetsStateService +} from '../notifications/reciter-suggestions/suggestion-targets/suggestion-targets.state.service'; describe('SuggestionPageComponent', () => { let component: SuggestionsPageComponent; @@ -38,7 +42,6 @@ describe('SuggestionPageComponent', () => { let scheduler: TestScheduler; const mockSuggestionsService = getMockSuggestionsService(); const mockSuggestionsTargetStateService = getMockSuggestionNotificationsStateService(); - const suggestionTargetsList: PaginatedList = buildPaginatedList(new PageInfo(), [mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); const router = new RouterStub(); const routeStub = { data: observableOf({ @@ -104,4 +107,111 @@ describe('SuggestionPageComponent', () => { expect(component.researcherName).toBe(mockSuggestionTargetsObjectOne.display); expect(component.updatePage).toHaveBeenCalled(); }); + + it('should update page on pagination change', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.onPaginationChange(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should update suggestion on page update', (done) => { + spyOn(component.processing$, 'next'); + spyOn(component.suggestionsRD$, 'next'); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + paginationService.getFindListOptions().subscribe(() => { + expect(component.processing$.next).toHaveBeenCalled(); + expect(mockSuggestionsService.getSuggestions).toHaveBeenCalled(); + expect(component.suggestionsRD$.next).toHaveBeenCalled(); + expect(mockSuggestionsService.clearSuggestionRequests).toHaveBeenCalled(); + done(); + }); + component.updatePage(); + }); + + it('should flag suggestion for deletion', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.notMine('1'); + expect(mockSuggestionsService.notMine).toHaveBeenCalledWith('1'); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should flag all suggestion for deletion', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.notMineAllSelected(); + expect(mockSuggestionsService.notMineMultiple).toHaveBeenCalled(); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should approve and import', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.approveAndImport({collectionId: '1234'} as unknown as SuggestionApproveAndImport); + expect(mockSuggestionsService.approveAndImport).toHaveBeenCalled(); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should approve and import multiple suggestions', () => { + spyOn(component, 'updatePage').and.stub(); + + scheduler.schedule(() => fixture.detectChanges()); + scheduler.flush(); + component.approveAndImportAllSelected({collectionId: '1234'} as unknown as SuggestionApproveAndImport); + expect(mockSuggestionsService.approveAndImportMultiple).toHaveBeenCalled(); + expect(mockSuggestionsTargetStateService.dispatchRefreshUserSuggestionsAction).toHaveBeenCalled(); + expect(component.updatePage).toHaveBeenCalled(); + }); + + it('should select and deselect suggestion', () => { + component.selectedSuggestions = {}; + component.onSelected(mockSuggestionPublicationOne, true); + expect(component.selectedSuggestions[mockSuggestionPublicationOne.id]).toBe(mockSuggestionPublicationOne); + component.onSelected(mockSuggestionPublicationOne, false); + expect(component.selectedSuggestions[mockSuggestionPublicationOne.id]).toBeUndefined(); + }); + + it('should toggle all suggestions', () => { + component.selectedSuggestions = {}; + component.onToggleSelectAll([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(component.selectedSuggestions[mockSuggestionPublicationOne.id]).toEqual(mockSuggestionPublicationOne); + expect(component.selectedSuggestions[mockSuggestionPublicationTwo.id]).toEqual(mockSuggestionPublicationTwo); + component.onToggleSelectAll([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(component.selectedSuggestions).toEqual({}); + }); + + it('should return all selected suggestions count', () => { + component.selectedSuggestions = {}; + component.onToggleSelectAll([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(component.getSelectedSuggestionsCount()).toEqual(2); + }); + + it('should check if all collection is fixed', () => { + component.isCollectionFixed([mockSuggestionPublicationOne, mockSuggestionPublicationTwo]); + expect(mockSuggestionsService.isCollectionFixed).toHaveBeenCalled(); + }); + + it('should translate suggestion source', () => { + component.translateSuggestionSource(); + expect(mockSuggestionsService.translateSuggestionSource).toHaveBeenCalled(); + }); + + it('should translate suggestion type', () => { + component.translateSuggestionType(); + expect(mockSuggestionsService.translateSuggestionType).toHaveBeenCalled(); + }); });