72 lines
3.9 KiB
JavaScript
72 lines
3.9 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFile } from "node:fs/promises";
|
|
|
|
const server = await readFile(new URL("../src/server.js", import.meta.url), "utf8");
|
|
const html = await readFile(new URL("../public/index.html", import.meta.url), "utf8");
|
|
const app = await readFile(new URL("../public/app.js", import.meta.url), "utf8");
|
|
const ocr = await readFile(new URL("../src/ocr.js", import.meta.url), "utf8");
|
|
|
|
test("temporary query API collects without appending to history", () => {
|
|
assert.match(server, /url\.pathname === "\/api\/query-once"/);
|
|
const block = server.match(/if \(url\.pathname === "\/api\/query-once"[\s\S]*?return sendJson\(response, 200, \{ items \}\);\s*\}/)?.[0] || "";
|
|
assert.match(block, /collectTemporaryQueryItems\(/);
|
|
assert.doesNotMatch(block, /appendCollection\(/);
|
|
});
|
|
|
|
test("temporary query UI has isolated input, action, and CSV export", () => {
|
|
assert.match(html, /id="temporary-query-panel"/);
|
|
assert.match(html, /id="temporary-file-input"[^>]*type="file"/);
|
|
assert.match(html, /id="temporary-query-text"/);
|
|
assert.match(html, /id="temporary-query-button"[^>]*>一键查询<\/button>/);
|
|
assert.match(html, /id="temporary-export-button"[^>]*>导出临时 CSV<\/button>/);
|
|
assert.match(app, /temporaryQueryButton\s*=\s*document\.querySelector\("#temporary-query-button"\)/);
|
|
assert.match(app, /temporaryFileInput\.addEventListener\("change"/);
|
|
assert.match(app, /postJson\("\/api\/query-once"/);
|
|
assert.match(app, /downloadTemporaryCsv\(/);
|
|
});
|
|
|
|
test("temporary query renders platform results as each request finishes", () => {
|
|
assert.match(app, /runTemporaryQueryProgressively\(names, platforms\)/);
|
|
assert.match(app, /temporaryQueryTasks\(names, platforms\)/);
|
|
assert.match(app, /postJson\("\/api\/query-once", \{\s*names: \[task\.name\],\s*platforms: \[task\.platform\]/);
|
|
assert.match(app, /mergeTemporaryQueryResult\(task\.name, payload\.items\?.\[0\]/);
|
|
assert.match(app, /renderTemporaryResults\(temporaryQueryItems\)/);
|
|
assert.match(app, /clientMapLimit\(tasks, 6/);
|
|
});
|
|
|
|
test("temporary query supports dropping Excel-style files into the list box", () => {
|
|
assert.match(html, /accept="\.txt,\.csv,\.xlsx,text\/plain,text\/csv/);
|
|
assert.match(app, /temporaryQueryText\.addEventListener\("drop"/);
|
|
assert.match(app, /loadTemporaryImportFile\(/);
|
|
assert.match(app, /extractXlsxText\(/);
|
|
assert.match(app, /normalizeTemporaryListText\(/);
|
|
});
|
|
|
|
test("temporary query supports OCR import for screenshot images", () => {
|
|
assert.match(server, /recognizeImageText/);
|
|
assert.match(server, /url\.pathname === "\/api\/temporary-ocr"/);
|
|
assert.match(server, /readImageUploadBody\(request\)/);
|
|
assert.match(app, /postJson\("\/api\/temporary-ocr"/);
|
|
assert.match(app, /readFileAsDataUrl\(/);
|
|
assert.doesNotMatch(app, /截图需要 OCR/);
|
|
assert.match(ocr, /windows-ocr\.ps1/);
|
|
assert.match(ocr, /mkdtemp/);
|
|
});
|
|
|
|
test("temporary query runs with bounded concurrency and per-program failures", () => {
|
|
assert.match(server, /async function collectTemporaryQueryItems/);
|
|
assert.match(server, /const history = await readHistory\(\)/);
|
|
assert.match(server, /mapLimit\(names, concurrency/);
|
|
assert.match(server, /const concurrency = Math\.min\(Math\.max\(Number\(body\.concurrency \|\| 3\), 1\), 5\)/);
|
|
assert.match(server, /const manualUrls = sanitizeUrls\(body\.urls \|\| \{\}\)/);
|
|
assert.match(server, /urls: \{ \.\.\.historyProgramUrls\(history, name\), \.\.\.manualUrls \}/);
|
|
assert.match(server, /freshSearchPlatforms: body\.freshSearch \? platforms\.filter\(\(platform\) => !manualUrls\[platform\]\) : \[\]/);
|
|
assert.match(server, /delayMs: 0/);
|
|
assert.match(server, /quickSearch: body\.quickSearch !== false/);
|
|
assert.match(server, /parallelPlatforms: true/);
|
|
assert.match(server, /temporaryErrorCollection/);
|
|
assert.match(server, /async function mapLimit/);
|
|
assert.match(server, /function historyProgramUrls/);
|
|
});
|