import { describe, expect, it } from "vitest"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; const readSource = () => readFileSync(resolve(__dirname, "./SecurityCenter.vue"), "utf8"); describe("SecurityCenter", () => { it("renders a compact security analysis summary in the same audit-card style as access logs", () => { const source = readSource(); expect(source).toContain("audit-filters"); expect(source).toContain("audit-metrics"); expect(source).toContain("metric-card"); expect(source).toContain("security-analysis-card"); expect(source).toContain("risk-preview-list"); expect(source).toContain("risk-summary-panel"); expect(source).toContain("risk-summary-title"); expect(source).toContain("topRiskPreview"); expect(source).toContain('class="security-overview"'); expect(source).toContain('aria-label="安全指标"'); expect(source).toContain('class="security-toolbar"'); expect(source).toContain("timeRangePreset"); expect(source).toContain("timeRangeOptions"); expect(source).toContain("buildTimeRangeFromPreset"); expect(source).toContain("onTimeRangeChange"); expect(source).not.toContain("audit-grid"); expect(source).not.toContain("ranking-card"); expect(source).not.toContain("security-summary"); expect(source).not.toContain("security-card"); }); it("places filters inside the event details section instead of the page header", () => { const source = readSource(); const tableIndex = source.indexOf('
'); const filtersIndex = source.indexOf('
'); expect(tableIndex).toBeGreaterThan(-1); expect(filtersIndex).toBeGreaterThan(tableIndex); expect(source).not.toContain('
\n { const source = readSource(); expect(source).toContain("异常分析"); expect(source).toContain("查看异常分析"); expect(source).toContain("analysisDialogVisible"); expect(source).toContain("openAnalysisDialog"); expect(source).toContain("jumpToSecurityEvents"); expect(source).toContain("securityEventsSectionRef"); expect(source).toContain("scrollIntoView"); expect(source).toContain(' { const source = readSource(); expect(source).toContain("securityQueryParams"); expect(source).toContain("keyword: keyword.value.trim() || undefined"); expect(source).toContain("paginatedEvents"); expect(source).toContain("openDetail"); expect(source).toContain("security-table-wrap"); expect(source).toContain('label="IP"'); expect(source).toContain('label="位置"'); expect(source).not.toContain('label="来源 IP"'); expect(source).not.toContain('label="IP来源"'); expect(source).toContain("搜索 IP、位置、账号、路径或 UA"); expect(source).toContain("loadSecurityEvents"); expect(source).toContain("安全事件加载失败,页面中可能是上次成功获取的数据"); expect(source).toContain("lastUpdatedAt"); expect(source).toContain("安全事件详情"); expect(source).toContain("请求概览"); expect(source).toContain("原始 HTTP 请求"); expect(source).toContain("User-Agent"); expect(source).toContain("构建信息"); expect(source).toContain("更多审计信息"); expect(source).toContain("日志标识"); expect(source).toContain("传输信息"); expect(source).toContain("客户端标识"); expect(source).toContain("securityRequestOverviewFields(selectedEvent)"); expect(source).toContain("securityAuditMetadataFields(selectedEvent)"); expect(source).toContain("securityRequestSnapshotFields(selectedEvent)"); expect(source).toContain("buildSecurityRawRequestBlock(selectedEvent)"); expect(source).toContain("securityClientSourceLabel(selectedEvent)"); expect(source).toContain("历史日志未采集原始请求快照"); expect(source).toContain("历史日志未采集原始 HTTP 请求"); expect(source).not.toContain("securityDetailFieldItems(selectedEvent)"); expect(source).not.toContain("

接口

"); expect(source).not.toContain("

访问字段

"); expect(source).not.toContain("

请求快照

"); expect(source).not.toContain("原始请求快照(脱敏)"); expect(source).not.toContain("请求头(脱敏)"); expect(source).not.toContain("未记录请求头"); }); it("opens full security logs as a dialog inside security center", () => { const source = readSource(); expect(source).toContain("安全日志"); expect(source).toContain("securityLogDialogVisible"); expect(source).toContain("securityLogDialogLoading"); expect(source).toContain("securityTerminalWindowRef"); expect(source).toContain("securityTerminalLines"); expect(source).toContain("buildSecurityTerminalLine"); expect(source).toContain("openSecurityLogDialog"); expect(source).toContain("scrollSecurityTerminalToBottom"); expect(source).toContain("downloadSecurityLog"); expect(source).toContain("saveFileWithFeedback"); expect(source).toContain("securityRequestTarget(event)"); expect(source).toContain(" { const source = readSource(); expect(source).not.toContain('value: "ABNORMAL_IP"'); expect(source).toContain('label: "风险来源 IP"'); expect(source).toContain('v-model:current-page="page"'); expect(source).toContain('v-model:page-size="pageSize"'); expect(source).toContain(':page-sizes="[10, 20, 50]"'); expect(source).toContain('layout="prev, pager, next, sizes, total"'); }); it("uses server-side pagination and aggregate facets instead of loading every event", () => { const source = readSource(); expect(source).toContain("statsEvents"); expect(source).toContain("securitySummary"); expect(source).toContain("loadSecurityStats"); expect(source).toContain("response.data.summary"); expect(source).toContain("@current-change=\"loadSecurityEvents\""); expect(source).not.toContain("for (let nextPage = 2; nextPage <= totalPages; nextPage += 1) {\n const res = await fetchSecurityAccessLogs"); expect(source).toContain("fetchAllSecurityEvents"); }); });