import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:rippr/src/domain/models.dart'; import 'package:rippr/src/telemetry/telemetry.dart'; /// Ported from `com.rippr.TelemetryTest`. /// /// Tolerances are carried over as-is. Note the speed assertions: Kotlin's `Float` /// widened to `Double` yields 88.5 only within 1e-4, which is exactly why the original /// used that tolerance. Dart's uniform binary64 is exact here, but the tolerance is kept /// so the two suites stay comparable line for line. void main() { test('converts meters per second to kmh', () { expect(msToKmh(10), closeTo(36, 0.001)); expect(msToKmh(0), closeTo(0, 0.001)); }); test('gps jitter below the noise floor reports as zero', () { expect(sanitizeSpeedKmh(0.9), closeTo(0, 0.001)); expect(sanitizeSpeedKmh(double.nan), closeTo(0, 0.001)); expect(sanitizeSpeedKmh(-5), closeTo(0, 0.001)); }); test('real speeds pass through untouched', () { expect(sanitizeSpeedKmh(97.3), closeTo(97.3, 0.001)); }); test('rejects fixes worse than the accuracy budget', () { expect(isUsableFix(12), isTrue); expect(isUsableFix(0), isTrue, reason: 'unknown accuracy must not be discarded'); expect(isUsableFix(120), isFalse); }); test('formats duration as hh mm ss', () { expect(formatDuration(0), '00:00:00'); expect(formatDuration(-1), '00:00:00'); expect(formatDuration(65000), '00:01:05'); expect(formatDuration(7384000), '02:03:04'); }); test('encodes a batch as the documented payload shape', () { final points = [ const TrackPoint( id: 7, tripId: 3, segmentId: 5, timestamp: 1700000000000, latitude: 51.0447, longitude: -114.0719, speedKmh: 88.5, altitudeM: 1045.0, accuracyM: 4.2, bearingDeg: 271.5, ), ]; final json = jsonDecode(encodeBatch('device-abc', points)) as Map; expect(json['device_id'], 'device-abc'); final first = (json['points'] as List).first as Map; expect(first['id'], 7); expect(first['trip_id'], 3); expect(first['segment_id'], 5); expect(first['ts'], 1700000000000); expect(first['lat'] as double, closeTo(51.0447, 1e-6)); expect(first['lon'] as double, closeTo(-114.0719, 1e-6)); expect(first['speed_kmh'] as double, closeTo(88.5, 1e-4)); }); test('a batch spanning two segments labels each point individually', () { // A batch is drawn by id and can cross a boundary, so identity must travel with // the point rather than the batch. final points = [ const TrackPoint( id: 1, tripId: 3, segmentId: 5, timestamp: 1, latitude: 51.0, longitude: -114.0, speedKmh: 40, altitudeM: 1000.0), const TrackPoint( id: 2, tripId: 3, segmentId: 6, timestamp: 2, latitude: 51.1, longitude: -114.0, speedKmh: 40, altitudeM: 1000.0), ]; final array = (jsonDecode(encodeBatch('d', points)) as Map)['points'] as List; expect((array[0] as Map)['segment_id'], 5); expect((array[1] as Map)['segment_id'], 6); expect((array[0] as Map)['trip_id'], 3); }); test('encodes an empty batch without failing', () { final json = jsonDecode(encodeBatch('d', const [])) as Map; expect((json['points'] as List).length, 0); }); }