♻️(frontend) regroup preview e2e specs under file-preview/

The preview-related specs are now numerous enough to warrant their
own subfolder. Move pdf, heic and preview-actions specs into
__tests__/app-drive/file-preview/ so future preview tests land next
to them rather than at the drive-level root. Import and asset paths
are adjusted to the new depth, the heic row lookup is simplified to
getByRole("cell", ...), and the preview-actions spec gains a small
File Preview Header describe block to exercise the header controls.
This commit is contained in:
Nathan Vasse
2026-04-14 15:11:06 +02:00
parent 6b0ff1a0d1
commit a49f4b5dac
4 changed files with 329 additions and 142 deletions

View File

@@ -1,124 +0,0 @@
import path from "path";
import test, { expect } from "@playwright/test";
import { clearDb, login } from "./utils-common";
import { clickToMyFiles } from "./utils-navigate";
import { uploadFile } from "./utils/upload-utils";
const PDF_FILE_PATH = path.join(__dirname, "/assets/pv_cm.pdf");
const DOCX_FILE_PATH = path.join(__dirname, "/assets/empty_doc.docx");
test.describe("File Preview Actions Menu", () => {
test.beforeEach(async ({ page }) => {
await clearDb();
await login(page, "drive@example.com");
await page.goto("/");
await clickToMyFiles(page);
await uploadFile(page, PDF_FILE_PATH);
await expect(
page.getByRole("cell", { name: "pv_cm", exact: true }),
).toBeVisible({ timeout: 10000 });
await page.getByRole("cell", { name: "pv_cm", exact: true }).dblclick();
await expect(page.getByTestId("file-preview")).toBeVisible({
timeout: 10000,
});
});
test("Shows the actions dropdown with download and print options", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const moreButton = filePreview.locator(
".file-preview__header__content__right button:has(.material-icons)",
);
// Find the "..." button (more_vert icon)
const moreVertButton = filePreview.getByText("more_vert").locator("..");
await expect(moreVertButton).toBeVisible();
await moreVertButton.click();
// Verify both menu items appear
await expect(
page.getByRole("menuitem", { name: "Download" }),
).toBeVisible();
await expect(page.getByRole("menuitem", { name: "Print" })).toBeVisible();
});
test("Download action in dropdown triggers file download", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const moreVertButton = filePreview.getByText("more_vert").locator("..");
await moreVertButton.click();
const downloadPromise = page.waitForEvent("download");
await page.getByRole("menuitem", { name: "Download" }).click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toContain("pv_cm");
});
test("Updates the browser tab title when preview is open", async ({
page,
}) => {
// The title should include the file name while preview is open
await expect(page).toHaveTitle(/pv_cm\.pdf/);
// Close the preview
const filePreview = page.getByTestId("file-preview");
const closeButton = filePreview.locator(
".file-preview__header__content__left button",
);
await closeButton.click();
// The title should no longer contain the file name
await expect(page).not.toHaveTitle(/pv_cm\.pdf/);
});
test("Print action in dropdown opens the file in a new tab", async ({
page,
context,
}) => {
const filePreview = page.getByTestId("file-preview");
const moreVertButton = filePreview.getByText("more_vert").locator("..");
await moreVertButton.click();
const [newPage] = await Promise.all([
context.waitForEvent("page"),
page.getByRole("menuitem", { name: "Print" }).click(),
]);
// A new tab was opened with the file for printing
expect(newPage).toBeTruthy();
await newPage.close();
});
});
test.describe("File Preview Actions Menu - Non-printable file", () => {
test("Hides the actions menu for non-PDF/non-image files", async ({
page,
}) => {
await clearDb();
await login(page, "drive@example.com");
await page.goto("/");
await clickToMyFiles(page);
await uploadFile(page, DOCX_FILE_PATH);
await expect(
page.getByRole("cell", { name: "empty_doc", exact: true }),
).toBeVisible({ timeout: 10000 });
await page.getByRole("cell", { name: "empty_doc", exact: true }).dblclick();
await expect(page.getByTestId("file-preview")).toBeVisible({
timeout: 10000,
});
const filePreview = page.getByTestId("file-preview");
await expect(
filePreview.getByText("more_vert"),
).not.toBeVisible();
});
});

