文件
hyb-oa/client/tests/e2e/helpers/liveInvoiceOcr.ts
T

84 行
3.0 KiB
TypeScript
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
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<LiveInvoiceOcrResult> {
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 });
try {
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 })
.toMatch(/^(available|ocr_failed)$/);
} catch (error) {
const detailText = await detailPanel.innerText().catch(() => "");
const bannerText = await page.getByTestId("invoice-ocr-status-banner").innerText().catch(() => "");
const invoiceId = extractField(detailText, "票据ID:");
throw new Error(
[
"live 腾讯 OCR 等待终态超时",
`invoiceId=${invoiceId ?? "unknown"}`,
`timeoutMs=${timeout}`,
`detail=${detailText || "<empty>"}`,
`banner=${bannerText || "<empty>"}`,
`cause=${error instanceof Error ? error.message : String(error)}`,
].join("\n"),
);
}
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, "开票日期:"),
};
}