From de13d7272c5585747cc5e88adef5211b56be2422 Mon Sep 17 00:00:00 2001 From: Dana Lee Date: Thu, 12 Dec 2024 15:28:39 +0100 Subject: [PATCH] Add tests for continue on fail for Redis --- .../nodes/Redis/test/Redis.node.test.ts | 132 ++++++++++++++++-- 1 file changed, 122 insertions(+), 10 deletions(-) diff --git a/packages/nodes-base/nodes/Redis/test/Redis.node.test.ts b/packages/nodes-base/nodes/Redis/test/Redis.node.test.ts index 029b85f4d49df..6339459eb1b92 100644 --- a/packages/nodes-base/nodes/Redis/test/Redis.node.test.ts +++ b/packages/nodes-base/nodes/Redis/test/Redis.node.test.ts @@ -1,6 +1,6 @@ -import { mock } from 'jest-mock-extended'; import type { RedisClientType } from '@redis/client'; -import type { IExecuteFunctions } from 'n8n-workflow'; +import { mock } from 'jest-mock-extended'; +import { NodeOperationError, type IExecuteFunctions } from 'n8n-workflow'; const mockClient = mock(); const createClient = jest.fn().mockReturnValue(mockClient); @@ -12,7 +12,11 @@ import { setupRedisClient } from '../utils'; describe('Redis Node', () => { const node = new Redis(); - beforeEach(() => jest.clearAllMocks()); + beforeEach(() => { + createClient.mockReturnValue(mockClient); + }); + + afterEach(() => jest.resetAllMocks()); describe('setupRedisClient', () => { it('should not configure TLS by default', () => { @@ -54,14 +58,23 @@ describe('Redis Node', () => { describe('operations', () => { const thisArg = mock({}); - const mockCredential = { - host: 'redis', - port: 1234, - database: 0, - password: 'random', - }; + beforeEach(() => { + setupRedisClient({ + host: 'redis.domain', + port: 1234, + database: 0, + ssl: true, + }); - thisArg.getCredentials.calledWith('redis').mockResolvedValue(mockCredential); + const mockCredential = { + host: 'redis', + port: 1234, + database: 0, + password: 'random', + }; + + thisArg.getCredentials.calledWith('redis').mockResolvedValue(mockCredential); + }); afterEach(() => { expect(createClient).toHaveBeenCalled(); @@ -119,6 +132,28 @@ master_failover_state:no-failover master_failover_state: 'no-failover', }); }); + + it('should continue and return an error when continue on fail is enabled and an error is thrown', async () => { + thisArg.getNodeParameter.calledWith('operation', 0).mockReturnValue('info'); + thisArg.continueOnFail.mockReturnValue(true); + mockClient.info.mockRejectedValue(new Error('Redis error')); + + const output = await node.execute.call(thisArg); + + expect(mockClient.info).toHaveBeenCalled(); + expect(output[0][0].json).toEqual({ error: 'Redis error' }); + }); + + it('should throw an error when continue on fail is disabled and an error is thrown', async () => { + thisArg.getNodeParameter.calledWith('operation', 0).mockReturnValue('info'); + thisArg.continueOnFail.mockReturnValue(false); + mockClient.info.mockRejectedValue(new Error('Redis error')); + + await expect(node.execute.call(thisArg)).rejects.toThrow(NodeOperationError); + + expect(mockClient.info).toHaveBeenCalled(); + expect(mockClient.quit).toHaveBeenCalled(); + }); }); describe('delete operation', () => { @@ -132,6 +167,33 @@ master_failover_state:no-failover expect(mockClient.del).toHaveBeenCalledWith('key1'); expect(output[0][0].json).toEqual({ x: 1 }); }); + + it('should continue and return an error when continue on fail is enabled and an error is thrown', async () => { + thisArg.getInputData.mockReturnValue([{ json: { x: 1 } }]); + thisArg.getNodeParameter.calledWith('operation', 0).mockReturnValue('delete'); + thisArg.getNodeParameter.calledWith('key', 0).mockReturnValue('key1'); + thisArg.continueOnFail.mockReturnValue(true); + + mockClient.del.mockRejectedValue(new Error('Redis error')); + + const output = await node.execute.call(thisArg); + + expect(mockClient.del).toHaveBeenCalled(); + expect(output[0][0].json).toEqual({ error: 'Redis error' }); + }); + + it('should throw an error when continue on fail is disabled and an error is thrown', async () => { + thisArg.getInputData.mockReturnValue([{ json: { x: 1 } }]); + thisArg.getNodeParameter.calledWith('operation', 0).mockReturnValue('delete'); + thisArg.getNodeParameter.calledWith('key', 0).mockReturnValue('key1'); + + mockClient.del.mockRejectedValue(new Error('Redis error')); + + await expect(node.execute.call(thisArg)).rejects.toThrow(NodeOperationError); + + expect(mockClient.del).toHaveBeenCalled(); + expect(mockClient.quit).toHaveBeenCalled(); + }); }); describe('get operation', () => { @@ -172,6 +234,31 @@ master_failover_state:no-failover }, }); }); + + it('should continue and return an error when continue on fail is enabled and an error is thrown', async () => { + thisArg.getNodeParameter.calledWith('keyType', 0).mockReturnValue('automatic'); + thisArg.continueOnFail.mockReturnValue(true); + + mockClient.type.calledWith('key1').mockResolvedValue('string'); + mockClient.get.mockRejectedValue(new Error('Redis error')); + + const output = await node.execute.call(thisArg); + expect(mockClient.get).toHaveBeenCalled(); + + expect(output[0][0].json).toEqual({ error: 'Redis error' }); + }); + + it('should throw an error when continue on fail is disabled and an error is thrown', async () => { + thisArg.getNodeParameter.calledWith('keyType', 0).mockReturnValue('automatic'); + + mockClient.type.calledWith('key1').mockResolvedValue('string'); + mockClient.get.mockRejectedValue(new Error('Redis error')); + + await expect(node.execute.call(thisArg)).rejects.toThrow(NodeOperationError); + + expect(mockClient.get).toHaveBeenCalled(); + expect(mockClient.quit).toHaveBeenCalled(); + }); }); describe('keys operation', () => { @@ -200,6 +287,31 @@ master_failover_state:no-failover expect(mockClient.keys).toHaveBeenCalledWith('key*'); expect(output[0][0].json).toEqual({ key1: 'value1', key2: 'value2' }); }); + + it('should continue and return an error when continue on fail is enabled and an error is thrown', async () => { + thisArg.continueOnFail.mockReturnValue(true); + thisArg.getNodeParameter.calledWith('getValues', 0).mockReturnValue(true); + + mockClient.type.mockResolvedValue('string'); + mockClient.get.mockRejectedValue(new Error('Redis error')); + + const output = await node.execute.call(thisArg); + expect(mockClient.get).toHaveBeenCalled(); + + expect(output[0][0].json).toEqual({ error: 'Redis error' }); + }); + + it('should throw an error when continue on fail is disabled and an error is thrown', async () => { + thisArg.getNodeParameter.calledWith('getValues', 0).mockReturnValue(true); + + mockClient.type.mockResolvedValue('string'); + mockClient.get.mockRejectedValue(new Error('Redis error')); + + await expect(node.execute.call(thisArg)).rejects.toThrow(NodeOperationError); + + expect(mockClient.get).toHaveBeenCalled(); + expect(mockClient.quit).toHaveBeenCalled(); + }); }); }); });