mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
- Updated QueueCard tests to use getAllByText for better resilience against multiple occurrences. - Modified useCodexLens tests to check for error existence instead of specific message. - Added mock for ResizeObserver in test setup to support components using it. - Introduced integration tests for appStore and hooks interactions, covering locale and theme flows. - Created layout-utils tests to validate pane manipulation functions. - Added queryKeys tests to ensure correct key generation for workspace queries. - Implemented utils tests for class name merging and memory metadata parsing.
294 lines
8.8 KiB
TypeScript
294 lines
8.8 KiB
TypeScript
// ========================================
|
|
// Layout Utilities Tests
|
|
// ========================================
|
|
// Tests for Allotment layout tree manipulation functions
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
isPaneId,
|
|
findPaneInLayout,
|
|
removePaneFromLayout,
|
|
addPaneToLayout,
|
|
getAllPaneIds,
|
|
} from './layout-utils';
|
|
import type { AllotmentLayoutGroup, PaneId } from '@/stores/viewerStore';
|
|
|
|
describe('layout-utils', () => {
|
|
// Helper to create test layouts
|
|
const createSimpleLayout = (): AllotmentLayoutGroup => ({
|
|
direction: 'horizontal',
|
|
children: ['pane-1', 'pane-2', 'pane-3'],
|
|
sizes: [33, 33, 34],
|
|
});
|
|
|
|
const createNestedLayout = (): AllotmentLayoutGroup => ({
|
|
direction: 'horizontal',
|
|
children: [
|
|
'pane-1',
|
|
{
|
|
direction: 'vertical',
|
|
children: ['pane-2', 'pane-3'],
|
|
sizes: [50, 50],
|
|
},
|
|
'pane-4',
|
|
],
|
|
sizes: [25, 50, 25],
|
|
});
|
|
|
|
describe('isPaneId', () => {
|
|
it('should return true for string values (PaneId)', () => {
|
|
expect(isPaneId('pane-1')).toBe(true);
|
|
expect(isPaneId('any-string')).toBe(true);
|
|
});
|
|
|
|
it('should return false for group objects', () => {
|
|
const group: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: ['pane-1'],
|
|
};
|
|
expect(isPaneId(group)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('findPaneInLayout', () => {
|
|
it('should find existing pane in simple layout', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = findPaneInLayout(layout, 'pane-2');
|
|
|
|
expect(result.found).toBe(true);
|
|
expect(result.index).toBe(1);
|
|
expect(result.parent).toBe(layout);
|
|
});
|
|
|
|
it('should return not found for non-existing pane', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = findPaneInLayout(layout, 'non-existing');
|
|
|
|
expect(result.found).toBe(false);
|
|
expect(result.index).toBe(-1);
|
|
expect(result.parent).toBeNull();
|
|
});
|
|
|
|
it('should find pane in nested layout', () => {
|
|
const layout = createNestedLayout();
|
|
const result = findPaneInLayout(layout, 'pane-3');
|
|
|
|
expect(result.found).toBe(true);
|
|
expect(result.index).toBe(1);
|
|
expect(result.parent).toEqual({
|
|
direction: 'vertical',
|
|
children: ['pane-2', 'pane-3'],
|
|
sizes: [50, 50],
|
|
});
|
|
});
|
|
|
|
it('should find pane at root level in nested layout', () => {
|
|
const layout = createNestedLayout();
|
|
const result = findPaneInLayout(layout, 'pane-1');
|
|
|
|
expect(result.found).toBe(true);
|
|
expect(result.index).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('removePaneFromLayout', () => {
|
|
it('should remove pane from simple layout', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = removePaneFromLayout(layout, 'pane-2');
|
|
|
|
expect(result.children).toEqual(['pane-1', 'pane-3']);
|
|
expect(result.children).toHaveLength(2);
|
|
});
|
|
|
|
it('should update sizes after removal', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = removePaneFromLayout(layout, 'pane-2');
|
|
|
|
expect(result.sizes).toBeDefined();
|
|
expect(result.sizes?.length).toBe(2);
|
|
// Sizes should be normalized to sum ~100
|
|
const sum = result.sizes?.reduce((a, b) => a + b, 0) ?? 0;
|
|
expect(Math.round(sum)).toBeCloseTo(100, 0);
|
|
});
|
|
|
|
it('should handle removal from empty layout', () => {
|
|
const layout: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: [],
|
|
};
|
|
const result = removePaneFromLayout(layout, 'pane-1');
|
|
|
|
expect(result.children).toEqual([]);
|
|
});
|
|
|
|
it('should remove pane from nested layout', () => {
|
|
const layout = createNestedLayout();
|
|
const result = removePaneFromLayout(layout, 'pane-3');
|
|
|
|
const allPanes = getAllPaneIds(result);
|
|
expect(allPanes).not.toContain('pane-3');
|
|
expect(allPanes).toContain('pane-1');
|
|
expect(allPanes).toContain('pane-2');
|
|
expect(allPanes).toContain('pane-4');
|
|
});
|
|
|
|
it('should handle removal of non-existing pane', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = removePaneFromLayout(layout, 'non-existing');
|
|
|
|
expect(result.children).toEqual(['pane-1', 'pane-2', 'pane-3']);
|
|
});
|
|
|
|
it('should clean up empty groups after removal', () => {
|
|
const layout: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: [
|
|
{
|
|
direction: 'vertical',
|
|
children: ['only-pane'],
|
|
sizes: [100],
|
|
},
|
|
],
|
|
sizes: [100],
|
|
};
|
|
|
|
const result = removePaneFromLayout(layout, 'only-pane');
|
|
expect(result.children).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('addPaneToLayout', () => {
|
|
it('should add pane to empty layout', () => {
|
|
const layout: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: [],
|
|
};
|
|
const result = addPaneToLayout(layout, 'new-pane');
|
|
|
|
expect(result.children).toEqual(['new-pane']);
|
|
expect(result.sizes).toEqual([100]);
|
|
});
|
|
|
|
it('should add pane to layout with same direction', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = addPaneToLayout(layout, 'new-pane');
|
|
|
|
expect(result.children).toHaveLength(4);
|
|
expect(result.children).toContain('new-pane');
|
|
});
|
|
|
|
it('should add pane next to specific parent pane', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = addPaneToLayout(layout, 'new-pane', 'pane-2', 'horizontal');
|
|
|
|
expect(result.children).toContain('new-pane');
|
|
// The new pane should be added relative to pane-2
|
|
});
|
|
|
|
it('should create nested group when direction differs', () => {
|
|
const layout: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: ['pane-1'],
|
|
sizes: [100],
|
|
};
|
|
const result = addPaneToLayout(layout, 'new-pane', undefined, 'vertical');
|
|
|
|
// Should create a vertical group containing the original layout and new pane
|
|
expect(result.direction).toBe('vertical');
|
|
});
|
|
|
|
it('should handle deeply nested layouts', () => {
|
|
const layout = createNestedLayout();
|
|
const result = addPaneToLayout(layout, 'new-pane', 'pane-3', 'horizontal');
|
|
|
|
const allPanes = getAllPaneIds(result);
|
|
expect(allPanes).toContain('new-pane');
|
|
expect(allPanes).toContain('pane-3');
|
|
});
|
|
|
|
it('should distribute sizes when adding to same direction', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = addPaneToLayout(layout, 'new-pane');
|
|
|
|
// Should have 4 children with distributed sizes
|
|
expect(result.sizes).toHaveLength(4);
|
|
const sum = result.sizes?.reduce((a, b) => a + b, 0) ?? 0;
|
|
expect(Math.round(sum)).toBeCloseTo(100, 0);
|
|
});
|
|
});
|
|
|
|
describe('getAllPaneIds', () => {
|
|
it('should get all pane IDs from simple layout', () => {
|
|
const layout = createSimpleLayout();
|
|
const result = getAllPaneIds(layout);
|
|
|
|
expect(result).toEqual(['pane-1', 'pane-2', 'pane-3']);
|
|
});
|
|
|
|
it('should get all pane IDs from nested layout', () => {
|
|
const layout = createNestedLayout();
|
|
const result = getAllPaneIds(layout);
|
|
|
|
expect(result).toHaveLength(4);
|
|
expect(result).toContain('pane-1');
|
|
expect(result).toContain('pane-2');
|
|
expect(result).toContain('pane-3');
|
|
expect(result).toContain('pane-4');
|
|
});
|
|
|
|
it('should return empty array for empty layout', () => {
|
|
const layout: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: [],
|
|
};
|
|
const result = getAllPaneIds(layout);
|
|
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it('should handle deeply nested layouts', () => {
|
|
const layout: AllotmentLayoutGroup = {
|
|
direction: 'horizontal',
|
|
children: [
|
|
{
|
|
direction: 'vertical',
|
|
children: [
|
|
'pane-1',
|
|
{
|
|
direction: 'horizontal',
|
|
children: ['pane-2', 'pane-3'],
|
|
},
|
|
],
|
|
},
|
|
'pane-4',
|
|
],
|
|
};
|
|
|
|
const result = getAllPaneIds(layout);
|
|
expect(result).toHaveLength(4);
|
|
expect(result).toContain('pane-1');
|
|
expect(result).toContain('pane-2');
|
|
expect(result).toContain('pane-3');
|
|
expect(result).toContain('pane-4');
|
|
});
|
|
});
|
|
|
|
describe('integration: remove then add', () => {
|
|
it('should maintain layout integrity after remove and add', () => {
|
|
const layout = createNestedLayout();
|
|
|
|
// Remove a pane
|
|
const afterRemove = removePaneFromLayout(layout, 'pane-2');
|
|
expect(getAllPaneIds(afterRemove)).not.toContain('pane-2');
|
|
|
|
// Add a new pane
|
|
const afterAdd = addPaneToLayout(afterRemove, 'new-pane');
|
|
const allPanes = getAllPaneIds(afterAdd);
|
|
|
|
expect(allPanes).toContain('new-pane');
|
|
expect(allPanes).not.toContain('pane-2');
|
|
expect(allPanes).toContain('pane-3');
|
|
});
|
|
});
|
|
});
|