fix(editor): Clear selection box when collapsing a node group (no-changelog) (#32396)

This commit is contained in:
Daria 2026-06-18 12:17:04 +03:00 committed by GitHub
parent 79746fc502
commit 220ff49ab5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 2 deletions

View File

@ -28,6 +28,7 @@ import { canvasEventBus } from '@/features/workflows/canvas/canvas.eventBus';
import { createEventBus } from '@n8n/utils/event-bus';
import { usePostHog } from '@/app/stores/posthog.store';
import { GROUP_PADDING_Y_BOTTOM, GROUP_PADDING_Y_TOP } from '../stores/canvasNodeGroups.constants';
import { NodeGroupViewKey, type CanvasNodeGroupView } from '../composables/useCanvasNodeGroupView';
let workflowDocumentStore: ReturnType<typeof useWorkflowDocumentStore>;
@ -224,6 +225,49 @@ describe('Canvas', () => {
);
});
it('should clear selected members when their group is collapsed', async () => {
vi.spyOn(usePostHog(), 'isFeatureEnabled').mockImplementation(
(name) => name === CANVAS_NODES_GROUPING_EXPERIMENT.name,
);
vi.spyOn(workflowDocumentStore, 'getGroupById').mockReturnValue({
id: 'g1',
name: 'Group 1',
nodeIds: ['node-1'],
});
let collapsed = false;
const nodeGroupView = {
isGroupCollapsed: () => collapsed,
toggleCollapsed: () => {
collapsed = !collapsed;
},
getVisualOffsetForNode: () => ({ x: 0, y: 0 }),
getVisualOffsetForComponent: () => ({ x: 0, y: 0 }),
syncLayoutComponents: () => {},
settleManualNodePositions: (events: unknown) => events,
commitMovedPushSourceEffects: () => [],
} as unknown as CanvasNodeGroupView;
const node = createCanvasNodeElement({ id: 'node-1' });
const groupNode = createCanvasGroupNode({ selectable: true });
const eventBus = createEventBus<CanvasEventBusEvents>();
const { container, getByTestId } = renderComponent({
props: { nodes: [node, groupNode], eventBus },
global: { provide: { [NodeGroupViewKey as symbol]: nodeGroupView } },
});
await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(2));
const { getSelectedNodes } = useVueFlow(canvasId);
eventBus.emit('nodes:selectAll');
await waitFor(() => expect(getSelectedNodes.value.map(({ id }) => id)).toContain('node-1'));
await fireEvent.click(getByTestId('canvas-node-group-toggle'));
await waitFor(() => expect(getSelectedNodes.value.map(({ id }) => id)).not.toContain('node-1'));
});
it('should expand a selected collapsed group to its members when copying', async () => {
vi.spyOn(usePostHog(), 'isFeatureEnabled').mockImplementation(
(name) => name === CANVAS_NODES_GROUPING_EXPERIMENT.name,

View File

@ -618,8 +618,19 @@ function onSelectionDrag(event: NodeDragEvent) {
function onCanvasGroupToggle(groupId: string) {
injectedNodeGroupView?.toggleCollapsed(groupId);
// Expanding makes the title bar non-selectable, so drop any selection lingering on it.
if (injectedNodeGroupView && !injectedNodeGroupView.isGroupCollapsed(groupId)) {
if (!injectedNodeGroupView) return;
if (injectedNodeGroupView.isGroupCollapsed(groupId)) {
// Collapsing hides the members, so drop them from the selection to clear the lingering box.
const memberNodeIds = workflowDocumentStore.value.getGroupById(groupId)?.nodeIds ?? [];
const selectedMembers = memberNodeIds
.map((nodeId) => findNode(nodeId))
.filter((node): node is NonNullable<typeof node> => node?.selected ?? false);
if (selectedMembers.length > 0) {
removeSelectedNodes(selectedMembers);
}
} else {
// Expanding makes the title bar non-selectable, so drop any selection lingering on it.
const groupNode = findNode(`${CANVAS_NODE_GROUP_ID_PREFIX}${groupId}`);
if (groupNode) {
removeSelectedNodes([groupNode]);