- 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.
105 lines
3.2 KiB
TypeScript
105 lines
3.2 KiB
TypeScript
import React, { act } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const mockStore = vi.hoisted(() => {
|
|
const state = {
|
|
messagesPanelMode: 'inline' as 'sidebar' | 'inline' | 'bottom-sheet',
|
|
setMessagesPanelMode: vi.fn((mode: 'sidebar' | 'inline' | 'bottom-sheet') => {
|
|
state.messagesPanelMode = mode;
|
|
}),
|
|
};
|
|
|
|
return { state };
|
|
});
|
|
|
|
vi.mock('@renderer/store', () => ({
|
|
useStore: (selector: (state: typeof mockStore.state) => unknown) => selector(mockStore.state),
|
|
}));
|
|
|
|
import { useGraphSidebarVisibility } from '@features/agent-graph/renderer/hooks/useGraphSidebarVisibility';
|
|
|
|
function HookProbe(): React.JSX.Element {
|
|
const { sidebarVisible, toggleSidebarVisible } = useGraphSidebarVisibility();
|
|
|
|
return React.createElement(
|
|
'button',
|
|
{
|
|
type: 'button',
|
|
onClick: toggleSidebarVisible,
|
|
'data-visible': sidebarVisible ? 'true' : 'false',
|
|
},
|
|
sidebarVisible ? 'visible' : 'hidden'
|
|
);
|
|
}
|
|
|
|
describe('useGraphSidebarVisibility', () => {
|
|
beforeEach(() => {
|
|
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
|
mockStore.state.messagesPanelMode = 'inline';
|
|
mockStore.state.setMessagesPanelMode.mockClear();
|
|
window.localStorage.clear();
|
|
});
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = '';
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it('forces sidebar mode on open when the messages panel is not currently in sidebar mode', async () => {
|
|
window.localStorage.setItem('team-graph-sidebar-visible', 'false');
|
|
const host = document.createElement('div');
|
|
document.body.appendChild(host);
|
|
const root = createRoot(host);
|
|
|
|
await act(async () => {
|
|
root.render(React.createElement(HookProbe));
|
|
await Promise.resolve();
|
|
});
|
|
|
|
const button = host.querySelector('button');
|
|
expect(button?.getAttribute('data-visible')).toBe('false');
|
|
|
|
await act(async () => {
|
|
button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
await Promise.resolve();
|
|
});
|
|
|
|
expect(mockStore.state.setMessagesPanelMode).toHaveBeenCalledWith('sidebar');
|
|
expect(button?.getAttribute('data-visible')).toBe('true');
|
|
|
|
await act(async () => {
|
|
root.unmount();
|
|
await Promise.resolve();
|
|
});
|
|
});
|
|
|
|
it('hides the graph sidebar locally without changing the global messages panel mode', async () => {
|
|
mockStore.state.messagesPanelMode = 'sidebar';
|
|
window.localStorage.setItem('team-graph-sidebar-visible', 'true');
|
|
const host = document.createElement('div');
|
|
document.body.appendChild(host);
|
|
const root = createRoot(host);
|
|
|
|
await act(async () => {
|
|
root.render(React.createElement(HookProbe));
|
|
await Promise.resolve();
|
|
});
|
|
|
|
const button = host.querySelector('button');
|
|
expect(button?.getAttribute('data-visible')).toBe('true');
|
|
|
|
await act(async () => {
|
|
button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
await Promise.resolve();
|
|
});
|
|
|
|
expect(mockStore.state.setMessagesPanelMode).not.toHaveBeenCalled();
|
|
expect(button?.getAttribute('data-visible')).toBe('false');
|
|
|
|
await act(async () => {
|
|
root.unmount();
|
|
await Promise.resolve();
|
|
});
|
|
});
|
|
});
|