Files
Notes/tests/unit/audit-rate.test.js
2026-10-16 16:34:15 +08:00

60 lines
2.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// P2-7(audit):app:open-config-dir 高频调用检测。
//
// 设计:main/audit-rate.js 提供 createAuditRateTracker({ windowMs, threshold, now })
// 返回 hit(key) → { count, exceeded }。滑动窗口按 key 计数:
// - 窗口内 count ≤ threshold → exceeded=false
// - 窗口内 count > threshold → exceeded=true(调用方据此 console.warn)
// - 超过 windowMs 的旧记录自动过期
//
// now 可注入(Date.now 默认),方便单测推进时间。
import { describe, it, expect } from 'vitest';
const { createAuditRateTracker } = require('../../main/audit-rate.js');
describe('createAuditRateTracker —— P2-7 高频调用检测', () => {
it('首次调用 count=1,不 exceeded', () => {
const t = createAuditRateTracker({ windowMs: 60_000, threshold: 5 });
expect(t.hit('k')).toEqual({ count: 1, exceeded: false });
});
it('窗口内累计到 threshold 不 exceeded,超过则 exceeded', () => {
let now = 1000;
const t = createAuditRateTracker({ windowMs: 60_000, threshold: 3, now: () => now });
expect(t.hit('k').exceeded).toBe(false); // 1
expect(t.hit('k').exceeded).toBe(false); // 2
expect(t.hit('k').exceeded).toBe(false); // 3
const fourth = t.hit('k'); // 4 > 3
expect(fourth.count).toBe(4);
expect(fourth.exceeded).toBe(true);
});
it('不同 key 独立计数', () => {
const t = createAuditRateTracker({ windowMs: 60_000, threshold: 1 });
t.hit('a');
expect(t.hit('b')).toEqual({ count: 1, exceeded: false });
});
it('超过 windowMs 的旧记录过期,重新计数', () => {
let now = 0;
const t = createAuditRateTracker({ windowMs: 1000, threshold: 2, now: () => now });
t.hit('k'); // t=0
t.hit('k'); // t=0, count=2
expect(t.hit('k').exceeded).toBe(true); // t=0, count=3
now = 1500; // 滑出窗口
expect(t.hit('k')).toEqual({ count: 1, exceeded: false });
});
it('边界:恰好 windowMs 的时间点视为过期([now-window, now) 语义)', () => {
let now = 0;
const t = createAuditRateTracker({ windowMs: 1000, threshold: 1, now: () => now });
t.hit('k'); // t=0
now = 1000; // 恰好 1000ms 后
expect(t.hit('k')).toEqual({ count: 1, exceeded: false });
});
it('默认 now=Date.now,不抛错', () => {
const t = createAuditRateTracker({ windowMs: 1000, threshold: 1 });
expect(() => t.hit('k')).not.toThrow();
});
});