- 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>
178 lines
5.0 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
});
|