mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
fix: Prevent chat modal opening on 'Test workflow' click (#9009)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> Co-authored-by: Oleg Ivaniv <me@olegivaniv.com>
This commit is contained in:
parent
bead7eb840
commit
3fd97e4c72
|
@ -48,6 +48,12 @@ export function getNodeByName(name: string) {
|
|||
return cy.getByTestId('canvas-node').filter(`[data-name="${name}"]`).eq(0);
|
||||
}
|
||||
|
||||
export function disableNode(name: string) {
|
||||
const target = getNodeByName(name);
|
||||
target.rightclick(name ? 'center' : 'topLeft', { force: true });
|
||||
cy.getByTestId(`context-menu-item-toggle_activation`).click();
|
||||
}
|
||||
|
||||
export function getConnectionBySourceAndTarget(source: string, target: string) {
|
||||
return cy
|
||||
.get('.jtk-connector')
|
||||
|
@ -110,14 +116,20 @@ export function addSupplementalNodeToParent(
|
|||
) {
|
||||
getAddInputEndpointByType(parentNodeName, endpointType).click({ force: true });
|
||||
if (exactMatch) {
|
||||
getNodeCreatorItems().contains(new RegExp("^" + nodeName + "$", "g")).click();
|
||||
getNodeCreatorItems()
|
||||
.contains(new RegExp('^' + nodeName + '$', 'g'))
|
||||
.click();
|
||||
} else {
|
||||
getNodeCreatorItems().contains(nodeName).click();
|
||||
}
|
||||
getConnectionBySourceAndTarget(parentNodeName, nodeName).should('exist');
|
||||
}
|
||||
|
||||
export function addLanguageModelNodeToParent(nodeName: string, parentNodeName: string, exactMatch = false) {
|
||||
export function addLanguageModelNodeToParent(
|
||||
nodeName: string,
|
||||
parentNodeName: string,
|
||||
exactMatch = false,
|
||||
) {
|
||||
addSupplementalNodeToParent(nodeName, 'ai_languageModel', parentNodeName, exactMatch);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
AI_TOOL_CODE_NODE_NAME,
|
||||
AI_TOOL_WIKIPEDIA_NODE_NAME,
|
||||
BASIC_LLM_CHAIN_NODE_NAME,
|
||||
EDIT_FIELDS_SET_NODE_NAME,
|
||||
} from './../constants';
|
||||
import { createMockNodeExecutionData, runMockWorkflowExcution } from '../utils';
|
||||
import {
|
||||
|
@ -17,7 +18,10 @@ import {
|
|||
addNodeToCanvas,
|
||||
addOutputParserNodeToParent,
|
||||
addToolNodeToParent,
|
||||
clickExecuteWorkflowButton,
|
||||
clickManualChatButton,
|
||||
disableNode,
|
||||
getExecuteWorkflowButton,
|
||||
navigateToNewWorkflowPage,
|
||||
openNode,
|
||||
} from '../composables/workflow';
|
||||
|
@ -32,6 +36,7 @@ import {
|
|||
closeManualChatModal,
|
||||
getManualChatDialog,
|
||||
getManualChatMessages,
|
||||
getManualChatModal,
|
||||
getManualChatModalLogs,
|
||||
getManualChatModalLogsEntries,
|
||||
getManualChatModalLogsTree,
|
||||
|
@ -43,13 +48,58 @@ describe('Langchain Integration', () => {
|
|||
navigateToNewWorkflowPage();
|
||||
});
|
||||
|
||||
it('should not open chat modal', () => {
|
||||
addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME, true);
|
||||
addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true);
|
||||
|
||||
clickGetBackToCanvas();
|
||||
|
||||
addNodeToCanvas(AGENT_NODE_NAME, true, true);
|
||||
clickGetBackToCanvas();
|
||||
|
||||
addLanguageModelNodeToParent(
|
||||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
||||
AGENT_NODE_NAME,
|
||||
true,
|
||||
);
|
||||
clickGetBackToCanvas();
|
||||
|
||||
clickExecuteWorkflowButton();
|
||||
getManualChatModal().should('not.exist');
|
||||
});
|
||||
|
||||
it('should disable test workflow button', () => {
|
||||
addNodeToCanvas('Schedule Trigger', true);
|
||||
addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true);
|
||||
|
||||
clickGetBackToCanvas();
|
||||
|
||||
addNodeToCanvas(AGENT_NODE_NAME, true, true);
|
||||
clickGetBackToCanvas();
|
||||
|
||||
addLanguageModelNodeToParent(
|
||||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
||||
AGENT_NODE_NAME,
|
||||
true,
|
||||
);
|
||||
clickGetBackToCanvas();
|
||||
|
||||
disableNode('Schedule Trigger');
|
||||
|
||||
getExecuteWorkflowButton().should('be.disabled');
|
||||
});
|
||||
|
||||
it('should add nodes to all Agent node input types', () => {
|
||||
addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME, true);
|
||||
addNodeToCanvas(AGENT_NODE_NAME, true, true);
|
||||
toggleParameterCheckboxInputByName('hasOutputParser');
|
||||
clickGetBackToCanvas();
|
||||
|
||||
addLanguageModelNodeToParent(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, AGENT_NODE_NAME, true);
|
||||
addLanguageModelNodeToParent(
|
||||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
||||
AGENT_NODE_NAME,
|
||||
true,
|
||||
);
|
||||
clickGetBackToCanvas();
|
||||
|
||||
addMemoryNodeToParent(AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME, AGENT_NODE_NAME);
|
||||
|
@ -85,7 +135,7 @@ describe('Langchain Integration', () => {
|
|||
addLanguageModelNodeToParent(
|
||||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
||||
BASIC_LLM_CHAIN_NODE_NAME,
|
||||
true
|
||||
true,
|
||||
);
|
||||
|
||||
clickCreateNewCredential();
|
||||
|
@ -98,7 +148,7 @@ describe('Langchain Integration', () => {
|
|||
const inputMessage = 'Hello!';
|
||||
const outputMessage = 'Hi there! How can I assist you today?';
|
||||
|
||||
clickExecuteNode()
|
||||
clickExecuteNode();
|
||||
runMockWorkflowExcution({
|
||||
trigger: () => sendManualChatMessage(inputMessage),
|
||||
runData: [
|
||||
|
@ -121,7 +171,11 @@ describe('Langchain Integration', () => {
|
|||
addNodeToCanvas(MANUAL_CHAT_TRIGGER_NODE_NAME, true);
|
||||
addNodeToCanvas(AGENT_NODE_NAME, true);
|
||||
|
||||
addLanguageModelNodeToParent(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, AGENT_NODE_NAME, true);
|
||||
addLanguageModelNodeToParent(
|
||||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
||||
AGENT_NODE_NAME,
|
||||
true,
|
||||
);
|
||||
|
||||
clickCreateNewCredential();
|
||||
setCredentialValues({
|
||||
|
@ -134,7 +188,7 @@ describe('Langchain Integration', () => {
|
|||
const inputMessage = 'Hello!';
|
||||
const outputMessage = 'Hi there! How can I assist you today?';
|
||||
|
||||
clickExecuteNode()
|
||||
clickExecuteNode();
|
||||
runMockWorkflowExcution({
|
||||
trigger: () => sendManualChatMessage(inputMessage),
|
||||
runData: [
|
||||
|
@ -157,7 +211,11 @@ describe('Langchain Integration', () => {
|
|||
addNodeToCanvas(MANUAL_CHAT_TRIGGER_NODE_NAME, true);
|
||||
addNodeToCanvas(AGENT_NODE_NAME, true);
|
||||
|
||||
addLanguageModelNodeToParent(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, AGENT_NODE_NAME, true);
|
||||
addLanguageModelNodeToParent(
|
||||
AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME,
|
||||
AGENT_NODE_NAME,
|
||||
true,
|
||||
);
|
||||
|
||||
clickCreateNewCredential();
|
||||
setCredentialValues({
|
||||
|
|
|
@ -247,6 +247,33 @@ export function useRunWorkflow(options: { router: ReturnType<typeof useRouter> }
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if no destination node is specified
|
||||
//and execution is not triggered from chat
|
||||
//and there are other triggers in the workflow
|
||||
//disable chat trigger node to avoid modal opening and webhook creation
|
||||
if (
|
||||
!options.destinationNode &&
|
||||
options.source !== 'RunData.ManualChatMessage' &&
|
||||
workflowData.nodes.some((node) => node.type === CHAT_TRIGGER_NODE_TYPE)
|
||||
) {
|
||||
const otherTriggers = workflowData.nodes.filter(
|
||||
(node) =>
|
||||
node.type !== CHAT_TRIGGER_NODE_TYPE &&
|
||||
node.type.toLowerCase().includes('trigger') &&
|
||||
!node.disabled,
|
||||
);
|
||||
|
||||
if (otherTriggers.length) {
|
||||
const chatTriggerNode = workflowData.nodes.find(
|
||||
(node) => node.type === CHAT_TRIGGER_NODE_TYPE,
|
||||
);
|
||||
if (chatTriggerNode) {
|
||||
chatTriggerNode.disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const startNodes: StartNodeData[] = startNodeNames.map((name) => {
|
||||
// Find for each start node the source data
|
||||
let sourceData = get(runData, [name, 0, 'source', 0], null);
|
||||
|
|
|
@ -728,6 +728,12 @@ export default defineComponent({
|
|||
return this.containsChatNodes && this.triggerNodes.length === 1;
|
||||
},
|
||||
isExecutionDisabled(): boolean {
|
||||
if (
|
||||
this.containsChatNodes &&
|
||||
this.triggerNodes.every((node) => node.disabled || node.type === CHAT_TRIGGER_NODE_TYPE)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return !this.containsTrigger || this.allTriggersDisabled;
|
||||
},
|
||||
getNodeViewOffsetPosition(): XYPosition {
|
||||
|
|
Loading…
Reference in a new issue