production
This commit is contained in:
214
test/group_accept_count_test.dart
Normal file
214
test/group_accept_count_test.dart
Normal file
@@ -0,0 +1,214 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:miler/data/service_profile.dart';
|
||||
import 'package:miler/views/Dashboard/home/route_timeline.dart';
|
||||
import 'package:miler/views/Dashboard/home/trip.dart';
|
||||
import 'package:miler/views/Dashboard/home/trip_card.dart';
|
||||
|
||||
/// ─────────────────────────────────────────────────────────────────────────
|
||||
/// `Accepted 1/10`, NOT `Accepted 1/63`
|
||||
///
|
||||
/// The kitchen card's state chip is a fraction: how many of this counter's
|
||||
/// orders the rider has taken, out of how many there are. The numerator was
|
||||
/// right and the denominator was the whole day.
|
||||
///
|
||||
/// ── What it was counting ──
|
||||
///
|
||||
/// [RouteGroup.allStops] is every order the trip ever bucketed under a source,
|
||||
/// and `groupSize` was its raw length. That deliberately includes orders the
|
||||
/// rider has **collected** — they left the visible list but not the counter,
|
||||
/// and renumbering the place under him is how a rider stops trusting a number.
|
||||
///
|
||||
/// It also included every order already **delivered** and every one he had
|
||||
/// **declined**, which are Activity's business and not this card's. Off a
|
||||
/// kitchen that supplies a rider all day that is most of the bucket: ten orders
|
||||
/// in the dropdown, one accepted, and a chip reading `Accepted 1/63` — a
|
||||
/// fraction whose denominator appears nowhere on the screen.
|
||||
///
|
||||
/// The load is now stated the way the rider would state it: **what is still in
|
||||
/// the dropdown, plus what he has already taken off this counter**.
|
||||
/// ─────────────────────────────────────────────────────────────────────────
|
||||
void main() {
|
||||
tearDown(() {
|
||||
Get.reset();
|
||||
ServiceProfile.setActive(ServiceProfile.parcel);
|
||||
});
|
||||
|
||||
/// One order off Vidhya Kitchen. [status] is what the backend calls it, which
|
||||
/// is what `stopStateOf` reads to place it on the ladder.
|
||||
Map<String, dynamic> order(int id, {required String status}) =>
|
||||
<String, dynamic>{
|
||||
'orderid': 'M-$id',
|
||||
'pickupid': id,
|
||||
'step': id,
|
||||
'kitchenname': 'Vidhya Kitchen',
|
||||
'sourceid': 'K1',
|
||||
'pickupcustomer': 'Customer $id',
|
||||
'pickupaddress': '9 Kitchen Street, Coimbatore',
|
||||
'dropaddress': 'Door $id, Peelamedu, Coimbatore',
|
||||
'orderstatus': status,
|
||||
'type': 'delivery',
|
||||
'pickuplat': 11.01,
|
||||
'pickuplon': 76.95,
|
||||
};
|
||||
|
||||
/// The card's own grouping, run the way the screen runs it.
|
||||
List<RouteGroup> groupsFor(
|
||||
List<Map<String, dynamic>> stops, {
|
||||
Set<String> accepted = const {},
|
||||
Set<String> collected = const {},
|
||||
}) {
|
||||
ServiceProfile.setActive(ServiceProfile.milkMan);
|
||||
return TripCard(
|
||||
trip: Trip.fromStops(id: 'T1', stops: stops),
|
||||
acceptedIds: accepted,
|
||||
collectedIds: collected,
|
||||
).routeGroups();
|
||||
}
|
||||
|
||||
group('the denominator is the counter, not the day', () {
|
||||
test('ten in the dropdown and one accepted reads 1 of 10', () {
|
||||
// The reported case, at the size it was reported: one kitchen, ten
|
||||
// orders still to decide, and fifty-three already delivered today.
|
||||
final stops = <Map<String, dynamic>>[
|
||||
for (var i = 1; i <= 10; i++) order(i, status: 'assigned'),
|
||||
for (var i = 11; i <= 63; i++) order(i, status: 'delivered'),
|
||||
];
|
||||
|
||||
final g = groupsFor(stops, accepted: {'M-1'}).single;
|
||||
|
||||
expect(g.stops.length, 10, reason: 'the dropdown holds ten');
|
||||
expect(g.allStops.length, 63, reason: 'the bucket still holds the day');
|
||||
expect(g.onRungCount, 1);
|
||||
expect(
|
||||
g.groupSize,
|
||||
10,
|
||||
reason: 'fifty-three delivered orders are Activity\'s, not this card\'s',
|
||||
);
|
||||
});
|
||||
|
||||
test('a collected order keeps its place in the arithmetic', () {
|
||||
// The original rationale, which must survive the fix: three bags are in
|
||||
// the rider's box and off Home, but they came off this counter and the
|
||||
// place still holds six.
|
||||
final stops = <Map<String, dynamic>>[
|
||||
for (var i = 1; i <= 6; i++) order(i, status: 'assigned'),
|
||||
];
|
||||
|
||||
final g = groupsFor(
|
||||
stops,
|
||||
accepted: {'M-1', 'M-2', 'M-3'},
|
||||
collected: {'M-1', 'M-2', 'M-3'},
|
||||
).single;
|
||||
|
||||
expect(g.stops.length, 3, reason: 'the collected three left Home');
|
||||
expect(
|
||||
g.groupSize,
|
||||
6,
|
||||
reason: 'renumbering the counter under him is the bug this prevents',
|
||||
);
|
||||
});
|
||||
|
||||
test('a declined order drops out of the load', () {
|
||||
final stops = <Map<String, dynamic>>[
|
||||
for (var i = 1; i <= 4; i++) order(i, status: 'assigned'),
|
||||
order(5, status: 'rejected'),
|
||||
];
|
||||
|
||||
final g = groupsFor(stops).single;
|
||||
|
||||
expect(g.groupSize, 4, reason: 'he has finished with the declined one');
|
||||
});
|
||||
|
||||
test('nothing delivered means the two counts agree', () {
|
||||
final stops = <Map<String, dynamic>>[
|
||||
for (var i = 1; i <= 5; i++) order(i, status: 'assigned'),
|
||||
];
|
||||
|
||||
final g = groupsFor(stops).single;
|
||||
|
||||
expect(g.groupSize, 5);
|
||||
expect(g.groupSize, g.allStops.length);
|
||||
});
|
||||
|
||||
test('a caller that tracks no states gets the old arithmetic', () {
|
||||
// Better to over-count than to invent a denominator: a hand-built group
|
||||
// with no `allStopStates` must not silently report zero.
|
||||
const g = RouteGroup(
|
||||
key: 'K1',
|
||||
name: 'Vidhya Kitchen',
|
||||
stops: [],
|
||||
allStops: [{}, {}, {}],
|
||||
firstIndex: 0,
|
||||
state: StopState.pending,
|
||||
stopStates: [],
|
||||
);
|
||||
|
||||
expect(g.groupSize, 3);
|
||||
});
|
||||
});
|
||||
|
||||
group('the chip on the card says the same number', () {
|
||||
Future<void> pump(
|
||||
WidgetTester tester,
|
||||
List<Map<String, dynamic>> stops, {
|
||||
Set<String> accepted = const {},
|
||||
}) async {
|
||||
ServiceProfile.setActive(ServiceProfile.milkMan);
|
||||
tester.view.physicalSize = const Size(390 * 3, 1600 * 3);
|
||||
tester.view.devicePixelRatio = 3;
|
||||
addTearDown(tester.view.reset);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ScreenUtilInit(
|
||||
designSize: const Size(390, 844),
|
||||
builder: (_, _) => MaterialApp(
|
||||
home: Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: TripCard(
|
||||
trip: Trip.fromStops(id: 'T1', stops: stops),
|
||||
acceptedIds: accepted,
|
||||
onToggleSelect: (_) {},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
testWidgets('the accepted chip is a fraction of the dropdown', (
|
||||
tester,
|
||||
) async {
|
||||
await pump(tester, [
|
||||
for (var i = 1; i <= 10; i++) order(i, status: 'assigned'),
|
||||
for (var i = 11; i <= 63; i++) order(i, status: 'delivered'),
|
||||
], accepted: {'M-1'});
|
||||
|
||||
expect(find.text('Accepted 1/10'), findsOneWidget);
|
||||
expect(
|
||||
find.text('Accepted 1/63'),
|
||||
findsNothing,
|
||||
reason: 'the day is not the counter',
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('a single-order place states no fraction at all', (
|
||||
tester,
|
||||
) async {
|
||||
// `Accepted (1 of 1)` is noise, and the guard for it reads `groupSize`.
|
||||
await pump(
|
||||
tester,
|
||||
[order(1, status: 'assigned')],
|
||||
accepted: {'M-1'},
|
||||
);
|
||||
|
||||
expect(find.text('Accepted'), findsOneWidget);
|
||||
expect(find.textContaining('Accepted 1/'), findsNothing);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user