From 181cee72d67825756b323d78ab56378f285d1a87 Mon Sep 17 00:00:00 2001 From: davidcanonieto Date: Thu, 18 Apr 2019 11:34:16 +0200 Subject: [PATCH] [ADF-4364] Fix Back button action on Viewer Component (#4613) * [ADF-3364] Fix Back button action on Viewer Component * [ADF-4364] Fix Module providers * [ADF-4364] Add unit tests * [ADF-4364] Fix unit tests * [ADF-4364] Fix lazy loading module of Viewer component --- .../services/previous-route.service.spec.ts | 61 +++++++++++++++++ lib/core/services/previous-route.service.ts | 42 ++++++++++++ lib/core/services/public-api.ts | 1 + .../components/pdfViewer.component.spec.ts | 6 +- .../components/viewer.component.spec.ts | 66 ++++++++++++++++++- .../viewer/components/viewer.component.ts | 16 ++++- .../viewer-extension.directive.spec.ts | 4 +- 7 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 lib/core/services/previous-route.service.spec.ts create mode 100644 lib/core/services/previous-route.service.ts diff --git a/lib/core/services/previous-route.service.spec.ts b/lib/core/services/previous-route.service.spec.ts new file mode 100644 index 0000000000..5972b95d1e --- /dev/null +++ b/lib/core/services/previous-route.service.spec.ts @@ -0,0 +1,61 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TestBed } from '@angular/core/testing'; +import { setupTestBed } from '../testing/setupTestBed'; +import { PreviousRouteService } from './previous-route.service'; +import { Router, NavigationEnd } from '@angular/router'; +import { Observable } from 'rxjs'; +import { CoreTestingModule } from 'core/testing/core.testing.module'; + +class MockRouter { + firstUrl = new NavigationEnd(0, '/files', '/files'); + secondUrl = new NavigationEnd(0, '/home', '/home'); + events = new Observable((observer) => { + observer.next(this.firstUrl); + observer.next(this.secondUrl); + observer.complete(); + }); +} + +describe('Previous route service ', () => { + + let previousRouteService: PreviousRouteService; + + setupTestBed({ + imports: [ + CoreTestingModule + ], + providers: [ + { provide: Router, useClass: MockRouter }, + PreviousRouteService + ] + }); + + beforeEach(() => { + previousRouteService = TestBed.get(PreviousRouteService); + }); + + it('should be able to create the service', () => { + expect(previousRouteService).not.toBeNull(); + expect(previousRouteService).toBeDefined(); + }); + + it('should set curent url when new page loads', () => { + expect(previousRouteService.getPreviousUrl()).toBe('/files'); + }); +}); diff --git a/lib/core/services/previous-route.service.ts b/lib/core/services/previous-route.service.ts new file mode 100644 index 0000000000..d545943723 --- /dev/null +++ b/lib/core/services/previous-route.service.ts @@ -0,0 +1,42 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; + +@Injectable({ + providedIn: 'root' +}) +export class PreviousRouteService { + + private previousUrl: string; + private currentUrl: string; + + constructor(private router: Router) { + this.currentUrl = this.router.url; + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + this.previousUrl = this.currentUrl; + this.currentUrl = event.url; + } + }); + } + + public getPreviousUrl(): string { + return this.previousUrl; + } +} diff --git a/lib/core/services/public-api.ts b/lib/core/services/public-api.ts index 3af0268852..f9bf816079 100644 --- a/lib/core/services/public-api.ts +++ b/lib/core/services/public-api.ts @@ -55,3 +55,4 @@ export * from './jwt-helper.service'; export * from './download-zip.service'; export * from './lock.service'; export * from './automation.service'; +export * from './previous-route.service'; diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index ae84a6424c..bf27dac71a 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -276,23 +276,21 @@ describe('Test PdfViewer component', () => { document.body.removeChild(elementBlobTestComponent); }); - it('should Canvas be present', (done) => { + it('should Canvas be present', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { expect(elementBlobTestComponent.querySelector('.adf-pdfViewer')).not.toBeNull(); expect(elementBlobTestComponent.querySelector('.adf-viewer-pdf-viewer')).not.toBeNull(); - done(); }); }); - it('should Next an Previous Buttons be present', (done) => { + it('should Next an Previous Buttons be present', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { expect(elementBlobTestComponent.querySelector('#viewer-previous-page-button')).not.toBeNull(); expect(elementBlobTestComponent.querySelector('#viewer-next-page-button')).not.toBeNull(); - done(); }); }); diff --git a/lib/core/viewer/components/viewer.component.spec.ts b/lib/core/viewer/components/viewer.component.spec.ts index a9865e1b30..c915d8713f 100644 --- a/lib/core/viewer/components/viewer.component.spec.ts +++ b/lib/core/viewer/components/viewer.component.spec.ts @@ -18,18 +18,21 @@ import { Location } from '@angular/common'; import { SpyLocation } from '@angular/common/testing'; import { Component } from '@angular/core'; -import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; +import { ComponentFixture, TestBed, fakeAsync, tick, async } from '@angular/core/testing'; import { AlfrescoApiService, RenditionsService } from '../../services'; import { CoreModule } from '../../core.module'; -import { throwError } from 'rxjs'; +import { throwError, Observable } from 'rxjs'; import { EventMock } from '../../mock/event.mock'; import { RenderingQueueServices } from '../services/rendering-queue.services'; import { ViewerComponent } from './viewer.component'; import { setupTestBed } from '../../testing/setupTestBed'; import { AlfrescoApiServiceMock } from '../../mock/alfresco-api.service.mock'; import { NodeEntry } from '@alfresco/js-api'; +import { PreviousRouteService } from 'core/services/previous-route.service'; +import { RouterTestingModule } from '@angular/router/testing'; +import { Router, NavigationEnd } from '@angular/router'; @Component({ selector: 'adf-viewer-container-toolbar', @@ -120,16 +123,28 @@ class ViewerWithCustomOpenWithComponent { class ViewerWithCustomMoreActionsComponent { } +class MockRouter { + navigate = jasmine.createSpy('navigate'); + firstUrl = new NavigationEnd(0, '/files', '/files'); + events = new Observable((observer) => { + observer.next(this.firstUrl); + observer.complete(); + }); +} + describe('ViewerComponent', () => { let component: ViewerComponent; let fixture: ComponentFixture; let alfrescoApiService: AlfrescoApiService; + let previousRouteService: PreviousRouteService; + let router: Router; let element: HTMLElement; setupTestBed({ imports: [ - CoreModule.forRoot() + CoreModule.forRoot(), + RouterTestingModule ], declarations: [ ViewerWithCustomToolbarComponent, @@ -147,7 +162,9 @@ describe('ViewerComponent', () => { } } }, + { provide: Router, useClass: MockRouter }, RenderingQueueServices, + PreviousRouteService, { provide: Location, useClass: SpyLocation } ] }); @@ -158,6 +175,8 @@ describe('ViewerComponent', () => { component = fixture.componentInstance; alfrescoApiService = TestBed.get(AlfrescoApiService); + previousRouteService = TestBed.get(PreviousRouteService); + router = TestBed.get(Router); }); describe('Extension Type Test', () => { @@ -623,6 +642,47 @@ describe('ViewerComponent', () => { }); }); + it('should render close viewer button if it is not a shared link', (done) => { + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(element.querySelector('[data-automation-id="adf-toolbar-back"]')).toBeDefined(); + expect(element.querySelector('[data-automation-id="adf-toolbar-back"]')).not.toBeNull(); + done(); + }); + }); + + it('should go back when back button is clicked', async(() => { + + spyOn(previousRouteService, 'getPreviousUrl').and.returnValue('home'); + + const button: HTMLButtonElement = element.querySelector('[data-automation-id="adf-toolbar-back"]') as HTMLButtonElement; + button.click(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(router.navigate).toHaveBeenCalled(); + }); + })); + + it('should render close viewer button if it is a shared link', (done) => { + spyOn(alfrescoApiService.getInstance().core.sharedlinksApi, 'getSharedLink') + .and.returnValue(Promise.reject({})); + + component.sharedLinkId = 'the-Shared-Link-id'; + component.urlFile = null; + component.mimeType = null; + + component.ngOnChanges(null); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(element.querySelector('[data-automation-id="adf-toolbar-back"]')).toBeNull(); + done(); + }); + }); + }); describe('View', () => { diff --git a/lib/core/viewer/components/viewer.component.ts b/lib/core/viewer/components/viewer.component.ts index 30787a25a4..1b95a7c66d 100644 --- a/lib/core/viewer/components/viewer.component.ts +++ b/lib/core/viewer/components/viewer.component.ts @@ -25,6 +25,7 @@ import { RenditionPaging, SharedLinkEntry, Node, RenditionEntry, NodeEntry } fro import { BaseEvent } from '../../events'; import { AlfrescoApiService } from '../../services/alfresco-api.service'; import { LogService } from '../../services/log.service'; +import { PreviousRouteService } from '../../services/previous-route.service'; import { ViewerMoreActionsComponent } from './viewer-more-actions.component'; import { ViewerOpenWithComponent } from './viewer-open-with.component'; import { ViewerSidebarComponent } from './viewer-sidebar.component'; @@ -32,6 +33,7 @@ import { ViewerToolbarComponent } from './viewer-toolbar.component'; import { Subscription } from 'rxjs'; import { ViewUtilService } from '../services/view-util.service'; import { AppExtensionService, ViewerExtensionRef } from '@alfresco/adf-extensions'; +import { Router } from '@angular/router'; @Component({ selector: 'adf-viewer', @@ -239,7 +241,9 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { private logService: LogService, private location: Location, private extensionService: AppExtensionService, - private el: ElementRef) { + private el: ElementRef, + private router: Router, + private previousRouteService: PreviousRouteService) { } isSourceDefined(): boolean { @@ -304,6 +308,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { } ); } else if (this.sharedLinkId) { + this.allowGoBack = false; this.apiService.sharedLinksApi.getSharedLink(this.sharedLinkId).then( (sharedLinkEntry: SharedLinkEntry) => { @@ -479,7 +484,14 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { this.goBack.next(event); if (!event.defaultPrevented) { - this.location.back(); + + const previousUrl = this.previousRouteService.getPreviousUrl(); + + if (previousUrl && previousUrl.includes('login') || window.history.length <= 2) { + this.router.navigate([{outlets: {overlay: null, primary: ['home']}}]); + } else { + this.location.back(); + } } } } diff --git a/lib/core/viewer/directives/viewer-extension.directive.spec.ts b/lib/core/viewer/directives/viewer-extension.directive.spec.ts index b6217502cf..4970b21fbe 100644 --- a/lib/core/viewer/directives/viewer-extension.directive.spec.ts +++ b/lib/core/viewer/directives/viewer-extension.directive.spec.ts @@ -23,6 +23,7 @@ import { ViewerComponent } from '../components/viewer.component'; import { ViewerExtensionDirective } from './viewer-extension.directive'; import { setupTestBed } from '../../testing/setupTestBed'; import { CoreModule } from '../../core.module'; +import { RouterTestingModule } from '@angular/router/testing'; describe('ExtensionViewerDirective', () => { let extensionViewerDirective: ViewerExtensionDirective; @@ -35,7 +36,8 @@ describe('ExtensionViewerDirective', () => { setupTestBed({ imports: [ - CoreModule.forRoot() + CoreModule.forRoot(), + RouterTestingModule ], providers: [ { provide: Location, useClass: SpyLocation },