From bbe8c3d8ed7d6cee83d52d84f13af71659fd765a Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 8 Apr 2017 17:09:54 +0200 Subject: [PATCH] Enable running a subset of the API unit-tests on Travis Notably, this patch skips all canvas rendering tests in Node.js. --- src/display/api.js | 7 +- test/unit/api_spec.js | 273 ++++++++++++++++++++++++---------------- test/unit/clitests.json | 1 + test/unit/test_utils.js | 9 ++ 4 files changed, 181 insertions(+), 109 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index e8f8d99cf..dc256148c 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -67,7 +67,12 @@ if (typeof PDFJSDev !== 'undefined' && typeof requirejs !== 'undefined' && requirejs.load; fakeWorkerFilesLoader = useRequireEnsure ? (function (callback) { require.ensure([], function () { - var worker = require('./pdf.worker.js'); + var worker; + if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('LIB')) { + worker = require('../pdf.worker.js'); + } else { + worker = require('./pdf.worker.js'); + } callback(worker.WorkerMessageHandler); }); }) : dynamicLoaderSupported ? (function (callback) { diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 357e2ad99..9cbfe02d0 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -14,27 +14,60 @@ */ import { - createPromiseCapability, FontType, InvalidPDFException, MissingPDFException, - PasswordException, PasswordResponses, StreamType + createPromiseCapability, FontType, InvalidPDFException, isNodeJS, + MissingPDFException, PasswordException, PasswordResponses, StreamType, + stringToBytes } from '../../src/shared/util'; import { DOMCanvasFactory, RenderingCancelledException } from '../../src/display/dom_utils'; -import { PDFDocumentProxy, PDFPageProxy } from '../../src/display/api'; +import { + getDocument, PDFDocumentProxy, PDFPageProxy +} from '../../src/display/api'; +import { NodeFileReaderFactory } from './test_utils'; import { PDFJS } from '../../src/display/global'; +const TEST_PDFS_PATH = { + dom: '../pdfs/', + node: './test/pdfs/', +}; + +function buildGetDocumentParams(filename, options) { + let params = Object.create(null); + if (isNodeJS()) { + params.data = NodeFileReaderFactory.fetch({ + path: TEST_PDFS_PATH.node + filename, + }); + } else { + params.url = new URL(TEST_PDFS_PATH.dom + filename, window.location).href; + } + for (let option in options) { + params[option] = options[option]; + } + return params; +} + describe('api', function() { - var basicApiUrl = new URL('../pdfs/basicapi.pdf', window.location).href; - var basicApiFileLength = 105779; // bytes - var CanvasFactory; + let basicApiFileName = 'basicapi.pdf'; + let basicApiFileLength = 105779; // bytes + let basicApiGetDocumentParams = buildGetDocumentParams(basicApiFileName); + + let CanvasFactory; beforeAll(function(done) { - CanvasFactory = new DOMCanvasFactory(); + if (isNodeJS()) { + PDFJS.pdfjsNext = true; + // NOTE: To support running the canvas-related tests in Node.js, + // a `NodeCanvasFactory` would need to be added (in test_utils.js). + } else { + CanvasFactory = new DOMCanvasFactory(); + } done(); }); - afterAll(function () { + afterAll(function(done) { CanvasFactory = null; + done(); }); function waitSome(callback) { @@ -47,7 +80,10 @@ describe('api', function() { describe('PDFJS', function() { describe('getDocument', function() { it('creates pdf doc from URL', function(done) { - var loadingTask = PDFJS.getDocument(basicApiUrl); + if (isNodeJS()) { + pending('XMLHttpRequest is not supported in Node.js.'); + } + var loadingTask = getDocument(basicApiGetDocumentParams); var isProgressReportedResolved = false; var progressReportedCapability = createPromiseCapability(); @@ -76,7 +112,10 @@ describe('api', function() { }); it('creates pdf doc from URL and aborts before worker initialized', function(done) { - var loadingTask = PDFJS.getDocument(basicApiUrl); + if (isNodeJS()) { + pending('XMLHttpRequest is not supported in Node.js.'); + } + var loadingTask = getDocument(basicApiGetDocumentParams); let destroyed = loadingTask.destroy(); loadingTask.promise.then(function(reason) { @@ -88,7 +127,10 @@ describe('api', function() { }); it('creates pdf doc from URL and aborts loading after worker initialized', function(done) { - var loadingTask = PDFJS.getDocument(basicApiUrl); + if (isNodeJS()) { + pending('XMLHttpRequest is not supported in Node.js.'); + } + var loadingTask = getDocument(basicApiGetDocumentParams); // This can be somewhat random -- we cannot guarantee perfect // 'Terminate' message to the worker before/after setting up pdfManager. var destroyed = loadingTask._worker.promise.then(function () { @@ -102,36 +144,38 @@ describe('api', function() { }); }); it('creates pdf doc from typed array', function(done) { - var nonBinaryRequest = PDFJS.disableWorker; - var request = new XMLHttpRequest(); - request.open('GET', basicApiUrl, false); - if (!nonBinaryRequest) { - try { - request.responseType = 'arraybuffer'; - nonBinaryRequest = request.responseType !== 'arraybuffer'; - } catch (e) { - nonBinaryRequest = true; - } - } - if (nonBinaryRequest && request.overrideMimeType) { - request.overrideMimeType('text/plain; charset=x-user-defined'); - } - request.send(null); - var typedArrayPdf; - if (nonBinaryRequest) { - var data = Array.prototype.map.call(request.responseText, - function (ch) { - return ch.charCodeAt(0) & 0xFF; + if (isNodeJS()) { + typedArrayPdf = NodeFileReaderFactory.fetch({ + path: TEST_PDFS_PATH.node + basicApiFileName, }); - typedArrayPdf = new Uint8Array(data); } else { - typedArrayPdf = new Uint8Array(request.response); + var nonBinaryRequest = PDFJS.disableWorker; + var request = new XMLHttpRequest(); + request.open('GET', TEST_PDFS_PATH.dom + basicApiFileName, false); + if (!nonBinaryRequest) { + try { + request.responseType = 'arraybuffer'; + nonBinaryRequest = request.responseType !== 'arraybuffer'; + } catch (e) { + nonBinaryRequest = true; + } + } + if (nonBinaryRequest && request.overrideMimeType) { + request.overrideMimeType('text/plain; charset=x-user-defined'); + } + request.send(null); + + if (nonBinaryRequest) { + typedArrayPdf = stringToBytes(request.responseText); + } else { + typedArrayPdf = new Uint8Array(request.response); + } } // Sanity check to make sure that we fetched the entire PDF file. expect(typedArrayPdf.length).toEqual(basicApiFileLength); - var loadingTask = PDFJS.getDocument(typedArrayPdf); + var loadingTask = getDocument(typedArrayPdf); loadingTask.promise.then(function(data) { expect(data instanceof PDFDocumentProxy).toEqual(true); loadingTask.destroy().then(done); @@ -141,9 +185,7 @@ describe('api', function() { }); it('creates pdf doc from invalid PDF file', function(done) { // A severely corrupt PDF file (even Adobe Reader fails to open it). - var url = new URL('../pdfs/bug1020226.pdf', window.location).href; - - var loadingTask = PDFJS.getDocument(url); + var loadingTask = getDocument(buildGetDocumentParams('bug1020226.pdf')); loadingTask.promise.then(function () { done.fail('shall fail loading'); }).catch(function (error) { @@ -152,9 +194,11 @@ describe('api', function() { }); }); it('creates pdf doc from non-existent URL', function(done) { - var nonExistentUrl = new URL('../pdfs/non-existent.pdf', - window.location).href; - var loadingTask = PDFJS.getDocument(nonExistentUrl); + if (isNodeJS()) { + pending('XMLHttpRequest is not supported in Node.js.'); + } + var loadingTask = getDocument( + buildGetDocumentParams('non-existent.pdf')); loadingTask.promise.then(function(error) { done.fail('shall fail loading'); }).catch(function (error) { @@ -163,9 +207,8 @@ describe('api', function() { }); }); it('creates pdf doc from PDF file protected with user and owner password', - function (done) { - var url = new URL('../pdfs/pr6531_1.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(url); + function (done) { + var loadingTask = getDocument(buildGetDocumentParams('pr6531_1.pdf')); var isPasswordNeededResolved = false; var passwordNeededCapability = createPromiseCapability(); @@ -208,12 +251,13 @@ describe('api', function() { }); }); it('creates pdf doc from PDF file protected with only a user password', - function (done) { - var url = new URL('../pdfs/pr6531_2.pdf', window.location).href; + function (done) { + var filename = 'pr6531_2.pdf'; - var passwordNeededLoadingTask = PDFJS.getDocument({ - url, password: '', - }); + var passwordNeededLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: '', + })); var result1 = passwordNeededLoadingTask.promise.then(function () { done.fail('shall fail with no password'); return Promise.reject(new Error('loadingTask should be rejected')); @@ -223,9 +267,10 @@ describe('api', function() { return passwordNeededLoadingTask.destroy(); }); - var passwordIncorrectLoadingTask = PDFJS.getDocument({ - url, password: 'qwerty', - }); + var passwordIncorrectLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: 'qwerty', + })); var result2 = passwordIncorrectLoadingTask.promise.then(function () { done.fail('shall fail with wrong password'); return Promise.reject(new Error('loadingTask should be rejected')); @@ -235,10 +280,10 @@ describe('api', function() { return passwordIncorrectLoadingTask.destroy(); }); - var passwordAcceptedLoadingTask = PDFJS.getDocument({ - url, password: 'asdfasdf', - }); - + var passwordAcceptedLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: 'asdfasdf', + })); var result3 = passwordAcceptedLoadingTask.promise.then(function (data) { expect(data instanceof PDFDocumentProxy).toEqual(true); return passwordAcceptedLoadingTask.destroy(); @@ -252,11 +297,14 @@ describe('api', function() { it('creates pdf doc from password protected PDF file and aborts/throws ' + 'in the onPassword callback (issue 7806)', function (done) { - var url = new URL('../pdfs/issue3371.pdf', window.location).href; - var passwordNeededLoadingTask = PDFJS.getDocument(url); - var passwordIncorrectLoadingTask = PDFJS.getDocument({ - url, password: 'qwerty', - }); + var filename = 'issue3371.pdf'; + + var passwordNeededLoadingTask = getDocument( + buildGetDocumentParams(filename)); + var passwordIncorrectLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: 'qwerty', + })); let passwordNeededDestroyed; passwordNeededLoadingTask.onPassword = function (callback, reason) { @@ -301,6 +349,10 @@ describe('api', function() { }); }); describe('PDFWorker', function() { + if (isNodeJS()) { + pending('Worker is not supported in Node.js.'); + } + it('worker created or destroyed', function (done) { var worker = new PDFJS.PDFWorker('test1'); worker.promise.then(function () { @@ -319,7 +371,7 @@ describe('api', function() { }); }); it('worker created or destroyed by getDocument', function (done) { - var loadingTask = PDFJS.getDocument(basicApiUrl); + var loadingTask = getDocument(basicApiGetDocumentParams); var worker; loadingTask.promise.then(function () { worker = loadingTask._worker; @@ -340,7 +392,10 @@ describe('api', function() { }); it('worker created and can be used in getDocument', function (done) { var worker = new PDFJS.PDFWorker('test1'); - var loadingTask = PDFJS.getDocument({ url: basicApiUrl, worker, }); + var loadingTask = getDocument( + buildGetDocumentParams(basicApiFileName, { + worker, + })); loadingTask.promise.then(function () { var docWorker = loadingTask._worker; expect(!!docWorker).toEqual(false); @@ -384,7 +439,7 @@ describe('api', function() { var doc; beforeAll(function(done) { - loadingTask = PDFJS.getDocument(basicApiUrl); + loadingTask = getDocument(basicApiGetDocumentParams); loadingTask.promise.then(function(data) { doc = data; done(); @@ -495,8 +550,7 @@ describe('api', function() { }); it('gets destinations, from /Names (NameTree) dictionary', function(done) { - var url = new URL('../pdfs/issue6204.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(url); + var loadingTask = getDocument(buildGetDocumentParams('issue6204.pdf')); var promise = loadingTask.promise.then(function (pdfDocument) { return pdfDocument.getDestinations(); }); @@ -512,8 +566,7 @@ describe('api', function() { }); }); it('gets a destination, from /Names (NameTree) dictionary', function(done) { - var url = new URL('../pdfs/issue6204.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(url); + var loadingTask = getDocument(buildGetDocumentParams('issue6204.pdf')); var promise = loadingTask.promise.then(function (pdfDocument) { return pdfDocument.getDestination('Page.1'); }); @@ -528,8 +581,7 @@ describe('api', function() { }); it('gets a non-existent destination, from /Names (NameTree) dictionary', function(done) { - var url = new URL('../pdfs/issue6204.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(url); + var loadingTask = getDocument(buildGetDocumentParams('issue6204.pdf')); var promise = loadingTask.promise.then(function (pdfDocument) { return pdfDocument.getDestination('non-existent-named-destination'); }); @@ -553,29 +605,26 @@ describe('api', function() { }); it('gets page labels', function (done) { // PageLabels with Roman/Arabic numerals. - var url0 = new URL('../pdfs/bug793632.pdf', window.location).href; - var loadingTask0 = PDFJS.getDocument(url0); + var loadingTask0 = getDocument(buildGetDocumentParams('bug793632.pdf')); var promise0 = loadingTask0.promise.then(function (pdfDoc) { return pdfDoc.getPageLabels(); }); // PageLabels with only a label prefix. - var url1 = new URL('../pdfs/issue1453.pdf', window.location).href; - var loadingTask1 = PDFJS.getDocument(url1); + var loadingTask1 = getDocument(buildGetDocumentParams('issue1453.pdf')); var promise1 = loadingTask1.promise.then(function (pdfDoc) { return pdfDoc.getPageLabels(); }); // PageLabels identical to standard page numbering. - var url2 = new URL('../pdfs/rotation.pdf', window.location).href; - var loadingTask2 = PDFJS.getDocument(url2); + var loadingTask2 = getDocument(buildGetDocumentParams('rotation.pdf')); var promise2 = loadingTask2.promise.then(function (pdfDoc) { return pdfDoc.getPageLabels(); }); // PageLabels with bad "Prefix" entries. - var url3 = new URL('../pdfs/bad-PageLabels.pdf', window.location).href; - var loadingTask3 = PDFJS.getDocument(url3); + var loadingTask3 = getDocument( + buildGetDocumentParams('bad-PageLabels.pdf')); var promise3 = loadingTask3.promise.then(function (pdfDoc) { return pdfDoc.getPageLabels(); }); @@ -608,8 +657,10 @@ describe('api', function() { }); }); it('gets attachments', function(done) { - var url = new URL('../pdfs/bug766138.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(url); + if (isNodeJS()) { // The PDF file used is a linked test-case. + pending('TODO: Use a non-linked test-case.'); + } + var loadingTask = getDocument(buildGetDocumentParams('bug766138.pdf')); var promise = loadingTask.promise.then(function (pdfDoc) { return pdfDoc.getAttachments(); }); @@ -640,8 +691,7 @@ describe('api', function() { it('gets javascript with printing instructions (Print action)', function(done) { // PDF document with "Print" Named action in OpenAction - var pdfUrl = new URL('../pdfs/bug1001080.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(pdfUrl); + var loadingTask = getDocument(buildGetDocumentParams('bug1001080.pdf')); var promise = loadingTask.promise.then(function(doc) { return doc.getJavaScript(); }); @@ -656,8 +706,7 @@ describe('api', function() { it('gets javascript with printing instructions (JS action)', function(done) { // PDF document with "JavaScript" action in OpenAction - var pdfUrl = new URL('../pdfs/issue6106.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(pdfUrl); + var loadingTask = getDocument(buildGetDocumentParams('issue6106.pdf')); var promise = loadingTask.promise.then(function(doc) { return doc.getJavaScript(); }); @@ -671,8 +720,7 @@ describe('api', function() { }); }); it('gets non-existent outline', function(done) { - var url = new URL('../pdfs/tracemonkey.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(url); + var loadingTask = getDocument(buildGetDocumentParams('tracemonkey.pdf')); var promise = loadingTask.promise.then(function (pdfDocument) { return pdfDocument.getOutline(); @@ -711,8 +759,7 @@ describe('api', function() { }); }); it('gets outline containing a url', function(done) { - var pdfUrl = new URL('../pdfs/issue3214.pdf', window.location).href; - var loadingTask = PDFJS.getDocument(pdfUrl); + var loadingTask = getDocument(buildGetDocumentParams('issue3214.pdf')); loadingTask.promise.then(function (pdfDocument) { pdfDocument.getOutline().then(function (outline) { @@ -738,6 +785,9 @@ describe('api', function() { }); }); it('gets metadata', function(done) { + if (isNodeJS()) { + pending('Document is not supported in Node.js.'); + } var promise = doc.getMetadata(); promise.then(function(metadata) { expect(metadata.info['Title']).toEqual('Basic API Test'); @@ -778,11 +828,9 @@ describe('api', function() { }); it('checks that fingerprints are unique', function(done) { - var url1 = new URL('../pdfs/issue4436r.pdf', window.location).href; - var loadingTask1 = PDFJS.getDocument(url1); + var loadingTask1 = getDocument(buildGetDocumentParams('issue4436r.pdf')); - var url2 = new URL('../pdfs/issue4575.pdf', window.location).href; - var loadingTask2 = PDFJS.getDocument(url2); + var loadingTask2 = getDocument(buildGetDocumentParams('issue4575.pdf')); var promises = [loadingTask1.promise, loadingTask2.promise]; @@ -811,7 +859,7 @@ describe('api', function() { var pdfDocument, page; beforeAll(function(done) { - loadingTask = PDFJS.getDocument(basicApiUrl); + loadingTask = getDocument(basicApiGetDocumentParams); loadingTask.promise.then(function(doc) { pdfDocument = doc; pdfDocument.getPage(1).then(function(data) { @@ -875,19 +923,19 @@ describe('api', function() { it('gets annotations containing relative URLs (bug 766086)', function (done) { - var url = new URL('../pdfs/bug766086.pdf', window.location).href; + var filename = 'bug766086.pdf'; - var defaultLoadingTask = PDFJS.getDocument(url); + var defaultLoadingTask = getDocument(buildGetDocumentParams(filename)); var defaultPromise = defaultLoadingTask.promise.then(function (pdfDoc) { return pdfDoc.getPage(1).then(function (pdfPage) { return pdfPage.getAnnotations(); }); }); - var docBaseUrlLoadingTask = PDFJS.getDocument({ - url, - docBaseUrl: 'http://www.example.com/test/pdfs/qwerty.pdf', - }); + var docBaseUrlLoadingTask = getDocument( + buildGetDocumentParams(filename, { + docBaseUrl: 'http://www.example.com/test/pdfs/qwerty.pdf', + })); var docBaseUrlPromise = docBaseUrlLoadingTask.promise.then( function (pdfDoc) { return pdfDoc.getPage(1).then(function (pdfPage) { @@ -895,10 +943,10 @@ describe('api', function() { }); }); - var invalidDocBaseUrlLoadingTask = PDFJS.getDocument({ - url, - docBaseUrl: 'qwerty.pdf', - }); + var invalidDocBaseUrlLoadingTask = getDocument( + buildGetDocumentParams(filename, { + docBaseUrl: 'qwerty.pdf', + })); var invalidDocBaseUrlPromise = invalidDocBaseUrlLoadingTask.promise.then( function (pdfDoc) { return pdfDoc.getPage(1).then(function (pdfPage) { @@ -989,6 +1037,9 @@ describe('api', function() { }); it('cancels rendering of page', function(done) { + if (isNodeJS()) { + pending('TODO: Support Canvas testing in Node.js.'); + } var viewport = page.getViewport(1); var canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height); @@ -1009,20 +1060,23 @@ describe('api', function() { }); }); describe('Multiple PDFJS instances', function() { + if (isNodeJS()) { + pending('TODO: Support Canvas testing in Node.js.'); + } // Regression test for https://github.com/mozilla/pdf.js/issues/6205 // A PDF using the Helvetica font. - var pdf1 = new URL('../pdfs/tracemonkey.pdf', window.location).href; + var pdf1 = buildGetDocumentParams('tracemonkey.pdf'); // A PDF using the Times font. - var pdf2 = new URL('../pdfs/TAMReview.pdf', window.location).href; + var pdf2 = buildGetDocumentParams('TAMReview.pdf'); // A PDF using the Arial font. - var pdf3 = new URL('../pdfs/issue6068.pdf', window.location).href; + var pdf3 = buildGetDocumentParams('issue6068.pdf'); var loadingTasks = []; var pdfDocuments = []; // Render the first page of the given PDF file. // Fulfills the promise with the base64-encoded version of the PDF. function renderPDF(filename) { - var loadingTask = PDFJS.getDocument(filename); + var loadingTask = getDocument(filename); loadingTasks.push(loadingTask); return loadingTask.promise .then(function(pdf) { @@ -1090,6 +1144,9 @@ describe('api', function() { }); }); describe('PDFDataRangeTransport', function () { + if (isNodeJS()) { + pending('XMLHttpRequest is not supported in Node.js.'); + } var pdfPath = new URL('../pdfs/tracemonkey.pdf', window.location).href; var loadPromise; function getDocumentData() { @@ -1124,7 +1181,7 @@ describe('api', function() { transport.onDataRange(begin, data.subarray(begin, end)); }); }; - var loadingTask = PDFJS.getDocument(transport); + var loadingTask = getDocument(transport); return loadingTask.promise; }); var pdfDocument; @@ -1161,7 +1218,7 @@ describe('api', function() { transport.onDataRange(begin, data.subarray(begin, end)); }); }; - var loadingTask = PDFJS.getDocument(transport); + var loadingTask = getDocument(transport); return loadingTask.promise; }); var pdfDocument; diff --git a/test/unit/clitests.json b/test/unit/clitests.json index 347fc0180..2ac082796 100644 --- a/test/unit/clitests.json +++ b/test/unit/clitests.json @@ -2,6 +2,7 @@ "spec_dir": "build/lib/test/unit", "spec_files": [ "annotation_spec.js", + "api_spec.js", "bidi_spec.js", "cff_parser_spec.js", "cmap_spec.js", diff --git a/test/unit/test_utils.js b/test/unit/test_utils.js index 7dab9f1e4..5754a4572 100644 --- a/test/unit/test_utils.js +++ b/test/unit/test_utils.js @@ -15,6 +15,14 @@ import { CMapCompressionType } from '../../src/shared/util'; +class NodeFileReaderFactory { + static fetch(params) { + var fs = require('fs'); + var file = fs.readFileSync(params.path); + return new Uint8Array(file); + } +} + class NodeCMapReaderFactory { constructor({ baseUrl = null, isCompressed = false, }) { this.baseUrl = baseUrl; @@ -47,5 +55,6 @@ class NodeCMapReaderFactory { } export { + NodeFileReaderFactory, NodeCMapReaderFactory, };