test(frontend): CBZ page-mode component test + e2e mode/RTL smoke (B1)
This commit is contained in:
@@ -51,6 +51,26 @@ test("登录 → 书架 → CBZ 阅读翻页 → 书签 → 退出", async ({ pa
|
||||
await expect(page.getByText("2/3")).toBeVisible();
|
||||
}).toPass({ timeout: 20_000 });
|
||||
|
||||
// 页模式 + RTL 冒烟:开设置面板 → 单页 → 右缘翻页 → 右开本(RTL) 方向翻转 → 回长卷。
|
||||
await page.getByRole("button", { name: "更多阅读设置" }).click();
|
||||
await page.getByRole("button", { name: "单页" }).click();
|
||||
await expect(page.getByText(/^1\/3 · /)).toBeVisible(); // 模式切换保持当前页:此时在第 2 页
|
||||
// 回到第 1 页:左缘点击
|
||||
const box2 = await reader.boundingBox();
|
||||
if (!box2) throw new Error("阅读器容器无 boundingBox");
|
||||
await page.mouse.click(box2.x + box2.width * 0.1, box2.y + box2.height / 2);
|
||||
await expect(page.getByText(/^1\/3 · /)).toBeVisible();
|
||||
// 右缘点击 → 第 2 页
|
||||
await page.mouse.click(box2.x + box2.width * 0.9, box2.y + box2.height / 2);
|
||||
await expect(page.getByText(/^2\/3 · /)).toBeVisible();
|
||||
// RTL:右缘点击变后退
|
||||
await page.getByRole("button", { name: "右开本(RTL)" }).click();
|
||||
await page.mouse.click(box2.x + box2.width * 0.9, box2.y + box2.height / 2);
|
||||
await expect(page.getByText(/^1\/3 · /)).toBeVisible();
|
||||
// 回长卷
|
||||
await page.getByRole("button", { name: "长卷", exact: true }).click();
|
||||
await expect(page.getByText("1/3")).toBeVisible();
|
||||
|
||||
// 导航抽屉(本 fixture 无内嵌目录,抽屉直接落在书签面板)→ 加书签 → toast
|
||||
await page.getByRole("button", { name: "导航", exact: true }).click();
|
||||
const nav = page.locator("#reader-nav");
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,53 @@
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { ThemeProvider } from "@/components/theme";
|
||||
import CbzReader from "@/readers/CbzReader";
|
||||
|
||||
const okResponse = (body: unknown) =>
|
||||
new Response(JSON.stringify(body), { status: 200, headers: { "Content-Type": "application/json" } });
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
vi.restoreAllMocks?.();
|
||||
// 全局网络打桩:页数接口 + 图片对象 URL + 进度上报(页图数据解不真实也无需:PageImg 有占位态)
|
||||
vi.spyOn(globalThis, "fetch").mockImplementation(async (input) => {
|
||||
const url = String(input instanceof Request ? input.url : input);
|
||||
if (url.includes("/pages")) return okResponse({ count: 3, chapters: null });
|
||||
if (url.includes("/progress")) return okResponse(null);
|
||||
return new Response("", { status: 200 }); // 页图 blob 等
|
||||
});
|
||||
Object.defineProperty(URL, "createObjectURL", { value: () => "blob:x", configurable: true });
|
||||
});
|
||||
|
||||
const book = {
|
||||
id: 1,
|
||||
library_id: 1,
|
||||
path: "p",
|
||||
title: "t",
|
||||
format: "cbz",
|
||||
state: "ok",
|
||||
percent: 0,
|
||||
pages_url: "/pages",
|
||||
page_url_fmt: "/page/{}",
|
||||
} as never;
|
||||
|
||||
describe("CbzReader 页模式设置区", () => {
|
||||
it("切「单页」后位置读数 1/3,切「双页」首页不变,切回「长卷」按钮仍可用", async () => {
|
||||
render(
|
||||
<ThemeProvider>
|
||||
<QueryClientProvider client={new QueryClient()}>
|
||||
<CbzReader book={book} chrome={{ on: true, toggle: () => {}, show: () => {} }} />
|
||||
</QueryClientProvider>
|
||||
</ThemeProvider>,
|
||||
);
|
||||
await screen.findByLabelText("漫画阅读器,点按左右两侧翻屏,点按中间显示工具栏");
|
||||
fireEvent.click(await screen.findByRole("button", { name: "更多阅读设置" }));
|
||||
fireEvent.click(await screen.findByRole("button", { name: "单页" }));
|
||||
expect(screen.getByText(/^1\/3 · /)).toBeInTheDocument();
|
||||
fireEvent.click(await screen.findByRole("button", { name: "双页" }));
|
||||
expect(screen.getByText(/^1\/3 · /)).toBeInTheDocument();
|
||||
// 模式按钮组仍在设置面板内(长卷收进同一展开区)
|
||||
expect(screen.getByRole("button", { name: "长卷" })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -221,6 +221,8 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
||||
} else {
|
||||
scrollToPage(t, false);
|
||||
}
|
||||
// 容器重挂后 scrollTop 归 0 且无 scroll 事件可刷 → 手动同步换算用的 top,避免沿用切走前的旧读数
|
||||
setTop(boxRef.current?.scrollTop ?? 0);
|
||||
}, [stripSeek, mode]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user