import { jest } from '@jest/globals' import Redis from '../../src/Cache/Redis.js' let _connectionId = 1 function createRedisConnection() { const connection = { connectionId: _connectionId++, isOpen: false, close: jest.fn(() => { connection.isOpen = false }), connect: jest.fn(async () => { connection.isOpen = true return { mget: jest.fn(() => { return true }), } }), } return connection as any } async function simpleRedisTest(config: any, concurrent?: boolean) { const RedisMock = jest.fn(() => createRedisConnection()) Redis['ClientFactory'] = RedisMock // Double call is intentional const [provider, provider2] = concurrent ? await Promise.all([Redis.connection(config), Redis.connection(config)]) : [await Redis.connection(config), await Redis.connection(config)] // client checks expect(RedisMock).toHaveBeenNthCalledWith(1, { username: config.username, ...(config.password ? { password: config.password } : {}), disableOfflineQueue: true, socket: { port: 6379, host: config.hostname, tls: config.enableTLS, connectTimeout: 10000, }, }) // Does not have double connection expect(provider['connectionId']).toEqual(provider2['connectionId']) expect(provider.connect).toHaveBeenCalledTimes(1) expect(provider2.connect).toHaveBeenCalledTimes(1) } describe('Redis (client)', () => { beforeEach(async () => { Redis['clearSingletons']() _connectionId = 1 }) test('Simple redis - do not connect twice', async () => { await simpleRedisTest({ hostname: 'redis://localhost', username: 'gabe', password: 'mypassword', enableTLS: true, type: 'redis', }) }) test('Simple redis (no SSL) - do not connect twice', async () => { await simpleRedisTest({ hostname: 'redis://localhost', username: 'gabe', password: 'mypassword', enableTLS: false, type: 'redis', }) }) test('Simple redis (passwordless) - do not connect twice', async () => { await simpleRedisTest({ hostname: 'redis://localhost', username: 'gabe', enableTLS: false, type: 'redis', }) }) test('Concurrent redis - do not connect twice', async () => { await simpleRedisTest( { hostname: 'redis://localhost', username: 'gabe', enableTLS: false, type: 'redis', }, true ) }) test('Standalone then cluster returns different clients', async () => { const clientFactory = jest.fn(() => createRedisConnection()) const clusterFactory = jest.fn(() => createRedisConnection()) Redis['ClientFactory'] = clientFactory Redis['ClusterFactory'] = clusterFactory const standalone = await Redis.connection({ hostname: 'redis://localhost', username: 'gabe', enableTLS: false, type: 'redis', }) const cluster = await Redis.connection({ hostname: 'redis://localhost', username: 'gabe', enableTLS: false, clusterMode: true, type: 'redis', }) expect(standalone['connectionId']).not.toEqual(cluster['connectionId']) expect(clientFactory).toHaveBeenCalledTimes(1) expect(clusterFactory).toHaveBeenCalledTimes(1) }) test('Different standalone configs return different clients', async () => { const clientFactory = jest.fn(() => createRedisConnection()) Redis['ClientFactory'] = clientFactory const first = await Redis.connection({ hostname: 'redis://localhost', username: 'gabe', password: 'first-password', enableTLS: false, type: 'redis', }) const second = await Redis.connection({ hostname: 'redis://cache.internal', username: 'other-user', password: 'second-password', enableTLS: false, type: 'redis', }) expect(first['connectionId']).not.toEqual(second['connectionId']) expect(clientFactory).toHaveBeenCalledTimes(2) }) })