Add missing provider tests

This commit is contained in:
Yana De Pauw
2025-01-06 14:38:19 +01:00
parent b8bb3ff815
commit cb4a7b31f0
31 changed files with 1329 additions and 338 deletions

View File

@@ -27,7 +27,7 @@ import { RegistriesMenuProvider } from './shared/menu/providers/registries.menu'
import { StatisticsMenuProvider } from './shared/menu/providers/statistics.menu';
import { SystemWideAlertMenuProvider } from './shared/menu/providers/system-wide-alert.menu';
import { WorkflowMenuProvider } from './shared/menu/providers/workflow.menu';
import { DsoOptionMenu } from './shared/menu/providers/dso-option.menu';
import { DsoOptionMenuProvider } from './shared/menu/providers/dso-option.menu';
import { MenuRoute } from './shared/menu/menu-route.model';
export const MENUS = buildMenuStructure({
@@ -51,7 +51,7 @@ export const MENUS = buildMenuStructure({
SystemWideAlertMenuProvider,
],
[MenuID.DSO_EDIT]: [
DsoOptionMenu.withSubs([
DsoOptionMenuProvider.withSubs([
SubscribeMenuProvider.onRoute(
MenuRoute.SIMPLE_COMMUNITY_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE,

View File

@@ -1,7 +1,7 @@
import { MenuID } from './menu-id.model';
import { CommunityListMenuProvider } from './providers/community-list.menu';
import { NewMenuProvider } from './providers/new.menu';
import { DsoOptionMenu } from './providers/dso-option.menu';
import { DsoOptionMenuProvider } from './providers/dso-option.menu';
import { SubscribeMenuProvider } from './providers/comcol-subscribe.menu';
import { buildMenuStructure } from './menu.structure';
import { MenuProviderService } from './menu-provider.service';
@@ -47,7 +47,7 @@ describe('buildMenuStructure', () => {
SystemWideAlertMenuProvider,
],
[MenuID.DSO_EDIT]: [
DsoOptionMenu.withSubs([
DsoOptionMenuProvider.withSubs([
SubscribeMenuProvider.onRoute(
MenuRoute.SIMPLE_COMMUNITY_PAGE,
MenuRoute.SIMPLE_COLLECTION_PAGE
@@ -97,7 +97,7 @@ describe('buildMenuStructure', () => {
VersioningMenuProvider,
OrcidMenuProvider,
ClaimMenuProvider,
DsoOptionMenu,
DsoOptionMenuProvider,
];

View File

@@ -17,6 +17,7 @@ import { ScriptDataService } from '../../../core/data/processes/script-data.serv
import { ScriptServiceStub } from '../../testing/script-service.stub';
import { PartialMenuSection } from '../menu-provider.model';
describe('AccessControlMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -53,7 +54,6 @@ const expectedSubSections: PartialMenuSection[] = [
},
];
describe('AccessControlMenuProvider', () => {
let provider: AccessControlMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -14,6 +14,8 @@ import { of as observableOf } from 'rxjs';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { PartialMenuSection } from '../menu-provider.model';
describe('AdminSearchMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -26,7 +28,7 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('AdminSearchMenuProvider', () => {
let provider: AdminSearchMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -18,6 +18,8 @@ import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
import { createPaginatedList } from '../../testing/utils.test';
import { PartialMenuSection } from '../menu-provider.model';
describe('BrowseMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -46,7 +48,7 @@ const expectedSubSections: PartialMenuSection[] = [
},
];
describe('BrowseMenuProvider', () => {
let provider: BrowseMenuProvider;
let browseServiceStub = new BrowseServiceStub();

View File

@@ -0,0 +1,64 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { SubscribeMenuProvider } from './comcol-subscribe.menu';
import { Collection } from '../../../core/shared/collection.model';
describe('SubscribeMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.ONCLICK,
text: 'subscriptions.tooltip',
function: jasmine.any(Function) as any,
},
icon: 'bell',
}
];
let provider: SubscribeMenuProvider;
const dso: Collection = Object.assign(new Collection(), {_links: {self: {href: 'self-link'}}});
let authorizationService;
let modalService;
beforeEach(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
'isAuthorized': observableOf(true)
});
modalService = jasmine.createSpyObj('modalService', ['open']);
TestBed.configureTestingModule({
providers: [
SubscribeMenuProvider,
{provide: AuthorizationDataService, useValue: authorizationService},
{provide: NgbModal, useValue: modalService},
],
});
provider = TestBed.inject(SubscribeMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the expected sections', (done) => {
provider.getSectionsForContext(dso).subscribe((sections) => {
expect(sections).toEqual(expectedSections);
done();
});
});
});
});

View File

@@ -11,6 +11,7 @@ import { CommunityListMenuProvider } from './community-list.menu';
import { MenuItemType } from '../menu-item-type.model';
import { PartialMenuSection } from '../menu-provider.model';
describe('CommunityListMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -23,7 +24,6 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('CommunityListMenuProvider', () => {
let provider: CommunityListMenuProvider;
beforeEach(() => {

View File

@@ -14,6 +14,7 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
import { CurationMenuProvider } from './curation.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('CurationMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -26,7 +27,6 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('CurationMenuProvider', () => {
let provider: CurationMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -0,0 +1,65 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { Collection } from '../../../core/shared/collection.model';
import { DSpaceObjectEditMenuProvider } from './dso-edit.menu';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { COLLECTION } from '../../../core/shared/collection.resource-type';
describe('DSpaceObjectEditMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.LINK,
text: 'collection.page.edit',
link: new URLCombiner('/collections/test-uuid', 'edit', 'metadata').toString(),
},
icon: 'pencil-alt',
}
];
let provider: DSpaceObjectEditMenuProvider;
const dso: Collection = Object.assign(new Collection(), {
type: COLLECTION.value,
uuid: 'test-uuid',
_links: {self: {href: 'self-link'}},
});
let authorizationService;
beforeEach(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
'isAuthorized': observableOf(true)
});
TestBed.configureTestingModule({
providers: [
DSpaceObjectEditMenuProvider,
{provide: AuthorizationDataService, useValue: authorizationService},
],
});
provider = TestBed.inject(DSpaceObjectEditMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the expected sections', (done) => {
provider.getSectionsForContext(dso).subscribe((sections) => {
expect(sections).toEqual(expectedSections);
done();
});
});
});
});

View File

@@ -0,0 +1,53 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { Collection } from '../../../core/shared/collection.model';
import { COLLECTION } from '../../../core/shared/collection.resource-type';
import { DsoOptionMenuProvider } from './dso-option.menu';
describe('DsoOptionMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'collection.page.options',
},
icon: 'ellipsis-vertical',
}
];
let provider: DsoOptionMenuProvider;
const dso: Collection = Object.assign(new Collection(), {
type: COLLECTION.value,
uuid: 'test-uuid',
_links: {self: {href: 'self-link'}},
});
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
DsoOptionMenuProvider,
],
});
provider = TestBed.inject(DsoOptionMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the expected sections', (done) => {
provider.getSectionsForContext(dso).subscribe((sections) => {
expect(sections).toEqual(expectedSections);
done();
});
});
});
});

