76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
const errorSpy = vi.fn();
|
|
const infoSpy = vi.fn();
|
|
|
|
vi.mock('@/utils/logger', () => ({
|
|
default: {
|
|
error: errorSpy,
|
|
info: infoSpy,
|
|
},
|
|
}));
|
|
|
|
class RedisMock extends EventTarget {
|
|
mget = vi.fn();
|
|
expire = vi.fn();
|
|
exists = vi.fn();
|
|
set = vi.fn();
|
|
|
|
on(event: string, listener: (...args: any[]) => void) {
|
|
this.addEventListener(event, (evt) => {
|
|
listener((evt as Event & { detail?: unknown }).detail);
|
|
});
|
|
return this;
|
|
}
|
|
|
|
emit(event: string, detail?: unknown) {
|
|
const evt = new Event(event) as Event & { detail?: unknown };
|
|
evt.detail = detail;
|
|
this.dispatchEvent(evt);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
vi.mock('ioredis', () => ({
|
|
default: RedisMock,
|
|
}));
|
|
|
|
describe('redis cache module', () => {
|
|
it('throws on reserved cache ttl key', async () => {
|
|
const redisCache = (await import('@/utils/cache/redis')).default;
|
|
redisCache.status.available = true;
|
|
redisCache.clients.redisClient = new RedisMock() as any;
|
|
|
|
await expect(redisCache.get('rsshub:cacheTtl:bad')).rejects.toThrow('reserved for the internal usage');
|
|
});
|
|
|
|
it('expires cache ttl key when present', async () => {
|
|
const redisCache = (await import('@/utils/cache/redis')).default;
|
|
const client = new RedisMock() as any;
|
|
client.mget.mockResolvedValue(['value', '30']);
|
|
client.exists.mockResolvedValue(true);
|
|
redisCache.status.available = true;
|
|
redisCache.clients.redisClient = client;
|
|
|
|
const value = await redisCache.get('mock', true);
|
|
expect(value).toBe('value');
|
|
expect(client.expire).toHaveBeenCalledWith('rsshub:cacheTtl:mock', '30');
|
|
expect(client.expire).toHaveBeenCalledWith('mock', '30');
|
|
|
|
await expect(redisCache.has('mock')).resolves.toBe(true);
|
|
client.exists.mockResolvedValue(false);
|
|
await expect(redisCache.has('missing')).resolves.toBe(false);
|
|
});
|
|
|
|
it('marks redis unavailable on error', async () => {
|
|
const redisCache = (await import('@/utils/cache/redis')).default;
|
|
redisCache.init();
|
|
const client = redisCache.clients.redisClient as RedisMock;
|
|
|
|
client.emit('error', new Error('boom'));
|
|
|
|
expect(redisCache.status.available).toBe(false);
|
|
expect(errorSpy).toHaveBeenCalled();
|
|
});
|
|
});
|