mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-05-31 07:11:00 +02:00
If the active page is corrupt that currently results in the entire dialog being "blank", thus providing no information, which seems unfortunate and it's easy enough to only skip `pageSizeField` in that rare case.
430 lines
13 KiB
JavaScript
430 lines
13 KiB
JavaScript
/* Copyright 2024 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 { closePages, FSI, loadAndWait, PDI } from "./test_utils.mjs";
|
||
import fs from "fs/promises";
|
||
|
||
const FIELDS = [
|
||
"fileName",
|
||
"fileSize",
|
||
"title",
|
||
"author",
|
||
"subject",
|
||
"keywords",
|
||
"creationDate",
|
||
"modificationDate",
|
||
"creator",
|
||
"producer",
|
||
"version",
|
||
"pageCount",
|
||
"pageSize",
|
||
"linearized",
|
||
];
|
||
|
||
async function openDocumentProperties(page) {
|
||
await page.click("#secondaryToolbarToggleButton");
|
||
await page.waitForSelector("#secondaryToolbar", { hidden: false });
|
||
|
||
await page.click("#documentProperties");
|
||
await page.waitForSelector("#documentPropertiesDialog", {
|
||
hidden: false,
|
||
});
|
||
}
|
||
|
||
async function closeDocumentProperties(page) {
|
||
await page.click("#documentPropertiesClose");
|
||
await page.waitForSelector("#documentPropertiesDialog", {
|
||
hidden: true,
|
||
});
|
||
}
|
||
|
||
async function checkFieldProperties(page, expectedProps) {
|
||
await page.waitForFunction(
|
||
`document.getElementById("fileSizeField").textContent !== "-"`
|
||
);
|
||
const promises = [];
|
||
|
||
for (const name of FIELDS) {
|
||
promises.push(
|
||
page.evaluate(
|
||
n => [n, document.getElementById(`${n}Field`).textContent],
|
||
name
|
||
)
|
||
);
|
||
}
|
||
const props = Object.fromEntries(await Promise.all(promises));
|
||
expect(props).toEqual(expectedProps);
|
||
}
|
||
|
||
function getFieldDataLastUpdated(page) {
|
||
return page.evaluate(
|
||
() =>
|
||
document.getElementById("documentPropertiesDialog").dataset
|
||
.fieldDataLastUpdated
|
||
);
|
||
}
|
||
|
||
describe("PDFDocumentProperties", () => {
|
||
describe("Document with both /Info and /Metadata", () => {
|
||
let pages;
|
||
|
||
beforeEach(async () => {
|
||
pages = await loadAndWait("basicapi.pdf", ".textLayer .endOfContent");
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await closePages(pages);
|
||
});
|
||
|
||
it("check that the document properties dialog has the correct information", async () => {
|
||
await Promise.all(
|
||
pages.map(async ([browserName, page]) => {
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "basicapi.pdf",
|
||
fileSize: `${FSI}103${PDI} KB (${FSI}105,779${PDI} bytes)`,
|
||
title: "Basic API Test",
|
||
author: "Brendan Dahl",
|
||
subject: "-",
|
||
keywords: "TCPDF",
|
||
creationDate: "4/10/12, 7:30:26 AM",
|
||
modificationDate: "4/10/12, 7:30:26 AM",
|
||
creator: "TCPDF",
|
||
producer: "TCPDF 5.9.133 (http://www.tcpdf.org)",
|
||
version: "1.7",
|
||
pageCount: "3",
|
||
pageSize: `${FSI}8.27${PDI} × ${FSI}11.69${PDI} ${FSI}in${PDI} (${FSI}A4${PDI}, ${FSI}portrait${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
})
|
||
);
|
||
});
|
||
});
|
||
|
||
describe("Document with approximately A4-sized page", () => {
|
||
let pages;
|
||
|
||
beforeEach(async () => {
|
||
pages = await loadAndWait(
|
||
"arial_unicode_en_cidfont.pdf",
|
||
".textLayer .endOfContent"
|
||
);
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await closePages(pages);
|
||
});
|
||
|
||
it("check that the document properties dialog has the correct information", async () => {
|
||
await Promise.all(
|
||
pages.map(async ([browserName, page]) => {
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "arial_unicode_en_cidfont.pdf",
|
||
fileSize: `${FSI}15.4${PDI} KB (${FSI}15,779${PDI} bytes)`,
|
||
title: "-",
|
||
author: "Adil Allawi",
|
||
subject: "-",
|
||
keywords: "-",
|
||
creationDate: "7/10/11, 7:17:28 PM",
|
||
modificationDate: "-",
|
||
creator: "Writer",
|
||
producer: "NeoOffice 3.2 Beta",
|
||
version: "1.4",
|
||
pageCount: "1",
|
||
pageSize: `${FSI}8.27${PDI} × ${FSI}11.69${PDI} ${FSI}in${PDI} (${FSI}A4${PDI}, ${FSI}portrait${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
})
|
||
);
|
||
});
|
||
});
|
||
|
||
describe("Document without contentLength", () => {
|
||
let pages;
|
||
|
||
beforeEach(async () => {
|
||
pages = await loadAndWait("empty.pdf", ".textLayer .endOfContent");
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await closePages(pages);
|
||
});
|
||
|
||
it("check that the document properties dialog has the correct information", async () => {
|
||
await Promise.all(
|
||
pages.map(async ([browserName, page]) => {
|
||
// Open a binary PDF document, such that `contentLength` is undefined.
|
||
const base64 = await fs.readFile("./pdfs/clippath.pdf", {
|
||
encoding: "base64",
|
||
});
|
||
|
||
await page.evaluate(async b64 => {
|
||
await window.PDFViewerApplication.open({
|
||
data: Uint8Array.fromBase64(b64),
|
||
});
|
||
}, base64);
|
||
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "document.pdf",
|
||
fileSize: `${FSI}0.448${PDI} KB (${FSI}459${PDI} bytes)`,
|
||
title: "-",
|
||
author: "-",
|
||
subject: "-",
|
||
keywords: "-",
|
||
creationDate: "-",
|
||
modificationDate: "-",
|
||
creator: "-",
|
||
producer: "-",
|
||
version: "1.1",
|
||
pageCount: "1",
|
||
pageSize: `${FSI}2.78${PDI} × ${FSI}1.39${PDI} ${FSI}in${PDI} (${FSI}landscape${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
})
|
||
);
|
||
});
|
||
});
|
||
|
||
describe("Document with multiple pages, and changed viewer page/rotation", () => {
|
||
let pages;
|
||
|
||
beforeEach(async () => {
|
||
pages = await loadAndWait("basicapi.pdf", ".textLayer .endOfContent");
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await closePages(pages);
|
||
});
|
||
|
||
it("check that the document properties dialog has the correct information", async () => {
|
||
await Promise.all(
|
||
pages.map(async ([browserName, page]) => {
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "basicapi.pdf",
|
||
fileSize: `${FSI}103${PDI} KB (${FSI}105,779${PDI} bytes)`,
|
||
title: "Basic API Test",
|
||
author: "Brendan Dahl",
|
||
subject: "-",
|
||
keywords: "TCPDF",
|
||
creationDate: "4/10/12, 7:30:26 AM",
|
||
modificationDate: "4/10/12, 7:30:26 AM",
|
||
creator: "TCPDF",
|
||
producer: "TCPDF 5.9.133 (http://www.tcpdf.org)",
|
||
version: "1.7",
|
||
pageCount: "3",
|
||
pageSize: `${FSI}8.27${PDI} × ${FSI}11.69${PDI} ${FSI}in${PDI} (${FSI}A4${PDI}, ${FSI}portrait${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
const fieldDataLastUpdated = await getFieldDataLastUpdated(page);
|
||
|
||
await closeDocumentProperties(page);
|
||
|
||
// Ensure that immediately re-opening the dialog doesn't cause
|
||
// the field-data to be fetched and parsed again.
|
||
await openDocumentProperties(page);
|
||
|
||
expect(await getFieldDataLastUpdated(page)).toEqual(
|
||
fieldDataLastUpdated
|
||
);
|
||
|
||
await closeDocumentProperties(page);
|
||
|
||
// Goto the second page, and rotate the document.
|
||
await page.click("#next");
|
||
await page.waitForFunction(
|
||
() => window.PDFViewerApplication.page === 2
|
||
);
|
||
await page.keyboard.press("r");
|
||
await page.waitForFunction(
|
||
() => window.PDFViewerApplication.pdfViewer.pagesRotation === 90
|
||
);
|
||
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "basicapi.pdf",
|
||
fileSize: `${FSI}103${PDI} KB (${FSI}105,779${PDI} bytes)`,
|
||
title: "Basic API Test",
|
||
author: "Brendan Dahl",
|
||
subject: "-",
|
||
keywords: "TCPDF",
|
||
creationDate: "4/10/12, 7:30:26 AM",
|
||
modificationDate: "4/10/12, 7:30:26 AM",
|
||
creator: "TCPDF",
|
||
producer: "TCPDF 5.9.133 (http://www.tcpdf.org)",
|
||
version: "1.7",
|
||
pageCount: "3",
|
||
pageSize: `${FSI}11.69${PDI} × ${FSI}8.27${PDI} ${FSI}in${PDI} (${FSI}A4${PDI}, ${FSI}landscape${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
})
|
||
);
|
||
});
|
||
});
|
||
|
||
describe("Document with different page sizes", () => {
|
||
let pages;
|
||
|
||
beforeEach(async () => {
|
||
pages = await loadAndWait("sizes.pdf", ".textLayer .endOfContent");
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await closePages(pages);
|
||
});
|
||
|
||
it("check that the document properties dialog has the correct information", async () => {
|
||
await Promise.all(
|
||
pages.map(async ([browserName, page]) => {
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "sizes.pdf",
|
||
fileSize: `${FSI}13.4${PDI} KB (${FSI}13,739${PDI} bytes)`,
|
||
title: "-",
|
||
author: "Yury ",
|
||
subject: "-",
|
||
keywords: "-",
|
||
creationDate: "6/26/11, 1:26:03 PM",
|
||
modificationDate: "-",
|
||
creator: "Writer",
|
||
producer: "OpenOffice.org 3.3",
|
||
version: "1.4",
|
||
pageCount: "3",
|
||
pageSize: `${FSI}8.5${PDI} × ${FSI}11${PDI} ${FSI}in${PDI} (${FSI}Letter${PDI}, ${FSI}portrait${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
|
||
// Goto the second page.
|
||
await page.click("#next");
|
||
await page.waitForFunction(
|
||
() => window.PDFViewerApplication.page === 2
|
||
);
|
||
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "sizes.pdf",
|
||
fileSize: `${FSI}13.4${PDI} KB (${FSI}13,739${PDI} bytes)`,
|
||
title: "-",
|
||
author: "Yury ",
|
||
subject: "-",
|
||
keywords: "-",
|
||
creationDate: "6/26/11, 1:26:03 PM",
|
||
modificationDate: "-",
|
||
creator: "Writer",
|
||
producer: "OpenOffice.org 3.3",
|
||
version: "1.4",
|
||
pageCount: "3",
|
||
pageSize: `${FSI}9.01${PDI} × ${FSI}4.49${PDI} ${FSI}in${PDI} (${FSI}landscape${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
})
|
||
);
|
||
});
|
||
});
|
||
|
||
describe("Document with corrupt page", () => {
|
||
let pages;
|
||
|
||
beforeEach(async () => {
|
||
pages = await loadAndWait(
|
||
"Pages-tree-refs.pdf",
|
||
".textLayer .endOfContent",
|
||
null,
|
||
null,
|
||
{ page: 2 }
|
||
);
|
||
});
|
||
|
||
afterEach(async () => {
|
||
await closePages(pages);
|
||
});
|
||
|
||
it("check that the document properties dialog has the correct information", async () => {
|
||
await Promise.all(
|
||
pages.map(async ([browserName, page]) => {
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "Pages-tree-refs.pdf",
|
||
fileSize: `${FSI}1.07${PDI} KB (${FSI}1,098${PDI} bytes)`,
|
||
title: "-",
|
||
author: "-",
|
||
subject: "-",
|
||
keywords: "-",
|
||
creationDate: "-",
|
||
modificationDate: "-",
|
||
creator: "-",
|
||
producer: "-",
|
||
version: "1.7",
|
||
pageCount: "2",
|
||
pageSize: "-",
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
|
||
// Goto the first page (which is *not* corrupt).
|
||
await page.click("#previous");
|
||
await page.waitForFunction(
|
||
() => window.PDFViewerApplication.page === 1
|
||
);
|
||
|
||
await openDocumentProperties(page);
|
||
|
||
await checkFieldProperties(page, {
|
||
fileName: "Pages-tree-refs.pdf",
|
||
fileSize: `${FSI}1.07${PDI} KB (${FSI}1,098${PDI} bytes)`,
|
||
title: "-",
|
||
author: "-",
|
||
subject: "-",
|
||
keywords: "-",
|
||
creationDate: "-",
|
||
modificationDate: "-",
|
||
creator: "-",
|
||
producer: "-",
|
||
version: "1.7",
|
||
pageCount: "2",
|
||
pageSize: `${FSI}8.27${PDI} × ${FSI}11.69${PDI} ${FSI}in${PDI} (${FSI}A4${PDI}, ${FSI}portrait${PDI})`,
|
||
linearized: "No",
|
||
});
|
||
|
||
await closeDocumentProperties(page);
|
||
})
|
||
);
|
||
});
|
||
});
|
||
});
|