/** * NavigationController Null Safety Tests * * Tests for null/undefined handling and edge cases in navigation logic */ import { NavigationController, ROUTES } from '../NavigationController'; import type { Beneficiary, EquipmentStatus } from '@/types'; describe('NavigationController - Null Safety', () => { describe('getRouteAfterLogin', () => { it('should handle null profile', () => { const result = NavigationController.getRouteAfterLogin(null, []); expect(result.path).toBe(ROUTES.AUTH.ENTER_NAME); }); it('should handle undefined profile', () => { const result = NavigationController.getRouteAfterLogin(undefined, []); expect(result.path).toBe(ROUTES.AUTH.ENTER_NAME); }); it('should handle profile without firstName', () => { const profile = { id: 1, email: 'test@example.com', firstName: null, lastName: null, phone: null, }; const result = NavigationController.getRouteAfterLogin(profile, []); expect(result.path).toBe(ROUTES.AUTH.ENTER_NAME); }); it('should handle null beneficiaries array', () => { const profile = { id: 1, email: 'test@example.com', firstName: 'John', lastName: 'Doe', phone: null, }; const result = NavigationController.getRouteAfterLogin(profile, null); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle undefined beneficiaries array', () => { const profile = { id: 1, email: 'test@example.com', firstName: 'John', lastName: 'Doe', phone: null, }; const result = NavigationController.getRouteAfterLogin(profile, undefined); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle empty beneficiaries array', () => { const profile = { id: 1, email: 'test@example.com', firstName: 'John', lastName: 'Doe', phone: null, }; const result = NavigationController.getRouteAfterLogin(profile, []); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle beneficiary with invalid id', () => { const profile = { id: 1, email: 'test@example.com', firstName: 'John', lastName: 'Doe', phone: null, }; const beneficiaries = [ { id: null as any, name: 'Mom', displayName: 'Mom', status: 'online' as const, }, ]; const result = NavigationController.getRouteAfterLogin(profile, beneficiaries); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should navigate to dashboard for active beneficiary', () => { const profile = { id: 1, email: 'test@example.com', firstName: 'John', lastName: 'Doe', phone: null, }; const beneficiaries: Beneficiary[] = [ { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', hasDevices: true, equipmentStatus: 'active', }, ]; const result = NavigationController.getRouteAfterLogin(profile, beneficiaries); expect(result.path).toBe(ROUTES.TABS.DASHBOARD); }); }); describe('getRouteForBeneficiarySetup', () => { it('should handle null beneficiary', () => { const result = NavigationController.getRouteForBeneficiarySetup(null); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle undefined beneficiary', () => { const result = NavigationController.getRouteForBeneficiarySetup(undefined); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle beneficiary with invalid id', () => { const beneficiary = { id: null as any, name: 'Mom', displayName: 'Mom', status: 'online' as const, }; const result = NavigationController.getRouteForBeneficiarySetup(beneficiary); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should navigate to purchase for beneficiary with no equipment', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', equipmentStatus: 'none', }; const result = NavigationController.getRouteForBeneficiarySetup(beneficiary); expect(result.path).toBe(ROUTES.AUTH.PURCHASE); expect(result.params).toEqual({ beneficiaryId: 1 }); }); it('should navigate to equipment page for ordered status', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', equipmentStatus: 'ordered', }; const result = NavigationController.getRouteForBeneficiarySetup(beneficiary); expect(result.path).toBe(ROUTES.BENEFICIARY.EQUIPMENT(1)); }); }); describe('getRouteAfterAddBeneficiary', () => { it('should handle null beneficiaryId', () => { const result = NavigationController.getRouteAfterAddBeneficiary(null, false); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle undefined beneficiaryId', () => { const result = NavigationController.getRouteAfterAddBeneficiary(undefined, false); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle invalid beneficiaryId type', () => { const result = NavigationController.getRouteAfterAddBeneficiary('invalid' as any, false); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should navigate to purchase for new equipment', () => { const result = NavigationController.getRouteAfterAddBeneficiary(1, false); expect(result.path).toBe(ROUTES.AUTH.PURCHASE); expect(result.params).toEqual({ beneficiaryId: 1 }); }); it('should navigate to activate for existing devices', () => { const result = NavigationController.getRouteAfterAddBeneficiary(1, true); expect(result.path).toBe(ROUTES.AUTH.ACTIVATE); expect(result.params).toEqual({ beneficiaryId: 1 }); }); }); describe('getRouteAfterPurchase', () => { it('should handle null beneficiaryId', () => { const result = NavigationController.getRouteAfterPurchase(null, {}); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle undefined beneficiaryId', () => { const result = NavigationController.getRouteAfterPurchase(undefined, {}); expect(result.path).toBe(ROUTES.AUTH.ADD_LOVED_ONE); }); it('should handle null purchaseResult', () => { const result = NavigationController.getRouteAfterPurchase(1, null); expect(result.path).toBe(ROUTES.BENEFICIARY.EQUIPMENT(1)); }); it('should handle undefined purchaseResult', () => { const result = NavigationController.getRouteAfterPurchase(1, undefined); expect(result.path).toBe(ROUTES.BENEFICIARY.EQUIPMENT(1)); }); it('should navigate to activate for demo mode', () => { const result = NavigationController.getRouteAfterPurchase(1, { demo: true }); expect(result.path).toBe(ROUTES.AUTH.ACTIVATE); expect(result.params).toEqual({ beneficiaryId: 1, demo: true }); }); it('should navigate to equipment page for normal purchase', () => { const result = NavigationController.getRouteAfterPurchase(1, {}); expect(result.path).toBe(ROUTES.BENEFICIARY.EQUIPMENT(1)); }); }); describe('getRouteAfterActivation', () => { it('should handle null beneficiaryId', () => { const result = NavigationController.getRouteAfterActivation(null); expect(result.path).toBe(ROUTES.TABS.DASHBOARD); }); it('should handle undefined beneficiaryId', () => { const result = NavigationController.getRouteAfterActivation(undefined); expect(result.path).toBe(ROUTES.TABS.DASHBOARD); }); it('should handle invalid beneficiaryId type', () => { const result = NavigationController.getRouteAfterActivation('invalid' as any); expect(result.path).toBe(ROUTES.TABS.DASHBOARD); }); it('should navigate to beneficiary detail for valid id', () => { const result = NavigationController.getRouteAfterActivation(1); expect(result.path).toBe(ROUTES.BENEFICIARY.DETAIL(1)); expect(result.params).toEqual({ justActivated: true }); }); }); describe('getBeneficiaryRoute', () => { it('should handle null beneficiary', () => { const result = NavigationController.getBeneficiaryRoute(null, 'view'); expect(result.path).toBe(ROUTES.TABS.BENEFICIARIES); }); it('should handle undefined beneficiary', () => { const result = NavigationController.getBeneficiaryRoute(undefined, 'view'); expect(result.path).toBe(ROUTES.TABS.BENEFICIARIES); }); it('should handle beneficiary with invalid id', () => { const beneficiary = { id: null as any, name: 'Mom', displayName: 'Mom', status: 'online' as const, }; const result = NavigationController.getBeneficiaryRoute(beneficiary, 'view'); expect(result.path).toBe(ROUTES.TABS.BENEFICIARIES); }); it('should navigate to view for valid beneficiary', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', }; const result = NavigationController.getBeneficiaryRoute(beneficiary, 'view'); expect(result.path).toBe(ROUTES.BENEFICIARY.DETAIL(1)); }); it('should navigate to subscription for valid beneficiary', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', }; const result = NavigationController.getBeneficiaryRoute(beneficiary, 'subscription'); expect(result.path).toBe(ROUTES.BENEFICIARY.SUBSCRIPTION(1)); }); }); describe('shouldShowEquipmentSetup', () => { it('should return false for null beneficiary', () => { const result = NavigationController.shouldShowEquipmentSetup(null); expect(result).toBe(false); }); it('should return false for undefined beneficiary', () => { const result = NavigationController.shouldShowEquipmentSetup(undefined); expect(result).toBe(false); }); it('should return true for beneficiary without devices', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', hasDevices: false, equipmentStatus: 'none', }; const result = NavigationController.shouldShowEquipmentSetup(beneficiary); expect(result).toBe(true); }); it('should return false for beneficiary with devices', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', hasDevices: true, equipmentStatus: 'active', }; const result = NavigationController.shouldShowEquipmentSetup(beneficiary); expect(result).toBe(false); }); }); describe('getBeneficiaryCallToAction', () => { it('should return null for null beneficiary', () => { const result = NavigationController.getBeneficiaryCallToAction(null); expect(result).toBe(null); }); it('should return null for undefined beneficiary', () => { const result = NavigationController.getBeneficiaryCallToAction(undefined); expect(result).toBe(null); }); it('should return null for beneficiary with invalid id', () => { const beneficiary = { id: null as any, name: 'Mom', displayName: 'Mom', status: 'online' as const, }; const result = NavigationController.getBeneficiaryCallToAction(beneficiary); expect(result).toBe(null); }); it('should return null for active beneficiary', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', hasDevices: true, equipmentStatus: 'active', }; const result = NavigationController.getBeneficiaryCallToAction(beneficiary); expect(result).toBe(null); }); it('should return setup action for beneficiary with no equipment', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', hasDevices: false, equipmentStatus: 'none', }; const result = NavigationController.getBeneficiaryCallToAction(beneficiary); expect(result).not.toBe(null); expect(result?.label).toBe('Setup Equipment'); }); it('should return track delivery action for ordered equipment', () => { const beneficiary: Beneficiary = { id: 1, name: 'Mom', displayName: 'Mom', status: 'online', hasDevices: false, equipmentStatus: 'ordered', }; const result = NavigationController.getBeneficiaryCallToAction(beneficiary); expect(result).not.toBe(null); expect(result?.label).toBe('Track Delivery'); }); }); describe('getEquipmentStatusText', () => { it('should handle undefined status', () => { const result = NavigationController.getEquipmentStatusText(undefined); expect(result).toBe('Unknown'); }); it('should return correct text for each status', () => { expect(NavigationController.getEquipmentStatusText('none')).toBe('No equipment'); expect(NavigationController.getEquipmentStatusText('ordered')).toBe('Equipment ordered'); expect(NavigationController.getEquipmentStatusText('shipped')).toBe('In transit'); expect(NavigationController.getEquipmentStatusText('delivered')).toBe('Ready to activate'); expect(NavigationController.getEquipmentStatusText('active')).toBe('Active'); expect(NavigationController.getEquipmentStatusText('demo')).toBe('Demo mode'); }); }); describe('getEquipmentStatusColor', () => { it('should handle undefined status', () => { const result = NavigationController.getEquipmentStatusColor(undefined); expect(result).toBe('#888888'); // gray }); it('should return correct color for each status', () => { expect(NavigationController.getEquipmentStatusColor('none')).toBe('#888888'); expect(NavigationController.getEquipmentStatusColor('ordered')).toBe('#FFA500'); expect(NavigationController.getEquipmentStatusColor('shipped')).toBe('#007AFF'); expect(NavigationController.getEquipmentStatusColor('delivered')).toBe('#34C759'); expect(NavigationController.getEquipmentStatusColor('active')).toBe('#34C759'); expect(NavigationController.getEquipmentStatusColor('demo')).toBe('#9C27B0'); }); }); });