View File

@@ -18,7 +18,7 @@ import { DSpaceObject } from 'src/app/core/shared/dspace-object.model';
* This section will be rendered as a button on the DSO pages if sub providers have been added
*/
@Injectable()
export class DsoOptionMenu extends DSpaceObjectPageMenuProvider {
export class DsoOptionMenuProvider extends DSpaceObjectPageMenuProvider {
alwaysRenderExpandable = true;

View File

@@ -15,6 +15,8 @@ import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
import { EditMenuProvider } from './edit.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('EditMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -51,7 +53,6 @@ const expectedSubSections: PartialMenuSection[] = [
},
];
describe('EditMenuProvider', () => {
let provider: EditMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -16,6 +16,7 @@ import { ScriptServiceStub } from '../../testing/script-service.stub';
import { ExportMenuProvider } from './export.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('ExportMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -44,7 +45,6 @@ const expectedSubSections: PartialMenuSection[] = [
}
];
describe('ExportMenuProvider', () => {
let provider: ExportMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -14,6 +14,7 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
import { HealthMenuProvider } from './health.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('HealthMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -26,7 +27,6 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('HealthMenuProvider', () => {
let provider: HealthMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -0,0 +1,139 @@
import { DSpaceObjectPageMenuProvider } from './dso.menu';
import { TestBed } from '@angular/core/testing';
import { Item } from '../../../../core/shared/item.model';
import { ITEM } from '../../../../core/shared/item.resource-type';
import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils';
import { Collection } from '../../../../core/shared/collection.model';
import { COLLECTION } from '../../../../core/shared/collection.resource-type';
describe('DSpaceObjectPageMenuProvider', () => {
let provider: DSpaceObjectPageMenuProvider;
const item: Item = Object.assign(new Item(), {
uuid: 'test-item-uuid',
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item'
}]
}
});
const item2: Item = Object.assign(new Item(), {
uuid: 'test-item2-uuid',
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item 2'
}]
}
});
const person: Item = Object.assign(new Item(), {
uuid: 'test-uuid',
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Person Entity'
}],
'dspace.entity.type': [{
'value': 'Person'
}],
}
});
const collection: Collection = Object.assign(new Collection(), {
uuid: 'test-collection-uuid',
type: COLLECTION.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Collection'
}]
}
});
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
DSpaceObjectPageMenuProvider,
],
});
provider = TestBed.inject(DSpaceObjectPageMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getRouteContext', () => {
it('should get the dso from the route', (done) => {
const route = {data: {dso: createSuccessfulRemoteDataObject(item)}} as any;
provider.getRouteContext(route, undefined).subscribe((dso) => {
expect(dso).toEqual(item);
done();
});
});
it('return undefined when no DSO is present on the current route', (done) => {
const route = {
data: {},
parent: {
data: {},
parent: {
data: {dso: createSuccessfulRemoteDataObject(item)},
parent: {data: {dso: createSuccessfulRemoteDataObject(item2)}}
}
}
} as any;
provider.getRouteContext(route, undefined).subscribe((dso) => {
expect(dso).toBeUndefined();
done();
});
});
it('should return undefined when no dso is found in the route', (done) => {
const route = {data: {}, parent: {data: {}, parent: {data: {}, parent: {data: {}}}}} as any;
provider.getRouteContext(route, undefined).subscribe((dso) => {
expect(dso).toBeUndefined();
done();
});
});
});
describe('getDsoType', () => {
it('should return the object type for an untyped item', () => {
const dsoType = (provider as any).getDsoType(item);
expect(dsoType).toEqual('item');
});
it('should return the entity type for an entity item', () => {
const dsoType = (provider as any).getDsoType(person);
expect(dsoType).toEqual('person');
});
it('should return the object type for a colletion', () => {
const dsoType = (provider as any).getDsoType(collection);
expect(dsoType).toEqual('collection');
});
});
describe('isApplicable', () => {
it('should return true when a dso is provided', () => {
const isApplicable = (provider as any).isApplicable(collection);
expect(isApplicable).toBeTrue();
});
it('should return false when no dso is provided', () => {
const isApplicable = (provider as any).isApplicable(undefined);
expect(isApplicable).toBeFalse();
});
});
});

