From d10da907dac86c103b787127110a59aed82c7aaa Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 28 Apr 2021 01:15:31 -0700 Subject: [PATCH] Fix position of highlighted all text. (#13306) Adds a new integration test to ensure we don't regress this again. --- test/integration-boot.js | 1 + test/integration/find_spec.js | 75 ++++++++++++++++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/find_all.pdf | Bin 0 -> 10432 bytes web/text_layer_builder.css | 1 + 5 files changed, 78 insertions(+) create mode 100644 test/integration/find_spec.js create mode 100644 test/pdfs/find_all.pdf diff --git a/test/integration-boot.js b/test/integration-boot.js index 7749c6681..7abedb82d 100644 --- a/test/integration-boot.js +++ b/test/integration-boot.js @@ -28,6 +28,7 @@ async function runTests(results) { "scripting_spec.js", "annotation_spec.js", "accessibility_spec.js", + "find_spec.js", ], }); diff --git a/test/integration/find_spec.js b/test/integration/find_spec.js new file mode 100644 index 000000000..93166bba1 --- /dev/null +++ b/test/integration/find_spec.js @@ -0,0 +1,75 @@ +/* Copyright 2021 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. + */ + +const { closePages, loadAndWait } = require("./test_utils.js"); + +function fuzzyMatch(a, b, browserName, pixelFuzz = 3) { + expect(a) + .withContext(`In ${browserName}`) + .toBeLessThan(b + pixelFuzz); + expect(a) + .withContext(`In ${browserName}`) + .toBeGreaterThan(b - pixelFuzz); +} + +describe("find bar", () => { + describe("highlight all", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("find_all.pdf#zoom=100", ".textLayer"); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must highlight text in the right position", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await page.click("#viewFind"); + await page.waitForSelector("#viewFind", { hidden: false }); + await page.type("#findInput", "a"); + await page.click("#findHighlightAll"); + await page.waitForSelector(".textLayer .highlight"); + // The PDF has the text "AB BA" in a monospace font. + // Make sure we have the right number of highlighted divs. + const highlights = await page.$$(".textLayer .highlight"); + expect(highlights.length).withContext(`In ${browserName}`).toEqual(2); + const glyphWidth = 15.98; // From the PDF. + const pageDiv = await page.$(".page canvas"); + const pageBox = await pageDiv.boundingBox(); + const firstA = await highlights[0].boundingBox(); + const secondA = await highlights[1].boundingBox(); + // Subtract the page offset from the text bounding boxes; + firstA.x = firstA.x - pageBox.x; + firstA.y = firstA.y - pageBox.y; + secondA.x = secondA.x - pageBox.x; + secondA.y = secondA.y - pageBox.y; + // They should be on the same line. + expect(firstA.y).withContext(`In ${browserName}`).toEqual(secondA.y); + const fontSize = 26.66; // From the PDF. + // The highlighted text has more padding. + fuzzyMatch(firstA.height, fontSize + 5, browserName); + fuzzyMatch(secondA.height, fontSize + 5, browserName); + const expectedFirstAX = 28; + fuzzyMatch(firstA.x, expectedFirstAX, browserName); + // The second 'A' should be 4 glyphs widths from the first. + fuzzyMatch(secondA.x, expectedFirstAX + glyphWidth * 4, browserName); + }) + ); + }); + }); +}); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index d3498e1c5..6915b4600 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -247,6 +247,7 @@ !S2.pdf !glyph_accent.pdf !personwithdog.pdf +!find_all.pdf !helloworld-bad.pdf !zerowidthline.pdf !js-colors.pdf diff --git a/test/pdfs/find_all.pdf b/test/pdfs/find_all.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7379e3f93911ffcc2477a6561118f4df2a860a05 GIT binary patch literal 10432 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