WellNuo/app/(tabs)/beneficiaries/__tests__/add-sensor.cleanup.test.tsx
Sergei a30769387f Add BLE scanning cleanup on screen blur
Implement proper cleanup of BLE scanning operations when users navigate
away from the add-sensor screen to prevent resource waste and potential
issues.

Changes:
- Add useFocusEffect hook to stop BLE scan when screen loses focus
- Remove unused imports (Device, WPDevice, connectDevice, etc.)
- Add comprehensive tests for BLE cleanup behavior
- Add tests for screen unmount/blur scenarios

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-29 12:08:37 -08:00

186 lines
5.0 KiB
TypeScript

/**
* Add Sensor Screen - BLE Cleanup Tests
* Tests that BLE scanning stops when user navigates away from the screen
*/
import React from 'react';
import { render, waitFor } from '@testing-library/react-native';
import { useLocalSearchParams, useFocusEffect } from 'expo-router';
import AddSensorScreen from '../[id]/add-sensor';
import { useBLE } from '@/contexts/BLEContext';
import { useBeneficiary } from '@/contexts/BeneficiaryContext';
// Mock dependencies
jest.mock('expo-router', () => ({
useLocalSearchParams: jest.fn(),
router: {
push: jest.fn(),
back: jest.fn(),
},
useFocusEffect: jest.fn(),
}));
jest.mock('@/contexts/BLEContext', () => ({
useBLE: jest.fn(),
}));
jest.mock('@/contexts/BeneficiaryContext', () => ({
useBeneficiary: jest.fn(),
}));
jest.mock('expo-device', () => ({
isDevice: true,
}));
describe('AddSensorScreen - BLE cleanup', () => {
const mockStopScan = jest.fn();
const mockScanDevices = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
// Mock route params
(useLocalSearchParams as jest.Mock).mockReturnValue({ id: '1' });
// Mock beneficiary context
(useBeneficiary as jest.Mock).mockReturnValue({
currentBeneficiary: {
id: 1,
name: 'Maria',
},
});
// Mock BLE context
(useBLE as jest.Mock).mockReturnValue({
foundDevices: [],
isScanning: false,
connectedDevices: new Set(),
isBLEAvailable: true,
error: null,
scanDevices: mockScanDevices,
stopScan: mockStopScan,
connectDevice: jest.fn(),
disconnectDevice: jest.fn(),
getWiFiList: jest.fn(),
setWiFi: jest.fn(),
getCurrentWiFi: jest.fn(),
rebootDevice: jest.fn(),
cleanupBLE: jest.fn(),
clearError: jest.fn(),
});
});
it('should register cleanup handler with useFocusEffect', () => {
render(<AddSensorScreen />);
expect(useFocusEffect).toHaveBeenCalled();
});
it('should stop scan when cleanup handler is called while scanning', () => {
// Mock scanning state
(useBLE as jest.Mock).mockReturnValue({
foundDevices: [],
isScanning: true, // Scan in progress
connectedDevices: new Set(),
isBLEAvailable: true,
error: null,
scanDevices: mockScanDevices,
stopScan: mockStopScan,
connectDevice: jest.fn(),
disconnectDevice: jest.fn(),
getWiFiList: jest.fn(),
setWiFi: jest.fn(),
getCurrentWiFi: jest.fn(),
rebootDevice: jest.fn(),
cleanupBLE: jest.fn(),
clearError: jest.fn(),
});
render(<AddSensorScreen />);
// Get the cleanup function from useFocusEffect
const focusEffectCall = (useFocusEffect as jest.Mock).mock.calls[0][0];
const cleanupFn = focusEffectCall(); // Call the effect to get cleanup function
// Simulate screen blur by calling cleanup
if (cleanupFn) {
cleanupFn();
}
expect(mockStopScan).toHaveBeenCalled();
});
it('should not stop scan when cleanup handler is called and not scanning', () => {
// Mock idle state
(useBLE as jest.Mock).mockReturnValue({
foundDevices: [],
isScanning: false, // Not scanning
connectedDevices: new Set(),
isBLEAvailable: true,
error: null,
scanDevices: mockScanDevices,
stopScan: mockStopScan,
connectDevice: jest.fn(),
disconnectDevice: jest.fn(),
getWiFiList: jest.fn(),
setWiFi: jest.fn(),
getCurrentWiFi: jest.fn(),
rebootDevice: jest.fn(),
cleanupBLE: jest.fn(),
clearError: jest.fn(),
});
render(<AddSensorScreen />);
// Get the cleanup function from useFocusEffect
const focusEffectCall = (useFocusEffect as jest.Mock).mock.calls[0][0];
const cleanupFn = focusEffectCall();
// Simulate screen blur by calling cleanup
if (cleanupFn) {
cleanupFn();
}
// stopScan should not be called when not scanning
expect(mockStopScan).not.toHaveBeenCalled();
});
it('should cleanup when component unmounts during active scan', () => {
(useBLE as jest.Mock).mockReturnValue({
foundDevices: [
{ id: 'device-1', name: 'WP_497_81a14c', mac: '81A14C', rssi: -55, wellId: 497 },
],
isScanning: true,
connectedDevices: new Set(),
isBLEAvailable: true,
error: null,
scanDevices: mockScanDevices,
stopScan: mockStopScan,
connectDevice: jest.fn(),
disconnectDevice: jest.fn(),
getWiFiList: jest.fn(),
setWiFi: jest.fn(),
getCurrentWiFi: jest.fn(),
rebootDevice: jest.fn(),
cleanupBLE: jest.fn(),
clearError: jest.fn(),
});
const { unmount } = render(<AddSensorScreen />);
// Get the cleanup function
const focusEffectCall = (useFocusEffect as jest.Mock).mock.calls[0][0];
const cleanupFn = focusEffectCall();
// Unmount component
unmount();
// Cleanup should have been called during unmount
if (cleanupFn) {
cleanupFn();
}
expect(mockStopScan).toHaveBeenCalled();
});
});