WellNuo/components/ble/__tests__/ConnectionStatusIndicator.test.tsx
Sergei f8156b2dc7 Add BLE auto-reconnect with exponential backoff
- Add ReconnectConfig and ReconnectState types for configurable reconnect behavior
- Implement auto-reconnect in BLEManager with exponential backoff (default: 3 attempts, 1.5x multiplier)
- Add connection monitoring via device.onDisconnected() for unexpected disconnections
- Update BLEContext with reconnectingDevices state and reconnect actions
- Create ConnectionStatusIndicator component for visual connection feedback
- Enhance device settings screen with reconnect UI and manual reconnect capability
- Add comprehensive tests for reconnect logic and UI component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-31 17:31:15 -08:00

178 lines
5.0 KiB
TypeScript

/**
* Tests for ConnectionStatusIndicator component
*/
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import { ConnectionStatusIndicator } from '../ConnectionStatusIndicator';
// Import just the types, not the full module to avoid native dependencies
import { BLEConnectionState } from '@/services/ble/types';
describe('ConnectionStatusIndicator', () => {
describe('Connection States', () => {
it('renders disconnected state correctly', () => {
const { getByText } = render(
<ConnectionStatusIndicator connectionState={BLEConnectionState.DISCONNECTED} />
);
expect(getByText('Not Connected')).toBeTruthy();
});
it('renders connecting state correctly', () => {
const { getByText } = render(
<ConnectionStatusIndicator connectionState={BLEConnectionState.CONNECTING} />
);
expect(getByText('Connecting...')).toBeTruthy();
});
it('renders connected/ready state correctly', () => {
const { getByText } = render(
<ConnectionStatusIndicator connectionState={BLEConnectionState.READY} />
);
expect(getByText('Connected')).toBeTruthy();
});
it('renders error state correctly', () => {
const { getByText } = render(
<ConnectionStatusIndicator connectionState={BLEConnectionState.ERROR} />
);
expect(getByText('Connection Error')).toBeTruthy();
});
it('renders disconnecting state correctly', () => {
const { getByText } = render(
<ConnectionStatusIndicator connectionState={BLEConnectionState.DISCONNECTING} />
);
expect(getByText('Disconnecting...')).toBeTruthy();
});
});
describe('Reconnecting State', () => {
it('shows reconnecting message when isReconnecting is true', () => {
const { getByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.DISCONNECTED}
isReconnecting={true}
reconnectAttempts={1}
maxAttempts={3}
/>
);
expect(getByText('Reconnecting... (1/3)')).toBeTruthy();
expect(getByText('Attempting to restore connection...')).toBeTruthy();
});
it('shows cancel button when reconnecting', () => {
const onCancel = jest.fn();
const { getByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.DISCONNECTED}
isReconnecting={true}
reconnectAttempts={2}
maxAttempts={3}
onCancel={onCancel}
/>
);
const cancelButton = getByText('Cancel');
expect(cancelButton).toBeTruthy();
fireEvent.press(cancelButton);
expect(onCancel).toHaveBeenCalledTimes(1);
});
});
describe('Reconnect Action', () => {
it('shows reconnect button when disconnected or errored', () => {
const onReconnect = jest.fn();
const { getByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.DISCONNECTED}
onReconnect={onReconnect}
/>
);
const reconnectButton = getByText('Reconnect');
expect(reconnectButton).toBeTruthy();
fireEvent.press(reconnectButton);
expect(onReconnect).toHaveBeenCalledTimes(1);
});
it('shows reconnect button on error state', () => {
const onReconnect = jest.fn();
const { getByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.ERROR}
onReconnect={onReconnect}
/>
);
const reconnectButton = getByText('Reconnect');
expect(reconnectButton).toBeTruthy();
});
it('does not show reconnect button when connected', () => {
const onReconnect = jest.fn();
const { queryByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.READY}
onReconnect={onReconnect}
/>
);
expect(queryByText('Reconnect')).toBeNull();
});
it('does not show reconnect button when reconnecting', () => {
const onReconnect = jest.fn();
const { queryByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.DISCONNECTED}
isReconnecting={true}
onReconnect={onReconnect}
/>
);
expect(queryByText('Reconnect')).toBeNull();
});
});
describe('Compact Mode', () => {
it('renders in compact mode', () => {
const { getByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.READY}
compact={true}
/>
);
expect(getByText('Connected')).toBeTruthy();
});
it('does not show action buttons in compact mode', () => {
const onReconnect = jest.fn();
const { queryByText } = render(
<ConnectionStatusIndicator
connectionState={BLEConnectionState.DISCONNECTED}
compact={true}
onReconnect={onReconnect}
/>
);
// Compact mode should not show action buttons
expect(queryByText('Reconnect')).toBeNull();
});
});
});