Files
imagefind/scripts/live-bulk-retry-ui-acceptance.mjs
T

90 lines
4.1 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { createRequire } from "node:module";
const require = createRequire(new URL("../frontend/package.json", import.meta.url));
const { chromium } = require("playwright");
const baseUrl = String(process.env.IMAGEFIND_LIVE_URL || "").replace(/\/$/, "");
const tokenFile = process.env.IMAGEFIND_LIVE_TOKEN_FILE || "";
const outputDir = path.resolve(process.env.IMAGEFIND_LIVE_OUTPUT || "dist/postdeploy-0.5.45-bulk-retry");
if (!baseUrl || !tokenFile) throw new Error("IMAGEFIND_LIVE_URL and IMAGEFIND_LIVE_TOKEN_FILE are required");
const token = fs.readFileSync(tokenFile, "utf8").trim();
fs.mkdirSync(outputDir, { recursive: true });
async function openTasks(browser, viewport) {
const context = await browser.newContext({ viewport, locale: "zh-CN" });
const origin = new URL(baseUrl).origin;
await context.route("**/*", async route => {
const url = new URL(route.request().url());
if (url.origin === origin && url.pathname.includes("/api/")) {
await route.continue({
headers: { ...route.request().headers(), authorization: `Bearer ${token}` },
});
return;
}
await route.continue();
});
const page = await context.newPage();
await page.goto(baseUrl, { waitUntil: "domcontentloaded", timeout: 30_000 });
await page.locator(".app-shell").waitFor({ timeout: 30_000 });
if (viewport.width <= 720) {
await page.getByRole("button", { name: "更多" }).click();
await page.locator(".mobile-more-menu").getByRole("button", { name: "设置" }).click();
} else {
await page.locator(".nav-item-8").click();
}
await page.getByRole("heading", { name: "设置" }).waitFor({ timeout: 20_000 });
await page.getByRole("button", { name: "任务与偏好" }).click();
await page.locator(".jobs-panel").waitFor({ timeout: 20_000 });
await page
.getByRole("navigation", { name: "后台任务通道" })
.getByRole("button", { name: "上传转存" })
.click();
await page.locator(".job-retry-all").waitFor({ timeout: 20_000 });
return { context, page };
}
const browser = await chromium.launch({ headless: true });
const report = {};
try {
{
const { context, page } = await openTasks(browser, { width: 390, height: 844 });
const button = page.locator(".job-retry-all");
const box = await button.boundingBox();
report.mobile = {
button: (await button.innerText()).replace(/\s+/g, " ").trim(),
min_touch_target: Boolean(box && box.height >= 44),
overflow: await page.evaluate(() => document.documentElement.scrollWidth - innerWidth),
};
await page.screenshot({ path: path.join(outputDir, "mobile-transfer-retry.png"), fullPage: true });
await context.close();
}
{
const { context, page } = await openTasks(browser, { width: 1440, height: 900 });
const button = page.locator(".job-retry-all");
report.desktop = { button: (await button.innerText()).replace(/\s+/g, " ").trim() };
await button.click();
const dialog = page.getByRole("alertdialog");
report.desktop.confirmation = (await dialog.innerText()).replace(/\s+/g, " ").trim();
await page.screenshot({ path: path.join(outputDir, "desktop-confirmation.png"), fullPage: true });
const retryResponse = page.waitForResponse(
response => response.url().includes("/api/v1/jobs/retry-failed") && response.request().method() === "POST",
);
await dialog.getByRole("button", { name: "继续" }).click();
const response = await retryResponse;
if (!response.ok()) throw new Error(`bulk retry failed: ${response.status()} ${await response.text()}`);
report.desktop.result = await response.json();
await page.waitForTimeout(1_000);
report.desktop.button_visible_after_retry = (await page.locator(".job-retry-all").count()) > 0;
await page.screenshot({ path: path.join(outputDir, "desktop-result.png"), fullPage: true });
await context.close();
}
} finally {
await browser.close();
}
fs.writeFileSync(path.join(outputDir, "report.json"), `${JSON.stringify(report, null, 2)}\n`);
console.log(JSON.stringify(report, null, 2));