Merge branch 'CST-5249_suggestion' of github.com:4Science/dspace-angular into CST-5249_suggestion

This commit is contained in:
frabacche
2024-01-23 14:31:51 +01:00
5 changed files with 398 additions and 4 deletions

View File

@@ -6,7 +6,7 @@ import { Suggestion } from '../../core/suggestion-notifications/reciter-suggesti
import { SUGGESTION } from '../../core/suggestion-notifications/reciter-suggestions/models/suggestion-objects.resource-type';
export const mockSuggestionPublicationOne: Suggestion = {
id: '24694772',
id: '24694773',
display: 'publication one',
source: 'reciter',
externalSourceUri: 'https://dspace7.4science.cloud/server/api/integration/reciterSourcesEntry/pubmed/entryValues/24694772',

View File

@@ -1,6 +1,7 @@
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { Item } from '../../core/shared/item.model';
import { SearchResult } from '../search/models/search-result.model';
import { of as observableOf } from 'rxjs';
// REST Mock ---------------------------------------------------------------------
// -------------------------------------------------------------------------------
@@ -1333,7 +1334,8 @@ export function getMockSuggestionNotificationsStateService(): any {
getOpenaireBrokerTopicsCurrentPage: jasmine.createSpy('getOpenaireBrokerTopicsCurrentPage'),
getOpenaireBrokerTopicsTotals: jasmine.createSpy('getOpenaireBrokerTopicsTotals'),
dispatchRetrieveOpenaireBrokerTopics: jasmine.createSpy('dispatchRetrieveOpenaireBrokerTopics'),
dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction')
dispatchMarkUserSuggestionsAsVisitedAction: jasmine.createSpy('dispatchMarkUserSuggestionsAsVisitedAction'),
dispatchRefreshUserSuggestionsAction: undefined
});
}
/**
@@ -1342,10 +1344,17 @@ export function getMockSuggestionNotificationsStateService(): any {
export function getMockSuggestionsService(): any {
return jasmine.createSpyObj('SuggestionsService', {
getTargets: jasmine.createSpy('getTargets'),
getSuggestions: jasmine.createSpy('getSuggestions'),
getSuggestions: observableOf([]),
clearSuggestionRequests: jasmine.createSpy('clearSuggestionRequests'),
deleteReviewedSuggestion: jasmine.createSpy('deleteReviewedSuggestion'),
retrieveCurrentUserSuggestions: jasmine.createSpy('retrieveCurrentUserSuggestions'),
getTargetUuid: jasmine.createSpy('getTargetUuid'),
notMine: observableOf(null),
notMineMultiple: observableOf({success: 1, fails: 0}),
approveAndImportMultiple: observableOf({success: 1, fails: 0}),
approveAndImport: observableOf({id: '1234'}),
isCollectionFixed: false,
translateSuggestionSource: 'testSource',
translateSuggestionType: 'testType',
});
}

View File

@@ -0,0 +1,81 @@
import { SuggestionListElementComponent } from './suggestion-list-element.component';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { TestScheduler } from 'rxjs/testing';
import { getTestScheduler } from 'jasmine-marbles';
import { mockSuggestionPublicationOne } from '../../../shared/mocks/reciter-suggestion.mock';
import { Item } from '../../../core/shared/item.model';
describe('SuggestionListElementComponent', () => {
let component: SuggestionListElementComponent;
let fixture: ComponentFixture<SuggestionListElementComponent>;
let scheduler: TestScheduler;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot()
],
declarations: [SuggestionListElementComponent],
providers: [
NgbModal
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents().then();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SuggestionListElementComponent);
component = fixture.componentInstance;
scheduler = getTestScheduler();
component.object = mockSuggestionPublicationOne;
});
describe('SuggestionListElementComponent test', () => {
it('should create', () => {
scheduler.schedule(() => fixture.detectChanges());
scheduler.flush();
const expectedIndexableObject = Object.assign(new Item(), {
id: mockSuggestionPublicationOne.id,
metadata: mockSuggestionPublicationOne.metadata
});
expect(component).toBeTruthy();
expect(component.listableObject.hitHighlights).toEqual({});
expect(component.listableObject.indexableObject).toEqual(expectedIndexableObject);
});
it('should check if has evidence', () => {
expect(component.hasEvidences()).toBeTruthy();
});
it('should set seeEvidences', () => {
component.onSeeEvidences(true);
expect(component.seeEvidence).toBeTruthy();
});
it('should emit selection', () => {
spyOn(component.selected, 'next');
component.changeSelected({target: { checked: true}});
expect(component.selected.next).toHaveBeenCalledWith(true);
});
it('should emit for deletion', () => {
spyOn(component.notMineClicked, 'emit');
component.onNotMine('1234');
expect(component.notMineClicked.emit).toHaveBeenCalledWith('1234');
});
it('should emit for approve and import', () => {
const event = {collectionId:'1234', suggestion: mockSuggestionPublicationOne};
spyOn(component.approveAndImport, 'emit');
component.onApproveAndImport(event);
expect(component.approveAndImport.emit).toHaveBeenCalledWith(event);
});
});
});

View File

@@ -0,0 +1,194 @@
import { SuggestionsService } from './suggestions.service';
import { AuthService } from '../../core/auth/auth.service';
import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service';
import {
SuggestionsDataService
} from '../../core/suggestion-notifications/reciter-suggestions/suggestions-data.service';
import {
SuggestionSourceDataService
} from '../../core/suggestion-notifications/reciter-suggestions/source/suggestion-source-data.service';
import {
SuggestionTargetDataService
} from '../../core/suggestion-notifications/reciter-suggestions/target/suggestion-target-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 {
SuggestionTarget
} from '../../core/suggestion-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();
});
});
});

View File

@@ -7,7 +7,10 @@ import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs';
import { SuggestionsPageComponent } from './suggestions-page.component';
import { SuggestionListElementComponent } from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component';
import {
SuggestionApproveAndImport,
SuggestionListElementComponent
} from '../suggestion-notifications/reciter-suggestions/suggestion-list-element/suggestion-list-element.component';
import { SuggestionsService } from '../suggestion-notifications/reciter-suggestions/suggestions.service';
import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock';
import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model';
@@ -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();
});
});