mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
fix(editor): Show test URL when trigger is listening because of a connected node (#18403)
Co-authored-by: Your Name <you@example.com>
This commit is contained in:
@@ -56,6 +56,7 @@ export const mockNode = ({
|
|||||||
|
|
||||||
export const mockNodeTypeDescription = ({
|
export const mockNodeTypeDescription = ({
|
||||||
name = SET_NODE_TYPE,
|
name = SET_NODE_TYPE,
|
||||||
|
displayName = name,
|
||||||
icon = 'fa:pen',
|
icon = 'fa:pen',
|
||||||
version = 1,
|
version = 1,
|
||||||
credentials = [],
|
credentials = [],
|
||||||
@@ -66,8 +67,10 @@ export const mockNodeTypeDescription = ({
|
|||||||
group,
|
group,
|
||||||
hidden,
|
hidden,
|
||||||
description,
|
description,
|
||||||
|
webhooks,
|
||||||
}: {
|
}: {
|
||||||
name?: INodeTypeDescription['name'];
|
name?: INodeTypeDescription['name'];
|
||||||
|
displayName?: INodeTypeDescription['displayName'];
|
||||||
icon?: INodeTypeDescription['icon'];
|
icon?: INodeTypeDescription['icon'];
|
||||||
version?: INodeTypeDescription['version'];
|
version?: INodeTypeDescription['version'];
|
||||||
credentials?: INodeTypeDescription['credentials'];
|
credentials?: INodeTypeDescription['credentials'];
|
||||||
@@ -78,11 +81,12 @@ export const mockNodeTypeDescription = ({
|
|||||||
group?: INodeTypeDescription['group'];
|
group?: INodeTypeDescription['group'];
|
||||||
hidden?: INodeTypeDescription['hidden'];
|
hidden?: INodeTypeDescription['hidden'];
|
||||||
description?: INodeTypeDescription['description'];
|
description?: INodeTypeDescription['description'];
|
||||||
|
webhooks?: INodeTypeDescription['webhooks'];
|
||||||
} = {}) =>
|
} = {}) =>
|
||||||
mock<INodeTypeDescription>({
|
mock<INodeTypeDescription>({
|
||||||
name,
|
name,
|
||||||
icon,
|
icon,
|
||||||
displayName: name,
|
displayName,
|
||||||
description: description ?? '',
|
description: description ?? '',
|
||||||
version,
|
version,
|
||||||
defaults: {
|
defaults: {
|
||||||
@@ -98,7 +102,7 @@ export const mockNodeTypeDescription = ({
|
|||||||
credentials,
|
credentials,
|
||||||
documentationUrl: 'https://docs',
|
documentationUrl: 'https://docs',
|
||||||
iconUrl: 'nodes/test-node/icon.svg',
|
iconUrl: 'nodes/test-node/icon.svg',
|
||||||
webhooks: undefined,
|
webhooks,
|
||||||
parameterPane: undefined,
|
parameterPane: undefined,
|
||||||
hidden,
|
hidden,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { renderComponent } from '@/__tests__/render';
|
||||||
|
import { mockedStore, type MockedStore } from '@/__tests__/utils';
|
||||||
|
import TriggerPanel from './TriggerPanel.vue';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
|
import { createTestNode, mockNodeTypeDescription } from '../__tests__/mocks';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
|
import { setActivePinia } from 'pinia';
|
||||||
|
|
||||||
|
let workflowsStore: MockedStore<typeof useWorkflowsStore>;
|
||||||
|
let nodeTypesStore: MockedStore<typeof useNodeTypesStore>;
|
||||||
|
|
||||||
|
describe('TriggerPanel.vue', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
setActivePinia(createTestingPinia());
|
||||||
|
workflowsStore = mockedStore(useWorkflowsStore);
|
||||||
|
workflowsStore.workflowName = 'Test Workflow';
|
||||||
|
workflowsStore.workflowId = '1';
|
||||||
|
const node = createTestNode({ id: '0', name: 'Webhook', type: 'n8n-nodes-base.webhook' });
|
||||||
|
workflowsStore.getNodeByName.mockReturnValue(node);
|
||||||
|
nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||||
|
const nodeTypeDescription = mockNodeTypeDescription({
|
||||||
|
name: 'n8n-nodes-base.webhook',
|
||||||
|
displayName: 'Webhook',
|
||||||
|
webhooks: [{ name: 'default', httpMethod: 'POST', path: 'webhook' }],
|
||||||
|
});
|
||||||
|
nodeTypesStore.getNodeType = vi.fn(() => nodeTypeDescription);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders default state', () => {
|
||||||
|
const { getByTestId } = renderComponent(TriggerPanel, {
|
||||||
|
props: { nodeName: 'Webhook' },
|
||||||
|
});
|
||||||
|
expect(getByTestId('trigger-header')).toBeInTheDocument();
|
||||||
|
expect(getByTestId('trigger-header')).toHaveTextContent('Pull in events from Webhook');
|
||||||
|
expect(getByTestId('trigger-execute-button')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders listening state for webhook node', () => {
|
||||||
|
workflowsStore.executionWaitingForWebhook = true;
|
||||||
|
workflowsStore.executedNode = 'Webhook';
|
||||||
|
const { getByTestId } = renderComponent(TriggerPanel, {
|
||||||
|
props: { nodeName: 'Webhook' },
|
||||||
|
});
|
||||||
|
expect(getByTestId('trigger-listening')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render listening state for other nodes', () => {
|
||||||
|
workflowsStore.executionWaitingForWebhook = true;
|
||||||
|
workflowsStore.executedNode = 'OtherNode';
|
||||||
|
const { queryByTestId } = renderComponent(TriggerPanel, {
|
||||||
|
props: { nodeName: 'Webhook' },
|
||||||
|
});
|
||||||
|
expect(queryByTestId('trigger-listening')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders listening state when executedNode is a child of the current node', () => {
|
||||||
|
workflowsStore.executionWaitingForWebhook = true;
|
||||||
|
workflowsStore.executedNode = 'ChildNode';
|
||||||
|
workflowsStore.workflowObject.getParentNodes = vi.fn(() => ['Webhook']);
|
||||||
|
const { getByTestId } = renderComponent(TriggerPanel, {
|
||||||
|
props: { nodeName: 'Webhook' },
|
||||||
|
});
|
||||||
|
expect(getByTestId('trigger-listening')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render listening state when executedNode is not a child or current node', () => {
|
||||||
|
workflowsStore.executionWaitingForWebhook = true;
|
||||||
|
workflowsStore.executedNode = 'UnrelatedNode';
|
||||||
|
workflowsStore.workflowObject.getParentNodes = vi.fn(() => []);
|
||||||
|
const { queryByTestId } = renderComponent(TriggerPanel, {
|
||||||
|
props: { nodeName: 'Webhook' },
|
||||||
|
});
|
||||||
|
expect(queryByTestId('trigger-listening')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -154,15 +154,21 @@ const isPollingNode = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const isListeningForEvents = computed(() => {
|
const isListeningForEvents = computed(() => {
|
||||||
const waitingOnWebhook = workflowsStore.executionWaitingForWebhook;
|
if (!node.value || node.value.disabled || !isWebhookBasedNode.value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workflowsStore.executionWaitingForWebhook) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const executedNode = workflowsStore.executedNode;
|
const executedNode = workflowsStore.executedNode;
|
||||||
return (
|
const isCurrentNodeExecuted = executedNode === props.nodeName;
|
||||||
!!node.value &&
|
const isChildNodeExecuted = executedNode
|
||||||
!node.value.disabled &&
|
? workflowsStore.workflowObject.getParentNodes(executedNode).includes(props.nodeName)
|
||||||
isWebhookBasedNode.value &&
|
: false;
|
||||||
waitingOnWebhook &&
|
|
||||||
(!executedNode || executedNode === props.nodeName)
|
return !executedNode || isCurrentNodeExecuted || isChildNodeExecuted;
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const workflowRunning = computed(() => workflowsStore.isWorkflowRunning);
|
const workflowRunning = computed(() => workflowsStore.isWorkflowRunning);
|
||||||
@@ -370,7 +376,7 @@ const onNodeExecute = () => {
|
|||||||
<div :class="$style.container">
|
<div :class="$style.container">
|
||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
<div v-if="hasIssues || hideContent" key="empty"></div>
|
<div v-if="hasIssues || hideContent" key="empty"></div>
|
||||||
<div v-else-if="isListeningForEvents" key="listening">
|
<div v-else-if="isListeningForEvents" key="listening" data-test-id="trigger-listening">
|
||||||
<n8n-pulse>
|
<n8n-pulse>
|
||||||
<NodeIcon :node-type="nodeType" :size="40"></NodeIcon>
|
<NodeIcon :node-type="nodeType" :size="40"></NodeIcon>
|
||||||
</n8n-pulse>
|
</n8n-pulse>
|
||||||
@@ -434,7 +440,7 @@ const onNodeExecute = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="$style.action">
|
<div :class="$style.action">
|
||||||
<div :class="$style.header">
|
<div data-test-id="trigger-header" :class="$style.header">
|
||||||
<n8n-heading v-if="header" tag="h1" bold>
|
<n8n-heading v-if="header" tag="h1" bold>
|
||||||
{{ header }}
|
{{ header }}
|
||||||
</n8n-heading>
|
</n8n-heading>
|
||||||
|
|||||||
Reference in New Issue
Block a user