150 lines
5.3 KiB
Dart
150 lines
5.3 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:miler/views/Dashboard/home/trip.dart';
|
|
import 'package:miler/data/service_profile.dart';
|
|
|
|
/// ─────────────────────────────────────────────────────────────────────────
|
|
/// THE BRIEF DESCRIBES WHAT IS LEFT
|
|
///
|
|
/// Home's brief card carries four figures — duration, distance, parcels,
|
|
/// payment — under a headline that counts down (`20 stops left`).
|
|
///
|
|
/// The headline moved as the rider worked. The figures did not. They were
|
|
/// counted once over every stop the slot ever held, so a rider with five
|
|
/// collections to go read `≈4h 15m · 29.0 km · 25 parcels`: the morning he
|
|
/// started with, including the twenty already in his box and gone to
|
|
/// Deliveries. The one question the card exists to answer — *what is in front
|
|
/// of me* — was the one thing on it that was stale.
|
|
///
|
|
/// [Trip.outstanding] is the recount. The line it draws is
|
|
/// `WorkBoundary.pickupComplete`, the same boundary Home and Deliveries split
|
|
/// on, so a stop cannot be counted here and owned there.
|
|
/// ─────────────────────────────────────────────────────────────────────────
|
|
void main() {
|
|
tearDown(() => ServiceProfile.setActive(ServiceProfile.parcel));
|
|
|
|
Map<String, dynamic> stop(
|
|
String id, {
|
|
String status = 'accepted',
|
|
int parcels = 1,
|
|
double lat = 11.0,
|
|
double lng = 76.95,
|
|
double cash = 0,
|
|
}) => {
|
|
'orderid': id,
|
|
'pickupid': id,
|
|
'orderstatus': status,
|
|
'pickupquantity': parcels,
|
|
'pickuplat': lat,
|
|
'pickuplon': lng,
|
|
'collectionamt': cash,
|
|
};
|
|
|
|
group('what the figures count', () {
|
|
test('a collected stop drops out of every figure', () {
|
|
final trip = Trip.fromStops(
|
|
id: 't1',
|
|
stops: [
|
|
stop('A', status: 'picked', lat: 11.00, lng: 76.90),
|
|
stop('B', lat: 11.05, lng: 76.95),
|
|
stop('C', lat: 11.10, lng: 77.00),
|
|
],
|
|
hubLat: 11.0,
|
|
hubLng: 76.95,
|
|
);
|
|
|
|
final left = trip.outstanding(originLat: 11.0, originLng: 76.95);
|
|
|
|
expect(trip.stopCount, 3, reason: 'the trip itself is untouched');
|
|
expect(left.stopCount, 2);
|
|
expect(left.totalParcels, lessThan(trip.totalParcels));
|
|
expect(left.totalDuration, lessThan(trip.totalDuration));
|
|
expect(left.routeMeters, lessThan(trip.routeMeters));
|
|
});
|
|
|
|
test('the local collected record counts, not just the status', () {
|
|
// The queue is a poll behind, so a stop the rider has just handed over
|
|
// still reports its old status. `collectedIds` is what closes that
|
|
// window — the same set Home writes after pickup-complete returns.
|
|
final trip = Trip.fromStops(
|
|
id: 't1',
|
|
stops: [stop('A'), stop('B')],
|
|
);
|
|
|
|
expect(trip.outstanding().stopCount, 2, reason: 'nothing collected yet');
|
|
expect(trip.outstanding(collectedIds: const {'A'}).stopCount, 1);
|
|
});
|
|
|
|
test('nothing collected returns the very same object', () {
|
|
// The common case — a rider who has not started — must not pay for a
|
|
// rebuild of the whole trip on every frame of the brief.
|
|
final trip = Trip.fromStops(id: 't1', stops: [stop('A'), stop('B')]);
|
|
expect(identical(trip.outstanding(), trip), isTrue);
|
|
});
|
|
|
|
test('skipped and cancelled work is not still-to-do', () {
|
|
final trip = Trip.fromStops(
|
|
id: 't1',
|
|
stops: [
|
|
stop('A', status: 'skipped'),
|
|
stop('B', status: 'cancelled'),
|
|
stop('C'),
|
|
],
|
|
);
|
|
expect(
|
|
trip.outstanding().stopCount,
|
|
1,
|
|
reason: 'a written-off stop is a record, not a stop to plan around',
|
|
);
|
|
});
|
|
|
|
test('a run with everything collected leaves nothing to describe', () {
|
|
final trip = Trip.fromStops(
|
|
id: 't1',
|
|
stops: [
|
|
stop('A', status: 'picked'),
|
|
stop('B', status: 'picked'),
|
|
],
|
|
);
|
|
final left = trip.outstanding();
|
|
expect(left.stopCount, 0);
|
|
expect(left.totalParcels, 0);
|
|
expect(
|
|
left.totalDuration,
|
|
Duration.zero,
|
|
reason: 'the four cells fall back to the em dash, not to a stale figure',
|
|
);
|
|
});
|
|
});
|
|
|
|
group('payment on a meal run', () {
|
|
test('is nothing to collect, whatever the payload says', () {
|
|
ServiceProfile.setActive(ServiceProfile.milkMan);
|
|
final trip = Trip.fromStops(
|
|
id: 't1',
|
|
stops: [stop('A', cash: 250), stop('B', cash: 130)],
|
|
);
|
|
// The cell prints the em dash when this is zero — the rider on a meal
|
|
// run is never asked for money, so a figure here would be a prompt to
|
|
// collect one.
|
|
expect(trip.outstanding().cashToCollect, 0);
|
|
});
|
|
|
|
test('but a parcel route still counts the cash it is owed', () {
|
|
ServiceProfile.setActive(ServiceProfile.parcel);
|
|
final trip = Trip.fromStops(
|
|
id: 't1',
|
|
stops: [
|
|
stop('A', status: 'picked', cash: 250),
|
|
stop('B', cash: 130),
|
|
],
|
|
);
|
|
expect(
|
|
trip.outstanding().cashToCollect,
|
|
130,
|
|
reason: 'the collected stop\'s cash is no longer waiting to be taken',
|
|
);
|
|
});
|
|
});
|
|
}
|