From bc0865bdb9db29b6ebae26c4f77670ee523e21a1 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Tue, 2 Oct 2018 18:53:43 +0100 Subject: [PATCH] [ADF-3610] fix pdf worker memory leak (#3843) * fix pdf worker memory leak * test fixes * fix computed style test * fix lint --- .../components/pdfViewer.component.spec.ts | 31 +++++-- .../viewer/components/pdfViewer.component.ts | 8 ++ .../components/viewer.component.spec.ts | 83 ++++++++++++------- 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index f5a0793509..d5f839445c 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -27,6 +27,7 @@ import { setupTestBed } from '../../testing/setupTestBed'; import { CoreModule } from '../../core.module'; import { TranslationService } from '../../services/translation.service'; import { TranslationMock } from '../../mock/translation.service.mock'; +import { take } from 'rxjs/operators'; declare const pdfjsLib: any; @@ -201,6 +202,10 @@ describe('Test PdfViewer component', () => { }); }); + afterEach(() => { + fixtureUrlTestComponent.destroy(); + }); + it('should Canvas be present', (done) => { fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { @@ -250,16 +255,22 @@ describe('Test PdfViewer component', () => { let componentBlobTestComponent: BlobTestComponent; let elementBlobTestComponent: HTMLElement; - beforeEach((done) => { + beforeEach(done => { fixtureBlobTestComponent = TestBed.createComponent(BlobTestComponent); componentBlobTestComponent = fixtureBlobTestComponent.componentInstance; elementBlobTestComponent = fixtureBlobTestComponent.nativeElement; fixtureBlobTestComponent.detectChanges(); - componentBlobTestComponent.pdfViewerComponent.rendered.subscribe(() => { - done(); - }); + componentBlobTestComponent.pdfViewerComponent.rendered + .pipe(take(1)) + .subscribe(() => { + done(); + }); + }); + + afterEach(() => { + fixtureBlobTestComponent.destroy(); }); it('should Canvas be present', async(() => { @@ -319,9 +330,15 @@ describe('Test PdfViewer component', () => { fixtureUrlTestComponent.detectChanges(); - componentUrlTestComponent.pdfViewerComponent.rendered.subscribe(() => { - done(); - }); + componentUrlTestComponent.pdfViewerComponent.rendered + .pipe(take(1)) + .subscribe(() => { + done(); + }); + }); + + afterEach(() => { + fixtureUrlTestComponent.destroy(); }); it('should Total number of pages be loaded', (done) => { diff --git a/lib/core/viewer/components/pdfViewer.component.ts b/lib/core/viewer/components/pdfViewer.component.ts index db47007c11..a4ad90feaf 100644 --- a/lib/core/viewer/components/pdfViewer.component.ts +++ b/lib/core/viewer/components/pdfViewer.component.ts @@ -187,6 +187,14 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { this.documentContainer.removeEventListener('pagesloaded', this.onPagesLoaded, true); this.documentContainer.removeEventListener('textlayerrendered', this.onPagerendered, true); } + + if (this.loadingTask) { + try { + this.loadingTask.destroy(); + } catch {} + + this.loadingTask = null; + } } toggleThumbnails() { diff --git a/lib/core/viewer/components/viewer.component.spec.ts b/lib/core/viewer/components/viewer.component.spec.ts index 39f67af9bd..e12a8ecc65 100644 --- a/lib/core/viewer/components/viewer.component.spec.ts +++ b/lib/core/viewer/components/viewer.component.spec.ts @@ -159,10 +159,6 @@ describe('ViewerComponent', () => { alfrescoApiService = TestBed.get(AlfrescoApiService); }); - afterEach(() => { - fixture.destroy(); - }); - it('should change display name every time node changes', fakeAsync(() => { spyOn(alfrescoApiService.nodesApi, 'getNodeInfo').and.returnValues( Promise.resolve({ name: 'file1', content: {} }), @@ -191,44 +187,63 @@ describe('ViewerComponent', () => { describe('Viewer Example Component Rendering', () => { - it('should use custom toolbar', () => { + it('should use custom toolbar', (done) => { let customFixture = TestBed.createComponent(ViewerWithCustomToolbarComponent); let customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); - expect(customElement.querySelector('.custom-toolbar-element')).toBeDefined(); + fixture.whenStable().then(() => { + expect(customElement.querySelector('.custom-toolbar-element')).toBeDefined(); + done(); + }); }); - it('should use custom toolbar actions', () => { + it('should use custom toolbar actions', (done) => { let customFixture = TestBed.createComponent(ViewerWithCustomToolbarActionsComponent); let customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); - expect(customElement.querySelector('#custom-button')).toBeDefined(); + fixture.whenStable().then(() => { + expect(customElement.querySelector('#custom-button')).toBeDefined(); + done(); + }); }); - it('should use custom info drawer', () => { + it('should use custom info drawer', (done) => { let customFixture = TestBed.createComponent(ViewerWithCustomSidebarComponent); let customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); - expect(customElement.querySelector('.custom-info-drawer-element')).toBeDefined(); + + fixture.whenStable().then(() => { + expect(customElement.querySelector('.custom-info-drawer-element')).toBeDefined(); + done(); + }); }); - it('should use custom open with menu', () => { + it('should use custom open with menu', (done) => { let customFixture = TestBed.createComponent(ViewerWithCustomOpenWithComponent); let customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); - expect(customElement.querySelector('.adf-viewer-container-open-with')).toBeDefined(); + + fixture.whenStable().then(() => { + expect(customElement.querySelector('.adf-viewer-container-open-with')).toBeDefined(); + done(); + }); }); - it('should use custom more actions menu', () => { + it('should use custom more actions menu', (done) => { let customFixture = TestBed.createComponent(ViewerWithCustomMoreActionsComponent); let customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); - expect(customElement.querySelector('.adf-viewer-container-more-actions')).toBeDefined(); + + fixture.whenStable().then(() => { + expect(customElement.querySelector('.adf-viewer-container-more-actions')).toBeDefined(); + done(); + }); + }); }); @@ -242,13 +257,9 @@ describe('ViewerComponent', () => { fixture.detectChanges(); }); - afterEach(() => { - fixture.destroy(); - }); - describe('SideBar Test', () => { - it('should NOT display sidebar if is not allowed', () => { + it('should NOT display sidebar if is not allowed', (done) => { component.showSidebar = true; component.allowSidebar = false; fixture.detectChanges(); @@ -256,20 +267,23 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { let sidebar = element.querySelector('#adf-right-sidebar'); expect(sidebar).toBeNull(); + done(); }); }); - it('should display sidebar on the right side', () => { + it('should display sidebar on the right side', (done) => { + component.allowSidebar = true; component.showSidebar = true; fixture.detectChanges(); fixture.whenStable().then(() => { let sidebar = element.querySelector('#adf-right-sidebar'); expect(getComputedStyle(sidebar).order).toEqual('4'); + done(); }); }); - it('should NOT display left sidebar if is not allowed', () => { + it('should NOT display left sidebar if is not allowed', (done) => { component.showLeftSidebar = true; component.allowSidebar = false; fixture.detectChanges(); @@ -277,17 +291,20 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { let sidebar = element.querySelector('#adf-left-sidebar'); expect(sidebar).toBeNull(); + done(); }); }); - it('should display sidebar on the left side', () => { + it('should display sidebar on the left side', (done) => { + component.allowSidebar = true; component.showLeftSidebar = true; fixture.detectChanges(); fixture.whenStable().then(() => { let sidebar = element.querySelector('#adf-left-sidebar'); - expect(getComputedStyle(sidebar).order).toEqual('4'); + expect(getComputedStyle(sidebar).order).toEqual('1'); + done(); }); }); }); @@ -441,8 +458,13 @@ describe('ViewerComponent', () => { }); })); - it('should Close button be present if overlay mode', () => { - expect(element.querySelector('.adf-viewer-close-button')).not.toBeNull(); + it('should Close button be present if overlay mode', (done) => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(element.querySelector('.adf-viewer-close-button')).not.toBeNull(); + done(); + }); }); it('should Click on close button hide the viewer', () => { @@ -723,7 +745,7 @@ describe('ViewerComponent', () => { }); }); - xit('should display the media player if the file identified by mimetype is a media when the filename has no extension', async(() => { + it('should display the media player if the file identified by mimetype is a media when the filename has no extension', (done) => { component.urlFile = 'content'; component.mimeType = 'video/mp4'; fixture.detectChanges(); @@ -732,10 +754,11 @@ describe('ViewerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); expect(element.querySelector('adf-media-player')).not.toBeNull(); + done(); }); - })); + }); - xit('should node without content show unkonwn', async(() => { + it('should node without content show unkonwn', async(() => { const displayName = 'the-name'; const nodeDetails = { name: displayName, id: '12' }; const contentUrl = '/content/url/path'; @@ -865,10 +888,6 @@ describe('ViewerComponent', () => { fixture.detectChanges(); }); - afterEach(() => { - fixture.destroy(); - }); - it('should request only if enabled', () => { const domElement = jasmine.createSpyObj('el', ['requestFullscreen']); spyOn(fixture.nativeElement, 'querySelector').and.returnValue(domElement);