fix: 重构所有定时器测试为 Jest fake timers,彻底解决 CI Run tests 卡死
tests/utils.test.ts: debounce/throttle/sleep 使用 useFakeTimers + advanceTimersByTime; tests/core.test.ts: 历史栈防抖合并测试用 fake timers 替代 400ms setTimeout; tests/plugins.test.ts: autoSave 三个测试用 fake timers 替代 setTimeout/done; README.md: 更新测试徽章为 353 passed; site/index.html, site/demo.html: 更新测试数为 353
This commit is contained in:
+39
-38
@@ -61,27 +61,26 @@ describe('prefersDark', () => {
|
||||
});
|
||||
|
||||
describe('debounce', () => {
|
||||
test('延迟执行', (done) => {
|
||||
beforeEach(() => jest.useFakeTimers());
|
||||
afterEach(() => jest.useRealTimers());
|
||||
|
||||
test('延迟执行', () => {
|
||||
let called = 0;
|
||||
const fn = debounce(() => { called++; }, 50);
|
||||
fn();
|
||||
expect(called).toBe(0);
|
||||
setTimeout(() => {
|
||||
expect(called).toBe(1);
|
||||
done();
|
||||
}, 100);
|
||||
jest.advanceTimersByTime(50);
|
||||
expect(called).toBe(1);
|
||||
});
|
||||
|
||||
test('多次调用只执行最后一次', (done) => {
|
||||
test('多次调用只执行最后一次', () => {
|
||||
let result = 0;
|
||||
const fn = debounce((v) => { result = v; }, 50);
|
||||
fn(1);
|
||||
fn(2);
|
||||
fn(3);
|
||||
setTimeout(() => {
|
||||
expect(result).toBe(3);
|
||||
done();
|
||||
}, 100);
|
||||
jest.advanceTimersByTime(50);
|
||||
expect(result).toBe(3);
|
||||
});
|
||||
|
||||
test('immediate 模式立即执行', () => {
|
||||
@@ -91,31 +90,30 @@ describe('debounce', () => {
|
||||
expect(called).toBe(1);
|
||||
});
|
||||
|
||||
test('保留 this 上下文', (done) => {
|
||||
test('保留 this 上下文', () => {
|
||||
const obj = {
|
||||
val: 42,
|
||||
getVal: debounce(function () { return this.val; }, 30),
|
||||
};
|
||||
const p = obj.getVal();
|
||||
// immediate=false 时首次不返回,但 this 应正确
|
||||
setTimeout(() => {
|
||||
expect(typeof p).toBe('undefined'); // debounce 返回的是 undefined(异步执行)
|
||||
done();
|
||||
}, 60);
|
||||
expect(typeof p).toBe('undefined');
|
||||
jest.advanceTimersByTime(30);
|
||||
});
|
||||
|
||||
test('传递参数', (done) => {
|
||||
test('传递参数', () => {
|
||||
let captured = null;
|
||||
const fn = debounce((a, b) => { captured = a + b; }, 30);
|
||||
fn(1, 2);
|
||||
setTimeout(() => {
|
||||
expect(captured).toBe(3);
|
||||
done();
|
||||
}, 60);
|
||||
jest.advanceTimersByTime(30);
|
||||
expect(captured).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('throttle', () => {
|
||||
beforeEach(() => jest.useFakeTimers());
|
||||
afterEach(() => jest.useRealTimers());
|
||||
|
||||
test('首次立即执行', () => {
|
||||
let called = 0;
|
||||
const fn = throttle(() => { called++; }, 50);
|
||||
@@ -132,25 +130,22 @@ describe('throttle', () => {
|
||||
expect(called).toBe(1);
|
||||
});
|
||||
|
||||
test('限流期后可再次执行', (done) => {
|
||||
test('限流期后可再次执行', () => {
|
||||
let called = 0;
|
||||
const fn = throttle(() => { called++; }, 40);
|
||||
fn();
|
||||
setTimeout(() => {
|
||||
fn();
|
||||
expect(called).toBe(2);
|
||||
done();
|
||||
}, 60);
|
||||
jest.advanceTimersByTime(40);
|
||||
fn();
|
||||
expect(called).toBe(2);
|
||||
});
|
||||
|
||||
test('保留 this 与参数', (done) => {
|
||||
test('保留 this 与参数', () => {
|
||||
const obj = {
|
||||
n: 10,
|
||||
run: throttle(function (x) { this.result = this.n + x; }, 30),
|
||||
};
|
||||
obj.run(5);
|
||||
expect(obj.result).toBe(15);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -225,22 +220,28 @@ describe('formatFileSize', () => {
|
||||
});
|
||||
|
||||
describe('sleep', () => {
|
||||
beforeEach(() => jest.useFakeTimers());
|
||||
afterEach(() => jest.useRealTimers());
|
||||
|
||||
test('返回 Promise', () => {
|
||||
expect(sleep(10)).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
test('延迟后 resolve', (done) => {
|
||||
const start = Date.now();
|
||||
sleep(50).then(() => {
|
||||
const elapsed = Date.now() - start;
|
||||
expect(elapsed).toBeGreaterThanOrEqual(40);
|
||||
done();
|
||||
});
|
||||
test('延迟后 resolve', async () => {
|
||||
let resolved = false;
|
||||
sleep(50).then(() => { resolved = true; });
|
||||
expect(resolved).toBe(false);
|
||||
jest.advanceTimersByTime(50);
|
||||
// 让微任务队列执行
|
||||
await Promise.resolve();
|
||||
expect(resolved).toBe(true);
|
||||
});
|
||||
|
||||
test('async/await 用法', async () => {
|
||||
const start = Date.now();
|
||||
await sleep(30);
|
||||
expect(Date.now() - start).toBeGreaterThanOrEqual(20);
|
||||
let resolved = false;
|
||||
const p = sleep(30).then(() => { resolved = true; });
|
||||
jest.advanceTimersByTime(30);
|
||||
await p;
|
||||
expect(resolved).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user