declare const process: { cwd(): string }; declare function require(name: string): { readFileSync?: (path: string, encoding: string) => string; join?: (...parts: string[]) => string; }; const { readFileSync } = require("node:fs"); const { join } = require("node:path"); if (!readFileSync || !join) { throw new Error("测试运行环境缺少文件读取能力"); } const view = readFileSync(join(process.cwd(), "src/views/ReportsView.vue"), "utf-8"); const css = readFileSync(join(process.cwd(), "src/assets/styles.css"), "utf-8"); assertIncludes(view, "report-page"); assertIncludes(view, "report-ledger-workspace"); assertIncludes(view, "工资明细台账"); assertIncludes(view, "report-ledger-toolbar"); assertIncludes(view, "report-ledger-totals"); assertIncludes(view, "report-inline-metrics"); assertIncludes(view, "report-detail-grid"); assertIncludes(view, "report-record-panel"); assertIncludes(view, "最近工资明细"); assertNotIncludes(view, "
"); assertNotIncludes(view, "StatCard"); assertNotIncludes(view, "report-summary-panel"); assertNotIncludes(view, "report-metric-card"); assertNotIncludes(view, "先看明细再看拆分"); assertNotIncludes(view, "汇总金额和最近工资明细"); assertBefore(view, "report-ledger-workspace", "report-detail-grid"); assertBefore(view, "最近工资明细", "report-detail-grid"); assertIncludes(css, ".report-ledger-workspace"); assertIncludes(css, ".report-ledger-toolbar"); assertIncludes(css, ".report-ledger-totals"); assertIncludes(css, ".report-inline-metrics"); assertIncludes(css, ".report-record-panel"); assertIncludes(css, ".report-detail-grid"); assertNotIncludes(css, ".report-summary-panel"); assertNotIncludes(css, ".report-metric-card"); const ledgerToolbarBlock = cssBlock(".report-ledger-toolbar"); assertIncludes(ledgerToolbarBlock, "padding: 10px var(--panel-padding) 8px;"); const totalItemBlock = cssBlock(".report-total-item"); assertIncludes(totalItemBlock, "min-height: 52px;"); const inlineMetricsBlock = cssBlock(".report-inline-metrics"); assertIncludes(inlineMetricsBlock, "padding: 7px var(--panel-padding);"); const tableHeadingBlock = cssBlock(".report-table-heading"); assertIncludes(tableHeadingBlock, "padding: 9px var(--panel-padding) 6px;"); function assertIncludes(content: string, expected: string): void { if (!content.includes(expected)) { throw new Error(`期望包含 ${expected}`); } } function assertNotIncludes(content: string, unexpected: string): void { if (content.includes(unexpected)) { throw new Error(`不应包含 ${unexpected}`); } } function assertBefore(content: string, earlier: string, later: string): void { const earlierIndex = content.indexOf(earlier); const laterIndex = content.indexOf(later); if (earlierIndex === -1 || laterIndex === -1 || earlierIndex >= laterIndex) { throw new Error(`期望 ${earlier} 出现在 ${later} 之前`); } } function cssBlock(selector: string): string { const pattern = new RegExp(`${escapeRegExp(selector)}\\s*\\{([\\s\\S]*?)\\n\\}`, "m"); const match = css.match(pattern); if (!match) { throw new Error(`缺少样式块 ${selector}`); } return match[1]; } function escapeRegExp(value: string): string { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }