diff --git a/e2e/src/item-statistics/item-statistics.e2e-spec.ts b/e2e/src/item-statistics/item-statistics.e2e-spec.ts new file mode 100644 index 00000000000..58cf569d2aa --- /dev/null +++ b/e2e/src/item-statistics/item-statistics.e2e-spec.ts @@ -0,0 +1,36 @@ +import { ProtractorPage } from './item-statistics.po'; +import { browser } from 'protractor'; +import { UIURLCombiner } from '../../../src/app/core/url-combiner/ui-url-combiner'; + +describe('protractor Item statics', () => { + let page: ProtractorPage; + + beforeEach(() => { + page = new ProtractorPage(); + }); + + it('should contain element ds-item-page when navigating when navigating to an item page', () => { + page.navigateToItemPage(); + expect(page.elementTagExists('ds-item-page')).toEqual(true); + expect(page.elementTagExists('ds-item-statistics-page')).toEqual(false); + }); + + it('should redirect to the entity page when navigating to an item page', () => { + page.navigateToItemPage(); + expect(browser.getCurrentUrl()).toEqual(new UIURLCombiner(page.ENTITYPAGE).toString()); + expect(browser.getCurrentUrl()).not.toEqual(new UIURLCombiner(page.ITEMSTATISTICSPAGE).toString()); + expect(browser.getCurrentUrl()).not.toEqual(new UIURLCombiner(page.ITEMPAGE).toString()); + }); + + it('should contain element ds-item-statistics-page when navigating when navigating to an item statistics page', () => { + page.navigateToItemStatisticsPage(); + expect(page.elementTagExists('ds-item-statistics-page')).toEqual(true); + expect(page.elementTagExists('ds-item-page')).toEqual(false); + }); + it('should contain the item statistics page url when navigating to an item statistics page', () => { + page.navigateToItemStatisticsPage(); + expect(browser.getCurrentUrl()).toEqual(new UIURLCombiner(page.ITEMSTATISTICSPAGE).toString()); + expect(browser.getCurrentUrl()).not.toEqual(new UIURLCombiner(page.ENTITYPAGE).toString()); + expect(browser.getCurrentUrl()).not.toEqual(new UIURLCombiner(page.ITEMPAGE).toString()); + }); +}); diff --git a/e2e/src/item-statistics/item-statistics.po.ts b/e2e/src/item-statistics/item-statistics.po.ts new file mode 100644 index 00000000000..ec227b9636e --- /dev/null +++ b/e2e/src/item-statistics/item-statistics.po.ts @@ -0,0 +1,18 @@ +import { browser, element, by } from 'protractor'; + +export class ProtractorPage { + ITEMPAGE = '/items/e98b0f27-5c19-49a0-960d-eb6ad5287067'; + ENTITYPAGE = '/entities/publication/e98b0f27-5c19-49a0-960d-eb6ad5287067'; + ITEMSTATISTICSPAGE = '/statistics/items/e98b0f27-5c19-49a0-960d-eb6ad5287067'; + + navigateToItemPage() { + return browser.get(this.ITEMPAGE); + } + navigateToItemStatisticsPage() { + return browser.get(this.ITEMSTATISTICSPAGE); + } + + elementTagExists(tag: string) { + return element(by.tagName(tag)).isPresent(); + } +} diff --git a/package.json b/package.json index 80af52e264c..652ab409ac5 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,8 @@ }, "private": true, "resolutions": { - "minimist": "^1.2.5" + "minimist": "^1.2.5", + "webdriver-manager": "^12.1.8" }, "dependencies": { "@angular/animations": "~10.2.3", diff --git a/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts b/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts index 17ec0ff1336..01d6cc74395 100644 --- a/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts +++ b/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts @@ -15,9 +15,9 @@ import { RemoteData } from '../../../core/data/remote-data'; import { AbstractTrackableComponent } from '../../../shared/trackable/abstract-trackable.component'; import { environment } from '../../../../environments/environment'; import { getItemPageRoute } from '../../item-page-routing-paths'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item-page.resolver'; import { getAllSucceededRemoteData } from '../../../core/shared/operators'; import { hasValue } from '../../../shared/empty.util'; +import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item.resolver'; @Component({ selector: 'ds-abstract-item-update', diff --git a/src/app/+item-page/item-page.resolver.ts b/src/app/+item-page/item-page.resolver.ts index a131cda7f86..7edffc53578 100644 --- a/src/app/+item-page/item-page.resolver.ts +++ b/src/app/+item-page/item-page.resolver.ts @@ -4,39 +4,24 @@ import { Observable } from 'rxjs'; import { RemoteData } from '../core/data/remote-data'; import { ItemDataService } from '../core/data/item-data.service'; import { Item } from '../core/shared/item.model'; -import { followLink, FollowLinkConfig } from '../shared/utils/follow-link-config.model'; -import { FindListOptions } from '../core/data/request.models'; -import { getFirstCompletedRemoteData } from '../core/shared/operators'; import { Store } from '@ngrx/store'; -import { ResolvedAction } from '../core/resolving/resolver.actions'; import { map } from 'rxjs/operators'; import { hasValue } from '../shared/empty.util'; import { getItemPageRoute } from './item-page-routing-paths'; +import { ItemResolver } from './item.resolver'; /** - * The self links defined in this list are expected to be requested somewhere in the near future - * Requesting them as embeds will limit the number of requests - */ -export const ITEM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig[] = [ - followLink('owningCollection', undefined, true, true, true, - followLink('parentCommunity', undefined, true, true, true, - followLink('parentCommunity')) - ), - followLink('bundles', new FindListOptions(), true, true, true, followLink('bitstreams')), - followLink('relationships'), - followLink('version', undefined, true, true, true, followLink('versionhistory')), -]; - -/** - * This class represents a resolver that requests a specific item before the route is activated + * This class represents a resolver that requests a specific item before the route is activated and will redirect to the + * entity page */ @Injectable() -export class ItemPageResolver implements Resolve> { +export class ItemPageResolver extends ItemResolver { constructor( - private itemService: ItemDataService, - private store: Store, - private router: Router + protected itemService: ItemDataService, + protected store: Store, + protected router: Router ) { + super(itemService, store, router); } /** @@ -47,12 +32,7 @@ export class ItemPageResolver implements Resolve> { * or an error if something went wrong */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { - const itemRD$ = this.itemService.findById(route.params.id, - true, - false, - ...ITEM_PAGE_LINKS_TO_FOLLOW - ).pipe( - getFirstCompletedRemoteData(), + return super.resolve(route, state).pipe( map((rd: RemoteData) => { if (rd.hasSucceeded && hasValue(rd.payload)) { const itemRoute = getItemPageRoute(rd.payload); @@ -66,11 +46,5 @@ export class ItemPageResolver implements Resolve> { return rd; }) ); - - itemRD$.subscribe((itemRD: RemoteData) => { - this.store.dispatch(new ResolvedAction(state.url, itemRD.payload)); - }); - - return itemRD$; } } diff --git a/src/app/+item-page/item.resolver.ts b/src/app/+item-page/item.resolver.ts new file mode 100644 index 00000000000..99b96511fe2 --- /dev/null +++ b/src/app/+item-page/item.resolver.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs'; +import { RemoteData } from '../core/data/remote-data'; +import { ItemDataService } from '../core/data/item-data.service'; +import { Item } from '../core/shared/item.model'; +import { followLink, FollowLinkConfig } from '../shared/utils/follow-link-config.model'; +import { FindListOptions } from '../core/data/request.models'; +import { getFirstCompletedRemoteData } from '../core/shared/operators'; +import { Store } from '@ngrx/store'; +import { ResolvedAction } from '../core/resolving/resolver.actions'; + +/** + * The self links defined in this list are expected to be requested somewhere in the near future + * Requesting them as embeds will limit the number of requests + */ +export const ITEM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig[] = [ + followLink('owningCollection', undefined, true, true, true, + followLink('parentCommunity', undefined, true, true, true, + followLink('parentCommunity')) + ), + followLink('bundles', new FindListOptions(), true, true, true, followLink('bitstreams')), + followLink('relationships'), + followLink('version', undefined, true, true, true, followLink('versionhistory')), +]; + +/** + * This class represents a resolver that requests a specific item before the route is activated + */ +@Injectable() +export class ItemResolver implements Resolve> { + constructor( + protected itemService: ItemDataService, + protected store: Store, + protected router: Router + ) { + } + + /** + * Method for resolving an item based on the parameters in the current route + * @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot + * @param {RouterStateSnapshot} state The current RouterStateSnapshot + * @returns Observable<> Emits the found item based on the parameters in the current route, + * or an error if something went wrong + */ + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { + const itemRD$ = this.itemService.findById(route.params.id, + true, + false, + ...ITEM_PAGE_LINKS_TO_FOLLOW + ).pipe( + getFirstCompletedRemoteData(), + ); + + itemRD$.subscribe((itemRD: RemoteData) => { + this.store.dispatch(new ResolvedAction(state.url, itemRD.payload)); + }); + + return itemRD$; + } +} diff --git a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts index 2b9bbd6b3d5..529349eb89b 100644 --- a/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts +++ b/src/app/core/breadcrumbs/item-breadcrumb.resolver.ts @@ -4,7 +4,7 @@ import { ItemDataService } from '../data/item-data.service'; import { Item } from '../shared/item.model'; import { DSOBreadcrumbResolver } from './dso-breadcrumb.resolver'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; -import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../+item-page/item-page.resolver'; +import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../+item-page/item.resolver'; /** * The class that resolves the BreadcrumbConfig object for an Item diff --git a/src/app/statistics-page/statistics-page-routing.module.ts b/src/app/statistics-page/statistics-page-routing.module.ts index 6a133fc9ac9..5b96bcca6e4 100644 --- a/src/app/statistics-page/statistics-page-routing.module.ts +++ b/src/app/statistics-page/statistics-page-routing.module.ts @@ -3,13 +3,13 @@ import { RouterModule } from '@angular/router'; import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.resolver'; import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service'; import { StatisticsPageModule } from './statistics-page.module'; -import { ItemPageResolver } from '../+item-page/item-page.resolver'; import { CollectionPageResolver } from '../+collection-page/collection-page.resolver'; import { CommunityPageResolver } from '../+community-page/community-page.resolver'; import { ThemedCollectionStatisticsPageComponent } from './collection-statistics-page/themed-collection-statistics-page.component'; import { ThemedCommunityStatisticsPageComponent } from './community-statistics-page/themed-community-statistics-page.component'; import { ThemedItemStatisticsPageComponent } from './item-statistics-page/themed-item-statistics-page.component'; import { ThemedSiteStatisticsPageComponent } from './site-statistics-page/themed-site-statistics-page.component'; +import { ItemResolver } from '../+item-page/item.resolver'; @NgModule({ imports: [ @@ -34,7 +34,7 @@ import { ThemedSiteStatisticsPageComponent } from './site-statistics-page/themed { path: `items/:id`, resolve: { - scope: ItemPageResolver, + scope: ItemResolver, breadcrumb: I18nBreadcrumbResolver }, data: { @@ -75,7 +75,7 @@ import { ThemedSiteStatisticsPageComponent } from './site-statistics-page/themed I18nBreadcrumbsService, CollectionPageResolver, CommunityPageResolver, - ItemPageResolver + ItemResolver ] }) export class StatisticsPageRoutingModule { diff --git a/yarn.lock b/yarn.lock index 9b6e2d31d66..d6388ddb537 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11933,10 +11933,10 @@ webdriver-js-extender@2.1.0: "@types/selenium-webdriver" "^3.0.0" selenium-webdriver "^3.0.1" -webdriver-manager@^12.1.7: - version "12.1.7" - resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.7.tgz#ed4eaee8f906b33c146e869b55e850553a1b1162" - integrity sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA== +webdriver-manager@^12.1.7, webdriver-manager@^12.1.8: + version "12.1.8" + resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.8.tgz#5e70e73eaaf53a0767d5745270addafbc5905fd4" + integrity sha512-qJR36SXG2VwKugPcdwhaqcLQOD7r8P2Xiv9sfNbfZrKBnX243iAkOueX1yAmeNgIKhJ3YAT/F2gq6IiEZzahsg== dependencies: adm-zip "^0.4.9" chalk "^1.1.1"