mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
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>
This commit is contained in:
303
packages/cli/src/chat/__tests__/utils.test.ts
Normal file
303
packages/cli/src/chat/__tests__/utils.test.ts
Normal file
@@ -0,0 +1,303 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user