import { expect, type Page } from "@playwright/test"; export type LiveInvoiceOcrStatus = "available" | "ocr_failed"; export type LiveInvoiceOcrResult = { status: LiveInvoiceOcrStatus; detailText: string; bannerText: string; durationMs: number; invoiceId: string | null; invoiceCode: string | null; invoiceNumber: string | null; sellerName: string | null; totalAmount: string | null; invoiceDate: string | null; }; function extractField(detailText: string, label: string) { const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const match = detailText.match(new RegExp(`${escaped}([^\\n]+)`)); return match?.[1]?.trim() || null; } export async function openInvoicePool(page: Page) { await page.goto("/invoice-pool"); await expect(page.getByTestId("invoice-pool-table")).toBeVisible(); } export async function uploadLiveInvoiceAndWait(page: Page, invoiceFilePath: string, timeout = 180_000): Promise { const startedAt = Date.now(); await page.getByTestId("invoice-upload-file").setInputFiles(invoiceFilePath); await page.getByTestId("invoice-upload-submit").click(); const detailPanel = page.getByTestId("invoice-detail-panel"); await expect(detailPanel).toBeVisible({ timeout: 30_000 }); await expect .poll(async () => { const text = await detailPanel.innerText().catch(() => ""); if (text.includes("状态:available")) return "available"; if (text.includes("状态:ocr_failed")) return "ocr_failed"; return "pending_ocr"; }, { timeout }) .not.toBe("pending_ocr"); const detailText = await detailPanel.innerText(); const bannerText = await page.getByTestId("invoice-ocr-status-banner").innerText().catch(() => ""); const status = detailText.includes("状态:ocr_failed") ? "ocr_failed" : "available"; const invoiceNo = extractField(detailText, "发票号:"); const [invoiceCode, invoiceNumber] = invoiceNo && invoiceNo.includes("-") ? invoiceNo.split("-", 2).map((item) => item.trim() || null) : [invoiceNo, null]; return { status, detailText, bannerText, durationMs: Date.now() - startedAt, invoiceId: extractField(detailText, "票据ID:"), invoiceCode, invoiceNumber, sellerName: extractField(detailText, "销售方:"), totalAmount: extractField(detailText, "总金额:"), invoiceDate: extractField(detailText, "开票日期:"), }; }