AAE-22975 update to the latest version of pdfjs-dist library (#10780)

* AAE-30877 squash-merged improvement/AAE-30877-update-package-pdfjs-dist

* AAE-30877 statically import pdf_viewer

* AAE-30877 fix failing worker load

* AAE-22975 attempt without excessive logs

* AAE-22975 remove pdf_viewer from karma includes

* AAE-22975 remove incorrect firstValueFrom

* AAE-22975 await rendered event callback

* AAE-22975 change pdf mock code

* AAE-22975 change pdf mock code

* AAE-22975 mock pdfjs-dist package in tests to improve performance

* AAE-22975 fix pagesLoaded test

* AAE-22975 fix insights tests

* AAE-22975 un-focus pdf-viewer tests, remove logs

* AAE-22975 add defer block

* AAE-22975 add pdfjsLib injection token

* AAE-22975 remove defer block

* AAE-22975 change pdfjs import path

* AAE-22975 change pdfjsviewer import path

* AAE-22975 limit usage of direct PDFViewer

* AAE-22975 cleanup
This commit is contained in:
Wojciech Duda 2025-04-22 10:05:44 +02:00 committed by GitHub
parent 0dc45e95af
commit fdd4f6c081
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 702 additions and 540 deletions

View File

@ -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: {

View File

@ -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');

View File

@ -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: {

View File

@ -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": "./",

View File

@ -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');
});
});
});

View File

@ -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<NotificationHistoryComponent>;
@ -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;

View File

@ -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 () => {

View File

@ -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
}
};

View File

@ -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: ` <adf-pdf-viewer [allowThumbnails]="true" [showToolbar]="true" [urlFile]="urlFile" /> `
@ -56,6 +49,7 @@ class UrlTestComponent {
}
@Component({
selector: 'adf-url-test-password-component',
standalone: true,
imports: [PdfViewerComponent],
template: ` <adf-pdf-viewer [allowThumbnails]="true" [showToolbar]="true" [urlFile]="urlFile" /> `
@ -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<UrlTestComponent>;
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<UrlTestComponent>;
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<UrlTestComponent>;
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<UrlTestComponent>;
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<PdfViewerComponent>;
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<PdfViewerComponent>;
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);
});
});
});

View File

@ -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<boolean>();
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 {

View File

@ -82,4 +82,8 @@
align-items: center;
display: flex;
}
&-pdf {
display: contents;
}
}

View File

@ -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();

View File

@ -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;

View File

@ -16,3 +16,4 @@
*/
import 'jest-preset-angular/setup-jest';
import 'resize-observer-polyfill/dist/ResizeObserver.global';

View File

@ -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: {

View File

@ -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'),

323
package-lock.json generated
View File

@ -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"
}

View File

@ -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",