- 5 张 PIL 生成的验证码图(共 30KB)入 __fixtures__/captcha - 测试路径从 D:/office-test2 硬编码改为 import.meta.dirname 仓库内解析 - fresh clone 后 npm test 即可跑全部 12 项(OCR 模型来自 npm 依赖)
61 lines
2.5 KiB
TypeScript
61 lines
2.5 KiB
TypeScript
import { existsSync } from "node:fs";
|
||
import path from "node:path";
|
||
import { describe, expect, it } from "vitest";
|
||
import { getHandler } from "../engine/registry";
|
||
import type { CatalogComponent, FlowNode } from "../types";
|
||
import type { RunContext } from "../engine/types";
|
||
import "./remaining-core";
|
||
import "./captcha-caps"; // last-wins:覆盖 remaining-core 的通用实现
|
||
import { cleanCodeText, parseCalculation } from "./captcha-caps";
|
||
|
||
// 测试图随仓库走(__fixtures__/captcha,PIL 生成),真实 OCR 模型来自 npm 依赖
|
||
const fixturesDir = path.join(import.meta.dirname, "__fixtures__", "captcha");
|
||
const fixture = (name: string) => path.join(fixturesDir, `${name}.png`);
|
||
const ctx = { signal: new AbortController().signal, log: () => {}, vars: {}, evidenceDir: fixturesDir } as unknown as RunContext;
|
||
const node: FlowNode = { id: "smoke", componentId: "smoke", position: { x: 0, y: 0 }, values: {}, options: {} };
|
||
|
||
describe("parseCalculation 解析层(纯逻辑)", () => {
|
||
it("基础四则与等号问号", () => {
|
||
expect(parseCalculation("3+5=?")).toEqual({ expression: "3+5", result: 8 });
|
||
});
|
||
it("x/X/* 归一为乘", () => {
|
||
expect(parseCalculation("6x4=?")!.result).toBe(24);
|
||
expect(parseCalculation("9X9=?")!.result).toBe(81);
|
||
});
|
||
it("全角与杂字符", () => {
|
||
expect(parseCalculation("12+7=?")!.result).toBe(19);
|
||
});
|
||
it("长破折号/Unicode 减号", () => {
|
||
expect(parseCalculation("12—7")!.result).toBe(5);
|
||
});
|
||
it("除法整除与小数", () => {
|
||
expect(parseCalculation("8/2")!.result).toBe(4);
|
||
expect(parseCalculation("7/2")!.result).toBe(3.5);
|
||
});
|
||
it("无算式返回 null", () => {
|
||
expect(parseCalculation("ab12cd")).toBeNull();
|
||
});
|
||
it("字符验证码清洗", () => {
|
||
expect(cleanCodeText("a b 7 X ? = ")).toBe("ab7X");
|
||
});
|
||
});
|
||
|
||
describe.skipIf(!existsSync(fixture("captcha_0_3p5_q")))("OCR_CalculationCode 端到端(真实模型)", () => {
|
||
const cases: Array<[string, string]> = [
|
||
["captcha_0_3p5_q", "8"],
|
||
["captcha_1_12m7_q", "5"],
|
||
["captcha_2_6t4_q", "24"],
|
||
["captcha_3_15p28_q", "43"],
|
||
["captcha_4_9t9_q", "81"],
|
||
];
|
||
for (const [file, expected] of cases) {
|
||
it(`${file} -> ${expected}`, async () => {
|
||
const handler = getHandler("OCR_CalculationCode");
|
||
expect(handler).toBeTruthy();
|
||
const out = await handler!(ctx, node, { path: fixture(file) }, {} as CatalogComponent);
|
||
console.log(`[${file}]`, String(out));
|
||
expect(String(out)).toBe(expected);
|
||
}, 300000);
|
||
}
|
||
});
|