feat: add ImageFind application and release pipelines
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import process from "node:process";
|
||||
import playwright from "../frontend/node_modules/@playwright/test/index.js";
|
||||
|
||||
const { chromium } = playwright;
|
||||
|
||||
const chunks = [];
|
||||
for await (const chunk of process.stdin) chunks.push(chunk);
|
||||
const password = Buffer.concat(chunks).toString("utf8").trim();
|
||||
if (!password) throw new Error("password is required on stdin");
|
||||
const baseURL = String(process.argv[2] || "").replace(/\/$/, "");
|
||||
if (!baseURL) throw new Error("base URL is required");
|
||||
const output = new URL("../.playwright-results/live-0516/", import.meta.url).pathname;
|
||||
await mkdir(output, { recursive: true });
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const reports = [];
|
||||
try {
|
||||
for (const viewport of [{ name: "desktop", width: 1440, height: 900 }, { name: "mobile", width: 390, height: 844 }]) {
|
||||
const context = await browser.newContext({ viewport });
|
||||
const page = await context.newPage();
|
||||
await page.goto(baseURL, { waitUntil: "domcontentloaded" });
|
||||
const passwordInput = page.getByLabel("管理员密码");
|
||||
if (await passwordInput.isVisible().catch(() => false)) {
|
||||
await passwordInput.fill(password);
|
||||
const remember = page.locator('.remember-device input[type="checkbox"]');
|
||||
if (await remember.isChecked()) await remember.uncheck();
|
||||
await page.getByRole("button", { name: "登录", exact: true }).click();
|
||||
}
|
||||
try {
|
||||
await page.locator(".app-shell").waitFor({ state: "visible", timeout: 30_000 });
|
||||
await page.locator(".video-card,.home-empty").first().waitFor({ state: "visible", timeout: 30_000 });
|
||||
} catch (error) {
|
||||
const message = (await page.locator("body").innerText()).replace(/\s+/g, " ").slice(0, 500);
|
||||
throw new Error(`${viewport.name} app shell did not become ready: ${message}`, { cause: error });
|
||||
}
|
||||
await page.locator(".nav-item-2").click();
|
||||
await page.locator(".search-coverage").waitFor({ state: "visible", timeout: 15_000 });
|
||||
await page.waitForFunction(
|
||||
() => !document.querySelector(".search-coverage")?.textContent?.includes("正在读取"),
|
||||
undefined,
|
||||
{ timeout: 30_000 },
|
||||
);
|
||||
const coverage = (await page.locator(".search-coverage").innerText()).replace(/\s+/g, " ").trim();
|
||||
const searchGeometry = await page.evaluate(() => ({
|
||||
viewport: innerWidth,
|
||||
document: document.documentElement.scrollWidth,
|
||||
content: document.querySelector(".content")?.scrollWidth || 0,
|
||||
}));
|
||||
if (searchGeometry.document > searchGeometry.viewport + 1 || searchGeometry.content > searchGeometry.viewport + 1) {
|
||||
throw new Error(`${viewport.name} search page overflows horizontally: ${JSON.stringify(searchGeometry)}`);
|
||||
}
|
||||
await page.screenshot({ path: `${output}/${viewport.name}-search.png`, fullPage: true });
|
||||
await page.locator(".nav-item-1").click();
|
||||
await page.locator(".video-card").first().click();
|
||||
await page.locator(".transcript-panel").waitFor({ state: "visible", timeout: 15_000 });
|
||||
await page.locator(".transcript-toggle").click();
|
||||
await page.waitForFunction(
|
||||
() => !document.querySelector(".transcript-toggle")?.textContent?.includes("正在读取"),
|
||||
undefined,
|
||||
{ timeout: 30_000 },
|
||||
);
|
||||
const transcriptStatus = (await page.locator(".transcript-toggle").innerText()).replace(/\s+/g, " ").trim();
|
||||
const transcriptItems = await page.locator(".transcript-list>button").count();
|
||||
await page.screenshot({ path: `${output}/${viewport.name}-player.png`, fullPage: true });
|
||||
reports.push({ viewport: viewport.name, coverage, transcriptStatus, transcriptItems, searchGeometry });
|
||||
await page.evaluate(async () => {
|
||||
const csrf = sessionStorage.getItem("imagefind:csrf") || "";
|
||||
await fetch("/api/v1/auth/logout", { method: "POST", headers: { "X-CSRF-Token": csrf } });
|
||||
});
|
||||
await context.close();
|
||||
}
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
console.log(JSON.stringify(reports, null, 2));
|
||||
Reference in New Issue
Block a user