整理测试代码并清理文档引用
This commit is contained in:
@@ -1,347 +0,0 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
const readSource = () => readFileSync(resolve(__dirname, "./PermissionIpLocations.vue"), "utf8");
|
||||
const readMapSource = () => readFileSync(resolve(__dirname, "./chinaProvinceMap.ts"), "utf8");
|
||||
const readWorldMapSource = () => readFileSync(resolve(__dirname, "./worldMapSource.ts"), "utf8");
|
||||
|
||||
describe("PermissionIpLocations", () => {
|
||||
it("renders IP location visualization without duplicate region detail table", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("fetchIpLocations");
|
||||
expect(source).toContain("unique_ip_count");
|
||||
expect(source).not.toContain("来源地域明细");
|
||||
expect(source).not.toContain("table-card");
|
||||
expect(source).not.toContain("<el-table :data=\"items\"");
|
||||
});
|
||||
|
||||
it("renders an interactive China map and primary metric cards", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("VChart");
|
||||
expect(source).toContain("sourceMapOption");
|
||||
expect(source).toContain("来源分布");
|
||||
expect(source).toContain("访问次数");
|
||||
expect(source).toContain("访问用户数");
|
||||
expect(source).toContain("来源 IP 数");
|
||||
expect(source).toContain("summary");
|
||||
});
|
||||
|
||||
it("defaults the access source period to 90 days", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("const days = ref(90);");
|
||||
expect(source).not.toContain("const days = ref(7);");
|
||||
expect(source).toContain('<el-radio-button :value="90">90天</el-radio-button>');
|
||||
expect(source).toContain('90: "近 90 天"');
|
||||
});
|
||||
|
||||
it("does not overlay the source distribution card with a loading mask", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain('<section class="distribution-card">');
|
||||
expect(source).toContain('<el-button :loading="loading" size="small" :disabled="loading" @click="loadData">');
|
||||
expect(source).not.toContain('<section v-loading="loading" class="distribution-card">');
|
||||
});
|
||||
|
||||
it("supports switching source distribution between China and global flow views without the global heat map", () => {
|
||||
const source = readSource();
|
||||
const worldMapSource = readWorldMapSource();
|
||||
|
||||
expect(source).toContain("../assets/world.json");
|
||||
expect(source).toContain('registerMap("ctms-world"');
|
||||
expect(source).toContain('const mapView = ref<"china" | "flow">("china");');
|
||||
expect(source).toContain("mapViewOptions");
|
||||
expect(source).toContain("<el-segmented v-model=\"mapView\"");
|
||||
expect(source).toContain("sourceMapOption");
|
||||
expect(source).toContain('label: "中国"');
|
||||
expect(source).toContain('label: "全球"');
|
||||
expect(source).not.toContain('label: "全球", value: "world"');
|
||||
expect(source).not.toContain("worldData");
|
||||
expect(source).not.toContain("buildMapOption");
|
||||
expect(worldMapSource).toContain("unpkg.com/echarts@4.9.0/map/json/world.json");
|
||||
expect(worldMapSource).toContain("ECharts 世界地图 GeoJSON");
|
||||
expect(worldMapSource).toContain('"United States": "United States"');
|
||||
});
|
||||
|
||||
it("supports a global access flow view pointing sources to the server location", () => {
|
||||
const source = readSource();
|
||||
const worldMapSource = readWorldMapSource();
|
||||
|
||||
expect(source).toContain('const mapView = ref<"china" | "flow">("china");');
|
||||
expect(source).toContain('label: "全球"');
|
||||
expect(source).toContain("LinesChart");
|
||||
expect(source).toContain("EffectScatterChart");
|
||||
expect(source).toContain("GeoComponent");
|
||||
expect(source).toContain("buildFlowMapOption");
|
||||
expect(source).toContain("serverLocation");
|
||||
expect(source).toContain("resolveSourceCoordinate");
|
||||
expect(source).toContain('coordinateSystem: "geo"');
|
||||
expect(source).toContain("coords: [point.coord, serverLocation.coord]");
|
||||
expect(source).toContain("服务器所在地");
|
||||
expect(worldMapSource).toContain("resolveSourceCoordinate");
|
||||
expect(worldMapSource).toContain('"United States": [-95.7129, 37.0902]');
|
||||
});
|
||||
|
||||
it("uses a China access flow map for the China view", () => {
|
||||
const source = readSource();
|
||||
const worldMapSource = readWorldMapSource();
|
||||
|
||||
expect(source).toContain("chinaFlowSourceData");
|
||||
expect(source).toContain('buildFlowMapOption(chinaFlowSourceData.value, "ctms-china", 1.08, "中国访问链路")');
|
||||
expect(source).not.toContain('buildMapOption("ctms-china", provinceData.value, 1.08)');
|
||||
expect(source).toContain('mapView.value === "china" ? chinaFlowSourceData.value');
|
||||
expect(worldMapSource).toContain('"江苏省": [118.7633, 32.0617]');
|
||||
expect(worldMapSource).toContain('"上海市": [121.4737, 31.2304]');
|
||||
});
|
||||
|
||||
it("uses the same source rows for the global flow map and the source ranking", () => {
|
||||
const source = readSource();
|
||||
const worldMapSource = readWorldMapSource();
|
||||
|
||||
expect(source).toContain("flowSourceData");
|
||||
expect(source).toContain('mapView.value === "flow" ? flowSourceData.value : rankedSourceRows.value');
|
||||
expect(source).toContain("buildFlowMapOption(flowSourceData.value)");
|
||||
expect(source).not.toContain("buildFlowMapOption(worldData.value)");
|
||||
expect(source).toContain('const buildFlowMapOption = (data: IpLocationStatItem[], mapName = "ctms-world"');
|
||||
expect(source).toContain("coord: resolveSourceCoordinate(item)");
|
||||
expect(source).toContain("name: formatLocation(point)");
|
||||
expect(worldMapSource).toContain("cityCoordinates");
|
||||
expect(worldMapSource).toContain('"重庆市": [106.5516, 29.563]');
|
||||
expect(worldMapSource).toContain('"南京市": [118.7969, 32.0603]');
|
||||
expect(worldMapSource).toContain('"Istanbul": [28.9784, 41.0082]');
|
||||
expect(worldMapSource).toContain('"South Holland": [4.493, 52.0208]');
|
||||
});
|
||||
|
||||
it("keeps global flow lines thin and readable", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("const lineWidth = point.abnormal ? 1.1 : 0.8");
|
||||
expect(source).toContain("width: lineWidth");
|
||||
expect(source).toContain("opacity: point.abnormal ? 0.58 : 0.38");
|
||||
expect(source).not.toContain("width: Math.min(5");
|
||||
expect(source).not.toContain("Math.sqrt(point.total_count");
|
||||
});
|
||||
|
||||
it("keeps domestic flow markers compact so nearby China locations stay visible", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("const isDomestic = !params?.data?.abnormal");
|
||||
expect(source).toContain("const maxSize = isDomestic ? 12 : 16");
|
||||
expect(source).toContain("const minSize = isDomestic ? 5 : 7");
|
||||
expect(source).toContain("scale: 1.7");
|
||||
expect(source).toContain("scale: 1.5");
|
||||
expect(source).toContain("symbolSize: 9");
|
||||
expect(source).not.toContain("scale: 3");
|
||||
expect(source).not.toContain("scale: 2.4");
|
||||
expect(source).not.toContain("symbolSize: 14");
|
||||
});
|
||||
|
||||
it("shows a compact flow legend and keeps the server tooltip address-only", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("source-map-wrap");
|
||||
expect(source).toContain("fullscreen-map-wrap");
|
||||
expect(source).toContain("flow-legend");
|
||||
expect(source).toContain("map-legend");
|
||||
expect(source).toContain("服务器");
|
||||
expect(source).toContain("正常访问点");
|
||||
expect(source).toContain("异常访问点");
|
||||
expect(source).toContain('class="legend-dot server"');
|
||||
expect(source).toContain('class="legend-dot normal"');
|
||||
expect(source).toContain('class="legend-dot abnormal"');
|
||||
expect(source).toContain('if (row.isServer) return "中国 / 上海";');
|
||||
expect(source).not.toContain('if (row.isServer) return `${serverLocation.name}<br/>中国 / 上海`;');
|
||||
expect(source).not.toContain("fullscreen-legend");
|
||||
});
|
||||
|
||||
it("supports fullscreen preview for the current source map", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("fullscreenVisible");
|
||||
expect(source).toContain("openFullscreenPreview");
|
||||
expect(source).toContain("resizeFullscreenChart");
|
||||
expect(source).toContain("<el-dialog");
|
||||
expect(source).toContain("fullscreen");
|
||||
expect(source).toContain("destroy-on-close");
|
||||
expect(source).toContain(':close-on-click-modal="false"');
|
||||
expect(source).toContain('aria-label="全屏预览"');
|
||||
expect(source).toContain("fullscreenMapKey");
|
||||
expect(source).toContain("fullscreen-source-map");
|
||||
expect(source).toContain("全屏预览");
|
||||
expect(source).toContain("退出全屏");
|
||||
expect(source).toContain(":option=\"sourceMapOption\"");
|
||||
});
|
||||
|
||||
it("raises canvas pixel ratio for sharper fullscreen map rendering", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("getDevicePixelRatio");
|
||||
expect(source).toContain("chartInitOptions");
|
||||
expect(source).toContain("fullscreenChartInitOptions");
|
||||
expect(source).toContain(":init-options=\"chartInitOptions\"");
|
||||
expect(source).toContain(":init-options=\"fullscreenChartInitOptions\"");
|
||||
expect(source).toContain("Math.min(getDevicePixelRatio(), 2)");
|
||||
expect(source).toContain("Math.min(getDevicePixelRatio() * 1.5, 3)");
|
||||
});
|
||||
|
||||
it("uses a flexible full-page layout so the source map fills the remaining viewport", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("height: 100%");
|
||||
expect(source).toContain("min-height: 0");
|
||||
expect(source).toContain("flex: 1 1 auto");
|
||||
expect(source).toContain("grid-template-rows: minmax(0, 1fr)");
|
||||
expect(source).toContain("height: 100%");
|
||||
expect(source).toContain("overflow-y: auto");
|
||||
expect(source).not.toContain("height: 320px");
|
||||
expect(source).not.toContain("min-height: 430px");
|
||||
});
|
||||
|
||||
it("prevents horizontal scrolling in the source ranking panel", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain(".rank-panel");
|
||||
expect(source).toContain("overflow: hidden");
|
||||
expect(source).toContain("overflow-x: hidden");
|
||||
expect(source).toContain("overflow-y: auto");
|
||||
expect(source).toContain("box-sizing: border-box");
|
||||
expect(source).toContain("grid-template-columns: 36px minmax(0, 1fr) minmax(72px, max-content)");
|
||||
expect(source).toContain("max-width: 100%");
|
||||
expect(source).toContain("text-overflow: ellipsis");
|
||||
expect(source).toContain("text-align: right");
|
||||
});
|
||||
|
||||
it("recreates the chart when switching map modes to avoid stale geo state", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain(':key="mapView"');
|
||||
expect(source).toContain(':update-options="chartUpdateOptions"');
|
||||
expect(source).toContain("const chartUpdateOptions = { notMerge: true }");
|
||||
});
|
||||
|
||||
it("resizes the source map after data load and keeps the chart container full width", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain('ref="sourceChartRef"');
|
||||
expect(source).toContain("const sourceChartRef = ref<{ resize?: () => void } | null>(null)");
|
||||
expect(source).toContain("const resizeSourceCharts = async () =>");
|
||||
expect(source).toContain("sourceChartRef.value?.resize?.()");
|
||||
expect(source).toContain("await resizeSourceCharts()");
|
||||
expect(source).toContain("defineExpose({ refresh: loadData, resize: resizeSourceCharts })");
|
||||
expect(source).not.toContain(".source-map :deep(> div)");
|
||||
});
|
||||
|
||||
it("uses source-analysis copy instead of IP-location tab wording", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("访问来源分析");
|
||||
expect(source).toContain("来源分布");
|
||||
expect(source).toContain("热点来源地");
|
||||
expect(source).not.toContain("查看访问来源的地理分布");
|
||||
expect(source).not.toContain("访问来源地理分布热力图");
|
||||
expect(source).not.toContain("按访问次数排序");
|
||||
expect(source).not.toContain("IP 属地分析");
|
||||
expect(source).not.toContain("中国地图");
|
||||
expect(source).not.toContain("热点属地");
|
||||
expect(source).not.toContain("用户分布图");
|
||||
});
|
||||
|
||||
it("uses the standard geojson.cn China map data instead of generated rectangles", () => {
|
||||
const source = readSource();
|
||||
const mapSource = readMapSource();
|
||||
|
||||
expect(source).toContain("../assets/china.json");
|
||||
expect(mapSource).toContain("geojson.cn/api/china/1.6.3/china.json");
|
||||
expect(mapSource).not.toContain("ProvinceBox");
|
||||
expect(mapSource).not.toContain("provinceBoxes");
|
||||
});
|
||||
|
||||
it("removes heat-map visual legends and keeps map zoom interactions disabled", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).not.toContain("visualMap:");
|
||||
expect(source).not.toContain("VisualMapComponent");
|
||||
expect(source).not.toContain("hasMapData");
|
||||
expect(source).not.toContain("maxValue");
|
||||
expect(source).not.toContain('color: ["#93c5fd", "#60a5fa", "#3b82f6", "#2563eb", "#1d4ed8"]');
|
||||
expect(source).not.toContain("outOfRange:");
|
||||
expect(source).toContain("roam: false");
|
||||
expect(source).not.toContain("scaleLimit");
|
||||
});
|
||||
|
||||
it("uses a stronger base map style so borders remain visible behind flow lines", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain('areaColor: "#e6edf8"');
|
||||
expect(source).toContain('borderColor: "#aebed2"');
|
||||
expect(source).toContain("borderWidth: 1");
|
||||
expect(source).toContain('shadowColor: "rgba(37, 99, 235, 0.08)"');
|
||||
expect(source).toContain("shadowBlur: 10");
|
||||
expect(source).toContain("shadowOffsetY: 2");
|
||||
expect(source).toContain('areaColor: "#dbeafe", borderColor: "#64748b", borderWidth: 1.3');
|
||||
expect(source).not.toContain('areaColor: "#eef4ff"');
|
||||
expect(source).not.toContain('borderColor: "#dbe7f7"');
|
||||
expect(source).not.toContain("borderWidth: 0.8");
|
||||
});
|
||||
|
||||
it("keeps geo hover interaction while avoiding empty white tooltip panels", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("const formatGeoTooltip = (params: any) =>");
|
||||
expect(source).toContain('return name || "暂无访问数据";');
|
||||
expect(source).toContain('trigger: "item"');
|
||||
expect(source).toContain("confine: true");
|
||||
expect(source).toContain("formatter: formatGeoTooltip");
|
||||
expect(source).toContain("tooltip: {\n show: true,\n formatter: formatGeoTooltip,\n }");
|
||||
expect(source).toContain("formatLineTooltip");
|
||||
expect(source).toContain("formatPointTooltip");
|
||||
expect(source).toContain("tooltip: {\n show: true,\n formatter: formatLineTooltip,\n }");
|
||||
expect(source).toContain("tooltip: {\n show: true,\n formatter: formatPointTooltip,\n }");
|
||||
expect(source).not.toContain("silent: true");
|
||||
expect(source).not.toContain("tooltip: { show: false }");
|
||||
});
|
||||
|
||||
it("uses narrow metric cards without helper subtitles", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("min-height: 64px");
|
||||
expect(source).toContain("padding: 10px 16px");
|
||||
expect(source).toContain("right: -34px");
|
||||
expect(source).toContain("bottom: -42px");
|
||||
expect(source).toContain("border-radius: 18px");
|
||||
expect(source).not.toContain("<small>{{ card.hint }}</small>");
|
||||
expect(source).not.toContain("hint:");
|
||||
expect(source).not.toContain("权限检查总量");
|
||||
});
|
||||
|
||||
it("removes the duplicated hero copy above the map", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain("ip-locations-toolbar");
|
||||
expect(source).not.toContain("权限监控 / IP属地");
|
||||
expect(source).not.toContain("按访问日志聚合省市、用户与来源 IP");
|
||||
expect(source).not.toContain("悬停省份查看访问次数、访问用户数和来源 IP 数");
|
||||
expect(source).not.toContain("hero-desc");
|
||||
expect(source).not.toContain("eyebrow");
|
||||
});
|
||||
|
||||
it("places the period filter toolbar on the right", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain(".ip-hero");
|
||||
expect(source).toContain("justify-content: space-between");
|
||||
expect(source).toContain("margin-left: auto");
|
||||
});
|
||||
|
||||
it("keeps non-China source labels visible and lists top 10 regions", () => {
|
||||
const source = readSource();
|
||||
|
||||
expect(source).toContain('row.country && row.country !== "中国" ? row.country : ""');
|
||||
expect(source).toContain("row.isp");
|
||||
expect(source).toContain('parts.join(" / ")');
|
||||
expect(source).toContain(".slice(0, 10)");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user