Skip to content

Commit 6c19752

Browse files
Merge pull request #20941 from calixteman/simple_viewer_test
Add an integration test for the simple viewer
2 parents 869f25a + 741649c commit 6c19752

4 files changed

Lines changed: 235 additions & 0 deletions

File tree

test/components/simple-viewer.html

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<!doctype html>
2+
<!--
3+
Copyright 2026 Mozilla Foundation
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<html dir="ltr" mozdisallowselectionprint lang="en">
19+
<head>
20+
<meta charset="utf-8" />
21+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
22+
<title>PDF.js — Simple viewer</title>
23+
24+
<style>
25+
body {
26+
background-color: #808080;
27+
margin: 0;
28+
padding: 0;
29+
}
30+
#viewerContainer {
31+
overflow: auto;
32+
position: absolute;
33+
width: 100%;
34+
height: 100%;
35+
}
36+
</style>
37+
38+
<link rel="resource" type="application/l10n" href="../../web/locale/locale.json" />
39+
<link rel="stylesheet" href="../../web/pdf_viewer.css" />
40+
<script type="importmap">
41+
{
42+
"imports": {
43+
"pdfjs/": "../../src/",
44+
"pdfjs-lib": "../../src/pdf.js",
45+
46+
"display-cmap_reader_factory": "../../src/display/cmap_reader_factory.js",
47+
"display-standard_fontdata_factory": "../../src/display/standard_fontdata_factory.js",
48+
"display-wasm_factory": "../../src/display/wasm_factory.js",
49+
"display-fetch_stream": "../../src/display/fetch_stream.js",
50+
"display-network": "../../src/display/network.js",
51+
"display-node_stream": "../../src/display/stubs.js",
52+
"display-node_utils": "../../src/display/stubs.js",
53+
54+
"fluent-bundle": "../../node_modules/@fluent/bundle/esm/index.js",
55+
"fluent-dom": "../../node_modules/@fluent/dom/esm/index.js",
56+
"cached-iterable": "../../node_modules/cached-iterable/src/index.mjs",
57+
58+
"web-null_l10n": "../../web/genericl10n.js"
59+
}
60+
}
61+
</script>
62+
<script src="simple-viewer.js" type="module"></script>
63+
</head>
64+
65+
<body tabindex="1">
66+
<div id="viewerContainer">
67+
<div id="viewer" class="pdfViewer"></div>
68+
</div>
69+
</body>
70+
</html>

