73 lines
2.7 KiB
Dart
73 lines
2.7 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:miler/data/rider_tier.dart';
|
|
|
|
/// The ladder behind the Rewards page. Modelled on Uber Pro: points earned over
|
|
/// a fixed period decide the status, and the screen's job is to answer "how far
|
|
/// is the next one" in points a rider can act on today.
|
|
void main() {
|
|
group('standing', () {
|
|
test('starts at the bottom rung', () {
|
|
final s = TierStanding.of(0);
|
|
expect(s.tier, RiderTier.blue);
|
|
expect(s.nextTier, RiderTier.silver);
|
|
expect(s.pointsToNext, kTierThresholds[RiderTier.silver]);
|
|
expect(s.progressToNext, 0);
|
|
});
|
|
|
|
test('lands on the highest threshold passed, not the nearest', () {
|
|
expect(TierStanding.of(149).tier, RiderTier.blue);
|
|
expect(TierStanding.of(150).tier, RiderTier.silver);
|
|
expect(TierStanding.of(399).tier, RiderTier.silver);
|
|
expect(TierStanding.of(400).tier, RiderTier.gold);
|
|
});
|
|
|
|
// A rider one point into Gold should see an empty bar to Platinum, not a
|
|
// bar already half full because his lifetime number is big.
|
|
test('progress is measured across the current band', () {
|
|
final justIn = TierStanding.of(400);
|
|
expect(justIn.tier, RiderTier.gold);
|
|
expect(justIn.progressToNext, 0);
|
|
|
|
final halfway = TierStanding.of(600); // 400 → 800
|
|
expect(halfway.progressToNext, closeTo(0.5, 0.001));
|
|
});
|
|
|
|
test('the top of the ladder has nothing left to chase', () {
|
|
final s = TierStanding.of(5000);
|
|
expect(s.tier, RiderTier.platinum);
|
|
expect(s.nextTier, isNull);
|
|
expect(s.pointsToNext, isNull);
|
|
expect(s.progressToNext, 1);
|
|
});
|
|
|
|
test('every tier knows the one above it, and the last one does not', () {
|
|
expect(RiderTier.blue.next, RiderTier.silver);
|
|
expect(RiderTier.gold.next, RiderTier.platinum);
|
|
expect(RiderTier.platinum.next, isNull);
|
|
});
|
|
});
|
|
|
|
group('reward period', () {
|
|
test('is the calendar month, whole and inclusive', () {
|
|
final p = RewardPeriod.current(DateTime(2026, 8, 5));
|
|
expect(p.start, DateTime(2026, 8, 1));
|
|
expect(p.end, DateTime(2026, 8, 31));
|
|
expect(p.label, 'August 2026');
|
|
});
|
|
|
|
test('counts today as a day left, and never goes negative', () {
|
|
final p = RewardPeriod.current(DateTime(2026, 8, 30));
|
|
expect(p.daysLeft(DateTime(2026, 8, 30)), 2);
|
|
expect(p.daysLeft(DateTime(2026, 8, 31)), 1);
|
|
expect(p.daysLeft(DateTime(2026, 9, 4)), 0);
|
|
});
|
|
|
|
test('handles a December period rolling into the new year', () {
|
|
final p = RewardPeriod.current(DateTime(2026, 12, 10));
|
|
expect(p.end, DateTime(2026, 12, 31));
|
|
expect(p.label, 'December 2026');
|
|
});
|
|
});
|
|
}
|