| 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(); |
| 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']); |
| 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'); |
| }); |
|
|
| 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(); |
| }); |
| }); |
|
|