diff --git a/src/app/app.menus.ts b/src/app/app.menus.ts index e530cfd55d..8240a9cb1b 100644 --- a/src/app/app.menus.ts +++ b/src/app/app.menus.ts @@ -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, diff --git a/src/app/shared/menu/menu.structure.spec.ts b/src/app/shared/menu/menu.structure.spec.ts index a54622731b..f62ef03cd1 100644 --- a/src/app/shared/menu/menu.structure.spec.ts +++ b/src/app/shared/menu/menu.structure.spec.ts @@ -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, ]; diff --git a/src/app/shared/menu/providers/access-control.menu.spec.ts b/src/app/shared/menu/providers/access-control.menu.spec.ts index dfb3b625e1..b55b851927 100644 --- a/src/app/shared/menu/providers/access-control.menu.spec.ts +++ b/src/app/shared/menu/providers/access-control.menu.spec.ts @@ -17,43 +17,43 @@ import { ScriptDataService } from '../../../core/data/processes/script-data.serv import { ScriptServiceStub } from '../../testing/script-service.stub'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.access_control', - }, - icon: 'key' -}; - -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.access_control_people', - link: '/access-control/epeople', - }, - }, - { - visible: false, - model: { - type: MenuItemType.LINK, - text: 'menu.section.access_control_groups', - link: '/access-control/groups', - }, - }, - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.access_control_bulk', - link: '/access-control/bulk-access', - }, - }, -]; - describe('AccessControlMenuProvider', () => { + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.access_control', + }, + icon: 'key' + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.access_control_people', + link: '/access-control/epeople', + }, + }, + { + visible: false, + model: { + type: MenuItemType.LINK, + text: 'menu.section.access_control_groups', + link: '/access-control/groups', + }, + }, + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.access_control_bulk', + link: '/access-control/bulk-access', + }, + }, + ]; + let provider: AccessControlMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -69,8 +69,8 @@ describe('AccessControlMenuProvider', () => { TestBed.configureTestingModule({ providers: [ AccessControlMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, - { provide: ScriptDataService, useClass: ScriptServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, + {provide: ScriptDataService, useClass: ScriptServiceStub}, ], }); provider = TestBed.inject(AccessControlMenuProvider); diff --git a/src/app/shared/menu/providers/admin-search.menu.spec.ts b/src/app/shared/menu/providers/admin-search.menu.spec.ts index ffd51425d7..b47b2354d4 100644 --- a/src/app/shared/menu/providers/admin-search.menu.spec.ts +++ b/src/app/shared/menu/providers/admin-search.menu.spec.ts @@ -14,19 +14,21 @@ import { of as observableOf } from 'rxjs'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.admin_search', - link: '/admin/search', - }, - icon: 'search', - }, -]; - describe('AdminSearchMenuProvider', () => { + + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.admin_search', + link: '/admin/search', + }, + icon: 'search', + }, + ]; + + let provider: AdminSearchMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -38,7 +40,7 @@ describe('AdminSearchMenuProvider', () => { TestBed.configureTestingModule({ providers: [ AdminSearchMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(AdminSearchMenuProvider); diff --git a/src/app/shared/menu/providers/browse.menu.spec.ts b/src/app/shared/menu/providers/browse.menu.spec.ts index 546d598183..0585db6d82 100644 --- a/src/app/shared/menu/providers/browse.menu.spec.ts +++ b/src/app/shared/menu/providers/browse.menu.spec.ts @@ -18,51 +18,53 @@ import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; import { createPaginatedList } from '../../testing/utils.test'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { +describe('BrowseMenuProvider', () => { + + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { type: MenuItemType.TEXT, text: 'menu.section.browse_global', }, icon: 'globe', }; -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.browse_global_by_author', - link: '/browse/author', + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.browse_global_by_author', + link: '/browse/author', + }, }, - }, - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.browse_global_by_subject', - link: '/browse/subject', + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.browse_global_by_subject', + link: '/browse/subject', + }, }, - }, -]; + ]; + -describe('BrowseMenuProvider', () => { let provider: BrowseMenuProvider; let browseServiceStub = new BrowseServiceStub(); beforeEach(() => { spyOn(browseServiceStub, 'getBrowseDefinitions').and.returnValue( createSuccessfulRemoteDataObject$(createPaginatedList([ - { id: 'author' } as BrowseDefinition, - { id: 'subject' } as BrowseDefinition, + {id: 'author'} as BrowseDefinition, + {id: 'subject'} as BrowseDefinition, ])) ); TestBed.configureTestingModule({ providers: [ BrowseMenuProvider, - { provide: BrowseService, useValue: browseServiceStub }, - { provide: ObjectCacheService, useValue: getMockObjectCacheService() }, + {provide: BrowseService, useValue: browseServiceStub}, + {provide: ObjectCacheService, useValue: getMockObjectCacheService()}, ], }); provider = TestBed.inject(BrowseMenuProvider); diff --git a/src/app/shared/menu/providers/comcol-subscribe.menu.spec.ts b/src/app/shared/menu/providers/comcol-subscribe.menu.spec.ts new file mode 100644 index 0000000000..32d64cb748 --- /dev/null +++ b/src/app/shared/menu/providers/comcol-subscribe.menu.spec.ts @@ -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(); + }); + }); + }); + + +}); diff --git a/src/app/shared/menu/providers/community-list.menu.spec.ts b/src/app/shared/menu/providers/community-list.menu.spec.ts index ef5bd81f2a..435e2d5396 100644 --- a/src/app/shared/menu/providers/community-list.menu.spec.ts +++ b/src/app/shared/menu/providers/community-list.menu.spec.ts @@ -11,19 +11,19 @@ import { CommunityListMenuProvider } from './community-list.menu'; import { MenuItemType } from '../menu-item-type.model'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: `menu.section.browse_global_communities_and_collections`, - link: `/community-list`, - }, - icon: 'diagram-project' - }, -]; - describe('CommunityListMenuProvider', () => { + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: `menu.section.browse_global_communities_and_collections`, + link: `/community-list`, + }, + icon: 'diagram-project' + }, + ]; + let provider: CommunityListMenuProvider; beforeEach(() => { diff --git a/src/app/shared/menu/providers/curation.menu.spec.ts b/src/app/shared/menu/providers/curation.menu.spec.ts index d3e92fbc00..93476490b4 100644 --- a/src/app/shared/menu/providers/curation.menu.spec.ts +++ b/src/app/shared/menu/providers/curation.menu.spec.ts @@ -14,19 +14,19 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { CurationMenuProvider } from './curation.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.curation_task', - link: 'admin/curation-tasks', - }, - icon: 'filter', - }, -]; - describe('CurationMenuProvider', () => { + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.curation_task', + link: 'admin/curation-tasks', + }, + icon: 'filter', + }, + ]; + let provider: CurationMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -38,7 +38,7 @@ describe('CurationMenuProvider', () => { TestBed.configureTestingModule({ providers: [ CurationMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(CurationMenuProvider); diff --git a/src/app/shared/menu/providers/dso-edit.menu.spec.ts b/src/app/shared/menu/providers/dso-edit.menu.spec.ts new file mode 100644 index 0000000000..15ca5c8130 --- /dev/null +++ b/src/app/shared/menu/providers/dso-edit.menu.spec.ts @@ -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(); + }); + }); + }); + + +}); diff --git a/src/app/shared/menu/providers/dso-option.menu.spec.ts b/src/app/shared/menu/providers/dso-option.menu.spec.ts new file mode 100644 index 0000000000..d04c63e98d --- /dev/null +++ b/src/app/shared/menu/providers/dso-option.menu.spec.ts @@ -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(); + }); + }); + }); + + +}); diff --git a/src/app/shared/menu/providers/dso-option.menu.ts b/src/app/shared/menu/providers/dso-option.menu.ts index 0fba0e19ef..45b3777a2e 100644 --- a/src/app/shared/menu/providers/dso-option.menu.ts +++ b/src/app/shared/menu/providers/dso-option.menu.ts @@ -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; diff --git a/src/app/shared/menu/providers/edit.menu.spec.ts b/src/app/shared/menu/providers/edit.menu.spec.ts index 570e2c4e9e..643f0efc24 100644 --- a/src/app/shared/menu/providers/edit.menu.spec.ts +++ b/src/app/shared/menu/providers/edit.menu.spec.ts @@ -15,43 +15,44 @@ import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; import { EditMenuProvider } from './edit.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.edit' - }, - icon: 'pencil', -}; - -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.edit_community', - function: jasmine.any(Function) as any, - }, - }, - { - visible: false, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.edit_collection', - function: jasmine.any(Function) as any, - }, - }, - { - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.edit_item', - function: jasmine.any(Function) as any, - }, - }, -]; - describe('EditMenuProvider', () => { + + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.edit' + }, + icon: 'pencil', + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.edit_community', + function: jasmine.any(Function) as any, + }, + }, + { + visible: false, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.edit_collection', + function: jasmine.any(Function) as any, + }, + }, + { + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.edit_item', + function: jasmine.any(Function) as any, + }, + }, + ]; + let provider: EditMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -67,7 +68,7 @@ describe('EditMenuProvider', () => { TestBed.configureTestingModule({ providers: [ EditMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(EditMenuProvider); diff --git a/src/app/shared/menu/providers/export.menu.spec.ts b/src/app/shared/menu/providers/export.menu.spec.ts index 7e46d2811b..9ffe75627e 100644 --- a/src/app/shared/menu/providers/export.menu.spec.ts +++ b/src/app/shared/menu/providers/export.menu.spec.ts @@ -16,35 +16,35 @@ import { ScriptServiceStub } from '../../testing/script-service.stub'; import { ExportMenuProvider } from './export.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.export', - }, - icon: 'file-export', -}; - -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.export_metadata', - function: jasmine.any(Function) as any, - }, - }, - { - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.export_batch', - function: jasmine.any(Function) as any, - }, - } -]; - describe('ExportMenuProvider', () => { + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.export', + }, + icon: 'file-export', + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.export_metadata', + function: jasmine.any(Function) as any, + }, + }, + { + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.export_batch', + function: jasmine.any(Function) as any, + }, + } + ]; + let provider: ExportMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -56,8 +56,8 @@ describe('ExportMenuProvider', () => { TestBed.configureTestingModule({ providers: [ ExportMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, - { provide: ScriptDataService, useClass: ScriptServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, + {provide: ScriptDataService, useClass: ScriptServiceStub}, ], }); provider = TestBed.inject(ExportMenuProvider); diff --git a/src/app/shared/menu/providers/health.menu.spec.ts b/src/app/shared/menu/providers/health.menu.spec.ts index 692fd2277c..82ba2ce790 100644 --- a/src/app/shared/menu/providers/health.menu.spec.ts +++ b/src/app/shared/menu/providers/health.menu.spec.ts @@ -14,19 +14,19 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { HealthMenuProvider } from './health.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.health', - link: '/health', - }, - icon: 'heartbeat', - }, -]; - describe('HealthMenuProvider', () => { + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.health', + link: '/health', + }, + icon: 'heartbeat', + }, + ]; + let provider: HealthMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -38,7 +38,7 @@ describe('HealthMenuProvider', () => { TestBed.configureTestingModule({ providers: [ HealthMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(HealthMenuProvider); diff --git a/src/app/shared/menu/providers/helper-providers/dso.menu.spec.ts b/src/app/shared/menu/providers/helper-providers/dso.menu.spec.ts new file mode 100644 index 0000000000..5d214da5f0 --- /dev/null +++ b/src/app/shared/menu/providers/helper-providers/dso.menu.spec.ts @@ -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(); + }); + }); + +}); diff --git a/src/app/shared/menu/providers/helper-providers/expandable-menu-provider.spec.ts b/src/app/shared/menu/providers/helper-providers/expandable-menu-provider.spec.ts new file mode 100644 index 0000000000..ff9cce812f --- /dev/null +++ b/src/app/shared/menu/providers/helper-providers/expandable-menu-provider.spec.ts @@ -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 { + return observableOf(topSection); + } + + getSubSections(): Observable { + 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(); + }); + }); + +}); diff --git a/src/app/shared/menu/providers/helper-providers/route-context.menu.spec.ts b/src/app/shared/menu/providers/helper-providers/route-context.menu.spec.ts new file mode 100644 index 0000000000..1120681c05 --- /dev/null +++ b/src/app/shared/menu/providers/helper-providers/route-context.menu.spec.ts @@ -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 { + getRouteContext(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return observableOf(object); + } + + getSectionsForContext(routeContext: CacheableObject): Observable { + 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; + + 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(); + }); + }); + +}); diff --git a/src/app/shared/menu/providers/helper-providers/route-context.menu.ts b/src/app/shared/menu/providers/helper-providers/route-context.menu.ts index bd03bcc0f3..56bd091f2b 100644 --- a/src/app/shared/menu/providers/helper-providers/route-context.menu.ts +++ b/src/app/shared/menu/providers/helper-providers/route-context.menu.ts @@ -24,7 +24,7 @@ export abstract class AbstractRouteContextMenuProvider extends AbstractMenuPr return this.getRouteContext(route, state).pipe( switchMap((routeContext: T) => { - if (this.isApplicable(routeContext)) { + if (this.isApplicable(routeContext)) { return this.getSectionsForContext(routeContext); } else { return observableOf([]); diff --git a/src/app/shared/menu/providers/import.menu.spec.ts b/src/app/shared/menu/providers/import.menu.spec.ts index 183dead399..f882a17ad6 100644 --- a/src/app/shared/menu/providers/import.menu.spec.ts +++ b/src/app/shared/menu/providers/import.menu.spec.ts @@ -16,35 +16,35 @@ import { ScriptDataService } from '../../../core/data/processes/script-data.serv import { ScriptServiceStub } from '../../testing/script-service.stub'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.import', - }, - icon: 'file-import', -}; - -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.import_metadata', - link: '/admin/metadata-import', - }, - }, - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.import_batch', - link: '/admin/batch-import', - }, - }, -]; - describe('ImportMenuProvider', () => { + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.import', + }, + icon: 'file-import', + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.import_metadata', + link: '/admin/metadata-import', + }, + }, + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.import_batch', + link: '/admin/batch-import', + }, + }, + ]; + let provider: ImportMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -56,8 +56,8 @@ describe('ImportMenuProvider', () => { TestBed.configureTestingModule({ providers: [ ImportMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, - { provide: ScriptDataService, useClass: ScriptServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, + {provide: ScriptDataService, useClass: ScriptServiceStub}, ], }); provider = TestBed.inject(ImportMenuProvider); diff --git a/src/app/shared/menu/providers/item-claim.menu.spec.ts b/src/app/shared/menu/providers/item-claim.menu.spec.ts new file mode 100644 index 0000000000..0889dc6713 --- /dev/null +++ b/src/app/shared/menu/providers/item-claim.menu.spec.ts @@ -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(); + }); + }); +}); diff --git a/src/app/shared/menu/providers/item-claim.menu.ts b/src/app/shared/menu/providers/item-claim.menu.ts index 92b27fc02e..06f26a773d 100644 --- a/src/app/shared/menu/providers/item-claim.menu.ts +++ b/src/app/shared/menu/providers/item-claim.menu.ts @@ -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 { 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'), diff --git a/src/app/shared/menu/providers/item-orcid.menu.spec.ts b/src/app/shared/menu/providers/item-orcid.menu.spec.ts new file mode 100644 index 0000000000..127e583ce2 --- /dev/null +++ b/src/app/shared/menu/providers/item-orcid.menu.spec.ts @@ -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(); + }); + }); + +}); diff --git a/src/app/shared/menu/providers/item-orcid.menu.ts b/src/app/shared/menu/providers/item-orcid.menu.ts index 208a3b26c6..3dc916ee6d 100644 --- a/src/app/shared/menu/providers/item-orcid.menu.ts +++ b/src/app/shared/menu/providers/item-orcid.menu.ts @@ -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 { 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; + } } diff --git a/src/app/shared/menu/providers/item-versioning.menu.spec.ts b/src/app/shared/menu/providers/item-versioning.menu.spec.ts new file mode 100644 index 0000000000..e5a80e78b7 --- /dev/null +++ b/src/app/shared/menu/providers/item-versioning.menu.spec.ts @@ -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(); + }); + }); + }); + +}); diff --git a/src/app/shared/menu/providers/new.menu.spec.ts b/src/app/shared/menu/providers/new.menu.spec.ts index c03f788275..01fa942548 100644 --- a/src/app/shared/menu/providers/new.menu.spec.ts +++ b/src/app/shared/menu/providers/new.menu.spec.ts @@ -15,51 +15,51 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { +describe('NewMenuProvider', () => { + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { type: MenuItemType.TEXT, text: 'menu.section.new' }, icon: 'plus', }; -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.new_community', - function: jasmine.any(Function) as any, + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.new_community', + function: jasmine.any(Function) as any, + }, }, - }, - { - visible: false, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.new_collection', - function: jasmine.any(Function) as any, + { + visible: false, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.new_collection', + function: jasmine.any(Function) as any, + }, }, - }, - { - visible: true, - model: { - type: MenuItemType.ONCLICK, - text: 'menu.section.new_item', - function: jasmine.any(Function) as any, + { + visible: true, + model: { + type: MenuItemType.ONCLICK, + text: 'menu.section.new_item', + function: jasmine.any(Function) as any, + }, }, - }, - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.new_process', - link: '/processes/new' + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.new_process', + link: '/processes/new' + }, }, - }, -]; + ]; -describe('NewMenuProvider', () => { let provider: NewMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -75,7 +75,7 @@ describe('NewMenuProvider', () => { TestBed.configureTestingModule({ providers: [ NewMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(NewMenuProvider); diff --git a/src/app/shared/menu/providers/processes.menu.spec.ts b/src/app/shared/menu/providers/processes.menu.spec.ts index eb72a02765..b0d353634c 100644 --- a/src/app/shared/menu/providers/processes.menu.spec.ts +++ b/src/app/shared/menu/providers/processes.menu.spec.ts @@ -14,19 +14,20 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { ProcessesMenuProvider } from './processes.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.processes', - link: '/processes', - }, - icon: 'terminal', - }, -]; - describe('ProcessesMenuProvider', () => { + + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.processes', + link: '/processes', + }, + icon: 'terminal', + }, + ]; + let provider: ProcessesMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -38,7 +39,7 @@ describe('ProcessesMenuProvider', () => { TestBed.configureTestingModule({ providers: [ ProcessesMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(ProcessesMenuProvider); diff --git a/src/app/shared/menu/providers/registries.menu.spec.ts b/src/app/shared/menu/providers/registries.menu.spec.ts index ae8c419163..2a182d606b 100644 --- a/src/app/shared/menu/providers/registries.menu.spec.ts +++ b/src/app/shared/menu/providers/registries.menu.spec.ts @@ -16,35 +16,36 @@ import { ScriptServiceStub } from '../../testing/script-service.stub'; import { RegistriesMenuProvider } from './registries.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedTopSection: PartialMenuSection = { - visible: true, - model: { - type: MenuItemType.TEXT, - text: 'menu.section.registries', - }, - icon: 'list', -}; - -const expectedSubSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.registries_metadata', - link: 'admin/registries/metadata', - }, - }, - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.registries_format', - link: 'admin/registries/bitstream-formats', - }, - }, -]; - describe('RegistriesMenuProvider', () => { + + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.registries', + }, + icon: 'list', + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.registries_metadata', + link: 'admin/registries/metadata', + }, + }, + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.registries_format', + link: 'admin/registries/bitstream-formats', + }, + }, + ]; + let provider: RegistriesMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -56,8 +57,8 @@ describe('RegistriesMenuProvider', () => { TestBed.configureTestingModule({ providers: [ RegistriesMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, - { provide: ScriptDataService, useClass: ScriptServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, + {provide: ScriptDataService, useClass: ScriptServiceStub}, ], }); provider = TestBed.inject(RegistriesMenuProvider); diff --git a/src/app/shared/menu/providers/statistics.menu.spec.ts b/src/app/shared/menu/providers/statistics.menu.spec.ts new file mode 100644 index 0000000000..0e5dbf83c7 --- /dev/null +++ b/src/app/shared/menu/providers/statistics.menu.spec.ts @@ -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(); + }); + }); + }); + +}); diff --git a/src/app/shared/menu/providers/statistics.menu.ts b/src/app/shared/menu/providers/statistics.menu.ts index 4690cdf1aa..356f2f53d2 100644 --- a/src/app/shared/menu/providers/statistics.menu.ts +++ b/src/app/shared/menu/providers/statistics.menu.ts @@ -49,7 +49,7 @@ export class StatisticsMenuProvider extends AbstractRouteContextMenuProvider { + + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.system-wide-alert', + link: '/admin/system-wide-alert', + }, + icon: 'exclamation-circle', + }, + ]; + let provider: SystemWideAlertMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -38,7 +39,7 @@ describe('SystemWideAlertMenuProvider', () => { TestBed.configureTestingModule({ providers: [ SystemWideAlertMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(SystemWideAlertMenuProvider); diff --git a/src/app/shared/menu/providers/workflow.menu.spec.ts b/src/app/shared/menu/providers/workflow.menu.spec.ts index 14b14db115..5c92bae656 100644 --- a/src/app/shared/menu/providers/workflow.menu.spec.ts +++ b/src/app/shared/menu/providers/workflow.menu.spec.ts @@ -14,19 +14,20 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { WorkflowMenuProvider } from './workflow.menu'; import { PartialMenuSection } from '../menu-provider.model'; -const expectedSections: PartialMenuSection[] = [ - { - visible: true, - model: { - type: MenuItemType.LINK, - text: 'menu.section.workflow', - link: '/admin/workflow', - }, - icon: 'user-check', - }, -]; - describe('WorkflowMenuProvider', () => { + + const expectedSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.workflow', + link: '/admin/workflow', + }, + icon: 'user-check', + }, + ]; + let provider: WorkflowMenuProvider; let authorizationServiceStub = new AuthorizationDataServiceStub(); @@ -38,7 +39,7 @@ describe('WorkflowMenuProvider', () => { TestBed.configureTestingModule({ providers: [ WorkflowMenuProvider, - { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + {provide: AuthorizationDataService, useValue: authorizationServiceStub}, ], }); provider = TestBed.inject(WorkflowMenuProvider);