View File

@@ -0,0 +1,113 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TestBed } from '@angular/core/testing';
import { Observable, of as observableOf } from 'rxjs';
import { AbstractExpandableMenuProvider } from './expandable-menu-provider';
import { MenuItemType } from '../../menu-item-type.model';
import { PartialMenuSection } from '../../menu-provider.model';
import { MenuID } from '../../menu-id.model';
describe('AbstractExpandableMenuProvider', () => {
const topSection: PartialMenuSection = {
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'top.section.test',
},
icon: 'file-import',
};
const subSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'sub.section.test.1',
},
},
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'sub.section.test.2',
},
},
];
class TestClass extends AbstractExpandableMenuProvider {
getTopSection(): Observable<PartialMenuSection> {
return observableOf(topSection);
}
getSubSections(): Observable<PartialMenuSection[]> {
return observableOf(subSections);
}
}
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'sub.section.test.1',
},
id: `${MenuID.ADMIN}_1_0`,
parentID: `${MenuID.ADMIN}_1`,
alwaysRenderExpandable: false,
},
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'sub.section.test.2',
},
id: `${MenuID.ADMIN}_1_1`,
parentID: `${MenuID.ADMIN}_1`,
alwaysRenderExpandable: false,
},
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'top.section.test',
},
icon: 'file-import',
id: `${MenuID.ADMIN}_1`,
alwaysRenderExpandable: true,
}
];
let provider: AbstractExpandableMenuProvider;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
TestClass,
],
});
provider = TestBed.inject(TestClass);
provider.menuProviderId = `${MenuID.ADMIN}_1`;
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
it('getSections should return a combination of top and sub sections', (done) => {
provider.getSections().subscribe((section) => {
expect(section).toEqual(expectedSections);
done();
});
});
});

