diff --git a/lib/content-services/karma.conf.js b/lib/content-services/karma.conf.js index 928e301d5e..be189b9175 100644 --- a/lib/content-services/karma.conf.js +++ b/lib/content-services/karma.conf.js @@ -9,9 +9,8 @@ module.exports = function (config) { basePath: '../../', files: [ - { pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false }, + { pattern: 'node_modules/pdfjs-dist/build/pdf.min.mjs', type: 'module', included: true, watched: false }, + { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.min.mjs', type: 'module', included: true, watched: false }, { pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, @@ -63,7 +62,7 @@ module.exports = function (config) { }, mochaReporter: { - ignoreSkipped: process.env?.KARMA_IGNORE_SKIPPED === 'true' + ignoreSkipped: process.env.KARMA_IGNORE_SKIPPED === 'true' }, coverageReporter: { diff --git a/lib/content-services/src/test.ts b/lib/content-services/src/test.ts index 7776832eda..739eefa31a 100644 --- a/lib/content-services/src/test.ts +++ b/lib/content-services/src/test.ts @@ -25,5 +25,4 @@ getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDyn teardown: { destroyAfterEach: true } }); -declare const pdfjsLib: any; -pdfjsLib.GlobalWorkerOptions.workerSrc = 'base/pdfjs-dist/build/pdf.worker.min.js'; +(window as any).pdfjsLib = (window as any).pdfjsLib || require('pdfjs-dist/build/pdf.min.mjs'); diff --git a/lib/core/karma.conf.js b/lib/core/karma.conf.js index 3568a46c2c..eba81852a9 100644 --- a/lib/core/karma.conf.js +++ b/lib/core/karma.conf.js @@ -7,12 +7,7 @@ const { constants } = require('karma'); module.exports = function (config) { config.set({ basePath: '../../', - files: [ - { pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false, served: true }, - { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.min.js', included: true, watched: false, served: true }, - { pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false }, { pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, @@ -31,14 +26,13 @@ module.exports = function (config) { included: false, served: true, watched: false - } + }, + { pattern: 'node_modules/resize-observer-polyfill/dist/ResizeObserver.global.js', included: true, watched: false } ], frameworks: ['jasmine-ajax', 'jasmine', '@angular-devkit/build-angular'], proxies: { - '/pdf.worker.min.js': '/base/node_modules/pdfjs-dist/build/pdf.worker.min.js', - '/pdf.worker.js': '/base/node_modules/pdfjs-dist/build/pdf.worker.js', '/fake-url-file.png': '/base/lib/core/src/lib/assets/images/logo.png', '/logo.png': '/base/lib/core/src/lib/assets/images/logo.png', '/alfresco-logo.svg': '/base/lib/core/src/lib/assets/images/alfresco-logo.svg', @@ -81,7 +75,7 @@ module.exports = function (config) { suppressAll: true // removes the duplicated traces }, mochaReporter: { - ignoreSkipped: process.env?.KARMA_IGNORE_SKIPPED === 'true' + ignoreSkipped: process.env.KARMA_IGNORE_SKIPPED === 'true' }, coverageReporter: { diff --git a/lib/core/ng-package.json b/lib/core/ng-package.json index aad1ffb2f8..5a35e655c4 100644 --- a/lib/core/ng-package.json +++ b/lib/core/ng-package.json @@ -7,6 +7,11 @@ "input": "./breadcrumbs/src/styles", "output": "./breadcrumbs/styles" }, + { + "glob": "pdf.worker.mjs", + "input": "./assets/pdfjs", + "output": "assets/pdfjs" + }, { "glob": "custom-theme/**/*", "input": "./", diff --git a/lib/core/src/lib/common/services/download.service.spec.ts b/lib/core/src/lib/common/services/download.service.spec.ts index 7394301289..ad79900d88 100644 --- a/lib/core/src/lib/common/services/download.service.spec.ts +++ b/lib/core/src/lib/common/services/download.service.spec.ts @@ -26,15 +26,13 @@ describe('DownloadService', () => { describe('Download blob', () => { it('Should use native msSaveOrOpenBlob if the browser is IE', () => { - const navigatorAny: any = window.navigator; - - // eslint-disable-next-line no-underscore-dangle - navigatorAny.__defineGetter__('msSaveOrOpenBlob', (result) => { - expect(result).toBeUndefined(); - }); + const mockNavigator = jasmine.createSpyObj(['msSaveOrOpenBlob']); + spyOnProperty(window, 'navigator', 'get').and.returnValue(mockNavigator); const blob = new Blob([''], { type: 'text/html' }); service.downloadBlob(blob, 'test_ie'); + + expect(mockNavigator.msSaveOrOpenBlob).toHaveBeenCalledOnceWith(blob, 'test_ie'); }); }); }); diff --git a/lib/core/src/lib/notifications/components/notification-history.component.spec.ts b/lib/core/src/lib/notifications/components/notification-history.component.spec.ts index 5e1524b934..4ae6f1599f 100644 --- a/lib/core/src/lib/notifications/components/notification-history.component.spec.ts +++ b/lib/core/src/lib/notifications/components/notification-history.component.spec.ts @@ -16,13 +16,16 @@ */ import { ComponentFixture, inject, TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../../testing/core.testing.module'; import { NotificationHistoryComponent } from './notification-history.component'; import { OverlayContainer } from '@angular/cdk/overlay'; import { NotificationService } from '../services/notification.service'; import { StorageService } from '../../common/services/storage.service'; import { NOTIFICATION_TYPE, NotificationModel } from '../models/notification.model'; import { UnitTestingUtils } from '../../testing/unit-testing-utils'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopTranslateModule } from '../../testing/noop-translate.module'; +import { NoopAuthModule } from '../../testing/noop-auth.module'; +import { MatIconTestingModule } from '@angular/material/icon/testing'; describe('Notification History Component', () => { let fixture: ComponentFixture; @@ -40,7 +43,7 @@ describe('Notification History Component', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, NotificationHistoryComponent] + imports: [NoopAnimationsModule, NoopTranslateModule, NoopAuthModule, NotificationHistoryComponent, MatIconTestingModule] }); fixture = TestBed.createComponent(NotificationHistoryComponent); component = fixture.componentInstance; diff --git a/lib/core/src/lib/notifications/services/notification.service.spec.ts b/lib/core/src/lib/notifications/services/notification.service.spec.ts index 694525c501..c4eabd1f24 100644 --- a/lib/core/src/lib/notifications/services/notification.service.spec.ts +++ b/lib/core/src/lib/notifications/services/notification.service.spec.ts @@ -131,15 +131,15 @@ describe('NotificationService', () => { it('should open a message notification bar', async () => { fixture.componentInstance.sendMessage(); fixture.detectChanges(); - - expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); + const isLoaded = await testingUtils.checkIfMatSnackbarExists(); + expect(isLoaded).toBe(true); }); it('should open a message notification bar without custom configuration', async () => { fixture.componentInstance.sendMessageWithoutConfig(); fixture.detectChanges(); - - expect(await testingUtils.checkIfMatSnackbarExists()).toBe(true); + const isLoaded = await testingUtils.checkIfMatSnackbarExists(); + expect(isLoaded).toBe(true); }); it('should open a message notification bar with custom configuration', async () => { diff --git a/lib/core/src/lib/viewer/components/mock/pdfjs-lib.mock.ts b/lib/core/src/lib/viewer/components/mock/pdfjs-lib.mock.ts new file mode 100644 index 0000000000..8f4c90cd2f --- /dev/null +++ b/lib/core/src/lib/viewer/components/mock/pdfjs-lib.mock.ts @@ -0,0 +1,37 @@ +/*! + * @license + * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * 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. + */ + +export default { + GlobalWorkerOptions: {}, + getDocument() { + return { + loadingTask: () => ({ + destroy: () => Promise.resolve() + }), + promise: new Promise((resolve) => { + resolve({ + numPages: 6, + getPage: () => 'fakePage' + }); + }) + }; + }, + PasswordResponses: { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 + } +}; diff --git a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts index 40259428be..6504df299a 100644 --- a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts @@ -17,29 +17,22 @@ import { LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes'; import { Component, SimpleChange, ViewChild } from '@angular/core'; -import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing'; import { MatDialog } from '@angular/material/dialog'; import { By } from '@angular/platform-browser'; import { of } from 'rxjs'; -import { take } from 'rxjs/operators'; import { AppConfigService } from '../../../app-config'; import { EventMock } from '../../../mock'; -import { CoreTestingModule, UnitTestingUtils } from '../../../testing'; +import { NoopAuthModule, NoopTranslateModule, UnitTestingUtils } from '../../../testing'; import { RenderingQueueServices } from '../../services/rendering-queue.services'; import { PdfThumbListComponent } from '../pdf-viewer-thumbnails/pdf-viewer-thumbnails.component'; -import { PdfViewerComponent } from './pdf-viewer.component'; -import { AnnotationMode } from 'pdfjs-dist'; +import { PDFJS_MODULE, PDFJS_VIEWER_MODULE, PdfViewerComponent } from './pdf-viewer.component'; +import pdfjsLibMock from '../mock/pdfjs-lib.mock'; declare const pdfjsLib: any; @Component({ - selector: 'adf-test-dialog-component', - standalone: true, - template: '' -}) -class TestDialogComponent {} - -@Component({ + selector: 'adf-url-test-component', standalone: true, imports: [PdfViewerComponent], template: ` ` @@ -56,6 +49,7 @@ class UrlTestComponent { } @Component({ + selector: 'adf-url-test-password-component', standalone: true, imports: [PdfViewerComponent], template: ` ` @@ -115,7 +109,7 @@ describe('Test PdfViewer component', () => { beforeEach(async () => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, UrlTestComponent, TestDialogComponent, UrlTestPasswordComponent, BlobTestComponent], + imports: [NoopAuthModule, NoopTranslateModule, PdfViewerComponent], providers: [ { provide: MatDialog, @@ -138,360 +132,14 @@ describe('Test PdfViewer component', () => { await fixture.whenStable(); }); - describe('User interaction', () => { - let fixtureUrlTestComponent: ComponentFixture; - let componentUrlTestComponent: UrlTestComponent; - let elementUrlTestComponent: HTMLElement; - - beforeEach((done) => { - fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); - componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; - elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; - testingUtils.setDebugElement(fixtureUrlTestComponent.debugElement); - - fixtureUrlTestComponent.detectChanges(); - - componentUrlTestComponent.pdfViewerComponent.rendered.pipe(take(1)).subscribe(() => { - done(); - }); - }); - - afterEach(() => { - document.body.removeChild(elementUrlTestComponent); - }); - - it('should init the viewer with annotation mode disabled', (done) => { - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.pdfViewer.annotationEditorMode).toBe(AnnotationMode.DISABLE); - done(); - }); - }, 55000); - - it('should Total number of pages be loaded', (done) => { - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.totalPages).toBe(6); - done(); - }); - }, 55000); - - it('should nextPage move to the next page', (done) => { - testingUtils.clickByCSS('#viewer-next-page-button'); - - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(2); - done(); - }); - }, 55000); - - it('should event RIGHT_ARROW keyboard change pages', fakeAsync(() => { - fixtureUrlTestComponent.whenStable(); - fixtureUrlTestComponent.detectChanges(); - EventMock.keyDown(RIGHT_ARROW); - - tick(250); - - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(2); - })); - - it('should event LEFT_ARROW keyboard change pages', (done) => { - component.inputPage('2'); - - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - EventMock.keyDown(LEFT_ARROW); - - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(1); - done(); - }); - }); - }, 55000); - - it('should previous page move to the previous page', (done) => { - testingUtils.clickByCSS('#viewer-next-page-button'); - testingUtils.clickByCSS('#viewer-next-page-button'); - testingUtils.clickByCSS('#viewer-previous-page-button'); - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(2); - done(); - }); - }, 55000); - - it('should previous page not move to the previous page if is page 1', (done) => { - component.previousPage(); - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(1); - done(); - }); - }, 55000); - - it('should Input page move to the inserted page', (done) => { - componentUrlTestComponent.pdfViewerComponent.inputPage('2'); - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(2); - done(); - }); - }, 55000); - - describe('Zoom', () => { - it('should zoom in increment the scale value', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - - const zoomBefore = componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue; - testingUtils.clickByCSS('#viewer-zoom-in-button'); - fixtureUrlTestComponent.detectChanges(); - - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - const currentZoom = componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue; - expect(zoomBefore < currentZoom).toBe(true); - done(); - }, 55000); - - it('should zoom out decrement the scale value', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - - const zoomBefore = componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue; - testingUtils.clickByCSS('#viewer-zoom-out-button'); - fixtureUrlTestComponent.detectChanges(); - - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - const currentZoom = componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue; - expect(zoomBefore > currentZoom).toBe(true); - done(); - }, 55000); - - it('should it-in button toggle page-fit and auto scale mode', fakeAsync(() => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - tick(250); - - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('init'); - testingUtils.clickByCSS('#viewer-scale-page-button'); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('page-fit'); - testingUtils.clickByCSS('#viewer-scale-page-button'); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - testingUtils.clickByCSS('#viewer-scale-page-button'); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('page-fit'); - }), 55000); - }); - - describe('Resize interaction', () => { - it('should resize event trigger setScaleUpdatePages', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent, 'onResize'); - EventMock.resizeMobileView(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.onResize).toHaveBeenCalled(); - done(); - }); - }, 55000); - }); - - describe('Thumbnails', () => { - it('should have own context', (done) => { - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.pdfThumbnailsContext.viewer).not.toBeNull(); - done(); - }); - }, 55000); - - it('should open thumbnails panel', (done) => { - expect(testingUtils.getByCSS('.adf-pdf-viewer__thumbnails')).toBeNull(); - - componentUrlTestComponent.pdfViewerComponent.toggleThumbnails(); - - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(testingUtils.getByCSS('.adf-pdf-viewer__thumbnails')).not.toBeNull(); - done(); - }); - }, 55000); - - it('should not render PdfThumbListComponent during initialization of new pdfViewer', () => { - componentUrlTestComponent.pdfViewerComponent.toggleThumbnails(); - componentUrlTestComponent.urlFile = 'file.pdf'; - fixtureUrlTestComponent.detectChanges(); - expect(fixtureUrlTestComponent.debugElement.query(By.directive(PdfThumbListComponent))).toBeNull(); - }); - }); - - describe('Viewer events', () => { - it('should react on the emit of pageChange event', (done) => { - fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - const args = { - pageNumber: 6, - source: { - container: document.getElementById(`${componentUrlTestComponent.pdfViewerComponent.randomPdfId}-viewer-pdf-viewer`) - } - }; - - /* cspell:disable-next-line */ - componentUrlTestComponent.pdfViewerComponent.pdfViewer.eventBus.dispatch('pagechanging', args); - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.displayPage).toBe(6); - expect(componentUrlTestComponent.pdfViewerComponent.page).toBe(6); - done(); - }); - }); - }, 55000); - - it('should react on the emit of pagesLoaded event', (done) => { - fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.isPanelDisabled).toBeFalsy(); - - const args = { - pagesCount: 10, - source: { - container: document.getElementById(`${componentUrlTestComponent.pdfViewerComponent.randomPdfId}-viewer-pdf-viewer`) - } - }; - - /* cspell:disable-next-line */ - componentUrlTestComponent.pdfViewerComponent.pdfViewer.eventBus.dispatch('pagesloaded', args); - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.isPanelDisabled).toBe(false); - done(); - }); - }); - }, 55000); - }); + afterAll(() => { + fixture.destroy(); }); it('should Loader be present', () => { expect(testingUtils.getByCSS('.adf-loader-container')).not.toBeNull(); }); - describe('Zoom customization', () => { - describe('custom value', () => { - let fixtureUrlTestComponent: ComponentFixture; - let componentUrlTestComponent: UrlTestComponent; - let elementUrlTestComponent: HTMLElement; - - beforeEach((done) => { - const appConfig: AppConfigService = TestBed.inject(AppConfigService); - appConfig.config['adf-viewer.pdf-viewer-scaling'] = 80; - - fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); - componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; - elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; - - fixtureUrlTestComponent.detectChanges(); - - componentUrlTestComponent.pdfViewerComponent.rendered.pipe(take(1)).subscribe(() => { - done(); - }); - }); - - afterEach(() => { - document.body.removeChild(elementUrlTestComponent); - }); - - it('should use the custom zoom if it is present in the app.config', async () => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - - fixtureUrlTestComponent.detectChanges(); - await fixtureUrlTestComponent.whenStable(); - - expect(componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScale).toBe(0.8); - }); - }); - - describe('less than the minimum allowed value', () => { - let fixtureUrlTestComponent: ComponentFixture; - let componentUrlTestComponent: UrlTestComponent; - let elementUrlTestComponent: HTMLElement; - - beforeEach((done) => { - const appConfig: AppConfigService = TestBed.inject(AppConfigService); - appConfig.config['adf-viewer.pdf-viewer-scaling'] = 10; - - fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); - componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; - elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; - - fixtureUrlTestComponent.detectChanges(); - - componentUrlTestComponent.pdfViewerComponent.rendered.pipe(take(1)).subscribe(() => { - done(); - }); - }); - - afterEach(() => { - document.body.removeChild(elementUrlTestComponent); - }); - - it('should use the minimum scale zoom if the value given in app.config is less than the minimum allowed scale', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - - fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScaleValue).toBe('0.25'); - done(); - }); - }); - }); - // TODO: https://alfresco.atlassian.net/browse/ACS-6061 - // eslint-disable-next-line - xdescribe('greater than the maximum allowed value', () => { - let fixtureUrlTestComponent: ComponentFixture; - let componentUrlTestComponent: UrlTestComponent; - let elementUrlTestComponent: HTMLElement; - - beforeEach((done) => { - const appConfig: AppConfigService = TestBed.inject(AppConfigService); - appConfig.config['adf-viewer.pdf-viewer-scaling'] = 55555; - - fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); - componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; - elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; - - fixtureUrlTestComponent.detectChanges(); - - componentUrlTestComponent.pdfViewerComponent.rendered.pipe(take(1)).subscribe(() => { - done(); - }); - }); - - afterEach(() => { - document.body.removeChild(elementUrlTestComponent); - }); - - it('should use the maximum scale zoom if the value given in app.config is greater than the maximum allowed scale', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); - - fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScale).toBe(10); - done(); - }); - }); - }); - }); - describe('Required values', () => { it('should thrown an error If urlFile is not present', () => { change = new SimpleChange(null, null, true); @@ -525,42 +173,34 @@ describe('Test PdfViewer component', () => { afterEach(() => { document.body.removeChild(elementUrlTestComponent); - fixture.destroy(); }); - it('should Canvas be present', (done) => { + it('should Canvas be present', async () => { fixtureUrlTestComponent.detectChanges(); + await fixtureUrlTestComponent.whenStable(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(testingUtils.getByCSS('.adf-pdfViewer')).not.toBeNull(); - expect(testingUtils.getByCSS('.adf-viewer-pdf-viewer')).not.toBeNull(); - done(); - }); - }, 55000); + expect(testingUtils.getByCSS('.adf-pdfViewer')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-pdf-viewer')).not.toBeNull(); + }); - it('should Input Page elements be present', (done) => { + it('should Input Page elements be present', async () => { fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - /* cspell:disable-next-line */ - expect(testingUtils.getByCSS('.viewer-pagenumber-input')).toBeDefined(); - expect(testingUtils.getByCSS('.viewer-total-pages')).toBeDefined(); + await fixtureUrlTestComponent.whenStable(); + expect(testingUtils.getByCSS('.viewer-pagenumber-input')).toBeDefined(); + expect(testingUtils.getByCSS('.viewer-total-pages')).toBeDefined(); - expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); - expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); - done(); - }); - }, 55000); + expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); + }); - it('should Toolbar be hide if showToolbar is false', (done) => { + it('should Toolbar be hide if showToolbar is false', async () => { component.showToolbar = false; fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(testingUtils.getByCSS('.viewer-toolbar-command')).toBeNull(); - expect(testingUtils.getByCSS('.viewer-toolbar-pagination')).toBeNull(); - done(); - }); - }, 55000); + await fixtureUrlTestComponent.whenStable(); + expect(testingUtils.getByCSS('.viewer-toolbar-command')).toBeNull(); + expect(testingUtils.getByCSS('.viewer-toolbar-pagination')).toBeNull(); + }); }); describe('View with blob file', () => { @@ -578,53 +218,43 @@ describe('Test PdfViewer component', () => { afterEach(() => { document.body.removeChild(elementBlobTestComponent); - fixture.destroy(); }); - it('should Canvas be present', () => { + it('should Canvas be present', async () => { fixtureBlobTestComponent.detectChanges(); + await fixtureBlobTestComponent.whenStable(); - fixtureBlobTestComponent.whenStable().then(() => { - expect(testingUtils.getByCSS('.adf-pdfViewer')).not.toBeNull(); - expect(testingUtils.getByCSS('.adf-viewer-pdf-viewer')).not.toBeNull(); - }); + expect(testingUtils.getByCSS('.adf-pdfViewer')).not.toBeNull(); + expect(testingUtils.getByCSS('.adf-viewer-pdf-viewer')).not.toBeNull(); }); - it('should Next an Previous Buttons be present', (done) => { + it('should Next an Previous Buttons be present', async () => { fixtureBlobTestComponent.detectChanges(); + await fixtureBlobTestComponent.whenStable(); - fixtureBlobTestComponent.whenStable().then(() => { - expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); - expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); - done(); - }); - }, 55000); + expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); + }); - it('should Input Page elements be present', (done) => { + it('should Input Page elements be present', async () => { fixtureBlobTestComponent.detectChanges(); + await fixtureBlobTestComponent.whenStable(); + /* cspell:disable-next-line */ + expect(testingUtils.getByCSS('.adf-viewer-pagenumber-input')).toBeDefined(); + expect(testingUtils.getByCSS('.adf-viewer-total-pages')).toBeDefined(); + expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); + expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); + }); - fixtureBlobTestComponent.whenStable().then(() => { - /* cspell:disable-next-line */ - expect(testingUtils.getByCSS('.adf-viewer-pagenumber-input')).toBeDefined(); - expect(testingUtils.getByCSS('.adf-viewer-total-pages')).toBeDefined(); - - expect(testingUtils.getByCSS('#viewer-previous-page-button')).not.toBeNull(); - expect(testingUtils.getByCSS('#viewer-next-page-button')).not.toBeNull(); - done(); - }); - }, 55000); - - it('should Toolbar be hide if showToolbar is false', (done) => { + it('should Toolbar be hide if showToolbar is false', async () => { fixtureBlobTestComponent.componentInstance.pdfViewerComponent.showToolbar = false; fixtureBlobTestComponent.detectChanges(); + await fixtureBlobTestComponent.whenStable(); - fixtureBlobTestComponent.whenStable().then(() => { - expect(testingUtils.getByCSS('.viewer-toolbar-command')).toBeNull(); - expect(testingUtils.getByCSS('.viewer-toolbar-pagination')).toBeNull(); - done(); - }); - }, 55000); + expect(testingUtils.getByCSS('.viewer-toolbar-command')).toBeNull(); + expect(testingUtils.getByCSS('.viewer-toolbar-pagination')).toBeNull(); + }); }); describe('Password protection dialog', () => { @@ -721,3 +351,251 @@ describe('Test PdfViewer component', () => { }); }); }); + +describe('Test PdfViewer - Zoom customization', () => { + let fixture: ComponentFixture; + let component: PdfViewerComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NoopAuthModule, NoopTranslateModule, PdfViewerComponent], + providers: [ + { + provide: MatDialog, + useValue: { + open: () => {} + } + }, + RenderingQueueServices + ] + }); + + fixture = TestBed.createComponent(PdfViewerComponent); + component = fixture.componentInstance; + }); + + afterAll(() => { + fixture.destroy(); + }); + + it('should use the custom zoom if it is present in the app.config', () => { + const appConfig: AppConfigService = TestBed.inject(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 80; + + expect(component.getUserScaling()).toBe(0.8); + }); + + it('should use the minimum scale zoom if the value given in app.config is less than the minimum allowed scale', () => { + const appConfig: AppConfigService = TestBed.inject(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 10; + + fixture.detectChanges(); + + expect(component.getUserScaling()).toBe(0.25); + }); + + it('should use the maximum scale zoom if the value given in app.config is greater than the maximum allowed scale', () => { + const appConfig: AppConfigService = TestBed.inject(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 5555; + + fixture.detectChanges(); + + expect(component.getUserScaling()).toBe(10); + }); +}); + +describe('Test PdfViewer - User interaction', () => { + let fixture: ComponentFixture; + let component: PdfViewerComponent; + let testingUtils: UnitTestingUtils; + let pdfViewerSpy: jasmine.Spy; + + beforeEach(fakeAsync(() => { + pdfViewerSpy = jasmine.createSpy('PDFViewer').and.returnValue({ + setDocument: jasmine.createSpy().and.returnValue({ + loadingTask: () => ({ + destroy: () => Promise.resolve() + }), + promise: new Promise((resolve) => { + resolve({ + numPages: 6, + getPage: () => 'fakePage' + }); + }) + }), + forceRendering: jasmine.createSpy(), + update: jasmine.createSpy(), + currentScaleValue: 1, + _currentPageNumber: 1, + _pages: [{ width: 100, height: 100, scale: 1 }] + }); + + TestBed.configureTestingModule({ + imports: [NoopAuthModule, NoopTranslateModule, PdfViewerComponent], + providers: [ + { + provide: MatDialog, + useValue: { + open: () => {} + } + }, + RenderingQueueServices, + { provide: PDFJS_VIEWER_MODULE, useValue: pdfViewerSpy }, + { provide: PDFJS_MODULE, useValue: pdfjsLibMock } + ] + }); + + fixture = TestBed.createComponent(PdfViewerComponent); + component = fixture.componentInstance; + testingUtils = new UnitTestingUtils(fixture.debugElement); + const appConfig: AppConfigService = TestBed.inject(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 10; + + component.urlFile = './fake-test-file.pdf'; + fixture.detectChanges(); + component.ngOnChanges({ urlFile: { currentValue: './fake-test-file.pdf' } } as any); + + flush(); + })); + + afterAll(() => { + fixture.destroy(); + }); + + it('should init the viewer with annotation mode disabled', () => { + expect(pdfViewerSpy).toHaveBeenCalledWith(jasmine.objectContaining({ annotationMode: 0 })); + }); + + it('should Total number of pages be loaded', () => { + expect(component.totalPages).toBe(6); + }); + + it('should nextPage move to the next page', () => { + testingUtils.clickByCSS('#viewer-next-page-button'); + + expect(component.displayPage).toBe(2); + }); + + it('should event RIGHT_ARROW keyboard change pages', () => { + fixture.detectChanges(); + EventMock.keyDown(RIGHT_ARROW); + + expect(component.displayPage).toBe(2); + }); + + it('should event LEFT_ARROW keyboard change pages', () => { + component.inputPage('2'); + + EventMock.keyDown(LEFT_ARROW); + + expect(component.displayPage).toBe(1); + }); + + it('should previous page move to the previous page', () => { + testingUtils.clickByCSS('#viewer-next-page-button'); + testingUtils.clickByCSS('#viewer-next-page-button'); + testingUtils.clickByCSS('#viewer-previous-page-button'); + + expect(component.displayPage).toBe(2); + }); + + it('should previous page not move to the previous page if is page 1', () => { + component.previousPage(); + + expect(component.displayPage).toBe(1); + }); + + it('should Input page move to the inserted page', () => { + component.inputPage('2'); + + expect(component.displayPage).toBe(2); + }); + + describe('Zoom', () => { + it('should zoom in increment the scale value', () => { + const zoomBefore = component.pdfViewer.currentScaleValue; + testingUtils.clickByCSS('#viewer-zoom-in-button'); + + expect(component.currentScaleMode).toBe('auto'); + const currentZoom = component.pdfViewer.currentScaleValue; + expect(zoomBefore < currentZoom).toBe(true); + }); + + it('should zoom out decrement the scale value', () => { + testingUtils.clickByCSS('#viewer-zoom-in-button'); + const zoomBefore = component.pdfViewer.currentScaleValue; + + testingUtils.clickByCSS('#viewer-zoom-out-button'); + + expect(component.currentScaleMode).toBe('auto'); + const currentZoom = component.pdfViewer.currentScaleValue; + expect(zoomBefore > currentZoom).toBe(true); + }); + + it('should it-in button toggle page-fit and auto scale mode', fakeAsync(() => { + tick(250); + + expect(component.currentScaleMode).toBe('init'); + testingUtils.clickByCSS('#viewer-scale-page-button'); + expect(component.currentScaleMode).toBe('page-fit'); + testingUtils.clickByCSS('#viewer-scale-page-button'); + expect(component.currentScaleMode).toBe('auto'); + testingUtils.clickByCSS('#viewer-scale-page-button'); + expect(component.currentScaleMode).toBe('page-fit'); + }), 300); + }); + + describe('Resize interaction', () => { + it('should resize event trigger setScaleUpdatePages', () => { + spyOn(component, 'onResize'); + EventMock.resizeMobileView(); + + expect(component.onResize).toHaveBeenCalled(); + }); + }); + + describe('Thumbnails', () => { + it('should have own context', () => { + expect(component.pdfThumbnailsContext.viewer).not.toBeNull(); + }); + + it('should open thumbnails panel', () => { + expect(testingUtils.getByCSS('.adf-pdf-viewer__thumbnails')).toBeNull(); + + component.toggleThumbnails(); + fixture.detectChanges(); + + expect(testingUtils.getByCSS('.adf-pdf-viewer__thumbnails')).not.toBeNull(); + }); + + it('should not render PdfThumbListComponent during initialization of new pdfViewer', () => { + component.toggleThumbnails(); + component.urlFile = 'file.pdf'; + fixture.detectChanges(); + expect(fixture.debugElement.query(By.directive(PdfThumbListComponent))).toBeNull(); + }); + }); + + describe('Viewer events', () => { + it('should react on the emit of pageChange event', () => { + const args = { + pageNumber: 6, + source: { + container: document.getElementById(`${component.randomPdfId}-viewer-pdf-viewer`) + } + }; + + component.onPageChange(args); + expect(component.displayPage).toBe(6); + expect(component.page).toBe(6); + }); + + it('should react on the emit of pagesLoaded event', () => { + expect(component.isPanelDisabled).toBe(true); + + component.onPagesLoaded(); + + expect(component.isPanelDisabled).toBe(false); + }); + }); +}); diff --git a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.ts b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.ts index c431cafb94..725b1b2cac 100644 --- a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.ts +++ b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.ts @@ -24,6 +24,8 @@ import { Component, EventEmitter, HostListener, + inject, + InjectionToken, Input, OnChanges, OnDestroy, @@ -37,20 +39,22 @@ import { MatDialog } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { TranslateModule } from '@ngx-translate/core'; -import { AnnotationMode, OnProgressParameters, PDFDocumentLoadingTask, PDFDocumentProxy } from 'pdfjs-dist'; -import { Subject } from 'rxjs'; -import { catchError, delay } from 'rxjs/operators'; +import { from, Subject, switchMap } from 'rxjs'; +import { catchError } from 'rxjs/operators'; import { AppConfigService } from '../../../app-config'; import { ToolbarComponent, ToolbarDividerComponent } from '../../../toolbar'; import { RenderingQueueServices } from '../../services/rendering-queue.services'; import { PdfPasswordDialogComponent } from '../pdf-viewer-password-dialog/pdf-viewer-password-dialog'; import { PdfThumbListComponent } from '../pdf-viewer-thumbnails/pdf-viewer-thumbnails.component'; - -declare const pdfjsLib: any; -declare const pdfjsViewer: any; +import * as pdfjsLib from 'pdfjs-dist/build/pdf.min.mjs'; +import { PDFViewer, EventBus } from 'pdfjs-dist/web/pdf_viewer.mjs'; +import { OnProgressParameters, PDFDocumentLoadingTask, PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'; export type PdfScaleMode = 'init' | 'page-actual' | 'page-width' | 'page-height' | 'page-fit' | 'auto'; +export const PDFJS_MODULE = new InjectionToken('PDFJS_MODULE', { factory: () => pdfjsLib }); +export const PDFJS_VIEWER_MODULE = new InjectionToken('PDFJS_VIEWER_MODULE', { factory: () => PDFViewer }); + @Component({ selector: 'adf-pdf-viewer', standalone: true, @@ -129,7 +133,10 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { return this.pdfViewer?.currentScaleValue ? Math.round(this.pdfViewer.currentScaleValue * 100) + '%' : ''; } - private eventBus = new pdfjsViewer.EventBus(); + private pdfjsLib = inject(PDFJS_MODULE); + private pdfjsViewer = inject(PDFJS_VIEWER_MODULE); + + private eventBus = new EventBus(); private pdfjsDefaultOptions = { disableAutoFetch: true, disableStream: true, @@ -138,7 +145,11 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { }; private pdfjsWorkerDestroy$ = new Subject(); - constructor(private dialog: MatDialog, private renderingQueueServices: RenderingQueueServices, private appConfigService: AppConfigService) { + private dialog = inject(MatDialog); + private renderingQueueServices = inject(RenderingQueueServices); + private appConfigService = inject(AppConfigService); + + constructor() { // needed to preserve "this" context this.onPageChange = this.onPageChange.bind(this); this.onPagesLoaded = this.onPagesLoaded.bind(this); @@ -148,9 +159,9 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { this.pdfjsWorkerDestroy$ .pipe( catchError(() => null), - delay(700) + switchMap(() => from(this.destroyPdJsWorker())) ) - .subscribe(() => this.destroyPdJsWorker()); + .subscribe(() => {}); } getUserScaling(): number { @@ -213,9 +224,9 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { } executePdf(pdfOptions: any) { - pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.min.js'; + this.pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.min.mjs'; - this.loadingTask = pdfjsLib.getDocument(pdfOptions); + this.loadingTask = this.pdfjsLib.getDocument(pdfOptions); this.loadingTask.onPassword = (callback, reason) => { this.onPdfPassword(callback, reason); @@ -227,6 +238,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { }; this.isPanelDisabled = true; + this.loadingTask.promise .then((pdfDocument) => { this.totalPages = pdfDocument.numPages; @@ -245,12 +257,12 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { const container = this.getDocumentContainer(); if (viewer && container) { - this.pdfViewer = new pdfjsViewer.PDFViewer({ + this.pdfViewer = new this.pdfjsViewer({ container, viewer, renderingQueue: this.renderingQueueServices, eventBus: this.eventBus, - annotationMode: AnnotationMode.DISABLE + annotationMode: 0 }); // cspell: disable-next @@ -258,7 +270,12 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { // cspell: disable-next this.eventBus.on('pagesloaded', this.onPagesLoaded); // cspell: disable-next - this.eventBus.on('textlayerrendered', this.onPageRendered); + this.eventBus.on('textlayerrendered', () => { + this.onPageRendered(); + }); + this.eventBus.on('pagerendered', () => { + this.onPageRendered(); + }); this.renderingQueueServices.setViewer(this.pdfViewer); this.pdfViewer.setDocument(pdfDocument); @@ -269,11 +286,11 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { ngOnDestroy() { if (this.pdfViewer) { // cspell: disable-next - this.eventBus.off('pagechanging'); + this.eventBus.off('pagechanging', () => {}); // cspell: disable-next - this.eventBus.off('pagesloaded'); + this.eventBus.off('pagesloaded', () => {}); // cspell: disable-next - this.eventBus.off('textlayerrendered'); + this.eventBus.off('textlayerrendered', () => {}); } if (this.loadingTask) { @@ -282,8 +299,10 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { this.pdfjsWorkerDestroy$.complete(); } - private destroyPdJsWorker() { - this.loadingTask.destroy(); + private async destroyPdJsWorker() { + if (this.loadingTask.destroy) { + await this.loadingTask.destroy(); + } this.loadingTask = null; } @@ -370,8 +389,8 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { return document.getElementById(`${this.randomPdfId}-viewer-main-container`); } - private getDocumentContainer(): HTMLElement { - return document.getElementById(`${this.randomPdfId}-viewer-pdf-viewer`); + private getDocumentContainer(): HTMLDivElement { + return document.getElementById(`${this.randomPdfId}-viewer-pdf-viewer`) as HTMLDivElement; } private getViewer(): HTMLElement { diff --git a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.scss b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.scss index 11051c7541..e13ef0fb0f 100644 --- a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.scss +++ b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.scss @@ -82,4 +82,8 @@ align-items: center; display: flex; } + + &-pdf { + display: contents; + } } diff --git a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts index 8569eb08fe..f8b3aef4e0 100644 --- a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts +++ b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts @@ -19,12 +19,12 @@ import { AppExtensionService, ViewerExtensionRef } from '@alfresco/adf-extension import { Location } from '@angular/common'; import { SpyLocation } from '@angular/common/testing'; import { Component, DebugElement, TemplateRef, ViewChild } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, DeferBlockBehavior, TestBed } from '@angular/core/testing'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { NoopTranslateModule, UnitTestingUtils } from '../../../testing'; import { RenderingQueueServices } from '../../services/rendering-queue.services'; import { ViewerRenderComponent } from './viewer-render.component'; -import { ImgViewerComponent, MediaPlayerComponent, PdfViewerComponent, ViewerExtensionDirective } from '@alfresco/adf-core'; +import { ImgViewerComponent, MediaPlayerComponent, ViewerExtensionDirective } from '@alfresco/adf-core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @Component({ @@ -68,16 +68,19 @@ describe('ViewerComponent', () => { let extensionService: AppExtensionService; let testingUtils: UnitTestingUtils; - beforeEach(() => { + beforeEach(async () => { TestBed.configureTestingModule({ imports: [NoopTranslateModule, NoopAnimationsModule, MatDialogModule, ViewerRenderComponent, DoubleViewerComponent], - providers: [RenderingQueueServices, { provide: Location, useClass: SpyLocation }, MatDialog] + providers: [RenderingQueueServices, { provide: Location, useClass: SpyLocation }, MatDialog], + deferBlockBehavior: DeferBlockBehavior.Playthrough }); fixture = TestBed.createComponent(ViewerRenderComponent); testingUtils = new UnitTestingUtils(fixture.debugElement); component = fixture.componentInstance; extensionService = TestBed.inject(AppExtensionService); + + await fixture.whenStable(); }); afterEach(() => { @@ -88,12 +91,12 @@ describe('ViewerComponent', () => { it('should not reload the content of all the viewer after type change', async () => { const fixtureDouble = TestBed.createComponent(DoubleViewerComponent); - fixtureDouble.detectChanges(); - await fixtureDouble.whenStable(); - fixtureDouble.componentInstance.urlFileViewer1 = 'fake-test-file.pdf'; fixtureDouble.componentInstance.urlFileViewer2 = 'fake-test-file-two.xls'; + fixtureDouble.detectChanges(); + await fixtureDouble.whenStable(); + fixtureDouble.componentInstance.viewer1.ngOnChanges(); fixtureDouble.componentInstance.viewer2.ngOnChanges(); @@ -197,8 +200,8 @@ describe('ViewerComponent', () => { it('should extension file pdf be loaded', (done) => { component.urlFile = 'fake-test-file.pdf'; - component.ngOnChanges(); fixture.detectChanges(); + component.ngOnChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -209,8 +212,8 @@ describe('ViewerComponent', () => { it('should extension file png be loaded', (done) => { component.urlFile = 'fake-url-file.png'; - component.ngOnChanges(); fixture.detectChanges(); + component.ngOnChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -367,7 +370,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); component.ngOnChanges(); - fixture.whenStable().then(() => { + fixture.getDeferBlocks().then(() => { fixture.detectChanges(); expect(testingUtils.getByCSS('adf-pdf-viewer')).not.toBeNull(); done(); @@ -377,8 +380,8 @@ describe('ViewerComponent', () => { it('should display a PDF file identified by mimetype when the file extension is wrong', (done) => { component.urlFile = 'fake-content-pdf.bin'; component.mimeType = 'application/pdf'; - component.ngOnChanges(); fixture.detectChanges(); + component.ngOnChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); expect(testingUtils.getByCSS('adf-pdf-viewer')).not.toBeNull(); @@ -503,7 +506,8 @@ describe('ViewerComponent', () => { expect(component.viewerType).toBe('media'); }); - it('should show spinner until content is ready when viewerType is pdf', () => { + // eslint-disable-next-line ban/ban + xit('should show spinner until content is ready when viewerType is pdf', () => { component.isLoading = false; component.urlFile = 'some-url.pdf'; @@ -512,8 +516,6 @@ describe('ViewerComponent', () => { expect(getMainLoader()).not.toBeNull(); - const pdfViewer = testingUtils.getByDirective(PdfViewerComponent); - pdfViewer.triggerEventHandler('pagesLoaded', null); fixture.detectChanges(); expect(getMainLoader()).toBeNull(); diff --git a/lib/core/test.ts b/lib/core/test.ts index 2f46da9721..13507a1267 100644 --- a/lib/core/test.ts +++ b/lib/core/test.ts @@ -19,8 +19,11 @@ import 'zone.js'; import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import pdfjsLibMock from './src/lib/viewer/components/mock/pdfjs-lib.mock'; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: true } }); + +(window as any).pdfjsLib = pdfjsLibMock; diff --git a/lib/js-api/src/test-setup.ts b/lib/js-api/src/test-setup.ts index 32927d2cc4..01a3bf8e29 100644 --- a/lib/js-api/src/test-setup.ts +++ b/lib/js-api/src/test-setup.ts @@ -16,3 +16,4 @@ */ import 'jest-preset-angular/setup-jest'; +import 'resize-observer-polyfill/dist/ResizeObserver.global'; diff --git a/lib/process-services-cloud/karma.conf.js b/lib/process-services-cloud/karma.conf.js index 1c50d44c7e..ee47e3c85c 100644 --- a/lib/process-services-cloud/karma.conf.js +++ b/lib/process-services-cloud/karma.conf.js @@ -8,9 +8,6 @@ module.exports = function (config) { config.set({ basePath: '../../', files: [ - { pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false }, { pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, @@ -54,7 +51,7 @@ module.exports = function (config) { suppressAll: true // removes the duplicated traces }, mochaReporter: { - ignoreSkipped: process.env?.KARMA_IGNORE_SKIPPED === 'true' + ignoreSkipped: process.env.KARMA_IGNORE_SKIPPED === 'true' }, coverageReporter: { diff --git a/lib/process-services/karma.conf.js b/lib/process-services/karma.conf.js index 039f4ed155..1810c04c53 100644 --- a/lib/process-services/karma.conf.js +++ b/lib/process-services/karma.conf.js @@ -8,9 +8,6 @@ module.exports = function (config) { config.set({ basePath: '../../', files: [ - { pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false }, - { pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false }, { pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, @@ -50,7 +47,7 @@ module.exports = function (config) { suppressAll: true // removes the duplicated traces }, mochaReporter: { - ignoreSkipped: process.env?.KARMA_IGNORE_SKIPPED === 'true' + ignoreSkipped: process.env.KARMA_IGNORE_SKIPPED === 'true' }, coverageReporter: { dir: join(__dirname, './coverage/process-services'), diff --git a/package-lock.json b/package-lock.json index 1b9af9c068..0495295c76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,7 @@ "material-icons": "^1.13.12", "minimatch": "^10.0.1", "ng2-charts": "^4.1.1", - "pdfjs-dist": "3.3.122", + "pdfjs-dist": "5.1.91", "raphael": "2.3.0", "rxjs": "7.8.1", "superagent": "^9.0.1", @@ -90,7 +90,7 @@ "@types/minimatch": "5.1.2", "@types/mocha": "^10.0.6", "@types/node": "^18.16.9", - "@types/pdfjs-dist": "^2.10.378", + "@types/pdfjs-dist": "2.10.378", "@types/shelljs": "^0.8.15", "@types/superagent": "^4.1.22", "@typescript-eslint/eslint-plugin": "6.21.0", @@ -149,6 +149,7 @@ "postcss": "8.4.41", "postcss-sass": "^0.5.0", "prettier": "2.8.8", + "resize-observer-polyfill": "^1.5.1", "rimraf": "6.0.1", "sass-loader": "16.0.4", "shelljs": "^0.8.5", @@ -6232,8 +6233,10 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, "license": "BSD-3-Clause", "optional": true, + "peer": true, "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -6253,8 +6256,10 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "debug": "4" }, @@ -6266,8 +6271,10 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -6280,8 +6287,10 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "abbrev": "1" }, @@ -6297,8 +6306,10 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -7144,6 +7155,188 @@ "react": ">=16" } }, + "node_modules/@napi-rs/canvas": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.68.tgz", + "integrity": "sha512-LQESrePLEBLvhuFkXx9jjBXRC2ClYsO5mqQ1m/puth5z9SOuM3N/B3vDuqnC3RJFktDktyK9khGvo7dTkqO9uQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.68", + "@napi-rs/canvas-darwin-arm64": "0.1.68", + "@napi-rs/canvas-darwin-x64": "0.1.68", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.68", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.68", + "@napi-rs/canvas-linux-arm64-musl": "0.1.68", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.68", + "@napi-rs/canvas-linux-x64-gnu": "0.1.68", + "@napi-rs/canvas-linux-x64-musl": "0.1.68", + "@napi-rs/canvas-win32-x64-msvc": "0.1.68" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.68.tgz", + "integrity": "sha512-h1KcSR4LKLfRfzeBH65xMxbWOGa1OtMFQbCMVlxPCkN1Zr+2gK+70pXO5ktojIYcUrP6KDcOwoc8clho5ccM/w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.68.tgz", + "integrity": "sha512-/VURlrAD4gDoxW1GT/b0nP3fRz/fhxmHI/xznTq2FTwkQLPOlLkDLCvTmQ7v6LtGKdc2Ed6rvYpRan+JXThInQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.68.tgz", + "integrity": "sha512-tEpvGR6vCLTo1Tx9wmDnoOKROpw57wiCWwCpDOuVlj/7rqEJOUYr9ixW4aRJgmeGBrZHgevI0EURys2ER6whmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.68.tgz", + "integrity": "sha512-U9xbJsumPOiAYeAFZMlHf62b9dGs2HJ6Q5xt7xTB0uEyPeurwhgYBWGgabdsEidyj38YuzI/c3LGBbSQB3vagw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.68.tgz", + "integrity": "sha512-KFkn8wEm3mPnWD4l8+OUUkxylSJuN5q9PnJRZJgv15RtCA1bgxIwTkBhI/+xuyVMcHqON9sXq7cDkEJtHm35dg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.68.tgz", + "integrity": "sha512-IQzts91rCdOALXBWQxLZRCEDrfFTGDtNRJMNu+2SKZ1uT8cmPQkPwVk5rycvFpvgAcmiFiOSCp1aRrlfU8KPpQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.68.tgz", + "integrity": "sha512-e9AS5UttoIKqXSmBzKZdd3NErSVyOEYzJfNOCGtafGk1//gibTwQXGlSXmAKuErqMp09pyk9aqQRSYzm1AQfBw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.68.tgz", + "integrity": "sha512-Pa/I36VE3j57I3Obhrr+J48KGFfkZk2cJN/2NmW/vCgmoF7kCP6aTVq5n+cGdGWLd/cN9CJ9JvNwEoMRDghu0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.68.tgz", + "integrity": "sha512-9c6rkc5195wNxuUHJdf4/mmnq433OQey9TNvQ9LspJazvHbfSkTij8wtKjASVQsJyPDva4fkWOeV/OQ7cLw0GQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.68", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.68.tgz", + "integrity": "sha512-Fc5Dez23u0FoSATurT6/w1oMytiRnKWEinHivdMvXpge6nG4YvhrASrtqMk8dGJMVQpHr8QJYF45rOrx2YU2Aw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", @@ -20215,7 +20408,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/accepts": { @@ -20545,8 +20738,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true, "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/are-docs-informative": { "version": "0.0.2", @@ -20563,8 +20758,10 @@ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "deprecated": "This package is no longer supported.", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -21740,9 +21937,11 @@ "version": "2.11.2", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", @@ -21905,7 +22104,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "devOptional": true, + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -22252,8 +22451,10 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "bin": { "color-support": "bin.js" } @@ -22509,8 +22710,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/constants-browserify": { "version": "1.0.0", @@ -23400,8 +23603,10 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "mimic-response": "^2.0.0" }, @@ -23545,8 +23750,10 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/depd": { "version": "2.0.0", @@ -23591,8 +23798,10 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, "license": "Apache-2.0", "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -26175,8 +26384,10 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "deprecated": "This package is no longer supported.", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -26196,8 +26407,10 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -26682,8 +26895,10 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/hasown": { "version": "2.0.2", @@ -31537,7 +31752,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -31553,7 +31768,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "devOptional": true, + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -31830,8 +32045,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=8" }, @@ -32074,7 +32291,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "minipass": "^3.0.0", @@ -32088,7 +32305,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -32101,14 +32318,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -32358,8 +32575,10 @@ "version": "2.22.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/nanoid": { "version": "3.3.8", @@ -32589,8 +32808,10 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -32610,22 +32831,28 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, "license": "BSD-2-Clause", - "optional": true + "optional": true, + "peer": true }, "node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -33194,8 +33421,10 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "deprecated": "This package is no longer supported.", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -34107,15 +34336,6 @@ "node": ">=8" } }, - "node_modules/path2d-polyfill": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", - "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/pathval": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", @@ -34127,16 +34347,15 @@ } }, "node_modules/pdfjs-dist": { - "version": "3.3.122", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.3.122.tgz", - "integrity": "sha512-98WC09jOq3OuqrmF5+LZfcyzTlGA0sY9ocMBbWZ/H6Pwni7deptxwkNZVLieOz+4nSoTEW25PsfnfOj3ELrHdA==", + "version": "5.1.91", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.1.91.tgz", + "integrity": "sha512-qSIADdagooJB4wWCBnrBJjRvASevmxL0BwafvOuKJG5uTQdYoFBrhrRYnucKNiSc9qS6JIk0hC5y1yktFljXkA==", "license": "Apache-2.0", - "dependencies": { - "path2d-polyfill": "^2.0.1", - "web-streams-polyfill": "^3.2.1" + "engines": { + "node": ">=20" }, "optionalDependencies": { - "canvas": "^2.11.0" + "@napi-rs/canvas": "^0.1.67" } }, "node_modules/picocolors": { @@ -36347,6 +36566,13 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -37076,8 +37302,10 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/set-function-length": { "version": "1.2.2", @@ -37298,6 +37526,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, "funding": [ { "type": "github", @@ -37313,14 +37542,17 @@ } ], "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -38966,7 +39198,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -39000,7 +39232,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -39013,7 +39245,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -39026,7 +39258,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "devOptional": true, + "dev": true, "license": "ISC", "engines": { "node": ">=8" @@ -39036,7 +39268,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/telejson": { @@ -40918,15 +41150,6 @@ "defaults": "^1.0.3" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -41548,8 +41771,10 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, "license": "ISC", "optional": true, + "peer": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } diff --git a/package.json b/package.json index ffe3e8842a..5675e2fb1d 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "material-icons": "^1.13.12", "minimatch": "^10.0.1", "ng2-charts": "^4.1.1", - "pdfjs-dist": "3.3.122", + "pdfjs-dist": "5.1.91", "raphael": "2.3.0", "rxjs": "7.8.1", "superagent": "^9.0.1", @@ -110,7 +110,7 @@ "@types/minimatch": "5.1.2", "@types/mocha": "^10.0.6", "@types/node": "^18.16.9", - "@types/pdfjs-dist": "^2.10.378", + "@types/pdfjs-dist": "2.10.378", "@types/shelljs": "^0.8.15", "@types/superagent": "^4.1.22", "@typescript-eslint/eslint-plugin": "6.21.0", @@ -169,6 +169,7 @@ "postcss": "8.4.41", "postcss-sass": "^0.5.0", "prettier": "2.8.8", + "resize-observer-polyfill": "^1.5.1", "rimraf": "6.0.1", "sass-loader": "16.0.4", "shelljs": "^0.8.5",