91 lines
4.8 KiB
TypeScript
91 lines
4.8 KiB
TypeScript
import { expect, test, type APIRequestContext, type Download } from "@playwright/test";
|
|
import sharp from "sharp";
|
|
|
|
const E2E_USERNAME = process.env.EDGE_EVER_E2E_USERNAME || "admin";
|
|
const E2E_PASSWORD = process.env.EDGE_EVER_E2E_PASSWORD || "admin123";
|
|
|
|
const login = async (request: APIRequestContext) => {
|
|
const response = await request.post("/api/v1/auth/login", {
|
|
data: { username: E2E_USERNAME, password: E2E_PASSWORD },
|
|
});
|
|
expect(response.ok(), `login failed: ${response.status()} ${await response.text()}`).toBe(true);
|
|
};
|
|
|
|
const inspectDownload = async (download: Download) => {
|
|
const path = await download.path();
|
|
expect(path).not.toBeNull();
|
|
const image = sharp(path!);
|
|
const metadata = await image.metadata();
|
|
const statistics = await image.stats();
|
|
const { data: pixels, info } = await sharp(path!).raw().toBuffer({ resolveWithObject: true });
|
|
return { metadata, statistics, topLeft: Array.from(pixels.slice(0, info.channels)) };
|
|
};
|
|
|
|
test("downloads a long note as one non-blank PNG or JPEG from the share dialog", async ({ page, request }) => {
|
|
test.setTimeout(90_000);
|
|
await login(request);
|
|
const notebooksResponse = await request.get("/api/v1/notebooks");
|
|
expect(notebooksResponse.ok()).toBe(true);
|
|
const notebooks = (await notebooksResponse.json() as { notebooks: Array<{ id: string; name: string }> }).notebooks;
|
|
const notebook = notebooks[0];
|
|
expect(notebook).toBeTruthy();
|
|
|
|
const title = `e2e-image-export-${Date.now()}`;
|
|
const contentMarkdown = Array.from(
|
|
{ length: 80 },
|
|
(_, index) => `## Section ${index + 1}\n\nVisible export content ${index + 1}: EdgeEver image regression test.`,
|
|
).join("\n\n");
|
|
const createResponse = await request.post("/api/v1/memos", {
|
|
data: { notebookId: notebook.id, title, contentMarkdown },
|
|
});
|
|
expect(createResponse.status(), await createResponse.text()).toBe(201);
|
|
const memoId = (await createResponse.json() as { memo: { id: string } }).memo.id;
|
|
|
|
try {
|
|
await page.goto("/");
|
|
await page.getByRole("button", { name: new RegExp(notebook.name) }).click();
|
|
await page.locator(`[data-memo-id="${memoId}"]`).locator("button").first().click();
|
|
await expect(page.locator(".ProseMirror")).toContainText("Visible export content 80");
|
|
|
|
await page.getByRole("button", { name: /笔记更多操作|More note actions/ }).click();
|
|
await expect(page.getByRole("menuitem", { name: /导出 PNG|Export PNG/ })).toHaveCount(0);
|
|
await expect(page.getByRole("menuitem", { name: /导出 JPEG|Export JPEG/ })).toHaveCount(0);
|
|
await page.getByRole("menuitem", { name: /分享为图片|Share as image/ }).click();
|
|
const dialog = page.getByRole("dialog", { name: /分享为图片|Share as image/ });
|
|
await expect(dialog).toBeVisible();
|
|
await expect(dialog.getByRole("img", { name: /笔记分享图片预览|Note image share preview/ })).toBeVisible({ timeout: 20_000 });
|
|
await expect(dialog.getByRole("checkbox", { name: /EdgeEver 品牌标识|EdgeEver branding/ })).toBeChecked();
|
|
|
|
const pngDownloadPromise = page.waitForEvent("download");
|
|
await dialog.getByRole("button", { name: /下载图片|Download image/ }).click();
|
|
const pngDownload = await pngDownloadPromise;
|
|
expect(pngDownload.suggestedFilename()).toMatch(/\.png$/i);
|
|
expect(pngDownload.suggestedFilename()).not.toMatch(/\.zip$/i);
|
|
const pngImage = await inspectDownload(pngDownload);
|
|
expect(pngImage.metadata.format).toBe("png");
|
|
expect(pngImage.metadata.width).toBeGreaterThan(700);
|
|
expect(pngImage.metadata.height).toBeGreaterThan(4_800);
|
|
expect(pngImage.statistics.channels.some((channel) => channel.stdev > 5)).toBe(true);
|
|
await expect(dialog).toBeVisible();
|
|
|
|
await dialog.getByRole("button", { name: /薄荷|Mint/ }).click();
|
|
await dialog.getByRole("checkbox", { name: /笔记本|Notebook/ }).click();
|
|
await dialog.getByRole("combobox").click();
|
|
await page.getByRole("option", { name: /JPEG/ }).click();
|
|
await expect(dialog.getByText(/正在生成预览|Generating preview/)).toBeHidden({ timeout: 20_000 });
|
|
|
|
const shareDownloadPromise = page.waitForEvent("download");
|
|
await dialog.getByRole("button", { name: /下载图片|Download image/ }).click();
|
|
const shareDownload = await shareDownloadPromise;
|
|
expect(shareDownload.suggestedFilename()).toMatch(/\.jpg$/i);
|
|
const sharedImage = await inspectDownload(shareDownload);
|
|
expect(sharedImage.metadata.format).toBe("jpeg");
|
|
expect(sharedImage.metadata.height).toBeGreaterThan(4_800);
|
|
expect(sharedImage.statistics.channels.some((channel) => channel.stdev > 5)).toBe(true);
|
|
expect(sharedImage.topLeft.slice(0, 3).every((value, index) => Math.abs(value - [236, 253, 245][index]) < 20)).toBe(true);
|
|
} finally {
|
|
await request.delete(`/api/v1/memos/${memoId}`);
|
|
await request.delete(`/api/v1/memos/${memoId}?permanent=1`);
|
|
}
|
|
});
|