import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import MessageInput from '../../../src/renderer/components/chat/MessageInput';
describe('MessageInput', () => {
const mockOnSendMessage = jest.fn();
beforeEach(() => {
mockOnSendMessage.mockClear();
});
it('should render input field and send button', () => {
render();
expect(screen.getByPlaceholderText('Type a message...')).toBeInTheDocument();
expect(screen.getByRole('button', { name: /send/i })).toBeInTheDocument();
});
it('should call onSendMessage when send button is clicked', async () => {
const user = userEvent.setup();
render();
const input = screen.getByPlaceholderText('Type a message...');
const sendButton = screen.getByRole('button', { name: /send/i });
await user.type(input, 'Hello, world!');
await user.click(sendButton);
expect(mockOnSendMessage).toHaveBeenCalledWith('Hello, world!');
});
it('should call onSendMessage when Enter key is pressed', async () => {
const user = userEvent.setup();
render();
const input = screen.getByPlaceholderText('Type a message...');
await user.type(input, 'Hello, world!');
await user.keyboard('{Enter}');
expect(mockOnSendMessage).toHaveBeenCalledWith('Hello, world!');
});
it('should not call onSendMessage when Shift+Enter is pressed', async () => {
const user = userEvent.setup();
render();
const input = screen.getByPlaceholderText('Type a message...');
await user.type(input, 'Hello');
await user.keyboard('{Shift>}{Enter}{/Shift}');
expect(mockOnSendMessage).not.toHaveBeenCalled();
});
it('should clear input after successful send', async () => {
const user = userEvent.setup();
mockOnSendMessage.mockResolvedValue(undefined);
render();
const input = screen.getByPlaceholderText('Type a message...');
const sendButton = screen.getByRole('button', { name: /send/i });
await user.type(input, 'Hello, world!');
await user.click(sendButton);
await waitFor(() => {
expect(input).toHaveValue('');
});
});
it('should show error message if send fails', async () => {
const user = userEvent.setup();
mockOnSendMessage.mockRejectedValue(new Error('Send failed'));
render();
const input = screen.getByPlaceholderText('Type a message...');
const sendButton = screen.getByRole('button', { name: /send/i });
await user.type(input, 'Hello, world!');
await user.click(sendButton);
await waitFor(() => {
expect(screen.getByText('Send failed')).toBeInTheDocument();
});
});
it('should disable input and button when disabled prop is true', () => {
render();
const input = screen.getByPlaceholderText('Connect to agent to start chatting...');
const sendButton = screen.getByRole('button', { name: /send/i });
expect(input).toBeDisabled();
expect(sendButton).toBeDisabled();
});
it('should disable send button when input is empty', () => {
render();
const sendButton = screen.getByRole('button', { name: /send/i });
expect(sendButton).toBeDisabled();
});
it('should enable send button when input has content', async () => {
const user = userEvent.setup();
render();
const input = screen.getByPlaceholderText('Type a message...');
const sendButton = screen.getByRole('button', { name: /send/i });
await user.type(input, 'Hello');
expect(sendButton).not.toBeDisabled();
});
it('should show character count', async () => {
const user = userEvent.setup();
render();
const input = screen.getByPlaceholderText('Type a message...');
await user.type(input, 'Hello');
expect(screen.getByText('5/2000')).toBeInTheDocument();
});
it('should show submitting state during send', async () => {
const user = userEvent.setup();
mockOnSendMessage.mockImplementation(() =>
new Promise(resolve => setTimeout(resolve, 100))
);
render();
const input = screen.getByPlaceholderText('Type a message...');
const sendButton = screen.getByRole('button', { name: /send/i });
await user.type(input, 'Hello');
await user.click(sendButton);
expect(screen.getByRole('button', { name: /sending.../i })).toBeInTheDocument();
expect(sendButton).toBeDisabled();
});
it('should clear error when user starts typing', async () => {
const user = userEvent.setup();
mockOnSendMessage.mockRejectedValue(new Error('Send failed'));
render();
const input = screen.getByPlaceholderText('Type a message...');
await user.type(input, 'Hello');
await user.keyboard('{Enter}');
await waitFor(() => {
expect(screen.getByText('Send failed')).toBeInTheDocument();
});
await user.type(input, ' World');
expect(screen.queryByText('Send failed')).not.toBeInTheDocument();
});
});