Files
ctms/frontend/src/components/SecurityCenter.test.ts
T
Cheng Zhou f11a5c84d9
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
feat(监控): 完善系统监控、登录状态与访问审计能力
2026-07-10 17:12:13 +08:00

172 lines
8.5 KiB
TypeScript

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('<section ref="securityEventsSectionRef" class="security-table-wrap">');
const filtersIndex = source.indexOf('<section class="audit-filters detail-filters">');
expect(tableIndex).toBeGreaterThan(-1);
expect(filtersIndex).toBeGreaterThan(tableIndex);
expect(source).not.toContain('<section class="audit-filters">\n <el-select');
});
it("keeps risk levels on the page and opens abnormal sources in a compact ranking dialog", () => {
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('<el-dialog v-model="analysisDialogVisible"');
expect(source).toContain('width="min(1180px, 96vw)"');
expect(source).toContain("analysis-ranking-dialog");
expect(source).toContain("analysis-ranking-head");
expect(source).toContain("endpoint-summary-chips");
expect(source).toContain("analysis-rank-grid");
expect(source).toContain("analysis-rank-card");
expect(source).toContain("analysis-rank-card-stats");
expect(source).toContain("查看事件明细");
expect(source).not.toContain('<section class="analysis-dialog-panel');
expect(source).toContain("风险等级");
expect(source).toContain("ipRiskStats");
expect(source).toContain("endpointTypeStats");
expect(source).toContain("riskLevelStats");
expect(source.match(/v-for="item in riskLevelStats"/g)).toHaveLength(1);
expect(source).not.toContain("compact-risk-section");
expect(source).toContain("resolveEndpointType");
expect(source).toContain("formatIpLocation");
expect(source).toContain("fallbackIpLocation");
expect(source).toContain("row.ip_province");
expect(source).toContain("row.ip_city");
expect(source).toContain("row.ip_isp");
expect(source).toContain("item.location");
expect(source).toContain("categoryText");
expect(source).toContain("analysis-rank-card-ip");
expect(source).toContain("analysis-rank-card-meta");
expect(source).toContain("lastSeenAt");
expect(source).toContain("最后访问");
expect(source).toContain("securitySummary.value.top_ips");
expect(source).toContain("securitySummary.value.endpoint_type_counts");
expect(source).toContain("securitySummary.value.severity_counts");
expect(source).not.toContain("公网位置待解析");
expect(source).not.toContain("异常IP(位置)排行");
expect(source).not.toContain("risk-level-card");
});
it("keeps detailed security events searchable and inspectable", () => {
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("<h4>接口</h4>");
expect(source).not.toContain("<h4>访问字段</h4>");
expect(source).not.toContain("<h4>请求快照</h4>");
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("<el-dialog v-model=\"securityLogDialogVisible\"");
expect(source).toContain("securityTerminalLines.join");
expect(source).toContain("security-access-logs.log");
expect(source).toContain("terminal-window dialog-terminal-window");
});
it("labels abnormal IP events and paginates details like account management", () => {
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");
});
});