View File

@@ -0,0 +1,96 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import { TestBed } from '@angular/core/testing';
import { Observable, of as observableOf } from 'rxjs';
import { MenuItemType } from '../../menu-item-type.model';
import { PartialMenuSection } from '../../menu-provider.model';
import { MenuID } from '../../menu-id.model';
import { AbstractRouteContextMenuProvider } from './route-context.menu';
import { CacheableObject } from '../../../../core/cache/cacheable-object.model';
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
describe('AbstractExpandableMenuProvider', () => {
class TestClass extends AbstractRouteContextMenuProvider<CacheableObject> {
getRouteContext(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<CacheableObject> {
return observableOf(object);
}
getSectionsForContext(routeContext: CacheableObject): Observable<PartialMenuSection[]> {
return observableOf(expectedSections);
}
}
const object = Object.assign(new CacheableObject());
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'sub.section.test.1',
},
id: `${MenuID.ADMIN}_1_0`,
parentID: `${MenuID.ADMIN}_1`,
alwaysRenderExpandable: false,
},
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'sub.section.test.2',
},
id: `${MenuID.ADMIN}_1_1`,
parentID: `${MenuID.ADMIN}_1`,
alwaysRenderExpandable: false,
},
{
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'top.section.test',
},
icon: 'file-import',
id: `${MenuID.ADMIN}_1`,
alwaysRenderExpandable: true,
}
];
let provider: AbstractRouteContextMenuProvider<CacheableObject>;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
TestClass,
],
});
provider = TestBed.inject(TestClass);
provider.menuProviderId = `${MenuID.ADMIN}_1`;
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
it('getSections should return the sections based on the retrieved route context and sections for that context', (done) => {
spyOn(provider, 'getRouteContext').and.callThrough();
spyOn(provider, 'getSectionsForContext').and.callThrough();
provider.getSections(undefined, undefined).subscribe((sections) => {
expect(sections).toEqual(expectedSections);
expect(provider.getRouteContext).toHaveBeenCalled();
expect(provider.getSectionsForContext).toHaveBeenCalledWith(object);
done();
});
});
});

View File

@@ -16,6 +16,7 @@ import { ScriptDataService } from '../../../core/data/processes/script-data.serv
import { ScriptServiceStub } from '../../testing/script-service.stub';
import { PartialMenuSection } from '../menu-provider.model';
describe('ImportMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -44,7 +45,6 @@ const expectedSubSections: PartialMenuSection[] = [
},
];
describe('ImportMenuProvider', () => {
let provider: ImportMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -0,0 +1,134 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ClaimMenuProvider } from './item-claim.menu';
import { Item } from '../../../core/shared/item.model';
import { TranslateModule } from '@ngx-translate/core';
import { NotificationsServiceStub } from '../../testing/notifications-service.stub';
import { MenuService } from '../menu.service';
import { NotificationsService } from '../../notifications/notifications.service';
import { ResearcherProfileDataService } from '../../../core/profile/researcher-profile-data.service';
import { ITEM } from '../../../core/shared/item.resource-type';
describe('ClaimMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.ONCLICK,
text: 'item.page.claim.button',
function: jasmine.any(Function) as any,
},
icon: 'hand-paper',
}
];
let provider: ClaimMenuProvider;
const item: Item = Object.assign(new Item(), {
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item'
}]
}
});
const person: Item = Object.assign(new Item(), {
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Person Entity'
}],
'dspace.entity.type': [{
'value': 'Person'
}],
}
});
let authorizationService;
let menuService;
let notificationsService;
let researcherProfileService;
let modalService;
beforeEach(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
'isAuthorized': observableOf(true),
'invalidateAuthorizationsRequestCache': {}
});
menuService = jasmine.createSpyObj('menuService', ['hideMenuSection']);
notificationsService = new NotificationsServiceStub();
researcherProfileService = jasmine.createSpyObj('authorizationService', {
'createFromExternalSourceAndReturnRelatedItemId': observableOf('profile-id')
});
modalService = jasmine.createSpyObj('modalService', ['open']);
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
providers: [
ClaimMenuProvider,
{provide: AuthorizationDataService, useValue: authorizationService},
{provide: MenuService, useValue: menuService},
{provide: NotificationsService, useValue: notificationsService},
{provide: ResearcherProfileDataService, useValue: researcherProfileService},
{provide: NgbModal, useValue: modalService},
],
});
provider = TestBed.inject(ClaimMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the expected sections', (done) => {
provider.getSectionsForContext(person).subscribe((sections) => {
expect(sections).toEqual(expectedSections);
done();
});
});
});
describe('isApplicable', () => {
it('should return true whe the provided dspace object is a person entity', () => {
const result = (provider as any).isApplicable(person);
expect(result).toBeTrue();
});
it('should return true whe the provided dspace object is not a person entity', () => {
const result = (provider as any).isApplicable(item);
expect(result).toBeFalse();
});
});
describe('claimResearcher', () => {
it('should show a success notification and hide the menu when an id is returned by the researcher profile service', () => {
(provider as any).claimResearcher(person);
expect(notificationsService.success).toHaveBeenCalled();
expect(authorizationService.invalidateAuthorizationsRequestCache).toHaveBeenCalled();
expect(menuService.hideMenuSection).toHaveBeenCalled();
});
it('should show an error notification when no id is returned by the researcher profile service', () => {
(researcherProfileService.createFromExternalSourceAndReturnRelatedItemId as jasmine.Spy).and.returnValue(observableOf(null));
(provider as any).claimResearcher(person);
expect(notificationsService.error).toHaveBeenCalled();
expect(authorizationService.invalidateAuthorizationsRequestCache).not.toHaveBeenCalled();
expect(menuService.hideMenuSection).not.toHaveBeenCalled();
});
});
});

