fix(editor): Don't show 'Test workflow' button if the canvas is read-only (#13199)

This commit is contained in:
autologie 2025-02-12 11:26:22 +01:00 committed by GitHub
parent 77be25d337
commit 56426e989f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 71 additions and 39 deletions

View file

@ -3,7 +3,8 @@ import { createComponentRenderer } from '@/__tests__/render';
import { createPinia, setActivePinia } from 'pinia'; import { createPinia, setActivePinia } from 'pinia';
import { NodeConnectionType } from 'n8n-workflow'; import { NodeConnectionType } from 'n8n-workflow';
import { fireEvent } from '@testing-library/vue'; import { fireEvent } from '@testing-library/vue';
import { createCanvasNodeProps, createCanvasProvide } from '@/__tests__/data'; import { createCanvasNodeData, createCanvasNodeProps, createCanvasProvide } from '@/__tests__/data';
import { CanvasNodeRenderType } from '@/types';
vi.mock('@/stores/nodeTypes.store', () => ({ vi.mock('@/stores/nodeTypes.store', () => ({
useNodeTypesStore: vi.fn(() => ({ useNodeTypesStore: vi.fn(() => ({
@ -150,4 +151,30 @@ describe('CanvasNode', () => {
expect(getByTestId('overflow-node-button')).toBeInTheDocument(); expect(getByTestId('overflow-node-button')).toBeInTheDocument();
}); });
}); });
describe('execute workflow button', () => {
const triggerNodeData = createCanvasNodeData({
name: 'foo',
render: {
type: CanvasNodeRenderType.Default,
options: { trigger: true },
},
});
it('should render execute workflow button if the node is a trigger node and is not read only', () => {
const { queryByTestId } = renderComponent({
props: createCanvasNodeProps({ readOnly: false, data: triggerNodeData }),
});
expect(queryByTestId('execute-workflow-button-foo')).toBeInTheDocument();
});
it('should not render execute workflow button if the node is a trigger node and is read only', () => {
const { queryByTestId } = renderComponent({
props: createCanvasNodeProps({ readOnly: true, data: triggerNodeData }),
});
expect(queryByTestId('execute-workflow-button-foo')).not.toBeInTheDocument();
});
});
}); });

View file

@ -417,6 +417,7 @@ onBeforeUnmount(() => {
:type="data.type" :type="data.type"
:hovered="nearbyHovered" :hovered="nearbyHovered"
:disabled="isDisabled" :disabled="isDisabled"
:read-only="readOnly"
:class="$style.trigger" :class="$style.trigger"
/> />
</div> </div>

View file

@ -14,12 +14,14 @@ const {
type, type,
hovered, hovered,
disabled, disabled,
readOnly,
class: cls, class: cls,
} = defineProps<{ } = defineProps<{
name: string; name: string;
type: string; type: string;
hovered?: boolean; hovered?: boolean;
disabled?: boolean; disabled?: boolean;
readOnly?: boolean;
class?: string; class?: string;
}>(); }>();
@ -29,7 +31,7 @@ const style = useCssModule();
const containerClass = computed(() => ({ const containerClass = computed(() => ({
[cls ?? '']: true, [cls ?? '']: true,
[style.container]: true, [style.container]: true,
[style.interactive]: !disabled, [style.interactive]: !disabled && !readOnly,
[style.hovered]: !!hovered, [style.hovered]: !!hovered,
[style.variant1]: variant.value === 1, [style.variant1]: variant.value === 1,
[style.variant2]: variant.value === 2, [style.variant2]: variant.value === 2,
@ -55,6 +57,7 @@ const testId = computed(() => `execute-workflow-button-${name}`);
<FontAwesomeIcon icon="bolt" size="lg" /> <FontAwesomeIcon icon="bolt" size="lg" />
</div> </div>
<template v-if="!readOnly">
<N8nButton <N8nButton
v-if="variant === 1 && type === CHAT_TRIGGER_NODE_TYPE" v-if="variant === 1 && type === CHAT_TRIGGER_NODE_TYPE"
type="secondary" type="secondary"
@ -91,6 +94,7 @@ const testId = computed(() => `execute-workflow-button-${name}`);
:label="i18n.baseText('nodeView.runButtonText.executeWorkflow')" :label="i18n.baseText('nodeView.runButtonText.executeWorkflow')"
@click.capture="runEntireWorkflow('node', name)" @click.capture="runEntireWorkflow('node', name)"
/> />
</template>
</div> </div>
</div> </div>
</template> </template>
@ -112,7 +116,7 @@ const testId = computed(() => `execute-workflow-button-${name}`);
align-items: center; align-items: center;
} }
&.hovered button { &.interactive.hovered button {
pointer-events: all; pointer-events: all;
} }
} }