import { describe, test, expect, jest, beforeEach } from '@jest/globals'; // Mock the dependencies jest.mock('../utils/logger.js', () => ({ Logger: { log: jest.fn(), info: jest.fn(), debug: jest.fn(), warn: jest.fn(), error: jest.fn(), }, })); jest.mock('../utils/events.js', () => ({ default: jest.fn(), })); // Since we can't import the actual WindowContainer that depends on GNOME APIs, // we'll test the logic patterns used in the container describe('Container Logic Tests', () => { describe('Orientation Toggle Logic', () => { enum Layout { HORIZONTAL = 0, VERTICAL = 1, TABBED = 2, } const toggleOrientation = (current: Layout): Layout => { if (current === Layout.TABBED) return Layout.HORIZONTAL; return current === Layout.HORIZONTAL ? Layout.VERTICAL : Layout.HORIZONTAL; }; test('should toggle from HORIZONTAL to VERTICAL', () => { const result = toggleOrientation(Layout.HORIZONTAL); expect(result).toBe(Layout.VERTICAL); }); test('should toggle from VERTICAL to HORIZONTAL', () => { const result = toggleOrientation(Layout.VERTICAL); expect(result).toBe(Layout.HORIZONTAL); }); test('should toggle from TABBED to HORIZONTAL', () => { const result = toggleOrientation(Layout.TABBED); expect(result).toBe(Layout.HORIZONTAL); }); test('enum reverse mapping should return string names', () => { expect(Layout[Layout.HORIZONTAL]).toBe('HORIZONTAL'); expect(Layout[Layout.VERTICAL]).toBe('VERTICAL'); expect(Layout[Layout.TABBED]).toBe('TABBED'); }); }); describe('Window Bounds Calculation', () => { test('should calculate horizontal bounds correctly', () => { const workArea = { x: 0, y: 0, width: 1000, height: 500 }; const itemCount = 3; const windowWidth = Math.floor(workArea.width / itemCount); const bounds = Array.from({ length: itemCount }, (_, index) => ({ x: workArea.x + (index * windowWidth), y: workArea.y, width: windowWidth, height: workArea.height, })); expect(bounds.length).toBe(3); expect(bounds[0].x).toBe(0); expect(bounds[1].x).toBe(333); expect(bounds[2].x).toBe(666); expect(bounds[0].width).toBe(333); }); test('should calculate vertical bounds correctly', () => { const workArea = { x: 0, y: 0, width: 1000, height: 900 }; const itemCount = 3; const windowHeight = Math.floor(workArea.height / itemCount); const bounds = Array.from({ length: itemCount }, (_, index) => ({ x: workArea.x, y: workArea.y + (index * windowHeight), width: workArea.width, height: windowHeight, })); expect(bounds.length).toBe(3); expect(bounds[0].y).toBe(0); expect(bounds[1].y).toBe(300); expect(bounds[2].y).toBe(600); expect(bounds[0].height).toBe(300); }); test('should handle single window bounds', () => { const workArea = { x: 100, y: 50, width: 800, height: 600 }; const itemCount = 1; const windowWidth = Math.floor(workArea.width / itemCount); const bounds = [{ x: workArea.x, y: workArea.y, width: windowWidth, height: workArea.height, }]; expect(bounds[0].x).toBe(100); expect(bounds[0].y).toBe(50); expect(bounds[0].width).toBe(800); expect(bounds[0].height).toBe(600); }); }); describe('Tabbed Bounds Calculation', () => { const TAB_BAR_HEIGHT = 24; test('should give all items the same content rect in tabbed mode', () => { const workArea = { x: 100, y: 0, width: 1000, height: 500 }; const itemCount = 3; const contentRect = { x: workArea.x, y: workArea.y + TAB_BAR_HEIGHT, width: workArea.width, height: workArea.height - TAB_BAR_HEIGHT, }; const bounds = Array.from({ length: itemCount }, () => contentRect); expect(bounds.length).toBe(3); // All bounds should be identical bounds.forEach(b => { expect(b.x).toBe(100); expect(b.y).toBe(TAB_BAR_HEIGHT); expect(b.width).toBe(1000); expect(b.height).toBe(500 - TAB_BAR_HEIGHT); }); }); test('tab bar rect should occupy top of work area', () => { const workArea = { x: 200, y: 50, width: 800, height: 600 }; const tabBarRect = { x: workArea.x, y: workArea.y, width: workArea.width, height: TAB_BAR_HEIGHT, }; expect(tabBarRect.x).toBe(200); expect(tabBarRect.y).toBe(50); expect(tabBarRect.width).toBe(800); expect(tabBarRect.height).toBe(TAB_BAR_HEIGHT); }); test('active tab index should clamp after removal', () => { let activeTabIndex = 2; const itemCount = 2; // after removing one from 3 if (activeTabIndex >= itemCount) { activeTabIndex = itemCount - 1; } expect(activeTabIndex).toBe(1); }); test('active tab index should stay at 0 when first item removed', () => { let activeTabIndex = 0; const itemCount = 2; // after removing one from 3 if (activeTabIndex >= itemCount) { activeTabIndex = itemCount - 1; } expect(activeTabIndex).toBe(0); }); }); describe('Window Index Finding', () => { test('should find window index in array', () => { const windows = [ { id: 1, title: 'Window 1' }, { id: 2, title: 'Window 2' }, { id: 3, title: 'Window 3' }, ]; const findIndex = (id: number) => { for (let i = 0; i < windows.length; i++) { if (windows[i].id === id) { return i; } } return -1; }; expect(findIndex(2)).toBe(1); expect(findIndex(3)).toBe(2); expect(findIndex(999)).toBe(-1); }); test('should safely remove window by index', () => { const windows = [ { id: 1, title: 'Window 1' }, { id: 2, title: 'Window 2' }, { id: 3, title: 'Window 3' }, ]; const removeWindow = (id: number) => { const index = windows.findIndex(w => w.id === id); if (index !== -1) { windows.splice(index, 1); return true; } return false; }; const removed = removeWindow(2); expect(removed).toBe(true); expect(windows.length).toBe(2); expect(windows.find(w => w.id === 2)).toBeUndefined(); }); }); describe('Container Item Reordering', () => { test('should reorder items correctly', () => { const items = ['A', 'B', 'C', 'D']; const originalIndex = 1; // 'B' const newIndex = 3; // Remove from original position and insert at new position const [item] = items.splice(originalIndex, 1); items.splice(newIndex, 0, item); expect(items).toEqual(['A', 'C', 'D', 'B']); }); test('should handle reordering to same position', () => { const items = ['A', 'B', 'C']; const originalIndex = 1; const newIndex = 1; if (originalIndex !== newIndex) { const [item] = items.splice(originalIndex, 1); items.splice(newIndex, 0, item); } expect(items).toEqual(['A', 'B', 'C']); }); test('should handle moving first item to last', () => { const items = ['A', 'B', 'C']; const [item] = items.splice(0, 1); items.splice(2, 0, item); expect(items).toEqual(['B', 'C', 'A']); }); }); });