fix(tests): fix FileContextPanel test mock setup
The original mock returned the same instance for all blessed.box() calls, but the implementation creates 4 separate boxes (main, fileInfo, fileContent, fileHistory). This caused tests to fail because they couldn't distinguish which methods were called on which elements. Changes: - Make the mock return a new instance for each blessed.box() call - Track all mock instances in a mockBoxes array - Keep mainBoxInstance reference for tests that need the primary box - Fix test expecting setContent on main box to use mockBoxes[1] (fileInfo) All 57 FileContextPanel tests now pass.
This commit is contained in:
parent
22a2739b91
commit
797c9f144e
1 changed files with 55 additions and 45 deletions
|
|
@ -7,9 +7,13 @@
|
||||||
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from 'vitest';
|
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from 'vitest';
|
||||||
import blessed from 'blessed';
|
import blessed from 'blessed';
|
||||||
|
|
||||||
|
// Track all mock box instances
|
||||||
|
const mockBoxes: any[] = [];
|
||||||
|
let mainBoxInstance: any;
|
||||||
|
|
||||||
// Mock the blessed module before importing FileContextPanel
|
// Mock the blessed module before importing FileContextPanel
|
||||||
vi.mock('blessed', () => {
|
vi.mock('blessed', () => {
|
||||||
const createMockElement = () => ({
|
const createMockElement = (index: number) => ({
|
||||||
setContent: vi.fn(),
|
setContent: vi.fn(),
|
||||||
setLabel: vi.fn(),
|
setLabel: vi.fn(),
|
||||||
show: vi.fn(),
|
show: vi.fn(),
|
||||||
|
|
@ -26,13 +30,21 @@ vi.mock('blessed', () => {
|
||||||
width: 80,
|
width: 80,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockBoxInstance = createMockElement();
|
const boxMock = vi.fn((...args: any[]) => {
|
||||||
|
const index = mockBoxes.length;
|
||||||
|
const mock = createMockElement(index);
|
||||||
|
mockBoxes.push(mock);
|
||||||
|
if (index === 0) {
|
||||||
|
mainBoxInstance = mock;
|
||||||
|
}
|
||||||
|
return mock;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
default: {
|
default: {
|
||||||
box: vi.fn(() => mockBoxInstance),
|
box: boxMock,
|
||||||
},
|
},
|
||||||
box: vi.fn(() => mockBoxInstance),
|
box: boxMock,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -76,19 +88,14 @@ function createMockEvent(overrides: Partial<LogEvent> = {}): LogEvent {
|
||||||
describe('FileContextPanel', () => {
|
describe('FileContextPanel', () => {
|
||||||
let panel: FileContextPanel;
|
let panel: FileContextPanel;
|
||||||
let mockScreen: blessed.Widgets.Screen;
|
let mockScreen: blessed.Widgets.Screen;
|
||||||
let mockBoxInstance: any;
|
|
||||||
let mockSubBox: any;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
mockBoxes.length = 0;
|
||||||
|
mainBoxInstance = undefined;
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|
||||||
mockScreen = createMockScreen();
|
mockScreen = createMockScreen();
|
||||||
|
|
||||||
// Get the mock box instance from the mock
|
|
||||||
const blessedMock = blessed as unknown as { box: Mock };
|
|
||||||
mockBoxInstance = blessedMock.box();
|
|
||||||
mockSubBox = blessedMock.box({ parent: mockBoxInstance });
|
|
||||||
|
|
||||||
panel = new FileContextPanel({
|
panel = new FileContextPanel({
|
||||||
parent: mockScreen,
|
parent: mockScreen,
|
||||||
top: 0,
|
top: 0,
|
||||||
|
|
@ -100,6 +107,8 @@ describe('FileContextPanel', () => {
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
mockBoxes.length = 0;
|
||||||
|
mainBoxInstance = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
|
|
@ -129,7 +138,7 @@ describe('FileContextPanel', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind key handlers on construction', () => {
|
it('should bind key handlers on construction', () => {
|
||||||
expect(mockBoxInstance.key).toHaveBeenCalled();
|
expect(mainBoxInstance.key).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -248,7 +257,7 @@ describe('FileContextPanel', () => {
|
||||||
panel.setContextFromEvent(event2);
|
panel.setContextFromEvent(event2);
|
||||||
|
|
||||||
// Should render without errors
|
// Should render without errors
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -276,7 +285,7 @@ describe('FileContextPanel', () => {
|
||||||
|
|
||||||
panel.setContent('/current.ts', 'new content');
|
panel.setContent('/current.ts', 'new content');
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not trigger render for non-current file', () => {
|
it('should not trigger render for non-current file', () => {
|
||||||
|
|
@ -291,7 +300,7 @@ describe('FileContextPanel', () => {
|
||||||
panel.setContent('/file1.ts', 'content');
|
panel.setContent('/file1.ts', 'content');
|
||||||
|
|
||||||
// Should not render since file2 is current
|
// Should not render since file2 is current
|
||||||
expect(mockBoxInstance.screen.render).not.toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -301,35 +310,35 @@ describe('FileContextPanel', () => {
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
// Render should include language indicator
|
// Render should include language indicator
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect JavaScript files', () => {
|
it('should detect JavaScript files', () => {
|
||||||
const event = createMockEvent({ path: '/src/test.js' });
|
const event = createMockEvent({ path: '/src/test.js' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect Python files', () => {
|
it('should detect Python files', () => {
|
||||||
const event = createMockEvent({ path: '/src/test.py' });
|
const event = createMockEvent({ path: '/src/test.py' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect Rust files', () => {
|
it('should detect Rust files', () => {
|
||||||
const event = createMockEvent({ path: '/src/test.rs' });
|
const event = createMockEvent({ path: '/src/test.rs' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle unknown file types', () => {
|
it('should handle unknown file types', () => {
|
||||||
const event = createMockEvent({ path: '/src/test.unknown' });
|
const event = createMockEvent({ path: '/src/test.unknown' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect multiple TypeScript extensions', () => {
|
it('should detect multiple TypeScript extensions', () => {
|
||||||
|
|
@ -347,28 +356,28 @@ describe('FileContextPanel', () => {
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
// Should render with read icon
|
// Should render with read icon
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show edit icon for edit operations', () => {
|
it('should show edit icon for edit operations', () => {
|
||||||
const event = createMockEvent({ path: '/test.txt', tool: 'Edit' });
|
const event = createMockEvent({ path: '/test.txt', tool: 'Edit' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show write icon for write operations', () => {
|
it('should show write icon for write operations', () => {
|
||||||
const event = createMockEvent({ path: '/test.txt', tool: 'Write' });
|
const event = createMockEvent({ path: '/test.txt', tool: 'Write' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show glob icon for glob operations', () => {
|
it('should show glob icon for glob operations', () => {
|
||||||
const event = createMockEvent({ path: '/src/*.ts', tool: 'Glob' });
|
const event = createMockEvent({ path: '/src/*.ts', tool: 'Glob' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -383,7 +392,7 @@ describe('FileContextPanel', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to previous file', () => {
|
it('should navigate to previous file', () => {
|
||||||
const mockBox = mockBoxInstance as any;
|
const mockBox = mainBoxInstance as any;
|
||||||
const keyCalls = mockBox.key.mock.calls;
|
const keyCalls = mockBox.key.mock.calls;
|
||||||
|
|
||||||
// Find the [ key handler
|
// Find the [ key handler
|
||||||
|
|
@ -396,11 +405,11 @@ describe('FileContextPanel', () => {
|
||||||
handler();
|
handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to next file', () => {
|
it('should navigate to next file', () => {
|
||||||
const mockBox = mockBoxInstance as any;
|
const mockBox = mainBoxInstance as any;
|
||||||
const keyCalls = mockBox.key.mock.calls;
|
const keyCalls = mockBox.key.mock.calls;
|
||||||
|
|
||||||
// Find the ] key handler
|
// Find the ] key handler
|
||||||
|
|
@ -413,34 +422,34 @@ describe('FileContextPanel', () => {
|
||||||
handler();
|
handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('show/hide/toggle', () => {
|
describe('show/hide/toggle', () => {
|
||||||
it('should show the panel', () => {
|
it('should show the panel', () => {
|
||||||
panel.show();
|
panel.show();
|
||||||
expect(mockBoxInstance.show).toHaveBeenCalled();
|
expect(mainBoxInstance.show).toHaveBeenCalled();
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide the panel', () => {
|
it('should hide the panel', () => {
|
||||||
panel.hide();
|
panel.hide();
|
||||||
expect(mockBoxInstance.hide).toHaveBeenCalled();
|
expect(mainBoxInstance.hide).toHaveBeenCalled();
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle visibility', () => {
|
it('should toggle visibility', () => {
|
||||||
// Initially not visible
|
// Initially not visible
|
||||||
panel.toggle();
|
panel.toggle();
|
||||||
expect(mockBoxInstance.show).toHaveBeenCalled();
|
expect(mainBoxInstance.show).toHaveBeenCalled();
|
||||||
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|
||||||
// Now visible, toggle should hide
|
// Now visible, toggle should hide
|
||||||
(panel as any).visible = true;
|
(panel as any).visible = true;
|
||||||
panel.toggle();
|
panel.toggle();
|
||||||
expect(mockBoxInstance.hide).toHaveBeenCalled();
|
expect(mainBoxInstance.hide).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return visibility state', () => {
|
it('should return visibility state', () => {
|
||||||
|
|
@ -454,14 +463,14 @@ describe('FileContextPanel', () => {
|
||||||
describe('focus', () => {
|
describe('focus', () => {
|
||||||
it('should focus the box element', () => {
|
it('should focus the box element', () => {
|
||||||
panel.focus();
|
panel.focus();
|
||||||
expect(mockBoxInstance.focus).toHaveBeenCalled();
|
expect(mainBoxInstance.focus).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getElement', () => {
|
describe('getElement', () => {
|
||||||
it('should return the box element', () => {
|
it('should return the box element', () => {
|
||||||
const element = panel.getElement();
|
const element = panel.getElement();
|
||||||
expect(element).toBe(mockBoxInstance);
|
expect(element).toBe(mainBoxInstance);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -507,13 +516,13 @@ describe('FileContextPanel', () => {
|
||||||
panel.setContextFromEvent(createMockEvent({ path: '/test.ts' }));
|
panel.setContextFromEvent(createMockEvent({ path: '/test.ts' }));
|
||||||
panel.clear();
|
panel.clear();
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('key bindings', () => {
|
describe('key bindings', () => {
|
||||||
it('should bind scroll up keys', () => {
|
it('should bind scroll up keys', () => {
|
||||||
const mockBox = mockBoxInstance as any;
|
const mockBox = mainBoxInstance as any;
|
||||||
const keyCalls = mockBox.key.mock.calls;
|
const keyCalls = mockBox.key.mock.calls;
|
||||||
|
|
||||||
expect(keyCalls.some((call: unknown[]) =>
|
expect(keyCalls.some((call: unknown[]) =>
|
||||||
|
|
@ -522,7 +531,7 @@ describe('FileContextPanel', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind scroll down keys', () => {
|
it('should bind scroll down keys', () => {
|
||||||
const mockBox = mockBoxInstance as any;
|
const mockBox = mainBoxInstance as any;
|
||||||
const keyCalls = mockBox.key.mock.calls;
|
const keyCalls = mockBox.key.mock.calls;
|
||||||
|
|
||||||
expect(keyCalls.some((call: unknown[]) =>
|
expect(keyCalls.some((call: unknown[]) =>
|
||||||
|
|
@ -531,7 +540,7 @@ describe('FileContextPanel', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind page up/down keys', () => {
|
it('should bind page up/down keys', () => {
|
||||||
const mockBox = mockBoxInstance as any;
|
const mockBox = mainBoxInstance as any;
|
||||||
const keyCalls = mockBox.key.mock.calls;
|
const keyCalls = mockBox.key.mock.calls;
|
||||||
|
|
||||||
expect(keyCalls.some((call: unknown[]) =>
|
expect(keyCalls.some((call: unknown[]) =>
|
||||||
|
|
@ -544,7 +553,7 @@ describe('FileContextPanel', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind open in editor key', () => {
|
it('should bind open in editor key', () => {
|
||||||
const mockBox = mockBoxInstance as any;
|
const mockBox = mainBoxInstance as any;
|
||||||
const keyCalls = mockBox.key.mock.calls;
|
const keyCalls = mockBox.key.mock.calls;
|
||||||
|
|
||||||
expect(keyCalls.some((call: unknown[]) =>
|
expect(keyCalls.some((call: unknown[]) =>
|
||||||
|
|
@ -606,28 +615,29 @@ describe('FileContextPanel', () => {
|
||||||
it('should show no file selected message when empty', () => {
|
it('should show no file selected message when empty', () => {
|
||||||
(panel as any).render();
|
(panel as any).render();
|
||||||
|
|
||||||
expect(mockBoxInstance.setContent).toHaveBeenCalled();
|
// fileInfo is the second box created (index 1), it gets the "No file selected" message
|
||||||
|
expect(mockBoxes[1]?.setContent).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include file path in header', () => {
|
it('should include file path in header', () => {
|
||||||
const event = createMockEvent({ path: '/src/component.ts' });
|
const event = createMockEvent({ path: '/src/component.ts' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include directory path', () => {
|
it('should include directory path', () => {
|
||||||
const event = createMockEvent({ path: '/src/components/Button.ts' });
|
const event = createMockEvent({ path: '/src/components/Button.ts' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include operation history', () => {
|
it('should include operation history', () => {
|
||||||
const event = createMockEvent({ path: '/test.ts', tool: 'Read' });
|
const event = createMockEvent({ path: '/test.ts', tool: 'Read' });
|
||||||
panel.setContextFromEvent(event);
|
panel.setContextFromEvent(event);
|
||||||
|
|
||||||
expect(mockBoxInstance.screen.render).toHaveBeenCalled();
|
expect(mainBoxInstance.screen.render).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue