0e1b5589e7
These were removed in PR 9170, since they were unused in the browsers that we'll support in PDF.js version `2.0`. However looking at the output of Travis, where a subset of the unit-tests are run using Node.js, there's warnings about `btoa` being undefined. This doesn't appear to cause any errors, which probably explains why we didn't notice this before (despite PR 9201).
402 lines
13 KiB
JavaScript
402 lines
13 KiB
JavaScript
/* Copyright 2017 Mozilla Foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import {
|
|
binarySearchFirstItem, EventBus, getPDFFileNameFromURL, isValidRotation,
|
|
waitOnEventOrTimeout, WaitOnType
|
|
} from '../../web/ui_utils';
|
|
import { createObjectURL } from '../../src/shared/util';
|
|
import isNodeJS from '../../src/shared/is_node';
|
|
|
|
describe('ui_utils', function() {
|
|
describe('binary search', function() {
|
|
function isTrue(boolean) {
|
|
return boolean;
|
|
}
|
|
function isGreater3(number) {
|
|
return number > 3;
|
|
}
|
|
|
|
it('empty array', function() {
|
|
expect(binarySearchFirstItem([], isTrue)).toEqual(0);
|
|
});
|
|
it('single boolean entry', function() {
|
|
expect(binarySearchFirstItem([false], isTrue)).toEqual(1);
|
|
expect(binarySearchFirstItem([true], isTrue)).toEqual(0);
|
|
});
|
|
it('three boolean entries', function() {
|
|
expect(binarySearchFirstItem([true, true, true], isTrue)).toEqual(0);
|
|
expect(binarySearchFirstItem([false, true, true], isTrue)).toEqual(1);
|
|
expect(binarySearchFirstItem([false, false, true], isTrue)).toEqual(2);
|
|
expect(binarySearchFirstItem([false, false, false], isTrue)).toEqual(3);
|
|
});
|
|
it('three numeric entries', function() {
|
|
expect(binarySearchFirstItem([0, 1, 2], isGreater3)).toEqual(3);
|
|
expect(binarySearchFirstItem([2, 3, 4], isGreater3)).toEqual(2);
|
|
expect(binarySearchFirstItem([4, 5, 6], isGreater3)).toEqual(0);
|
|
});
|
|
});
|
|
|
|
describe('getPDFFileNameFromURL', function() {
|
|
it('gets PDF filename', function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL('/pdfs/file1.pdf')).toEqual('file1.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL(
|
|
'http://www.example.com/pdfs/file2.pdf')).toEqual('file2.pdf');
|
|
});
|
|
|
|
it('gets fallback filename', function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL('/pdfs/file1.txt')).toEqual('document.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL(
|
|
'http://www.example.com/pdfs/file2.txt')).toEqual('document.pdf');
|
|
});
|
|
|
|
it('gets custom fallback filename', function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL('/pdfs/file1.txt', 'qwerty1.pdf')).
|
|
toEqual('qwerty1.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL('http://www.example.com/pdfs/file2.txt',
|
|
'qwerty2.pdf')).toEqual('qwerty2.pdf');
|
|
|
|
// An empty string should be a valid custom fallback filename.
|
|
expect(getPDFFileNameFromURL('/pdfs/file3.txt', '')).toEqual('');
|
|
});
|
|
|
|
it('gets PDF filename from URL containing leading/trailing whitespace',
|
|
function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL(
|
|
' /pdfs/file1.pdf ')).toEqual('file1.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL(
|
|
' http://www.example.com/pdfs/file2.pdf ')).toEqual('file2.pdf');
|
|
});
|
|
|
|
it('gets PDF filename from query string', function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL(
|
|
'/pdfs/pdfs.html?name=file1.pdf')).toEqual('file1.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL(
|
|
'http://www.example.com/pdfs/pdf.html?file2.pdf')).toEqual('file2.pdf');
|
|
});
|
|
|
|
it('gets PDF filename from hash string', function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL(
|
|
'/pdfs/pdfs.html#name=file1.pdf')).toEqual('file1.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL(
|
|
'http://www.example.com/pdfs/pdf.html#file2.pdf')).toEqual('file2.pdf');
|
|
});
|
|
|
|
it('gets correct PDF filename when multiple ones are present', function() {
|
|
// Relative URL
|
|
expect(getPDFFileNameFromURL(
|
|
'/pdfs/file1.pdf?name=file.pdf')).toEqual('file1.pdf');
|
|
// Absolute URL
|
|
expect(getPDFFileNameFromURL(
|
|
'http://www.example.com/pdfs/file2.pdf#file.pdf')).toEqual('file2.pdf');
|
|
});
|
|
|
|
it('gets PDF filename from URI-encoded data', function() {
|
|
var encodedUrl = encodeURIComponent(
|
|
'http://www.example.com/pdfs/file1.pdf');
|
|
expect(getPDFFileNameFromURL(encodedUrl)).toEqual('file1.pdf');
|
|
|
|
var encodedUrlWithQuery = encodeURIComponent(
|
|
'http://www.example.com/pdfs/file.txt?file2.pdf');
|
|
expect(getPDFFileNameFromURL(encodedUrlWithQuery)).toEqual('file2.pdf');
|
|
});
|
|
|
|
it('gets PDF filename from data mistaken for URI-encoded', function() {
|
|
expect(getPDFFileNameFromURL('/pdfs/%AA.pdf')).toEqual('%AA.pdf');
|
|
|
|
expect(getPDFFileNameFromURL('/pdfs/%2F.pdf')).toEqual('%2F.pdf');
|
|
});
|
|
|
|
it('gets PDF filename from (some) standard protocols', function() {
|
|
// HTTP
|
|
expect(getPDFFileNameFromURL('http://www.example.com/file1.pdf')).
|
|
toEqual('file1.pdf');
|
|
// HTTPS
|
|
expect(getPDFFileNameFromURL('https://www.example.com/file2.pdf')).
|
|
toEqual('file2.pdf');
|
|
// File
|
|
expect(getPDFFileNameFromURL('file:///path/to/files/file3.pdf')).
|
|
toEqual('file3.pdf');
|
|
// FTP
|
|
expect(getPDFFileNameFromURL('ftp://www.example.com/file4.pdf')).
|
|
toEqual('file4.pdf');
|
|
});
|
|
|
|
it('gets PDF filename from query string appended to "blob:" URL',
|
|
function() {
|
|
if (isNodeJS()) {
|
|
pending('Blob in not supported in Node.js.');
|
|
}
|
|
var typedArray = new Uint8Array([1, 2, 3, 4, 5]);
|
|
var blobUrl = createObjectURL(typedArray, 'application/pdf');
|
|
// Sanity check to ensure that a "blob:" URL was returned.
|
|
expect(blobUrl.indexOf('blob:') === 0).toEqual(true);
|
|
|
|
expect(getPDFFileNameFromURL(blobUrl + '?file.pdf')).toEqual('file.pdf');
|
|
});
|
|
|
|
it('gets fallback filename from query string appended to "data:" URL',
|
|
function() {
|
|
var typedArray = new Uint8Array([1, 2, 3, 4, 5]);
|
|
var dataUrl = createObjectURL(typedArray, 'application/pdf',
|
|
/* forceDataSchema = */ true);
|
|
// Sanity check to ensure that a "data:" URL was returned.
|
|
expect(dataUrl.indexOf('data:') === 0).toEqual(true);
|
|
|
|
expect(getPDFFileNameFromURL(dataUrl + '?file1.pdf')).
|
|
toEqual('document.pdf');
|
|
|
|
// Should correctly detect a "data:" URL with leading whitespace.
|
|
expect(getPDFFileNameFromURL(' ' + dataUrl + '?file2.pdf')).
|
|
toEqual('document.pdf');
|
|
});
|
|
});
|
|
|
|
describe('EventBus', function () {
|
|
it('dispatch event', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
eventBus.on('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.dispatch('test');
|
|
expect(count).toEqual(1);
|
|
});
|
|
it('dispatch different event', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
eventBus.on('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.dispatch('nottest');
|
|
expect(count).toEqual(0);
|
|
});
|
|
it('dispatch event multiple times', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
eventBus.dispatch('test');
|
|
eventBus.on('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.dispatch('test');
|
|
eventBus.dispatch('test');
|
|
expect(count).toEqual(2);
|
|
});
|
|
it('dispatch event to multiple handlers', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
eventBus.on('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.on('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.dispatch('test');
|
|
expect(count).toEqual(2);
|
|
});
|
|
it('dispatch to detached', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
var listener = function () {
|
|
count++;
|
|
};
|
|
eventBus.on('test', listener);
|
|
eventBus.dispatch('test');
|
|
eventBus.off('test', listener);
|
|
eventBus.dispatch('test');
|
|
expect(count).toEqual(1);
|
|
});
|
|
it('dispatch to wrong detached', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
eventBus.on('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.dispatch('test');
|
|
eventBus.off('test', function () {
|
|
count++;
|
|
});
|
|
eventBus.dispatch('test');
|
|
expect(count).toEqual(2);
|
|
});
|
|
it('dispatch to detached during handling', function () {
|
|
var eventBus = new EventBus();
|
|
var count = 0;
|
|
var listener1 = function () {
|
|
eventBus.off('test', listener2);
|
|
count++;
|
|
};
|
|
var listener2 = function () {
|
|
eventBus.off('test', listener1);
|
|
count++;
|
|
};
|
|
eventBus.on('test', listener1);
|
|
eventBus.on('test', listener2);
|
|
eventBus.dispatch('test');
|
|
eventBus.dispatch('test');
|
|
expect(count).toEqual(2);
|
|
});
|
|
});
|
|
|
|
describe('isValidRotation', function() {
|
|
it('should reject non-integer angles', function() {
|
|
expect(isValidRotation()).toEqual(false);
|
|
expect(isValidRotation(null)).toEqual(false);
|
|
expect(isValidRotation(NaN)).toEqual(false);
|
|
expect(isValidRotation([90])).toEqual(false);
|
|
expect(isValidRotation('90')).toEqual(false);
|
|
expect(isValidRotation(90.5)).toEqual(false);
|
|
});
|
|
|
|
it('should reject non-multiple of 90 degree angles', function() {
|
|
expect(isValidRotation(45)).toEqual(false);
|
|
expect(isValidRotation(-123)).toEqual(false);
|
|
});
|
|
|
|
it('should accept valid angles', function() {
|
|
expect(isValidRotation(0)).toEqual(true);
|
|
expect(isValidRotation(90)).toEqual(true);
|
|
expect(isValidRotation(-270)).toEqual(true);
|
|
expect(isValidRotation(540)).toEqual(true);
|
|
});
|
|
});
|
|
|
|
describe('waitOnEventOrTimeout', function() {
|
|
let eventBus;
|
|
|
|
beforeAll(function(done) {
|
|
eventBus = new EventBus();
|
|
done();
|
|
});
|
|
|
|
afterAll(function() {
|
|
eventBus = null;
|
|
});
|
|
|
|
it('should reject invalid parameters', function(done) {
|
|
let invalidTarget = waitOnEventOrTimeout({
|
|
target: 'window',
|
|
name: 'DOMContentLoaded',
|
|
}).then(function() {
|
|
throw new Error('Should reject invalid parameters.');
|
|
}, function(reason) {
|
|
expect(reason instanceof Error).toEqual(true);
|
|
});
|
|
|
|
let invalidName = waitOnEventOrTimeout({
|
|
target: eventBus,
|
|
name: '',
|
|
}).then(function() {
|
|
throw new Error('Should reject invalid parameters.');
|
|
}, function(reason) {
|
|
expect(reason instanceof Error).toEqual(true);
|
|
});
|
|
|
|
let invalidDelay = waitOnEventOrTimeout({
|
|
target: eventBus,
|
|
name: 'pagerendered',
|
|
delay: -1000,
|
|
}).then(function() {
|
|
throw new Error('Should reject invalid parameters.');
|
|
}, function(reason) {
|
|
expect(reason instanceof Error).toEqual(true);
|
|
});
|
|
|
|
Promise.all([invalidTarget, invalidName, invalidDelay]).then(done,
|
|
done.fail);
|
|
});
|
|
|
|
it('should resolve on event, using the DOM', function(done) {
|
|
if (isNodeJS()) {
|
|
pending('Document in not supported in Node.js.');
|
|
}
|
|
let button = document.createElement('button');
|
|
|
|
let buttonClicked = waitOnEventOrTimeout({
|
|
target: button,
|
|
name: 'click',
|
|
delay: 10000,
|
|
});
|
|
// Immediately dispatch the expected event.
|
|
button.click();
|
|
|
|
buttonClicked.then(function(type) {
|
|
expect(type).toEqual(WaitOnType.EVENT);
|
|
done();
|
|
}, done.fail);
|
|
});
|
|
|
|
it('should resolve on timeout, using the DOM', function(done) {
|
|
if (isNodeJS()) {
|
|
pending('Document in not supported in Node.js.');
|
|
}
|
|
let button = document.createElement('button');
|
|
|
|
let buttonClicked = waitOnEventOrTimeout({
|
|
target: button,
|
|
name: 'click',
|
|
delay: 10,
|
|
});
|
|
// Do *not* dispatch the event, and wait for the timeout.
|
|
|
|
buttonClicked.then(function(type) {
|
|
expect(type).toEqual(WaitOnType.TIMEOUT);
|
|
done();
|
|
}, done.fail);
|
|
});
|
|
|
|
it('should resolve on event, using the EventBus', function(done) {
|
|
let pageRendered = waitOnEventOrTimeout({
|
|
target: eventBus,
|
|
name: 'pagerendered',
|
|
delay: 10000,
|
|
});
|
|
// Immediately dispatch the expected event.
|
|
eventBus.dispatch('pagerendered');
|
|
|
|
pageRendered.then(function(type) {
|
|
expect(type).toEqual(WaitOnType.EVENT);
|
|
done();
|
|
}, done.fail);
|
|
});
|
|
|
|
it('should resolve on timeout, using the EventBus', function(done) {
|
|
let pageRendered = waitOnEventOrTimeout({
|
|
target: eventBus,
|
|
name: 'pagerendered',
|
|
delay: 10,
|
|
});
|
|
// Do *not* dispatch the event, and wait for the timeout.
|
|
|
|
pageRendered.then(function(type) {
|
|
expect(type).toEqual(WaitOnType.TIMEOUT);
|
|
done();
|
|
}, done.fail);
|
|
});
|
|
});
|
|
});
|