/** * 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(); 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(); // 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(); // 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(); // 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(); }); });