mirror of
https://github.com/meshtastic/web.git
synced 2026-04-21 22:40:01 -04:00
148 lines
4.3 KiB
TypeScript
148 lines
4.3 KiB
TypeScript
import { MessageInput } from '@components/PageComponents/Messages/MessageInput.tsx';
|
|
import { useDevice } from "@core/stores/deviceStore.ts";
|
|
import { vi, describe, it, expect, beforeEach, Mock } from 'vitest';
|
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
|
|
vi.mock("@core/stores/deviceStore.ts", () => ({
|
|
useDevice: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@core/utils/debounce.ts", () => ({
|
|
debounce: (fn: () => void) => fn,
|
|
}));
|
|
|
|
vi.mock("@components/UI/Button.tsx", () => ({
|
|
Button: ({ children, ...props }: { children: React.ReactNode }) => <button {...props}>{children}</button>
|
|
}));
|
|
|
|
vi.mock("@components/UI/Input.tsx", () => ({
|
|
Input: (props: any) => <input {...props} />
|
|
}));
|
|
|
|
vi.mock("lucide-react", () => ({
|
|
SendIcon: () => <div data-testid="send-icon">Send</div>
|
|
}));
|
|
|
|
// TODO: getting an error with this test
|
|
describe.skip('MessageInput Component', () => {
|
|
const mockProps = {
|
|
to: "broadcast" as const,
|
|
channel: 0 as const,
|
|
maxBytes: 100,
|
|
};
|
|
|
|
const mockSetMessageDraft = vi.fn();
|
|
const mockSetMessageState = vi.fn();
|
|
const mockSendText = vi.fn().mockResolvedValue(123); // mock ID returned from sendText
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
|
|
// Setup the mock implementation for useDevice
|
|
(useDevice as Mock).mockReturnValue({
|
|
connection: {
|
|
sendText: mockSendText,
|
|
},
|
|
setMessageState: mockSetMessageState,
|
|
messageDraft: "",
|
|
setMessageDraft: mockSetMessageDraft,
|
|
hardware: {
|
|
myNodeNum: 1234567890,
|
|
},
|
|
});
|
|
});
|
|
|
|
it('renders correctly with initial state', () => {
|
|
render(<MessageInput {...mockProps} />);
|
|
|
|
expect(screen.getByPlaceholderText('Enter Message')).toBeInTheDocument();
|
|
expect(screen.getByTestId('send-icon')).toBeInTheDocument();
|
|
|
|
expect(screen.getByText('0/100')).toBeInTheDocument();
|
|
});
|
|
|
|
it('updates local draft and byte count when typing', () => {
|
|
render(<MessageInput {...mockProps} />);
|
|
|
|
const inputField = screen.getByPlaceholderText('Enter Message');
|
|
fireEvent.change(inputField, { target: { value: 'Hello' } })
|
|
|
|
expect(screen.getByText('5/100')).toBeInTheDocument();
|
|
expect(inputField).toHaveValue('Hello');
|
|
expect(mockSetMessageDraft).toHaveBeenCalledWith('Hello');
|
|
});
|
|
|
|
it('does not allow input exceeding max bytes', () => {
|
|
render(<MessageInput {...mockProps} maxBytes={5} />);
|
|
|
|
const inputField = screen.getByPlaceholderText('Enter Message');
|
|
|
|
expect(screen.getByText('5/5')).toBeInTheDocument();
|
|
|
|
|
|
fireEvent.change(inputField, { target: { value: 'Hello' } })
|
|
expect(inputField).toHaveValue('Hello');
|
|
expect(screen.getByText('5/5')).toBeInTheDocument();
|
|
});
|
|
|
|
it('sends message and resets form when submitting', async () => {
|
|
render(<MessageInput {...mockProps} />);
|
|
|
|
const inputField = screen.getByPlaceholderText('Enter Message');
|
|
const submitButton = screen.getByText('Send');
|
|
|
|
fireEvent.change(inputField, { target: { value: 'Test Message' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
const form = screen.getByRole('form');
|
|
fireEvent.submit(form);
|
|
|
|
expect(mockSendText).toHaveBeenCalledWith('Test message', 'broadcast', true, 0);
|
|
|
|
await waitFor(() => {
|
|
expect(mockSetMessageState).toHaveBeenCalledWith(
|
|
'broadcast',
|
|
0,
|
|
'broadcast',
|
|
1234567890,
|
|
123,
|
|
'ack'
|
|
);
|
|
});
|
|
|
|
expect(inputField).toHaveValue('');
|
|
expect(screen.getByText('0/100')).toBeInTheDocument();
|
|
expect(mockSetMessageDraft).toHaveBeenCalledWith('');
|
|
});
|
|
it('prevents sending empty messages', () => {
|
|
render(<MessageInput {...mockProps} />);
|
|
|
|
const form = screen.getByPlaceholderText('Enter Message')
|
|
fireEvent.submit(form);
|
|
|
|
expect(mockSendText).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('initializes with existing message draft', () => {
|
|
(useDevice as Mock).mockReturnValue({
|
|
connection: {
|
|
sendText: mockSendText,
|
|
},
|
|
setMessageState: mockSetMessageState,
|
|
messageDraft: "Existing draft",
|
|
setMessageDraft: mockSetMessageDraft,
|
|
isQueueingMessages: false,
|
|
queueStatus: { free: 10 },
|
|
hardware: {
|
|
myNodeNum: 1234567890,
|
|
},
|
|
});
|
|
|
|
render(<MessageInput {...mockProps} />);
|
|
|
|
const inputField = screen.getByRole('label');
|
|
|
|
expect(inputField).toHaveValue('Existing draft');
|
|
expect(screen.getByText('14/100')).toBeInTheDocument();
|
|
});
|
|
}); |