agent-ecosystem/test/renderer/features/agent-graph/GraphControls.test.ts
777genius aed08113e6 feat(agent-graph): integrate stable slot layout for improved node positioning and interaction
- Added stable slot layout support in various components, enhancing the layout and interaction of nodes.
- Updated TypeScript configuration to include new paths for the agent-graph package.
- Refactored layout logic in activity lanes and kanban to accommodate stable slot assignments.
- Enhanced GraphView and GraphControls to support sidebar visibility toggling and owner slot drop handling.
- Introduced new types for layout management in GraphDataPort and related files.
- Updated README to include stable slot layout documentation.
2026-04-15 16:18:11 +03:00

115 lines
3.5 KiB
TypeScript

import React, { act } from 'react';
import { createRoot } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
vi.mock('@radix-ui/react-tooltip', () => ({
Root: ({ children }: { children: React.ReactNode }) =>
React.createElement(React.Fragment, null, children),
Trigger: ({ children }: { children: React.ReactNode }) =>
React.createElement(React.Fragment, null, children),
Portal: ({ children }: { children: React.ReactNode }) =>
React.createElement(React.Fragment, null, children),
Content: ({ children }: { children: React.ReactNode }) =>
React.createElement('div', { 'data-testid': 'tooltip-content' }, children),
Arrow: () => null,
}));
import { GraphControls } from '../../../../packages/agent-graph/src/ui/GraphControls';
describe('GraphControls', () => {
beforeEach(() => {
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
});
afterEach(() => {
document.body.innerHTML = '';
vi.unstubAllGlobals();
});
it('renders the sidebar toggle before the team and task buttons and triggers the callback', async () => {
const host = document.createElement('div');
document.body.appendChild(host);
const root = createRoot(host);
const onToggleSidebar = vi.fn();
await act(async () => {
root.render(
React.createElement(GraphControls, {
filters: {
showTasks: true,
showProcesses: true,
showEdges: true,
paused: false,
},
onFiltersChange: vi.fn(),
onZoomIn: vi.fn(),
onZoomOut: vi.fn(),
onZoomToFit: vi.fn(),
onToggleSidebar,
isSidebarVisible: true,
onOpenTeamPage: vi.fn(),
onCreateTask: vi.fn(),
teamName: 'demo-team',
})
);
await Promise.resolve();
});
const labels = Array.from(host.querySelectorAll('button[aria-label]')).map((button) =>
button.getAttribute('aria-label')
);
expect(labels.indexOf('Hide sidebar')).toBeGreaterThanOrEqual(0);
expect(labels.indexOf('Open team page')).toBeGreaterThan(labels.indexOf('Hide sidebar'));
expect(labels.indexOf('Create task')).toBeGreaterThan(labels.indexOf('Open team page'));
const toggleButton = host.querySelector('button[aria-label="Hide sidebar"]');
expect(toggleButton).not.toBeNull();
await act(async () => {
toggleButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await Promise.resolve();
});
expect(onToggleSidebar).toHaveBeenCalledTimes(1);
await act(async () => {
root.unmount();
await Promise.resolve();
});
});
it('shows the open-sidebar label when the sidebar is hidden', async () => {
const host = document.createElement('div');
document.body.appendChild(host);
const root = createRoot(host);
await act(async () => {
root.render(
React.createElement(GraphControls, {
filters: {
showTasks: true,
showProcesses: true,
showEdges: true,
paused: false,
},
onFiltersChange: vi.fn(),
onZoomIn: vi.fn(),
onZoomOut: vi.fn(),
onZoomToFit: vi.fn(),
onToggleSidebar: vi.fn(),
isSidebarVisible: false,
teamName: 'demo-team',
})
);
await Promise.resolve();
});
expect(host.querySelector('button[aria-label="Show sidebar"]')).not.toBeNull();
await act(async () => {
root.unmount();
await Promise.resolve();
});
});
});