/** * A subscription must ring while the app is not focused. * * On Android the JS runtime (and therefore the JS socket) stops when the app is * backgrounded; the only supported delivery path is the native foreground * service, which holds its own WebSocket. Nothing in the app used to start it — * the toggle lived on one screen — so a plain subscriber only ever rang while * the app was open. These assertions pin the automatic arming and the facts it * depends on (a credential the service can use, and its notification). */ export {}; declare const __dirname: string; const fs = require('fs') as { readFileSync(p: string, enc: string): string }; const path = require('path') as { join(...parts: string[]): string }; const context = fs.readFileSync( path.join(__dirname, '..', 'src', 'state', 'AlarmContext.tsx'), 'utf8', ); const moduleKt = fs.readFileSync( path.join( __dirname, '..', 'android', 'app', 'src', 'main', 'java', 'com', 'dcntrlized', 'alarm', 'AlarmModule.kt', ), 'utf8', ); const home = fs.readFileSync( path.join(__dirname, '..', 'src', 'screens', 'HomeScreen.tsx'), 'utf8', ); describe('background arming', () => { it('starts the foreground service from the provider, not from one screen', () => { expect(context).toContain('startForegroundService('); expect(context).toContain('alarmSocketUrl('); }); it('arms the alert the provider is actively listening to', () => { const at = context.indexOf('const armedAttemptRef'); expect(at).toBeGreaterThan(-1); const body = context.slice(at, at + 2200); expect(body).toContain('activeAlert.alertId'); expect(body).toContain('activeAlert.subscribeToken'); // The service cannot refresh a session, so only a device token works here. expect(body).toContain('if (!activeAlert.deviceToken) return;'); expect(body).toContain('activeAlert.deviceToken'); }); it('asks for the notification a foreground service cannot run without', () => { expect(context).toContain('requestPermission('); expect(context).toContain("'notifications'"); // The native side refuses to start a service whose notification cannot show. expect(moduleKt).toContain('notifications-not-granted'); }); it('does not retry a refused start in a tight loop', () => { expect(context).toMatch(/300_000/); }); it('reports whether the background listener is running, and does not pretend', () => { expect(home).toContain('backgroundListening'); expect(home).toContain('triggers arrive even when this app is closed'); }); });