test/components/simple-viewer.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* Copyright 2026 Mozilla Foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
import { getDocument, GlobalWorkerOptions } from "pdfjs-lib";
17+
import { EventBus } from "../../web/event_utils.js";
18+
import { GenericL10n } from "../../web/genericl10n.js";
19+
import { PDFFindController } from "../../web/pdf_find_controller.js";
20+
import { PDFLinkService } from "../../web/pdf_link_service.js";
21+
import { PDFScriptingManager } from "../../web/pdf_scripting_manager.js";
22+
import { PDFViewer } from "../../web/pdf_viewer.js";
23+
24+
// The workerSrc property shall be specified.
25+
//
26+
GlobalWorkerOptions.workerSrc =
27+
typeof PDFJSDev === "undefined"
28+
? "../../src/pdf.worker.js"
29+
: "../../build/pdf.worker.mjs";
30+
31+
// Some PDFs need external cmaps.
32+
//
33+
const CMAP_URL =
34+
typeof PDFJSDev === "undefined"
35+
? "../../external/bcmaps/"
36+
: "../../web/cmaps/";
37+
38+
const DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
39+
40+
const ENABLE_XFA = true;
41+
const SEARCH_FOR = ""; // try "Mozilla";
42+
43+
const SANDBOX_BUNDLE_SRC = new URL(
44+
typeof PDFJSDev === "undefined"
45+
? "../../src/pdf.sandbox.js"
46+
: "../../build/pdf.sandbox.mjs",
47+
window.location
48+
);
49+
50+
const fileUrl = new URLSearchParams(location.search).get("file") ?? DEFAULT_URL;
51+
52+
const container = document.getElementById("viewerContainer");
53+
54+
const eventBus = new EventBus();
55+
56+
// (Optionally) enable hyperlinks within PDF files.
57+
const pdfLinkService = new PDFLinkService({
58+
eventBus,
59+
});
60+
61+
// (Optionally) enable find controller.
62+
const pdfFindController = new PDFFindController({
63+
eventBus,
64+
linkService: pdfLinkService,
65+
});
66+
67+
// (Optionally) enable scripting support.
68+
const pdfScriptingManager = new PDFScriptingManager({
69+
eventBus,
70+
sandboxBundleSrc: SANDBOX_BUNDLE_SRC,
71+
});
72+
73+
const pdfViewer = new PDFViewer({
74+
container,
75+
eventBus,
76+
l10n: new GenericL10n(navigator.language),
77+
linkService: pdfLinkService,
78+
findController: pdfFindController,
79+
scriptingManager: pdfScriptingManager,
80+
});
81+
pdfLinkService.setViewer(pdfViewer);
82+
pdfScriptingManager.setViewer(pdfViewer);
83+
84+
eventBus.on("pagesinit", function () {
85+
// We can use pdfViewer now, e.g. let's change default scale.
86+
pdfViewer.currentScaleValue = "page-width";
87+
88+
// We can try searching for things.
89+
if (SEARCH_FOR) {
90+
eventBus.dispatch("find", { type: "", query: SEARCH_FOR });
91+
}
92+
});
93+
94+
// Loading document.
95+
const loadingTask = getDocument({
96+
url: fileUrl,
97+
cMapUrl: CMAP_URL,
98+
enableXfa: ENABLE_XFA,
99+
});
100+
101+
const pdfDocument = await loadingTask.promise;
102+
// Document loaded, specifying document for the viewer and
103+
// the (optional) linkService.
104+
pdfViewer.setDocument(pdfDocument);
105+
106+
pdfLinkService.setDocument(pdfDocument, null);

test/integration/jasmine-boot.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ async function runTests(results) {
4040
"reorganize_pages_spec.mjs",
4141
"scripting_spec.mjs",
4242
"signature_editor_spec.mjs",
43+
"simple_viewer_spec.mjs",
4344
"stamp_editor_spec.mjs",
4445
"text_field_spec.mjs",
4546
"text_layer_spec.mjs",
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright 2026 Mozilla Foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
// Integration tests for the simple viewer (test/components/).
17+
18+
describe("Simple viewer", () => {
19+
describe("TextLayerBuilder without abortSignal", () => {
20+
let pages;
21+
22+
beforeEach(async () => {
23+
const origin = new URL(global.integrationBaseUrl).origin;
24+
pages = await Promise.all(
25+
global.integrationSessions.map(async session => {
26+
const page = await session.browser.newPage();
27+
await page.goto(
28+
`${origin}/test/components/simple-viewer.html` +
29+
`?file=/test/pdfs/tracemonkey.pdf`
30+
);
31+
await page.bringToFront();
32+
await page.waitForSelector(
33+
"[data-page-number='1'] .textLayer .endOfContent"
34+
);
35+
await page.waitForSelector(
36+
"[data-page-number='2'] .textLayer .endOfContent"
37+
);
38+
return [session.name, page];
39+
})
40+
);
41+
});
42+
43+
afterEach(async () => {
44+
await Promise.all(pages.map(([, page]) => page.close()));
45+
});
46+
47+
it("must produce text spans in the text layer", async () => {
48+
await Promise.all(
49+
pages.map(async ([browserName, page]) => {
50+
const count = await page.evaluate(
51+
() => document.querySelectorAll(".textLayer span").length
52+
);
53+
expect(count).withContext(`In ${browserName}`).toBeGreaterThan(0);
54+
})
55+
);
56+
});
57+
});
58+
});

0 commit comments

Comments
 (0)