mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 09:36:44 +00:00
535 lines
19 KiB
TypeScript
535 lines
19 KiB
TypeScript
import {
|
|
AGENT_NODE_NAME,
|
|
EDIT_FIELDS_SET_NODE_NAME,
|
|
MANUAL_CHAT_TRIGGER_NODE_NAME,
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME,
|
|
AI_MEMORY_POSTGRES_NODE_NAME,
|
|
AI_TOOL_CALCULATOR_NODE_NAME,
|
|
AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME,
|
|
AI_TOOL_CODE_NODE_NAME,
|
|
AI_TOOL_WIKIPEDIA_NODE_NAME,
|
|
BASIC_LLM_CHAIN_NODE_NAME,
|
|
CHAT_TRIGGER_NODE_DISPLAY_NAME,
|
|
SCHEDULE_TRIGGER_NODE_NAME,
|
|
} from '../../config/constants';
|
|
import { test, expect } from '../../fixtures/base';
|
|
import type { n8nPage } from '../../pages/n8nPage';
|
|
|
|
// Helper functions for common operations
|
|
async function addOpenAILanguageModelWithCredentials(
|
|
n8n: n8nPage,
|
|
parentNode: string,
|
|
options: { exactMatch?: boolean; closeNDV?: boolean } = { exactMatch: true, closeNDV: false },
|
|
) {
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
'ai_languageModel',
|
|
parentNode,
|
|
options,
|
|
);
|
|
|
|
await n8n.ndv.clickCreateNewCredential();
|
|
await n8n.credentialsModal.setValues({
|
|
apiKey: 'abcd',
|
|
});
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
}
|
|
|
|
async function waitForWorkflowSuccess(n8n: n8nPage, timeout = 3000) {
|
|
await n8n.notifications.waitForNotificationAndClose('Workflow executed successfully', {
|
|
timeout,
|
|
});
|
|
}
|
|
|
|
async function executeChatAndWaitForResponse(n8n: n8nPage, message: string) {
|
|
await n8n.canvas.logsPanel.sendManualChatMessage(message);
|
|
await waitForWorkflowSuccess(n8n);
|
|
}
|
|
|
|
async function verifyChatMessages(n8n: n8nPage, expectedCount: number, inputMessage?: string) {
|
|
const messages = n8n.canvas.getManualChatMessages();
|
|
await expect(messages).toHaveCount(expectedCount);
|
|
if (inputMessage) {
|
|
await expect(messages.first()).toContainText(inputMessage);
|
|
}
|
|
await expect(messages.last()).toBeVisible();
|
|
return messages;
|
|
}
|
|
|
|
async function verifyLogsPanelEntries(n8n: n8nPage, expectedEntries: string[]) {
|
|
await expect(n8n.canvas.logsPanel.getLogEntries().first()).toBeVisible();
|
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(expectedEntries.length);
|
|
for (let i = 0; i < expectedEntries.length; i++) {
|
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(i)).toHaveText(expectedEntries[i]);
|
|
}
|
|
}
|
|
|
|
async function setupBasicAgentWorkflow(n8n: n8nPage, additionalNodes: string[] = []) {
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
// Add additional nodes if specified
|
|
for (const nodeName of additionalNodes) {
|
|
await n8n.canvas.addSupplementalNodeToParent(nodeName, 'ai_tool', AGENT_NODE_NAME, {
|
|
closeNDV: true,
|
|
});
|
|
}
|
|
|
|
// Always add OpenAI Language Model
|
|
await addOpenAILanguageModelWithCredentials(n8n, AGENT_NODE_NAME);
|
|
}
|
|
|
|
test.describe('Langchain Integration @capability:proxy', () => {
|
|
test.beforeEach(async ({ n8n, proxyServer }) => {
|
|
await proxyServer.clearAllExpectations();
|
|
await proxyServer.loadExpectations('langchain');
|
|
await n8n.canvas.openNewWorkflow();
|
|
});
|
|
|
|
test.describe('Workflow Execution Behavior', () => {
|
|
test('should not open chat modal', async ({ n8n }) => {
|
|
await n8n.canvas.addNode(EDIT_FIELDS_SET_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
'ai_languageModel',
|
|
AGENT_NODE_NAME,
|
|
{ exactMatch: true, closeNDV: true },
|
|
);
|
|
|
|
await n8n.canvas.clickExecuteWorkflowButton();
|
|
await expect(n8n.canvas.getManualChatModal()).toBeHidden();
|
|
});
|
|
|
|
test('should remove test workflow button', async ({ n8n }) => {
|
|
await n8n.canvas.addNode(SCHEDULE_TRIGGER_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addNode(EDIT_FIELDS_SET_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
'ai_languageModel',
|
|
AGENT_NODE_NAME,
|
|
{ exactMatch: true, closeNDV: true },
|
|
);
|
|
|
|
await n8n.canvas.disableNodeFromContextMenu(SCHEDULE_TRIGGER_NODE_NAME);
|
|
await expect(n8n.canvas.getExecuteWorkflowButton()).toBeHidden();
|
|
});
|
|
});
|
|
|
|
test.describe('Node Connection and Configuration', () => {
|
|
test('should add nodes to all Agent node input types', async ({ n8n }) => {
|
|
const agentSubNodes = [
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME,
|
|
AI_TOOL_CALCULATOR_NODE_NAME,
|
|
AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME,
|
|
];
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: false });
|
|
|
|
await n8n.ndv.checkParameterCheckboxInputByName('hasOutputParser');
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
'ai_languageModel',
|
|
AGENT_NODE_NAME,
|
|
{ exactMatch: true, closeNDV: true },
|
|
);
|
|
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME,
|
|
'ai_memory',
|
|
AGENT_NODE_NAME,
|
|
{ closeNDV: true },
|
|
);
|
|
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_TOOL_CALCULATOR_NODE_NAME,
|
|
'ai_tool',
|
|
AGENT_NODE_NAME,
|
|
{ closeNDV: true },
|
|
);
|
|
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME,
|
|
'ai_outputParser',
|
|
AGENT_NODE_NAME,
|
|
{ closeNDV: true },
|
|
);
|
|
for (const nodeName of agentSubNodes) {
|
|
await expect(n8n.canvas.connectionBetweenNodes(nodeName, AGENT_NODE_NAME)).toBeAttached();
|
|
}
|
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2 + agentSubNodes.length); // Chat Trigger + Agent + 4 inputs
|
|
});
|
|
|
|
test('should add multiple tool nodes to Agent node tool input type', async ({ n8n }) => {
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
const tools = [
|
|
AI_TOOL_CALCULATOR_NODE_NAME,
|
|
AI_TOOL_CODE_NODE_NAME,
|
|
AI_TOOL_CODE_NODE_NAME,
|
|
AI_TOOL_WIKIPEDIA_NODE_NAME,
|
|
];
|
|
|
|
for (const tool of tools) {
|
|
await n8n.canvas.addSupplementalNodeToParent(tool, 'ai_tool', AGENT_NODE_NAME, {
|
|
closeNDV: true,
|
|
});
|
|
await expect(n8n.canvas.connectionBetweenNodes(tool, AGENT_NODE_NAME)).toBeAttached();
|
|
}
|
|
|
|
// Chat Trigger + Agent + Tools
|
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2 + tools.length);
|
|
});
|
|
});
|
|
|
|
test.describe('Auto-add Behavior', () => {
|
|
test('should auto-add chat trigger and basic LLM chain when adding LLM node', async ({
|
|
n8n,
|
|
}) => {
|
|
await n8n.canvas.addNode(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, { closeNDV: true });
|
|
|
|
await expect(
|
|
n8n.canvas.connectionBetweenNodes(
|
|
CHAT_TRIGGER_NODE_DISPLAY_NAME,
|
|
BASIC_LLM_CHAIN_NODE_NAME,
|
|
),
|
|
).toBeAttached();
|
|
|
|
await expect(
|
|
n8n.canvas.connectionBetweenNodes(
|
|
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
|
BASIC_LLM_CHAIN_NODE_NAME,
|
|
),
|
|
).toBeAttached();
|
|
|
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(3);
|
|
});
|
|
|
|
test('should not auto-add nodes if AI nodes are already present', async ({ n8n }) => {
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addNode(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, { closeNDV: true });
|
|
|
|
await expect(
|
|
n8n.canvas.connectionBetweenNodes(CHAT_TRIGGER_NODE_DISPLAY_NAME, AGENT_NODE_NAME),
|
|
).toBeAttached();
|
|
|
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(3);
|
|
});
|
|
|
|
test('should not auto-add nodes if ChatTrigger is already present', async ({ n8n }) => {
|
|
await n8n.canvas.addNode(MANUAL_CHAT_TRIGGER_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
await n8n.canvas.addNode(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, { closeNDV: true });
|
|
|
|
await expect(
|
|
n8n.canvas.connectionBetweenNodes(CHAT_TRIGGER_NODE_DISPLAY_NAME, AGENT_NODE_NAME),
|
|
).toBeAttached();
|
|
|
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(3);
|
|
});
|
|
});
|
|
|
|
test.describe('Chat Execution and Interaction', () => {
|
|
test('should be able to open and execute Basic LLM Chain node', async ({ n8n }) => {
|
|
await n8n.canvas.addNode(BASIC_LLM_CHAIN_NODE_NAME, { closeNDV: true });
|
|
|
|
await addOpenAILanguageModelWithCredentials(n8n, BASIC_LLM_CHAIN_NODE_NAME);
|
|
|
|
await n8n.canvas.openNode(BASIC_LLM_CHAIN_NODE_NAME);
|
|
const inputMessage = 'Hello!';
|
|
|
|
await n8n.ndv.execute();
|
|
await executeChatAndWaitForResponse(n8n, inputMessage);
|
|
|
|
// Verify chat message appears
|
|
await expect(n8n.canvas.getManualChatLatestBotMessage()).toBeVisible();
|
|
});
|
|
test('should be able to open and execute Agent node', async ({ n8n }) => {
|
|
await setupBasicAgentWorkflow(n8n);
|
|
|
|
const inputMessage = 'Hello!';
|
|
await n8n.canvas.clickManualChatButton();
|
|
await executeChatAndWaitForResponse(n8n, inputMessage);
|
|
|
|
// Verify chat message appears
|
|
await expect(n8n.canvas.getManualChatLatestBotMessage()).toBeVisible();
|
|
});
|
|
test('should add and use Manual Chat Trigger node together with Agent node', async ({
|
|
n8n,
|
|
}) => {
|
|
await setupBasicAgentWorkflow(n8n);
|
|
|
|
const inputMessage = 'Hello!';
|
|
await n8n.canvas.clickManualChatButton();
|
|
await executeChatAndWaitForResponse(n8n, inputMessage);
|
|
|
|
await verifyChatMessages(n8n, 2, inputMessage);
|
|
await verifyLogsPanelEntries(n8n, [
|
|
'When chat message received',
|
|
'AI Agent',
|
|
'OpenAI Chat Model',
|
|
]);
|
|
|
|
await n8n.canvas.closeManualChatModal();
|
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toBeHidden();
|
|
await expect(n8n.canvas.getManualChatInput()).toBeHidden();
|
|
});
|
|
});
|
|
|
|
test.describe('Tool Usage Notifications', () => {
|
|
test('should show tool info notice if no existing tools were used during execution', async ({
|
|
n8n,
|
|
}) => {
|
|
await setupBasicAgentWorkflow(n8n, [AI_TOOL_CALCULATOR_NODE_NAME]);
|
|
await n8n.canvas.openNode(AGENT_NODE_NAME);
|
|
|
|
const inputMessage = 'Hello!';
|
|
await n8n.ndv.execute();
|
|
await executeChatAndWaitForResponse(n8n, inputMessage);
|
|
|
|
await n8n.canvas.closeManualChatModal();
|
|
await n8n.canvas.openNode(AGENT_NODE_NAME);
|
|
|
|
await expect(n8n.ndv.getRunDataInfoCallout()).toBeVisible();
|
|
});
|
|
test('should not show tool info notice if tools were used during execution', async ({
|
|
n8n,
|
|
}) => {
|
|
await n8n.canvas.addNode(MANUAL_CHAT_TRIGGER_NODE_NAME, { closeNDV: true });
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: false });
|
|
await expect(n8n.ndv.getRunDataInfoCallout()).toBeHidden();
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
|
|
await addOpenAILanguageModelWithCredentials(n8n, AGENT_NODE_NAME);
|
|
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_TOOL_CALCULATOR_NODE_NAME,
|
|
'ai_tool',
|
|
AGENT_NODE_NAME,
|
|
{ closeNDV: true },
|
|
);
|
|
|
|
const inputMessage = 'What is 1000 * 10?';
|
|
await n8n.canvas.clickManualChatButton();
|
|
await executeChatAndWaitForResponse(n8n, inputMessage);
|
|
|
|
await n8n.canvas.closeManualChatModal();
|
|
await n8n.canvas.openNode(AGENT_NODE_NAME);
|
|
|
|
await expect(n8n.ndv.getRunDataInfoCallout()).toBeHidden();
|
|
});
|
|
});
|
|
|
|
test.describe('Error Handling and Logs Display', () => {
|
|
// Helper function to set up the agent workflow with Postgres error configuration
|
|
async function setupAgentWorkflowWithPostgresError(n8n: n8nPage) {
|
|
await n8n.canvas.addNode(AGENT_NODE_NAME, { closeNDV: true });
|
|
|
|
// Add Calculator Tool (required for OpenAI model)
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_TOOL_CALCULATOR_NODE_NAME,
|
|
'ai_tool',
|
|
AGENT_NODE_NAME,
|
|
{ closeNDV: true },
|
|
);
|
|
|
|
// Add and configure Postgres Memory
|
|
await n8n.canvas.addSupplementalNodeToParent(
|
|
AI_MEMORY_POSTGRES_NODE_NAME,
|
|
'ai_memory',
|
|
AGENT_NODE_NAME,
|
|
{ closeNDV: false },
|
|
);
|
|
|
|
await n8n.ndv.clickCreateNewCredential();
|
|
await n8n.credentialsModal.setValues({
|
|
password: 'testtesttest',
|
|
});
|
|
|
|
await n8n.ndv.getParameterInput('sessionIdType').click();
|
|
await n8n.page.getByRole('option', { name: 'Define below' }).click();
|
|
await n8n.ndv.getParameterInput('sessionKey').locator('input').fill('asdasd');
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
|
|
// Add and configure OpenAI Language Model
|
|
await addOpenAILanguageModelWithCredentials(n8n, AGENT_NODE_NAME);
|
|
|
|
await n8n.canvas.clickZoomToFitButton();
|
|
}
|
|
|
|
// Helper function to assert logs tab is active
|
|
async function assertLogsTabIsActive(n8n: n8nPage) {
|
|
await expect(n8n.ndv.getOutputDataContainer()).toBeVisible();
|
|
await expect(n8n.ndv.getAiOutputModeToggle()).toBeVisible();
|
|
|
|
const radioButtons = n8n.ndv.getAiOutputModeToggle().locator('[role="radio"]');
|
|
await expect(radioButtons).toHaveCount(2);
|
|
await expect(radioButtons.nth(1)).toHaveAttribute('aria-checked', 'true');
|
|
}
|
|
|
|
// Helper function to assert error message is visible
|
|
async function assertErrorMessageVisible(n8n: n8nPage) {
|
|
await expect(
|
|
n8n.ndv.getOutputPanel().getByTestId('node-error-message').first(),
|
|
).toBeVisible();
|
|
await expect(
|
|
n8n.ndv.getOutputPanel().getByTestId('node-error-message').first(),
|
|
).toContainText('Error in sub-node');
|
|
}
|
|
|
|
test('should open logs tab by default when there was an error', async ({ n8n }) => {
|
|
await setupAgentWorkflowWithPostgresError(n8n);
|
|
|
|
const inputMessage = 'Test the code tool';
|
|
|
|
// Execute workflow with chat trigger
|
|
await n8n.canvas.clickManualChatButton();
|
|
await executeChatAndWaitForResponse(n8n, inputMessage);
|
|
|
|
// Check that messages and logs are displayed
|
|
const messages = await verifyChatMessages(n8n, 2, inputMessage);
|
|
await expect(messages.last()).toContainText(
|
|
'[ERROR: The service refused the connection - perhaps it is offline]',
|
|
);
|
|
|
|
await expect(n8n.canvas.logsPanel.getLogEntries().first()).toBeVisible();
|
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(3);
|
|
await expect(n8n.canvas.logsPanel.getSelectedLogEntry()).toHaveText('AI Agent');
|
|
await expect(n8n.canvas.logsPanel.outputPanel.get()).toContainText(
|
|
AI_MEMORY_POSTGRES_NODE_NAME,
|
|
);
|
|
|
|
await n8n.canvas.closeManualChatModal();
|
|
|
|
// Open the AI Agent node to see the logs
|
|
await n8n.canvas.openNode(AGENT_NODE_NAME);
|
|
|
|
// Assert that logs tab is active and error is displayed
|
|
await assertLogsTabIsActive(n8n);
|
|
await assertErrorMessageVisible(n8n);
|
|
});
|
|
|
|
test('should switch to logs tab on error, when NDV is already opened', async ({ n8n }) => {
|
|
// Remove the auto-added chat trigger
|
|
await n8n.canvas.addNode(MANUAL_CHAT_TRIGGER_NODE_NAME, { closeNDV: false });
|
|
|
|
// Set manual trigger to output standard pinned data
|
|
await n8n.ndv.getEditPinnedDataButton().click();
|
|
await n8n.ndv.savePinnedData();
|
|
await n8n.ndv.close();
|
|
|
|
// Set up the same workflow components but with manual trigger
|
|
await setupAgentWorkflowWithPostgresError(n8n);
|
|
|
|
// Open the AI Agent node
|
|
await n8n.canvas.openNode(AGENT_NODE_NAME);
|
|
await n8n.ndv.getParameterInput('promptType').click();
|
|
await n8n.page.getByRole('option', { name: 'Define below' }).click();
|
|
await n8n.ndv.getParameterInput('text').locator('textarea').fill('Some text');
|
|
await n8n.ndv.execute();
|
|
await waitForWorkflowSuccess(n8n);
|
|
|
|
// Assert that logs tab is active and error is displayed
|
|
await assertLogsTabIsActive(n8n);
|
|
await assertErrorMessageVisible(n8n);
|
|
});
|
|
});
|
|
|
|
test.describe('Advanced Workflow Features', () => {
|
|
test('should render runItems for sub-nodes and allow switching between them', async ({
|
|
n8n,
|
|
}) => {
|
|
await n8n.start.fromImportedWorkflow('In_memory_vector_store_fake_embeddings.json');
|
|
await n8n.canvas.clickZoomToFitButton();
|
|
await n8n.canvas.deselectAll();
|
|
|
|
await n8n.canvas.executeNode('Populate VS');
|
|
await waitForWorkflowSuccess(n8n);
|
|
|
|
const assertInputOutputTextExists = async (text: string) => {
|
|
await expect(n8n.ndv.getOutputPanel()).toContainText(text);
|
|
await expect(n8n.ndv.getInputPanel()).toContainText(text);
|
|
};
|
|
|
|
const assertInputOutputTextNotExists = async (text: string) => {
|
|
await expect(n8n.ndv.getOutputPanel()).not.toContainText(text);
|
|
await expect(n8n.ndv.getInputPanel()).not.toContainText(text);
|
|
};
|
|
|
|
await n8n.canvas.openNode('Character Text Splitter');
|
|
|
|
await expect(n8n.ndv.getOutputRunSelector()).toBeVisible();
|
|
await expect(n8n.ndv.getInputRunSelector()).toBeVisible();
|
|
await expect(n8n.ndv.getInputRunSelectorInput()).toHaveValue('3 of 3');
|
|
await expect(n8n.ndv.getOutputRunSelectorInput()).toHaveValue('3 of 3');
|
|
await assertInputOutputTextExists('Kyiv');
|
|
await assertInputOutputTextNotExists('Berlin');
|
|
await assertInputOutputTextNotExists('Prague');
|
|
|
|
await n8n.ndv.changeOutputRunSelector('2 of 3');
|
|
await assertInputOutputTextExists('Berlin');
|
|
await assertInputOutputTextNotExists('Kyiv');
|
|
await assertInputOutputTextNotExists('Prague');
|
|
|
|
await n8n.ndv.changeOutputRunSelector('1 of 3');
|
|
await assertInputOutputTextExists('Prague');
|
|
await assertInputOutputTextNotExists('Berlin');
|
|
await assertInputOutputTextNotExists('Kyiv');
|
|
|
|
await n8n.ndv.toggleInputRunLinking();
|
|
await n8n.ndv.changeOutputRunSelector('2 of 3');
|
|
await expect(n8n.ndv.getInputRunSelectorInput()).toHaveValue('1 of 3');
|
|
await expect(n8n.ndv.getOutputRunSelectorInput()).toHaveValue('2 of 3');
|
|
await expect(n8n.ndv.getInputPanel()).toContainText('Prague');
|
|
await expect(n8n.ndv.getInputPanel()).not.toContainText('Berlin');
|
|
|
|
await expect(n8n.ndv.getOutputPanel()).toContainText('Berlin');
|
|
await expect(n8n.ndv.getOutputPanel()).not.toContainText('Prague');
|
|
|
|
await n8n.ndv.toggleInputRunLinking();
|
|
await expect(n8n.ndv.getInputRunSelectorInput()).toHaveValue('1 of 3');
|
|
await expect(n8n.ndv.getOutputRunSelectorInput()).toHaveValue('1 of 3');
|
|
await assertInputOutputTextExists('Prague');
|
|
await assertInputOutputTextNotExists('Berlin');
|
|
await assertInputOutputTextNotExists('Kyiv');
|
|
});
|
|
|
|
test('should execute up to Node 1 when using partial execution', async ({ n8n }) => {
|
|
await n8n.start.fromImportedWorkflow('Test_workflow_chat_partial_execution.json');
|
|
await n8n.canvas.clickZoomToFitButton();
|
|
|
|
// Check that chat modal is not initially visible
|
|
await expect(n8n.canvas.getManualChatModal().locator('main')).toBeHidden();
|
|
|
|
// Open Node 1 and execute it
|
|
await n8n.canvas.openNode('Node 1');
|
|
await n8n.ndv.execute();
|
|
// Chat modal should now be visible
|
|
await expect(n8n.canvas.getManualChatModal().locator('main')).toBeVisible();
|
|
|
|
// Send first message
|
|
await n8n.canvas.logsPanel.sendManualChatMessage('Test');
|
|
await expect(n8n.canvas.getManualChatLatestBotMessage()).toContainText('this_my_field_1');
|
|
|
|
// Refresh session
|
|
await n8n.page.getByTestId('refresh-session-button').click();
|
|
await expect(n8n.canvas.getManualChatMessages()).not.toBeAttached();
|
|
|
|
// Send another message
|
|
await n8n.canvas.logsPanel.sendManualChatMessage('Another test');
|
|
await expect(n8n.canvas.getManualChatLatestBotMessage()).toContainText('this_my_field_3');
|
|
await expect(n8n.canvas.getManualChatLatestBotMessage()).toContainText('this_my_field_4');
|
|
});
|
|
});
|
|
});
|