V3-10: trip splitting

TripRepository.splitTrip mirrors mergeTrips' transaction shape: splits at a segment boundary, moves the target segment and everything after it to a new trip, recomputes both trips' aggregates from scratch. startedAt/endedAt derive from each trip's actual remaining segments, not copied from the pre-split row. Trip detail gained a split action with a segment-boundary picker and a naming confirmation; a single-segment ride explains why it can't split instead of offering a dead control.
This commit is contained in:
2026-08-17 19:23:44 -05:00
parent a1e99684e0
commit 0e605ef174
7 changed files with 417 additions and 2 deletions

View File

@@ -593,5 +593,65 @@ void main() {
expect(find.text(imperialValue), findsWidgets);
}
});
screenTest('a single-segment ride explains why it cannot be split (V3-10)',
(tester) async {
final id = await seedCompletedTrip(startedAt: 1000, endedAt: 5000);
await tester.pumpWidget(host(TripDetailScreen(tripId: id), map: false));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('split')));
await tester.pumpAndSettle();
expect(find.textContaining('nothing to split'), findsOneWidget);
expect(await repo.segmentsForTrip(id), hasLength(1),
reason: 'a rejected split must not touch anything');
});
screenTest('splitting a multi-segment ride creates a second ride (V3-10)',
(tester) async {
final h = await repo.startTrip(1000);
await repo.appendPoints([
TrackPoint(
tripId: h.tripId,
segmentId: h.segmentId,
timestamp: 1000,
latitude: 51.0,
longitude: -114.0,
speedKmh: 40.0,
altitudeM: 1000.0,
),
]);
await repo.pauseTrip(2000);
final h2 = (await repo.resumeTrip(3000))!;
await repo.appendPoints([
TrackPoint(
tripId: h2.tripId,
segmentId: h2.segmentId,
timestamp: 3000,
latitude: 52.0,
longitude: -114.0,
speedKmh: 40.0,
altitudeM: 1000.0,
),
]);
await repo.completeTrip(4000);
final segments = await repo.segmentsForTrip(h.tripId);
expect(segments, hasLength(2));
await tester.pumpWidget(host(TripDetailScreen(tripId: h.tripId), map: false));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('split')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(Key('split-at-${segments[1].id}')));
await tester.pumpAndSettle();
await tester.tap(find.text('Split'));
await tester.pumpAndSettle();
expect(await db.countTrips(), 2);
expect(await repo.segmentsForTrip(h.tripId), hasLength(1));
});
});
}