first commit
This commit is contained in:
114
test/stop_compliance_test.dart
Normal file
114
test/stop_compliance_test.dart
Normal file
@@ -0,0 +1,114 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:miler/data/stop_compliance.dart';
|
||||
|
||||
/// The two verdicts the hub pays on. Both were already being measured — the
|
||||
/// bonus rule is "before the ETA" and the distance is measured to bill rider
|
||||
/// charges — and neither reached the rider until now, so the arithmetic behind
|
||||
/// them is worth pinning.
|
||||
void main() {
|
||||
group('one stop', () {
|
||||
test('on time and within the route tolerance is clean', () {
|
||||
const c = StopCompliance(onTime: true, actualKm: 5.4, plannedKm: 5.0);
|
||||
expect(c.onRoute, isTrue);
|
||||
expect(c.isClean, isTrue);
|
||||
expect(c.extraKm, isNull);
|
||||
});
|
||||
|
||||
test('a wander past the tolerance is off route, and says by how much', () {
|
||||
const c = StopCompliance(onTime: true, actualKm: 12.0, plannedKm: 5.0);
|
||||
expect(c.onRoute, isFalse);
|
||||
expect(c.extraKm, 7.0);
|
||||
expect(c.isClean, isFalse, reason: 'both halves have to hold');
|
||||
});
|
||||
|
||||
// Traffic, one-ways and diversions are the rider's normal, not a detour.
|
||||
test('ordinary slack does not count as leaving the route', () {
|
||||
const near = StopCompliance(actualKm: 6.2, plannedKm: 5.0); // +24%
|
||||
expect(near.onRoute, isTrue);
|
||||
const grace = StopCompliance(actualKm: 1.4, plannedKm: 1.0); // short hop
|
||||
expect(grace.onRoute, isTrue,
|
||||
reason: 'a fixed grace keeps short stops from failing on rounding');
|
||||
});
|
||||
|
||||
test('late is not clean, however good the route', () {
|
||||
const c = StopCompliance(
|
||||
onTime: false,
|
||||
lateBy: Duration(minutes: 9),
|
||||
actualKm: 4.0,
|
||||
plannedKm: 5.0,
|
||||
);
|
||||
expect(c.onRoute, isTrue);
|
||||
expect(c.isClean, isFalse);
|
||||
});
|
||||
|
||||
// A hub that set no ETA, a GPS that never resolved: not the rider's fault
|
||||
// and never shown as a miss.
|
||||
test('missing inputs are unknown, not failures', () {
|
||||
const nothing = StopCompliance();
|
||||
expect(nothing.isUnknown, isTrue);
|
||||
expect(nothing.onRoute, isNull);
|
||||
expect(nothing.isClean, isFalse);
|
||||
|
||||
const zeroPlan = StopCompliance(actualKm: 3.0, plannedKm: 0);
|
||||
expect(zeroPlan.onRoute, isNull,
|
||||
reason: 'a planned distance of zero is missing, not perfect');
|
||||
});
|
||||
});
|
||||
|
||||
group('reading a stored stop', () {
|
||||
test('prefers the stamp written at completion', () {
|
||||
final c = StopCompliance.of({
|
||||
'compliance': {
|
||||
'ontime': true,
|
||||
'latebyseconds': 0,
|
||||
'actualkm': 4.0,
|
||||
'plannedkm': 4.0,
|
||||
},
|
||||
'riderkms': '99',
|
||||
'kms': '1',
|
||||
});
|
||||
expect(c.onTime, isTrue);
|
||||
expect(c.actualKm, 4.0);
|
||||
expect(c.onRoute, isTrue);
|
||||
});
|
||||
|
||||
test('falls back to the backend row when there is no stamp', () {
|
||||
final c = StopCompliance.of({'riderkms': '9.0', 'kms': '4'});
|
||||
expect(c.onTime, isNull);
|
||||
expect(c.onRoute, isFalse, reason: '9km against a 4km plan is a wander');
|
||||
});
|
||||
});
|
||||
|
||||
group('the day', () {
|
||||
test('scores only what could be measured', () {
|
||||
final summary = ComplianceSummary.from([
|
||||
{
|
||||
'compliance': {'ontime': true, 'actualkm': 4.0, 'plannedkm': 4.0}
|
||||
},
|
||||
{
|
||||
'compliance': {'ontime': false, 'actualkm': 4.0, 'plannedkm': 4.0}
|
||||
},
|
||||
{
|
||||
'compliance': {'ontime': true, 'actualkm': 20.0, 'plannedkm': 4.0}
|
||||
},
|
||||
{'orderid': 'no-data'},
|
||||
]);
|
||||
|
||||
expect(summary.measured, 3);
|
||||
expect(summary.unmeasured, 1, reason: 'and it is not in the denominator');
|
||||
expect(summary.onTime, 2);
|
||||
expect(summary.onRoute, 2);
|
||||
expect(summary.clean, 1);
|
||||
expect(summary.points, 1, reason: 'a point per stop that cleared both');
|
||||
expect(summary.onTimePercent, 67);
|
||||
});
|
||||
|
||||
test('an empty day scores nothing rather than dividing by zero', () {
|
||||
final summary = ComplianceSummary.from(const []);
|
||||
expect(summary.points, 0);
|
||||
expect(summary.onTimePercent, 0);
|
||||
expect(summary.cleanPercent, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user