Files
n8n-enterprise-unlocked/packages/cli/src/chat/__tests__/utils.test.ts
Michael Kret a98ed2ca49 feat: Respond to chat and wait for response (#12546)
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-07-24 09:48:40 +01:00

304 lines
6.7 KiB
TypeScript

import type { IExecutionResponse } from '@n8n/db';
import type { IDataObject, INode } from 'n8n-workflow';
import { CHAT_WAIT_USER_REPLY, RESPOND_TO_WEBHOOK_NODE_TYPE } from 'n8n-workflow';
import { getMessage, getLastNodeExecuted, shouldResumeImmediately } from '../utils';
// helpers --------------------------------------------------------
const createMockExecution = (
overrides: IDataObject = {},
firstExecutionData?: IDataObject,
nodeData?: IDataObject[],
): IExecutionResponse => {
const firstItem = firstExecutionData ?? {
json: { test: 'data' },
sendMessage: 'Test message',
};
const nodeRunData = nodeData ?? [
{
data: {
main: [[firstItem]],
},
},
];
return {
id: 'test-execution-id',
data: {
resultData: {
lastNodeExecuted: 'TestNode',
runData: {
TestNode: nodeRunData,
},
},
},
workflowData: {
nodes: [
{
name: 'TestNode',
type: 'test-node',
parameters: {},
},
],
},
...overrides,
} as unknown as IExecutionResponse;
};
const createMockNode = (overrides: Partial<INode> = {}): INode =>
({
name: 'TestNode',
type: 'test-node',
parameters: {},
...overrides,
}) as INode;
// ---------------------------------------------------------
describe('getMessage', () => {
it('should return sendMessage from the last node execution', () => {
const execution = createMockExecution();
const result = getMessage(execution);
expect(result).toBe('Test message');
});
it('should return undefined when no sendMessage exists', () => {
const execution = createMockExecution(
{},
{
json: { test: 'data' },
},
);
const result = getMessage(execution);
expect(result).toBeUndefined();
});
it('should return undefined when nodeExecutionData is empty', () => {
const execution = createMockExecution({}, undefined, [
{
data: {
main: [[]],
},
},
]);
const result = getMessage(execution);
expect(result).toBeUndefined();
});
it('should handle multiple run data entries and use the last one', () => {
const execution = createMockExecution({}, undefined, [
{
data: {
main: [
[
{
json: { test: 'first' },
sendMessage: 'First message',
},
],
],
},
},
{
data: {
main: [
[
{
json: { test: 'second' },
sendMessage: 'Second message',
},
],
],
},
},
]);
const result = getMessage(execution);
expect(result).toBe('Second message');
});
it('should return undefined when main data is missing', () => {
const execution = createMockExecution({}, undefined, [
{
data: {},
},
]);
const result = getMessage(execution);
expect(result).toBeUndefined();
});
it('should return undefined when nodeExecutionData is undefined', () => {
const execution = createMockExecution({
data: {
resultData: {
lastNodeExecuted: 'TestNode',
runData: {
TestNode: [
{
data: {
main: undefined,
},
},
],
},
},
},
});
const result = getMessage(execution);
expect(result).toBeUndefined();
});
});
describe('getLastNodeExecuted', () => {
it('should return the node that was last executed', () => {
const execution = createMockExecution();
const result = getLastNodeExecuted(execution);
expect(result).toEqual({
name: 'TestNode',
type: 'test-node',
parameters: {},
});
});
it('should return undefined when last executed node is not found', () => {
const execution = createMockExecution({
data: {
resultData: {
lastNodeExecuted: 'NonExistentNode',
runData: {},
},
},
});
const result = getLastNodeExecuted(execution);
expect(result).toBeUndefined();
});
it('should find the correct node among multiple nodes', () => {
const execution = createMockExecution({
data: {
resultData: {
lastNodeExecuted: 'SecondNode',
runData: {},
},
},
workflowData: {
nodes: [
{
name: 'FirstNode',
type: 'first-type',
parameters: {},
},
{
name: 'SecondNode',
type: 'second-type',
parameters: { test: 'value' },
},
],
},
});
const result = getLastNodeExecuted(execution);
expect(result).toEqual({
name: 'SecondNode',
type: 'second-type',
parameters: { test: 'value' },
});
});
it('should return undefined when workflowData.nodes is undefined', () => {
const execution = createMockExecution({
workflowData: undefined,
});
const result = getLastNodeExecuted(execution);
expect(result).toBeUndefined();
});
});
describe('shouldResumeImmediately', () => {
it('should return true for RESPOND_TO_WEBHOOK_NODE_TYPE', () => {
const node = createMockNode({
type: RESPOND_TO_WEBHOOK_NODE_TYPE,
});
const result = shouldResumeImmediately(node);
expect(result).toBe(true);
});
it('should return true when CHAT_WAIT_USER_REPLY is false', () => {
const node = createMockNode({
parameters: {
options: {
[CHAT_WAIT_USER_REPLY]: false,
},
},
});
const result = shouldResumeImmediately(node);
expect(result).toBe(true);
});
it('should return false when CHAT_WAIT_USER_REPLY is true', () => {
const node = createMockNode({
parameters: {
options: {
[CHAT_WAIT_USER_REPLY]: true,
},
},
});
const result = shouldResumeImmediately(node);
expect(result).toBe(false);
});
it('should return false when CHAT_WAIT_USER_REPLY is undefined', () => {
const node = createMockNode({
parameters: {
options: {},
},
});
const result = shouldResumeImmediately(node);
expect(result).toBe(false);
});
it('should return false when no options exist', () => {
const node = createMockNode({
parameters: {},
});
const result = shouldResumeImmediately(node);
expect(result).toBe(false);
});
it('should return false when no parameters exist', () => {
const node = createMockNode({
parameters: undefined,
});
const result = shouldResumeImmediately(node);
expect(result).toBe(false);
});
it('should handle null node', () => {
const result = shouldResumeImmediately(null as any);
expect(result).toBe(false);
});
it('should handle undefined node', () => {
const result = shouldResumeImmediately(undefined as any);
expect(result).toBe(false);
});
it('should return true when CHAT_WAIT_USER_REPLY is false directly in parameters', () => {
const node = createMockNode({
parameters: {
[CHAT_WAIT_USER_REPLY]: false,
},
});
const result = shouldResumeImmediately(node);
expect(result).toBe(true);
});
it('should return false when CHAT_WAIT_USER_REPLY is true directly in parameters', () => {
const node = createMockNode({
parameters: {
[CHAT_WAIT_USER_REPLY]: true,
},
});
const result = shouldResumeImmediately(node);
expect(result).toBe(false);
});
});