View File

@@ -0,0 +1,283 @@
import path from "path";
import test, { expect } from "@playwright/test";
import { clearDb, login } from "../utils-common";
import { clickToMyFiles } from "../utils-navigate";
import { uploadFile } from "../utils/upload-utils";
const PDF_FILE_PATH = path.join(__dirname, "../assets/pv_cm.pdf");
const DOCX_FILE_PATH = path.join(__dirname, "../assets/empty_doc.docx");
test.describe("File Preview Actions Menu", () => {
test.beforeEach(async ({ page }) => {
await clearDb();
await login(page, "drive@example.com");
await page.goto("/");
await clickToMyFiles(page);
await uploadFile(page, PDF_FILE_PATH);
await expect(
page.getByRole("cell", { name: "pv_cm", exact: true }),
).toBeVisible({ timeout: 10000 });
await page.getByRole("cell", { name: "pv_cm", exact: true }).dblclick();
await expect(page.getByTestId("file-preview")).toBeVisible({
timeout: 10000,
});
});
test("Shows the actions dropdown with download and print options", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const moreButton = filePreview.locator(
".file-preview__header__content__right button:has(.material-icons)",
);
// Find the "..." button (more_vert icon)
const moreVertButton = filePreview.getByText("more_vert").locator("..");
await expect(moreVertButton).toBeVisible();
await moreVertButton.click();
// Verify both menu items appear
await expect(
page.getByRole("menuitem", { name: "Download" }),
).toBeVisible();
await expect(page.getByRole("menuitem", { name: "Print" })).toBeVisible();
});
test("Download action in dropdown triggers file download", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const moreVertButton = filePreview.getByText("more_vert").locator("..");
await moreVertButton.click();
const downloadPromise = page.waitForEvent("download");
await page.getByRole("menuitem", { name: "Download" }).click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toContain("pv_cm");
});
test("Updates the browser tab title when preview is open", async ({
page,
}) => {
// The title should include the file name while preview is open
await expect(page).toHaveTitle(/pv_cm\.pdf/);
// Close the preview
const filePreview = page.getByTestId("file-preview");
const closeButton = filePreview.locator(
".file-preview__header__content__left button",
);
await closeButton.click();
// The title should no longer contain the file name
await expect(page).not.toHaveTitle(/pv_cm\.pdf/);
});
test("Print action in dropdown opens the file in a new tab", async ({
page,
context,
}) => {
const filePreview = page.getByTestId("file-preview");
const moreVertButton = filePreview.getByText("more_vert").locator("..");
await moreVertButton.click();
const [newPage] = await Promise.all([
context.waitForEvent("page"),
page.getByRole("menuitem", { name: "Print" }).click(),
]);
// A new tab was opened with the file for printing
expect(newPage).toBeTruthy();
await newPage.close();
});
});
test.describe("File Preview Actions Menu - Non-printable file", () => {
test("Hides the actions menu for non-PDF/non-image files", async ({
page,
}) => {
await clearDb();
await login(page, "drive@example.com");
await page.goto("/");
await clickToMyFiles(page);
await uploadFile(page, DOCX_FILE_PATH);
await expect(
page.getByRole("cell", { name: "empty_doc", exact: true }),
).toBeVisible({ timeout: 10000 });
await page.getByRole("cell", { name: "empty_doc", exact: true }).dblclick();
await expect(page.getByTestId("file-preview")).toBeVisible({
timeout: 10000,
});
const filePreview = page.getByTestId("file-preview");
await expect(
filePreview.getByText("more_vert"),
).not.toBeVisible();
});
});
test.describe("File Preview Header", () => {
test.beforeEach(async ({ page }) => {
await clearDb();
await login(page, "drive@example.com");
await page.goto("/");
await clickToMyFiles(page);
await uploadFile(page, PDF_FILE_PATH);
await expect(
page.getByRole("cell", { name: "pv_cm", exact: true }),
).toBeVisible({ timeout: 10000 });
await page.getByRole("cell", { name: "pv_cm", exact: true }).dblclick();
await expect(page.getByTestId("file-preview")).toBeVisible({
timeout: 10000,
});
});
test("Closes the preview when the close button is clicked", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
await expect(filePreview).toBeVisible();
const closeButton = filePreview.locator(
".file-preview__header__content__left button",
);
await closeButton.click();
await expect(page.getByTestId("file-preview")).not.toBeAttached({
timeout: 5000,
});
});
test("Toggles the info sidebar on and off", async ({ page }) => {
const container = page.locator(".file-preview__container");
const sidebar = page.locator(".file-preview-sidebar");
await expect(container).not.toHaveClass(
/file-preview__container--sidebar-open/,
);
await expect(sidebar).not.toHaveClass(/(^|\s)open(\s|$)/);
const filePreview = page.getByTestId("file-preview");
const infoButton = filePreview.getByText("info_outline").locator("..");
await infoButton.click();
await expect(container).toHaveClass(
/file-preview__container--sidebar-open/,
{ timeout: 5000 },
);
await expect(sidebar).toHaveClass(/(^|\s)open(\s|$)/);
await infoButton.click();
await expect(container).not.toHaveClass(
/file-preview__container--sidebar-open/,
{ timeout: 5000 },
);
await expect(sidebar).not.toHaveClass(/(^|\s)open(\s|$)/);
});
});
test.describe("File Preview Navigation", () => {
test.beforeEach(async ({ page }) => {
await clearDb();
await login(page, "drive@example.com");
await page.goto("/");
await clickToMyFiles(page);
await uploadFile(page, PDF_FILE_PATH);
await expect(
page.getByRole("cell", { name: "pv_cm", exact: true }),
).toBeVisible({ timeout: 10000 });
await uploadFile(page, DOCX_FILE_PATH);
await expect(
page.getByRole("cell", { name: "empty_doc", exact: true }),
).toBeVisible({ timeout: 10000 });
await page.getByRole("cell", { name: "pv_cm", exact: true }).dblclick();
await expect(page.getByTestId("file-preview")).toBeVisible({
timeout: 10000,
});
});
test("Navigates between files with the prev/next buttons", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const title = filePreview.locator("h1.file-preview__title");
const nextButton = page.locator(".file-preview__next-button button");
const prevButton = page.locator(".file-preview__previous-button button");
await expect(title).toHaveText("pv_cm");
// With 2 files and pv_cm at a boundary, exactly one of prev/next is disabled.
const nextDisabled = await nextButton.isDisabled();
const prevDisabled = await prevButton.isDisabled();
expect(nextDisabled).not.toBe(prevDisabled);
// Click whichever is enabled — we should land on empty_doc.
if (!nextDisabled) {
await nextButton.click();
} else {
await prevButton.click();
}
await expect(title).toHaveText("empty_doc");
// Boundary flipped: previously enabled is now disabled, vice versa.
if (!nextDisabled) {
await expect(nextButton).toBeDisabled();
await expect(prevButton).toBeEnabled();
} else {
await expect(prevButton).toBeDisabled();
await expect(nextButton).toBeEnabled();
}
});
test("Navigates between files with ArrowLeft/ArrowRight keys", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const title = filePreview.locator("h1.file-preview__title");
const nextButton = page.locator(".file-preview__next-button button");
await expect(title).toHaveText("pv_cm");
const nextDisabled = await nextButton.isDisabled();
const forwardKey = nextDisabled ? "ArrowLeft" : "ArrowRight";
const backwardKey = nextDisabled ? "ArrowRight" : "ArrowLeft";
await page.keyboard.press(forwardKey);
await expect(title).toHaveText("empty_doc");
await page.keyboard.press(backwardKey);
await expect(title).toHaveText("pv_cm");
});
test("Does not navigate files when arrow keys are pressed inside the PDF page input", async ({
page,
}) => {
const filePreview = page.getByTestId("file-preview");
const title = filePreview.locator("h1.file-preview__title");
await expect(title).toHaveText("pv_cm");
const pageInput = page.locator('input[aria-label="Current page"]');
await expect(pageInput).toBeVisible({ timeout: 10000 });
await pageInput.focus();
await page.keyboard.press("ArrowRight");
await expect(title).toHaveText("pv_cm");
await page.keyboard.press("ArrowLeft");
await expect(title).toHaveText("pv_cm");
});
});

