mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-09-14 21:55:31 +02:00
82 lines
4.1 KiB
JavaScript
82 lines
4.1 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const vm = require('node:vm');
|
|
|
|
const source = fs.readFileSync('web/static/js/monitor.js', 'utf8');
|
|
const statsSource = source.slice(source.indexOf('const MCP_STATS_TOP_N'), source.indexOf('function renderMonitorExecutions('));
|
|
|
|
function harness() {
|
|
const container = { innerHTML: '' };
|
|
const escapeHtml = (value) => String(value).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
|
const context = vm.createContext({
|
|
window: { __locale: 'zh-CN' },
|
|
document: { getElementById: (id) => id === 'monitor-stats' ? container : null },
|
|
localStorage: { getItem: () => null },
|
|
monitorState: {},
|
|
escapeHtml,
|
|
escapeAttrLocal: escapeHtml,
|
|
formatMonitorToolName: (name) => name,
|
|
monitorToolNamesEqual: (a, b) => a === b,
|
|
});
|
|
vm.runInContext(statsSource, context);
|
|
Object.assign(context, {
|
|
bindMonitorStatsPanelEvents() {},
|
|
bindMcpStatsTimelineEvents() {},
|
|
updateMonitorStatsSubtitle() {},
|
|
});
|
|
return { context, container };
|
|
}
|
|
|
|
test('安全拦截计入总调用量,但不归入失败或终止', () => {
|
|
const { context } = harness();
|
|
const totals = context.buildMonitorTotals({ totalCalls: 10, successCalls: 4, failedCalls: 1, blockedCalls: 3 });
|
|
assert.deepEqual({ ...totals }, { total: 10, success: 4, failed: 1, blocked: 3, neutral: 2, lastCallTime: null });
|
|
assert.equal(context.buildMonitorTotals({ totalCalls: 3, blockedCalls: 3 }).neutral, 0);
|
|
assert.equal(context.buildMonitorTotals({ totalCalls: 2, successCalls: 1, failedCalls: 1 }).blocked, 0);
|
|
});
|
|
|
|
test('概览成功率排除安全拦截,只有拦截时不显示失败率或终止标签', () => {
|
|
const { context, container } = harness();
|
|
context.renderMonitorStats({ totalCalls: 5, successCalls: 1, failedCalls: 1, blockedCalls: 3 });
|
|
assert.match(container.innerHTML, />50\.0%<\/span>/);
|
|
assert.match(container.innerHTML, /is-blocked">安全拦截 3<\/span>/);
|
|
assert.doesNotMatch(container.innerHTML, /is-neutral/);
|
|
|
|
context.renderMonitorStats({ totalCalls: 3, blockedCalls: 3 });
|
|
assert.match(container.innerHTML, /value--rate is-muted">-<\/span>/);
|
|
assert.match(container.innerHTML, /is-fail">失败 0<\/span>/);
|
|
assert.doesNotMatch(container.innerHTML, /is-danger|is-neutral|0\.0%/);
|
|
});
|
|
|
|
test('工具统计独立展示安全拦截,拦截不降低工具成功率', () => {
|
|
const { context } = harness();
|
|
for (const render of [context.renderMcpStatsToolTable, context.renderMcpStatsToolsPanel]) {
|
|
const blockedOnly = render([{ toolName: 'safe-tool', totalCalls: 4, blockedCalls: 4 }], { total: 4 });
|
|
assert.match(blockedOnly, /安全拦截 4/);
|
|
assert.match(blockedOnly, /is-muted">-<\/span>/);
|
|
assert.doesNotMatch(blockedOnly, /is-danger|>0\.0%<\/span>/);
|
|
|
|
const mixed = render([{ toolName: 'safe-tool', totalCalls: 10, successCalls: 3, failedCalls: 1, blockedCalls: 6 }], { total: 10 });
|
|
assert.match(mixed, /75\.0%/);
|
|
assert.match(mixed, /安全拦截 6/);
|
|
assert.match(mixed, /失败 1/);
|
|
}
|
|
});
|
|
|
|
test('趋势图区分安全拦截和失败,并保留悬停的独立计数', () => {
|
|
const { context } = harness();
|
|
const points = [{ t: '2026-09-07T00:00:00Z', total: 3, failed: 0, blocked: 3 }];
|
|
const html = context.renderMcpStatsTimelineBody({ range: '24h', points, summary: { totalCalls: 3, peak: 3 } });
|
|
assert.match(html, /legend-item--blocked">安全拦截/);
|
|
assert.match(html, /mcp-stats-timeline-bar-blocked/);
|
|
assert.match(html, /mcp-stats-timeline-line--blocked/);
|
|
assert.match(html, /data-total="3" data-failed="0" data-blocked="3"/);
|
|
assert.doesNotMatch(html, /legend-item--fail|mcp-stats-timeline-bar-fail/);
|
|
|
|
const mixed = context.buildMcpTimelineSvg([{ ...points[0], total: 4, failed: 1, blocked: 2 }], '24h');
|
|
assert.match(mixed, /data-total="4" data-failed="1" data-blocked="2"/);
|
|
assert.match(mixed, /mcp-stats-timeline-bar-fail/);
|
|
assert.match(mixed, /mcp-stats-timeline-bar-blocked/);
|
|
});
|