104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
import { render, screen, act, cleanup, waitFor } from '@testing-library/react';
|
|
import ConnectedRobots from '../../../src/pages/ConnectedRobots/ConnectedRobots';
|
|
|
|
// Mock event source
|
|
const mockInstances: MockEventSource[] = [];
|
|
class MockEventSource {
|
|
url: string;
|
|
onmessage: ((event: MessageEvent) => void) | null = null;
|
|
closed = false;
|
|
|
|
constructor(url: string) {
|
|
this.url = url;
|
|
mockInstances.push(this);
|
|
}
|
|
|
|
sendMessage(data: string) {
|
|
// Trigger whatever the component listens to
|
|
this.onmessage?.({ data } as MessageEvent);
|
|
}
|
|
|
|
close() {
|
|
this.closed = true;
|
|
}
|
|
}
|
|
|
|
// mock event source generation with fake function that returns our fake mock source
|
|
beforeAll(() => {
|
|
// Cast globalThis to a type exposing EventSource and assign a mocked constructor.
|
|
(globalThis as unknown as { EventSource?: typeof EventSource }).EventSource =
|
|
jest.fn((url: string) => new MockEventSource(url)) as unknown as typeof EventSource;
|
|
});
|
|
|
|
// clean after tests
|
|
afterEach(() => {
|
|
cleanup();
|
|
jest.restoreAllMocks();
|
|
mockInstances.length = 0;
|
|
});
|
|
|
|
describe('ConnectedRobots', () => {
|
|
test('renders initial state correctly', () => {
|
|
render(<ConnectedRobots />);
|
|
|
|
// Check initial texts (before connection)
|
|
expect(screen.getByText('Is robot currently connected?')).toBeInTheDocument();
|
|
expect(screen.getByText(/Robot is currently:\s*checking/i)).toBeInTheDocument();
|
|
expect(
|
|
screen.getByText(/If checking continues, make sure CB is properly loaded/i)
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
test('updates to connected when message data is true', async () => {
|
|
render(<ConnectedRobots />);
|
|
const eventSource = mockInstances[0];
|
|
expect(eventSource).toBeDefined();
|
|
|
|
// Check state after getting 'true' message
|
|
await act(async () => {
|
|
eventSource.sendMessage('true');
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/connected! 🟢/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
test('updates to not connected when message data is false', async () => {
|
|
render(<ConnectedRobots />);
|
|
const eventSource = mockInstances[0];
|
|
|
|
// Check statew after getting 'false' message
|
|
await act(async () => {
|
|
eventSource.sendMessage('false');
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/not connected.*🔴/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
test('handles invalid JSON gracefully', async () => {
|
|
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
render(<ConnectedRobots />);
|
|
const eventSource = mockInstances[0];
|
|
|
|
await act(async () => {
|
|
eventSource.sendMessage('not-json');
|
|
});
|
|
|
|
expect(logSpy).toHaveBeenCalledWith(
|
|
'Ping message not in correct format:',
|
|
'not-json'
|
|
);
|
|
});
|
|
|
|
test('closes EventSource on unmount', () => {
|
|
render(<ConnectedRobots />);
|
|
const eventSource = mockInstances[0];
|
|
const closeSpy = jest.spyOn(eventSource, 'close');
|
|
cleanup();
|
|
expect(closeSpy).toHaveBeenCalled();
|
|
expect(eventSource.closed).toBe(true);
|
|
});
|
|
}); |