import 'package:flutter_test/flutter_test.dart'; import 'package:rippr/src/crash/crash_reporter.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; /// V3-12: a crash reporter in a location app is a privacy surface. Every test here /// exists to make a specific claim provable rather than assumed -- "the scrubber strips /// coordinates" and "disabled means never initialised" are both named directly in the /// ticket's Tests section. void main() { group('shouldInitializeCrashReporting', () { test('requires enabled, release, and a configured dsn all at once', () { expect( shouldInitializeCrashReporting(enabled: true, isDebug: false, dsn: 'https://x'), isTrue, ); }); test('the user toggle being off means the client is never initialised', () { expect( shouldInitializeCrashReporting(enabled: false, isDebug: false, dsn: 'https://x'), isFalse, ); }); test('debug builds send nothing, even if enabled', () { expect( shouldInitializeCrashReporting(enabled: true, isDebug: true, dsn: 'https://x'), isFalse, ); }); test('no dsn configured means no client, regardless of the toggle', () { expect( shouldInitializeCrashReporting(enabled: true, isDebug: false, dsn: ''), isFalse, ); }); }); group('scrubExtra', () { test('strips every coordinate-shaped key', () { final scrubbed = scrubExtra({ 'latitude': 51.0447, 'longitude': -114.0719, 'lat': 51.0, 'lon': -114.0, 'startLat': 51.0, 'gps_coords': '51.0,-114.0', 'altitude': 1045.0, 'safe_field': 'kept', })!; expect(scrubbed.containsKey('safe_field'), isTrue); expect(scrubbed, hasLength(1), reason: 'no field describing a location may survive: $scrubbed'); }); test('strips device and trip identity', () { final scrubbed = scrubExtra({ 'device_id': 'abc-123', 'deviceId': 'abc-123', 'trip_id': 42, 'tripId': 42, 'screen': 'record', })!; expect(scrubbed, {'screen': 'record'}); }); test('matching is case-insensitive and matches substrings', () { final scrubbed = scrubExtra({'Latitude': 1.0, 'nested.longitude': 2.0})!; expect(scrubbed, isEmpty); }); test('null in, null out', () { expect(scrubExtra(null), isNull); }); test('an already-clean map is returned unchanged in content', () { final scrubbed = scrubExtra({'screen': 'settings', 'action': 'tap'})!; expect(scrubbed, {'screen': 'settings', 'action': 'tap'}); }); }); group('event scrubbing end to end', () { test('a representative event with coordinates in extra and a breadcrumb comes ' 'out clean', () { final event = SentryEvent( // ignore: deprecated_member_use extra: {'latitude': 51.0447, 'longitude': -114.0719, 'screen': 'record'}, breadcrumbs: [ Breadcrumb( message: 'fix received', data: {'lat': 51.0, 'lon': -114.0, 'accuracy': 5.0}, ), ], ); // Exercises the same path SentryOptions.beforeSend is configured with in // maybeInitCrashReporting, without needing a real Sentry client. // ignore: deprecated_member_use final scrubbedExtra = scrubExtra(event.extra)!; final scrubbedBreadcrumbData = scrubExtra(event.breadcrumbs!.single.data)!; expect(scrubbedExtra.containsKey('latitude'), isFalse); expect(scrubbedExtra.containsKey('longitude'), isFalse); expect(scrubbedExtra['screen'], 'record'); expect(scrubbedBreadcrumbData.containsKey('lat'), isFalse); expect(scrubbedBreadcrumbData.containsKey('lon'), isFalse); expect(scrubbedBreadcrumbData['accuracy'], 5.0, reason: 'accuracy is not a coordinate and carries no location on its own'); }); }); }