Skip to content

Commit 00a19e4

Browse files
committed
Added input component tests
1 parent 2982695 commit 00a19e4

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

src/components/input.test.tsx

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2+
import React from 'react';
3+
import { render, fireEvent, screen } from '@testing-library/react';
4+
import CommandInput from './input';
5+
import { CommandHistory } from '../CommandHistory';
6+
7+
// Mock CommandHistory
8+
vi.mock('../CommandHistory', () => ({
9+
CommandHistory: class MockCommandHistory {
10+
private history: string[] = [];
11+
private index: number = -1;
12+
13+
addCommand = vi.fn();
14+
navigateUp = vi.fn();
15+
navigateDown = vi.fn();
16+
getHistory = vi.fn(() => []);
17+
}
18+
}));
19+
20+
// Mock localStorage
21+
const localStorageMock = (() => {
22+
let store: Record<string, string> = {};
23+
return {
24+
getItem: vi.fn((key: string) => store[key] || null),
25+
setItem: vi.fn((key: string, value: string) => {
26+
store[key] = value.toString();
27+
}),
28+
clear: vi.fn(() => {
29+
store = {};
30+
})
31+
};
32+
})();
33+
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
34+
35+
describe('CommandInput Component', () => {
36+
const onSendMock = vi.fn();
37+
const inputRef = React.createRef<HTMLTextAreaElement>();
38+
39+
beforeEach(() => {
40+
vi.clearAllMocks();
41+
localStorageMock.clear();
42+
});
43+
44+
it('renders a textarea and a button', () => {
45+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
46+
47+
expect(screen.getByRole('textbox')).toBeTruthy();
48+
expect(screen.getByRole('button', { name: /send/i })).toBeTruthy();
49+
});
50+
51+
it('updates input value when user types', () => {
52+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
53+
54+
const textarea = screen.getByRole('textbox');
55+
fireEvent.change(textarea, { target: { value: 'hello world' } });
56+
57+
expect((textarea as HTMLTextAreaElement).value).toBe('hello world');
58+
});
59+
60+
it('calls onSend when send button is clicked', () => {
61+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
62+
63+
const textarea = screen.getByRole('textbox');
64+
fireEvent.change(textarea, { target: { value: 'look' } });
65+
66+
const sendButton = screen.getByRole('button', { name: /send/i });
67+
fireEvent.click(sendButton);
68+
69+
expect(onSendMock).toHaveBeenCalledWith('look');
70+
expect((textarea as HTMLTextAreaElement).value).toBe(''); // Input should clear after sending
71+
});
72+
73+
it('calls onSend when Enter key is pressed', () => {
74+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
75+
76+
const textarea = screen.getByRole('textbox');
77+
fireEvent.change(textarea, { target: { value: 'examine sword' } });
78+
fireEvent.keyDown(textarea, { key: 'Enter' });
79+
80+
expect(onSendMock).toHaveBeenCalledWith('examine sword');
81+
expect((textarea as HTMLTextAreaElement).value).toBe(''); // Input should clear after sending
82+
});
83+
84+
it('does not send empty input', () => {
85+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
86+
87+
const textarea = screen.getByRole('textbox');
88+
fireEvent.change(textarea, { target: { value: ' ' } }); // Just spaces
89+
fireEvent.keyDown(textarea, { key: 'Enter' });
90+
91+
expect(onSendMock).not.toHaveBeenCalled();
92+
});
93+
94+
it('adds command to history when sent', () => {
95+
// Since CommandHistory is mocked at the module level, we'll just verify
96+
// that the command is sent via onSend
97+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
98+
99+
const textarea = screen.getByRole('textbox');
100+
fireEvent.change(textarea, { target: { value: 'look' } });
101+
fireEvent.keyDown(textarea, { key: 'Enter' });
102+
103+
expect(onSendMock).toHaveBeenCalledWith('look');
104+
});
105+
106+
it('handles arrow key navigation', () => {
107+
// This test just verifies that the component handles arrow key presses
108+
// without errors - we can't directly test the navigation functionality
109+
// since CommandHistory is fully mocked
110+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
111+
112+
const textarea = screen.getByRole('textbox');
113+
114+
// First send a command
115+
fireEvent.change(textarea, { target: { value: 'command1' } });
116+
fireEvent.keyDown(textarea, { key: 'Enter' });
117+
118+
// Verify no errors when navigating with arrow keys
119+
expect(() => {
120+
fireEvent.keyDown(textarea, { key: 'ArrowUp' });
121+
fireEvent.keyDown(textarea, { key: 'ArrowDown' });
122+
}).not.toThrow();
123+
});
124+
125+
it('loads command history from localStorage on mount', () => {
126+
// Setup saved history
127+
localStorageMock.getItem.mockReturnValueOnce(JSON.stringify(['command1', 'command2']));
128+
129+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
130+
131+
// Check that localStorage was accessed with the correct key
132+
expect(localStorageMock.getItem).toHaveBeenCalledWith('command_history');
133+
});
134+
135+
it('saves command history to localStorage', () => {
136+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
137+
138+
const textarea = screen.getByRole('textbox');
139+
fireEvent.change(textarea, { target: { value: 'save this command' } });
140+
fireEvent.keyDown(textarea, { key: 'Enter' });
141+
142+
expect(localStorageMock.setItem).toHaveBeenCalledWith('command_history', expect.any(String));
143+
});
144+
145+
it('limits command history size when saving', () => {
146+
// Mock getHistory to return a large array
147+
const largeMockHistory = Array(1010).fill(0).map((_, i) => `command${i}`);
148+
const mockCommandHistory = new CommandHistory();
149+
vi.spyOn(mockCommandHistory, 'getHistory').mockReturnValue(largeMockHistory);
150+
vi.spyOn(React, 'useRef').mockReturnValue({ current: mockCommandHistory });
151+
152+
render(<CommandInput onSend={onSendMock} inputRef={inputRef} />);
153+
154+
const textarea = screen.getByRole('textbox');
155+
fireEvent.change(textarea, { target: { value: 'one more command' } });
156+
fireEvent.keyDown(textarea, { key: 'Enter' });
157+
158+
// Should have saved only the last 1000 commands
159+
const savedValue = JSON.parse(localStorageMock.setItem.mock.calls[0][1]);
160+
expect(savedValue.length).toBeLessThanOrEqual(1000);
161+
});
162+
});

0 commit comments

Comments
 (0)