Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(Redis Node): Continue on Fail for Redis (no-changelog) #12190

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 122 additions & 10 deletions packages/nodes-base/nodes/Redis/test/Redis.node.test.ts
Original file line number Diff line number Diff line change
@@ -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<RedisClientType>();
const createClient = jest.fn().mockReturnValue(mockClient);
Expand All @@ -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', () => {
Expand Down Expand Up @@ -54,14 +58,23 @@ describe('Redis Node', () => {
describe('operations', () => {
const thisArg = mock<IExecuteFunctions>({});

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();
Expand Down Expand Up @@ -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', () => {
Expand All @@ -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', () => {
Expand Down Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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();
});
});
});
});
Loading