mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-04-09 23:04:02 +02:00
And make sure that the sidebar is fully open before starting the tests in order to have an intermittent exception when finishing the test.
549 lines
16 KiB
JavaScript
549 lines
16 KiB
JavaScript
import {
|
|
awaitPromise,
|
|
closePages,
|
|
FSI,
|
|
kbFocusNext,
|
|
loadAndWait,
|
|
PDI,
|
|
} from "./test_utils.mjs";
|
|
|
|
function waitForThumbnailVisible(page, pageNum) {
|
|
return page.waitForSelector(
|
|
`.thumbnailImageContainer[data-l10n-args='{"page":${pageNum}}']`,
|
|
{ visible: true }
|
|
);
|
|
}
|
|
|
|
async function waitForMenu(page, buttonSelector, visible = true) {
|
|
return page.waitForFunction(
|
|
(selector, vis) => {
|
|
const button = document.querySelector(selector);
|
|
if (!button) {
|
|
return false;
|
|
}
|
|
return button.getAttribute("aria-expanded") === (vis ? "true" : "false");
|
|
},
|
|
{},
|
|
buttonSelector,
|
|
visible
|
|
);
|
|
}
|
|
|
|
async function showViewsManager(page) {
|
|
const hasAnimations = await page.evaluate(
|
|
() => !window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
);
|
|
await page.click("#viewsManagerToggleButton");
|
|
if (hasAnimations) {
|
|
await page.waitForSelector("#outerContainer.viewsManagerMoving", {
|
|
visible: true,
|
|
});
|
|
}
|
|
await page.waitForSelector("#viewsManager", { visible: true });
|
|
await page.waitForSelector(
|
|
"#outerContainer:not(.viewsManagerMoving).viewsManagerOpen",
|
|
{ visible: true }
|
|
);
|
|
}
|
|
|
|
describe("PDF Thumbnail View", () => {
|
|
describe("Works without errors", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait("tracemonkey.pdf", "#viewsManagerToggleButton");
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
it("should render thumbnails without errors", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
|
|
const thumbSelector =
|
|
"#thumbnailsView .thumbnailImageContainer > img";
|
|
await page.waitForSelector(thumbSelector, { visible: true });
|
|
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
await page.waitForSelector(`${thumbSelector}[src^="blob:http:"]`, {
|
|
visible: true,
|
|
});
|
|
})
|
|
);
|
|
});
|
|
|
|
it("should have accessible label on resizer", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
|
|
const ariaLabel = await page.$eval("#viewsManagerResizer", el =>
|
|
el.getAttribute("aria-label")
|
|
);
|
|
expect(ariaLabel)
|
|
.withContext(`In ${browserName}`)
|
|
.toBe("Sidebar resizer");
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("The view is scrolled correctly", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait("tracemonkey.pdf", "#viewsManagerToggleButton");
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
async function goToPage(page, number) {
|
|
const handle = await page.evaluateHandle(
|
|
num => [
|
|
new Promise(resolve => {
|
|
const container = document.getElementById("viewsManagerContent");
|
|
container.addEventListener("scrollend", resolve, { once: true });
|
|
// eslint-disable-next-line no-undef
|
|
PDFViewerApplication.pdfLinkService.goToPage(num);
|
|
}),
|
|
],
|
|
number
|
|
);
|
|
return awaitPromise(handle);
|
|
}
|
|
|
|
it("should scroll the view", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
for (const pageNum of [14, 1, 13, 2]) {
|
|
await goToPage(page, pageNum);
|
|
const thumbSelector = `.thumbnailImageContainer[data-l10n-args='{"page":${pageNum}}']`;
|
|
await page.waitForSelector(
|
|
`.thumbnail ${thumbSelector}[aria-current="page"]`,
|
|
{ visible: true }
|
|
);
|
|
await page.waitForSelector(
|
|
`${thumbSelector} > img[src^="blob:http:"]`,
|
|
{
|
|
visible: true,
|
|
}
|
|
);
|
|
}
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("The view is accessible with the keyboard", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait("tracemonkey.pdf", "#viewsManagerToggleButton");
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
it("should navigate with the keyboard", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
await waitForThumbnailVisible(page, 2);
|
|
await waitForThumbnailVisible(page, 3);
|
|
|
|
await kbFocusNext(page);
|
|
await page.waitForSelector("#viewsManagerSelectorButton:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
await kbFocusNext(page);
|
|
await page.waitForSelector("#viewsManagerStatusActionButton:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
await kbFocusNext(page);
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":1}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
await page.keyboard.press("ArrowDown");
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":2}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
await page.keyboard.press("ArrowUp");
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":1}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
await page.keyboard.press("ArrowDown");
|
|
await page.keyboard.press("ArrowDown");
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":3}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
await page.keyboard.press("Enter");
|
|
const currentPage = await page.$eval(
|
|
"#pageNumber",
|
|
el => el.valueAsNumber
|
|
);
|
|
expect(currentPage).withContext(`In ${browserName}`).toBe(3);
|
|
|
|
await page.keyboard.press("End");
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":14}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
await page.keyboard.press("Home");
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":1}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("The manage dropdown menu", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait(
|
|
"tracemonkey.pdf",
|
|
"#viewsManagerToggleButton",
|
|
null,
|
|
null,
|
|
{ enableSplitMerge: true }
|
|
);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
async function enableMenuItems(page) {
|
|
await page.evaluate(() => {
|
|
document
|
|
.querySelectorAll("#viewsManagerStatusActionOptions button")
|
|
.forEach(button => {
|
|
button.disabled = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
it("should open with Enter key and remain open", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
await enableMenuItems(page);
|
|
|
|
// Focus the manage button
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
await page.waitForSelector("#viewsManagerStatusActionButton:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Press Enter to open the menu
|
|
await page.keyboard.press("Enter");
|
|
|
|
await waitForMenu(page, "#viewsManagerStatusActionButton");
|
|
|
|
// Verify first menu item can be focused
|
|
await page.waitForSelector("#viewsManagerStatusActionCopy:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Close menu with Escape
|
|
await page.keyboard.press("Escape");
|
|
await waitForMenu(page, "#viewsManagerStatusActionButton", false);
|
|
})
|
|
);
|
|
});
|
|
|
|
it("should open with Space key and remain open", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
await enableMenuItems(page);
|
|
|
|
// Focus the manage button
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
await page.waitForSelector("#viewsManagerStatusActionButton:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Press Space to open the menu
|
|
await page.keyboard.press(" ");
|
|
|
|
await waitForMenu(page, "#viewsManagerStatusActionButton");
|
|
|
|
// Verify first menu item can be focused
|
|
await page.waitForSelector("#viewsManagerStatusActionCopy:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Navigate menu items with arrow keys
|
|
await page.keyboard.press("ArrowDown");
|
|
await page.waitForSelector("#viewsManagerStatusActionCut:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Menu should still be open
|
|
await waitForMenu(page, "#viewsManagerStatusActionButton");
|
|
|
|
// Close menu with Escape
|
|
await page.keyboard.press("Escape");
|
|
await waitForMenu(page, "#viewsManagerStatusActionButton", false);
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Checkbox accessibility", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait(
|
|
"tracemonkey.pdf",
|
|
"#viewsManagerToggleButton",
|
|
null,
|
|
null,
|
|
{ enableSplitMerge: true }
|
|
);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
it("should have accessible label on checkbox", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
const ariaLabel = await page.$eval(
|
|
`.thumbnail[page-number="1"] input[type="checkbox"]`,
|
|
el => el.getAttribute("aria-label")
|
|
);
|
|
expect(ariaLabel)
|
|
.withContext(`In ${browserName}`)
|
|
.toBe(`Select page ${FSI}1${PDI}`);
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Menu keyboard navigation with multi-character keys (bug 2016212)", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait(
|
|
"page_with_number_and_link.pdf",
|
|
"#viewsManagerSelectorButton",
|
|
null,
|
|
null,
|
|
{ enableSplitMerge: true }
|
|
);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
it("must navigate menus with ArrowDown and Tab keys", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
// Focus the views manager selector button
|
|
await page.waitForSelector("#viewsManagerSelectorButton", {
|
|
visible: true,
|
|
});
|
|
await page.focus("#viewsManagerSelectorButton");
|
|
|
|
// Open menu with Enter key
|
|
await page.keyboard.press("Enter");
|
|
|
|
// Wait for menu to be expanded
|
|
await waitForMenu(page, "#viewsManagerSelectorButton");
|
|
|
|
// Check that focus moved to the first menu button (pages)
|
|
await page.waitForSelector("#thumbnailsViewMenu:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Press ArrowDown to navigate to second item
|
|
await page.keyboard.press("ArrowDown");
|
|
|
|
// Should now be on outlines button
|
|
await page.waitForSelector("#outlinesViewMenu:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Press Tab to move to the manage button (should close views menu)
|
|
await page.keyboard.press("Tab");
|
|
|
|
// Wait for views manager menu to be collapsed
|
|
await waitForMenu(page, "#viewsManagerSelectorButton", false);
|
|
|
|
// Focus should be on manage button
|
|
await page.waitForSelector("#viewsManagerStatusActionButton:focus", {
|
|
visible: true,
|
|
});
|
|
|
|
// Open manage menu with Space key
|
|
await page.keyboard.press(" ");
|
|
|
|
// Wait for manage menu to be expanded
|
|
await waitForMenu(page, "#viewsManagerStatusActionButton");
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Views manager status visibility (bug 2016656)", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait(
|
|
"page_with_number_and_link.pdf",
|
|
"#viewsManagerToggleButton",
|
|
null,
|
|
null,
|
|
{ enableSplitMerge: true }
|
|
);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
it("should show the manage button in thumbnail view and hide it in outline view", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
// The status bar (Select pages + Manage button) must be visible in
|
|
// thumbnail view.
|
|
await page.waitForSelector("#viewsManagerStatus", { visible: true });
|
|
|
|
// Switch to outline view.
|
|
await page.click("#viewsManagerSelectorButton");
|
|
await page.waitForSelector("#outlinesViewMenu", { visible: true });
|
|
await page.click("#outlinesViewMenu");
|
|
await page.waitForSelector("#outlinesView", { visible: true });
|
|
|
|
// The status bar must no longer be visible in outline view.
|
|
await page.waitForSelector("#viewsManagerStatus", { hidden: true });
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Checkbox keyboard navigation", () => {
|
|
let pages;
|
|
|
|
beforeEach(async () => {
|
|
pages = await loadAndWait(
|
|
"tracemonkey.pdf",
|
|
"#viewsManagerToggleButton",
|
|
null,
|
|
null,
|
|
{ enableSplitMerge: true }
|
|
);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await closePages(pages);
|
|
});
|
|
|
|
it("should focus checkboxes with Tab key", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
|
|
// Focus the first thumbnail button
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
|
|
// Verify we're on the first thumbnail
|
|
await page.waitForSelector(
|
|
`#thumbnailsView .thumbnailImageContainer[data-l10n-args='{"page":1}']:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
// Tab to checkbox
|
|
await kbFocusNext(page);
|
|
await page.waitForSelector(
|
|
`.thumbnail[page-number="1"] input[type="checkbox"]:focus`,
|
|
{ visible: true }
|
|
);
|
|
})
|
|
);
|
|
});
|
|
|
|
it("should navigate checkboxes with arrow keys", async () => {
|
|
await Promise.all(
|
|
pages.map(async ([browserName, page]) => {
|
|
await showViewsManager(page);
|
|
await waitForThumbnailVisible(page, 1);
|
|
await waitForThumbnailVisible(page, 2);
|
|
|
|
// Navigate to first checkbox
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
await kbFocusNext(page);
|
|
|
|
// Verify first checkbox is focused
|
|
await page.waitForSelector(
|
|
`.thumbnail[page-number="1"] input[type="checkbox"]:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
// Navigate to next checkbox with ArrowDown
|
|
await page.keyboard.press("ArrowDown");
|
|
await page.waitForSelector(
|
|
`.thumbnail[page-number="2"] input[type="checkbox"]:focus`,
|
|
{ visible: true }
|
|
);
|
|
|
|
// Navigate back with ArrowUp
|
|
await page.keyboard.press("ArrowUp");
|
|
await page.waitForSelector(
|
|
`.thumbnail[page-number="1"] input[type="checkbox"]:focus`,
|
|
{ visible: true }
|
|
);
|
|
})
|
|
);
|
|
});
|
|
});
|
|
});
|