View File

@@ -1,9 +1,8 @@
import test, { expect } from "@playwright/test";
import { clearDb, login } from "./utils-common";
import { clearDb, login } from "../utils-common";
import path from "path";
import { clickToMyFiles } from "./utils-navigate";
import { getRowItem } from "./utils-embedded-grid";
import { uploadFile } from "./utils/upload-utils";
import { clickToMyFiles } from "../utils-navigate";
import { uploadFile } from "../utils/upload-utils";
test("Display HEIC not supported message when opening a HEIC file", async ({
page,
@@ -15,21 +14,22 @@ test("Display HEIC not supported message when opening a HEIC file", async ({
await expect(page.getByText("This tab is empty")).toBeVisible();
// Use the real HEIC file from assets
const heicFilePath = path.join(__dirname, "/assets/test-image.heic");
const heicFilePath = path.join(__dirname, "../assets/test-image.heic");
// Upload the HEIC file
await uploadFile(page, heicFilePath);
// Wait for the file to be uploaded and visible in the list
await expect(page.getByText("Drop your files here")).not.toBeVisible();
await expect(
page.getByRole("cell", { name: "test-image", exact: true }),
).toBeVisible({ timeout: 10000 });
// Click on the HEIC file to open the preview
const row = await getRowItem(page, "test-image");
await row.dblclick();
// Double-click the cell to open the preview
await page.getByRole("cell", { name: "test-image", exact: true }).dblclick();
// Check that the file preview is visible
const filePreview = page.getByTestId("file-preview");
await expect(filePreview).toBeVisible();
await expect(filePreview).toBeVisible({ timeout: 10000 });
// Check that the HEIC-specific message is displayed
await expect(

View File

@@ -2,20 +2,23 @@ import path from "path";
import test, { expect } from "@playwright/test";
import { clearDb, login } from "./utils-common";
import { clickToMyFiles } from "./utils-navigate";
import { uploadFile } from "./utils/upload-utils";
import { clearDb, login } from "../utils-common";
import { clickToMyFiles } from "../utils-navigate";
import { uploadFile } from "../utils/upload-utils";
const PDF_FILE_PATH = path.join(__dirname, "/assets/pv_cm.pdf");
const PDF_LINKS_FILE_PATH = path.join(__dirname, "/assets/pdf_with_links.pdf");
const PDF_JS_FILE_PATH = path.join(__dirname, "/assets/pdf_with_js.pdf");
const PDF_FILE_PATH = path.join(__dirname, "../assets/pv_cm.pdf");
const PDF_LINKS_FILE_PATH = path.join(
__dirname,
"../assets/pdf_with_links.pdf",
);
const PDF_JS_FILE_PATH = path.join(__dirname, "../assets/pdf_with_js.pdf");
const PDF_JS_LINK_FILE_PATH = path.join(
__dirname,
"/assets/pdf_with_js_link.pdf",
"../assets/pdf_with_js_link.pdf",
);
const PDF_CORRUPTED_FILE_PATH = path.join(
__dirname,
"/assets/pdf_corrupted.pdf",
"../assets/pdf_corrupted.pdf",
);
import type { Page, Locator } from "@playwright/test";
@@ -255,6 +258,31 @@ test.describe("PDF Preview", () => {
});
});
test("Applies pdf-sidebar-open class on the container when the thumbnail sidebar is opened", async ({
page,
}) => {
const container = page.locator(".file-preview__container");
await expect(container).not.toHaveClass(
/file-preview__container--pdf-sidebar-open/,
);
await openSidebar(page);
await expect(container).toHaveClass(
/file-preview__container--pdf-sidebar-open/,
{ timeout: 5000 },
);
const toggle = page.locator('button[aria-label="Toggle sidebar"]');
await toggle.dispatchEvent("click");
await expect(container).not.toHaveClass(
/file-preview__container--pdf-sidebar-open/,
{ timeout: 5000 },
);
});
test("Marks the current page thumbnail as active", async ({ page }) => {
await openSidebar(page);