View File

@@ -40,14 +40,6 @@ export class ClaimMenuProvider extends DSpaceObjectPageMenuProvider {
super();
}
protected isApplicable(item: DSpaceObject): boolean {
if (item instanceof Item) {
return this.getDsoType(item) === 'person';
}
return false;
}
public getSectionsForContext(item: Item): Observable<PartialMenuSection[]> {
return combineLatest([
this.authorizationService.isAuthorized(FeatureID.CanClaimItem, item.self),
@@ -70,6 +62,13 @@ export class ClaimMenuProvider extends DSpaceObjectPageMenuProvider {
);
}
protected isApplicable(item: DSpaceObject): boolean {
if (item instanceof Item) {
return this.getDsoType(item) === 'person';
}
return false;
}
/**
* Claim a researcher by creating a profile
* Shows notifications and/or hides the menu section on success/error
@@ -82,7 +81,7 @@ export class ClaimMenuProvider extends DSpaceObjectPageMenuProvider {
this.translate.get('researcherprofile.success.claim.body'),
);
this.authorizationService.invalidateAuthorizationsRequestCache();
this.menuService.hideMenuSection(MenuID.DSO_EDIT, 'claim-dso-' + item.uuid);
this.menuService.hideMenuSection(MenuID.DSO_EDIT, this.menuProviderId);
} else {
this.notificationsService.error(
this.translate.get('researcherprofile.error.claim.title'),

View File

@@ -0,0 +1,94 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { Item } from '../../../core/shared/item.model';
import { TranslateModule } from '@ngx-translate/core';
import { ITEM } from '../../../core/shared/item.resource-type';
import { URLCombiner } from '../../../core/url-combiner/url-combiner';
import { OrcidMenuProvider } from './item-orcid.menu';
describe('OrcidMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.LINK,
text: 'item.page.orcid.tooltip',
link: new URLCombiner('/entities/person/test-uuid', 'orcid').toString(),
},
icon: 'orcid fab fa-lg',
}
];
let provider: OrcidMenuProvider;
const item: Item = Object.assign(new Item(), {
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item'
}]
}
});
const person: Item = Object.assign(new Item(), {
uuid: 'test-uuid',
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Person Entity'
}],
'dspace.entity.type': [{
'value': 'Person'
}],
}
});
let authorizationService;
beforeEach(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
'isAuthorized': observableOf(true),
});
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
providers: [
OrcidMenuProvider,
{provide: AuthorizationDataService, useValue: authorizationService},
],
});
provider = TestBed.inject(OrcidMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the expected sections', (done) => {
provider.getSectionsForContext(person).subscribe((sections) => {
expect(sections).toEqual(expectedSections);
done();
});
});
});
describe('isApplicable', () => {
it('should return true whe the provided dspace object is a person entity', () => {
const result = (provider as any).isApplicable(person);
expect(result).toBeTrue();
});
it('should return true whe the provided dspace object is not a person entity', () => {
const result = (provider as any).isApplicable(item);
expect(result).toBeFalse();
});
});
});

View File

@@ -29,13 +29,6 @@ export class OrcidMenuProvider extends DSpaceObjectPageMenuProvider {
super();
}
protected isApplicable(item: Item): boolean {
if (item instanceof Item) {
return this.getDsoType(item) === 'person';
}
return false;
}
public getSectionsForContext(item: Item): Observable<PartialMenuSection[]> {
return combineLatest([
this.authorizationService.isAuthorized(FeatureID.CanSynchronizeWithORCID, item.self),
@@ -55,4 +48,11 @@ export class OrcidMenuProvider extends DSpaceObjectPageMenuProvider {
}),
);
}
protected isApplicable(item: Item): boolean {
if (item instanceof Item) {
return this.getDsoType(item) === 'person';
}
return false;
}
}

View File

@@ -0,0 +1,98 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { Item } from '../../../core/shared/item.model';
import { TranslateModule } from '@ngx-translate/core';
import { ITEM } from '../../../core/shared/item.resource-type';
import { VersioningMenuProvider } from './item-versioning.menu';
import { DsoVersioningModalService } from '../../dso-page/dso-versioning-modal-service/dso-versioning-modal.service';
describe('VersioningMenuProvider', () => {
const expectedSectionsWhenVersionNotPresent: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.ONCLICK,
text: 'item.page.version.create',
disabled: false,
function: jasmine.any(Function) as any,
},
icon: 'code-branch',
}
];
const expectedSectionsWhenVersionPresent: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.ONCLICK,
text: 'item.page.version.hasDraft',
disabled: true,
function: jasmine.any(Function) as any,
},
icon: 'code-branch',
}
];
let provider: VersioningMenuProvider;
const item: Item = Object.assign(new Item(), {
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item'
}]
}
});
let authorizationService;
let dsoVersioningModalService;
beforeEach(() => {
authorizationService = jasmine.createSpyObj('authorizationService', {
isAuthorized: observableOf(true),
});
dsoVersioningModalService = jasmine.createSpyObj('dsoVersioningModalService', {
isNewVersionButtonDisabled: observableOf(false),
getVersioningTooltipMessage: observableOf('item.page.version.create'),
});
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
providers: [
VersioningMenuProvider,
{provide: AuthorizationDataService, useValue: authorizationService},
{provide: DsoVersioningModalService, useValue: dsoVersioningModalService},
],
});
provider = TestBed.inject(VersioningMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the section to create a new version when no version draft is present yet', (done) => {
provider.getSectionsForContext(item).subscribe((sections) => {
expect(sections).toEqual(expectedSectionsWhenVersionNotPresent);
done();
});
});
it('should return the section to that a version is present when a version draft is present', (done) => {
(dsoVersioningModalService.isNewVersionButtonDisabled as jasmine.Spy).and.returnValue(observableOf(true));
(dsoVersioningModalService.getVersioningTooltipMessage as jasmine.Spy).and.returnValue(observableOf('item.page.version.hasDraft'));
provider.getSectionsForContext(item).subscribe((sections) => {
expect(sections).toEqual(expectedSectionsWhenVersionPresent);
done();
});
});
});
});

View File

@@ -15,6 +15,7 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
import { PartialMenuSection } from '../menu-provider.model';
describe('NewMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -59,7 +60,6 @@ const expectedSubSections: PartialMenuSection[] = [
},
];
describe('NewMenuProvider', () => {
let provider: NewMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -14,6 +14,8 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
import { ProcessesMenuProvider } from './processes.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('ProcessesMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -26,7 +28,6 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('ProcessesMenuProvider', () => {
let provider: ProcessesMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -16,6 +16,8 @@ import { ScriptServiceStub } from '../../testing/script-service.stub';
import { RegistriesMenuProvider } from './registries.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('RegistriesMenuProvider', () => {
const expectedTopSection: PartialMenuSection = {
visible: true,
model: {
@@ -44,7 +46,6 @@ const expectedSubSections: PartialMenuSection[] = [
},
];
describe('RegistriesMenuProvider', () => {
let provider: RegistriesMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -0,0 +1,127 @@
import { PartialMenuSection } from '../menu-provider.model';
import { MenuItemType } from '../menu-item-type.model';
import { TestBed } from '@angular/core/testing';
import { Item } from '../../../core/shared/item.model';
import { TranslateModule } from '@ngx-translate/core';
import { ITEM } from '../../../core/shared/item.resource-type';
import { StatisticsMenuProvider } from './statistics.menu';
import { createSuccessfulRemoteDataObject } from '../../remote-data.utils';
describe('StatisticsMenuProvider', () => {
const expectedSectionsNoDSO: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.LINK,
text: 'menu.section.statistics',
link: `statistics`,
},
icon: 'chart-line',
}
];
const expectedSectionsForItem: PartialMenuSection[] = [
{
visible: true,
model: {
type: MenuItemType.LINK,
text: 'menu.section.statistics',
link: `statistics/items/test-item-uuid`,
},
icon: 'chart-line',
}
];
let provider: StatisticsMenuProvider;
const item: Item = Object.assign(new Item(), {
uuid: 'test-item-uuid',
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item'
}]
}
});
const item2: Item = Object.assign(new Item(), {
uuid: 'test-item2-uuid',
type: ITEM.value,
_links: {self: {href: 'self-link'}},
metadata: {
'dc.title': [{
'value': 'Untyped Item 2'
}]
}
});
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
providers: [
StatisticsMenuProvider,
],
});
provider = TestBed.inject(StatisticsMenuProvider);
});
it('should be created', () => {
expect(provider).toBeTruthy();
});
describe('getSectionsForContext', () => {
it('should return the general statistics link when no DSO is provided', (done) => {
provider.getSectionsForContext(undefined).subscribe((sections) => {
expect(sections).toEqual(expectedSectionsNoDSO);
done();
});
});
it('should return a statistics link to the DSO when a DSO is provided', (done) => {
provider.getSectionsForContext(item).subscribe((sections) => {
expect(sections).toEqual(expectedSectionsForItem);
done();
});
});
});
describe('getRouteContext', () => {
it('should get the dso from the route', (done) => {
const route = {data: {dso: createSuccessfulRemoteDataObject(item)}} as any;
provider.getRouteContext(route, undefined).subscribe((dso) => {
expect(dso).toEqual(item);
done();
});
});
it('should get the dso from first parent route with a dso when the route itself has none', (done) => {
const route = {
data: {},
parent: {
data: {},
parent: {
data: {dso: createSuccessfulRemoteDataObject(item)},
parent: {data: {dso: createSuccessfulRemoteDataObject(item2)}}
}
}
} as any;
provider.getRouteContext(route, undefined).subscribe((dso) => {
expect(dso).toEqual(item);
expect(dso).not.toEqual(item2);
done();
});
});
it('should return undefined when no dso is found in the route', (done) => {
const route = {data: {}, parent: {data: {}, parent: {data: {}, parent: {data: {}}}}} as any;
provider.getRouteContext(route, undefined).subscribe((dso) => {
expect(dso).toBeUndefined();
done();
});
});
});
});

View File

@@ -49,7 +49,7 @@ export class StatisticsMenuProvider extends AbstractRouteContextMenuProvider<DSp
if (hasValue(dso)) {
dsoRoute = getDSORoute(dso);
if (hasValue(dsoRoute)) {
link = `statistics/${dsoRoute}`;
link = `statistics${dsoRoute}`;
}
}

View File

@@ -14,6 +14,8 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
import { SystemWideAlertMenuProvider } from './system-wide-alert.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('SystemWideAlertMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -26,7 +28,6 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('SystemWideAlertMenuProvider', () => {
let provider: SystemWideAlertMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();

View File

@@ -14,6 +14,8 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
import { WorkflowMenuProvider } from './workflow.menu';
import { PartialMenuSection } from '../menu-provider.model';
describe('WorkflowMenuProvider', () => {
const expectedSections: PartialMenuSection[] = [
{
visible: true,
@@ -26,7 +28,6 @@ const expectedSections: PartialMenuSection[] = [
},
];
describe('WorkflowMenuProvider', () => {
let provider: WorkflowMenuProvider;
let authorizationServiceStub = new AuthorizationDataServiceStub();