Refresh the Flutter snapshot: v3 tickets V3-04 through V3-16, plus a fresh installable APK
V3-04 through V3-07, V3-10, V3-16 shipped complete; V3-11/V3-12/V3-14 shipped code-complete pending device/account verification; V3-08/V3-09 deferred behind a new V3-17 (self-hosted OSRM investigation). 316 tests passing, up from 221. The APK is a fresh release build (debug-signed, no release signing config exists yet) with two build fixes applied: core library desugaring enabled for flutter_local_notifications, and sentry_flutter bumped to 9.27.0 (8.14.2's bundled Kotlin plugin was incompatible with this project's Kotlin 2.4.0 toolchain).
This commit is contained in:
114
rippr-flutter-src/test/crash_reporter_test.dart
Normal file
114
rippr-flutter-src/test/crash_reporter_test.dart
Normal file
@@ -0,0 +1,114 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user