FB-07: fix Route Planner opening on Null Island

A brand-new route (or one with fewer than two pins) now falls back to the
ambient GPS position for its initial map center instead of (0, 0) in the
middle of the ocean, reusing FB-01's ambientPositionProvider. Routes with
one or more real waypoints are unaffected. Falls back to (0, 0) as before
when no ambient fix is available.

Adds three widget tests covering the fixed-fix, no-fix, and
real-waypoint-wins cases. Emulator verification was attempted but the
Android emulator became unresponsive partway through and was abandoned
per the ticket's conservative-use guidance; details in the ticket's
Outcome section.
This commit is contained in:
2026-08-25 00:10:32 -05:00
parent 08f2cfbf02
commit 97e3aaa5a0
3 changed files with 289 additions and 3 deletions

View File

@@ -7,6 +7,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:rippr/src/app/providers.dart';
import 'package:rippr/src/data/database.dart';
import 'package:rippr/src/data/route_plan_repository.dart';
import 'package:rippr/src/recording/location_source.dart' show LocationFix;
import 'package:rippr/src/ui/app_shell.dart';
import 'package:rippr/src/ui/components/floating_pill.dart';
import 'package:rippr/src/ui/components/ride_map.dart' show ambientZoom;
@@ -30,8 +31,8 @@ void main() {
tearDown(() async => db.close());
Widget host(Widget child) => ProviderScope(
overrides: [databaseProvider.overrideWithValue(db)],
Widget host(Widget child, {List<Override> overrides = const []}) => ProviderScope(
overrides: [databaseProvider.overrideWithValue(db), ...overrides],
child: MaterialApp(theme: ripprTheme(), home: child),
);
@@ -227,6 +228,79 @@ void main() {
expect(map.options.initialZoom, ambientZoom);
});
screenTest('a brand-new route opens centered on the rider\'s real location, '
'not Null Island (FB-07)', (tester) async {
const fix = LocationFix(
timestamp: 1000,
latitude: 51.05,
longitude: -114.07,
speedMps: 0,
altitudeM: 0,
accuracyM: 5,
bearingDeg: 0,
);
final id = await repo.createRoutePlan(1000);
await pumpMap(
tester,
host(
RoutePlannerScreen(routeId: id),
overrides: [
ambientPositionProvider.overrideWith((ref) => Stream.value(fix)),
],
),
);
final map = tester.widget<FlutterMap>(find.byType(FlutterMap));
expect(map.options.initialCenter.latitude, closeTo(51.05, 1e-9));
expect(map.options.initialCenter.longitude, closeTo(-114.07, 1e-9));
});
screenTest('a brand-new route falls back to (0, 0) when no ambient fix is '
'available (FB-07)', (tester) async {
final id = await repo.createRoutePlan(1000);
await pumpMap(
tester,
host(
RoutePlannerScreen(routeId: id),
overrides: [
ambientPositionProvider.overrideWith((ref) => Stream.value(null)),
],
),
);
final map = tester.widget<FlutterMap>(find.byType(FlutterMap));
expect(map.options.initialCenter.latitude, 0);
expect(map.options.initialCenter.longitude, 0);
});
screenTest('a route with a real waypoint still centers on the pin, not the '
'ambient position (FB-07)', (tester) async {
const fix = LocationFix(
timestamp: 1000,
latitude: 51.05,
longitude: -114.07,
speedMps: 0,
altitudeM: 0,
accuracyM: 5,
bearingDeg: 0,
);
final id = await repo.createRoutePlan(1000);
await repo.addWaypoint(id, 51.0, -114.0);
await pumpMap(
tester,
host(
RoutePlannerScreen(routeId: id),
overrides: [
ambientPositionProvider.overrideWith((ref) => Stream.value(fix)),
],
),
);
final map = tester.widget<FlutterMap>(find.byType(FlutterMap));
expect(map.options.initialCenter.latitude, closeTo(51.0, 1e-9));
expect(map.options.initialCenter.longitude, closeTo(-114.0, 1e-9));
});
screenTest('the offline-tiles download menu item is disabled with no pins '
'(V3-11, UI-06: now a PopupMenuItem behind the overflow menu)',
(tester) async {