Design system - MilerSurface ladder (canvas → working → raised → floating) with MilerPanel as layer 1; canvas moved to #DEE3EA so white separates at 1.290:1. - Visible vocabulary applied across Home, Deliveries, Activity, Account and the sheets: hero heads (tabular numeral + small caption, clamped at 1.3x), canvas wells for anything that opens, small filled tags for shelf labels, demoted placeholders. Recorded in DESIGN_SYSTEM.md §6. - One icon family: 222 Material glyphs migrated to Lucide; none left outside lib/xpress. - Colour semantics corrected: amber only for what is genuinely owed, brand red reserved for the live stop, disabled primaries go neutral rather than pale. Data and lifecycle - lib/data/lifecycle.dart reads mutations for what they prove; route_order.dart makes admin sequence the single ordering authority; service_day.dart, and stop_area.dart rewritten against live Coimbatore addresses (digit-token stripping, city stoplist, street suffixes, stammer collapse). - countLabel states the load once, in bags. Testing - 1440 tests passing; golden shot harnesses for Home, Deliveries, Activity, sheets and verify, with test/failures/ now gitignored (diff debris). - New pins: home_gutter_test, stop_area_test, plus updated structural bounds. Note: this commit also carries pre-existing working-tree deletions that were present before this work (API_SPEC.md, README.md, demo test fixtures). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
110 lines
4.7 KiB
Dart
110 lines
4.7 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:miler/data/meal_run_mock.dart';
|
|
import 'package:miler/data/mock_backend.dart';
|
|
import 'package:miler/data/service_profile.dart';
|
|
import 'package:miler/providers/pickup/pickup_provider.dart';
|
|
|
|
/// ─────────────────────────────────────────────────────────────────────────
|
|
/// A MISSING BACKEND IS A STATE, NOT A FIXTURE
|
|
///
|
|
/// The `/miler/*` contract serves bookings and consignments. Kitchens, crates
|
|
/// and subscribers are not concepts it has — there is no endpoint that returns
|
|
/// a meal run. That is a backend capability that does not exist yet.
|
|
///
|
|
/// It was being papered over by [MealRunMock], which was on by default in every
|
|
/// debug build. So the meal line *looked* integrated, and the gap was invisible
|
|
/// until somebody built a release.
|
|
///
|
|
/// These pin the boundary: the fixture is opt-in only, and with it off the
|
|
/// provider **refuses** rather than returning an empty list — because "no work
|
|
/// today" and "your hub has not switched this on" are different answers and the
|
|
/// rider acts differently on each.
|
|
/// ─────────────────────────────────────────────────────────────────────────
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
tearDown(() {
|
|
MockBackend.enabled = kMockBackend;
|
|
MealRunMock.reset();
|
|
ServiceProfile.setActive(ServiceProfile.parcel);
|
|
});
|
|
|
|
group('the capability is named, not implied', () {
|
|
test('the lines whose work IS bookings are served', () {
|
|
expect(ServiceProfile.parcel.hasBookingsEndpoint, isTrue);
|
|
expect(ServiceProfile.delivery.hasBookingsEndpoint, isTrue);
|
|
});
|
|
|
|
test('the milk-man line is served too — the hub dispatches it', () {
|
|
// This asserted `isFalse`, and that is what kept a real rider empty:
|
|
// tenant 13 resolves to this profile, the hub assigns him bookings in the
|
|
// console, and the app refused to ask for them. The console reads the
|
|
// round from /admin/bookings and assigns with
|
|
// /hub/bookings/:id/auto-assign — the same rows /miler/bookings returns.
|
|
expect(ServiceProfile.milkMan.hasBookingsEndpoint, isTrue);
|
|
});
|
|
|
|
test('the capability does not depend on the fixture', () {
|
|
// Whichever way it answers, an opt-in dev flag must not be what decides.
|
|
MockBackend.enabled = true;
|
|
expect(
|
|
ServiceProfile.milkMan.hasBookingsEndpoint,
|
|
isTrue,
|
|
reason: 'the fixture must never be what answers a backend capability',
|
|
);
|
|
});
|
|
});
|
|
|
|
group('with the fixture off, which is the default', () {
|
|
setUp(() => MockBackend.enabled = false);
|
|
|
|
test('a milk-man rider is not refused — he is dispatched bookings', () {
|
|
// Asserted on the capability rather than by calling, for the same reason
|
|
// as the parcel case below: the path now proceeds to a real request.
|
|
//
|
|
// This used to expect a [LineNotServedException]. It was the assertion
|
|
// that made the bug look intentional: a rider the hub had assigned work
|
|
// to could not be handed it, because his line was believed to have no
|
|
// endpoint. The refusal is still reachable — see [LineNotServedException]
|
|
// and the test below — it is just no longer this line's answer.
|
|
ServiceProfile.setActive(ServiceProfile.milkMan);
|
|
expect(ServiceProfile.active.hasBookingsEndpoint, isTrue);
|
|
});
|
|
|
|
test('the refusal explains itself', () {
|
|
expect(
|
|
const LineNotServedException().toString(),
|
|
contains('not served by the backend yet'),
|
|
);
|
|
});
|
|
|
|
test('a parcel rider is never refused — he has an endpoint', () {
|
|
// Asserted on the capability rather than by calling: the parcel path
|
|
// proceeds to a real request, and a test that reaches the network is a
|
|
// test about the network.
|
|
ServiceProfile.setActive(ServiceProfile.parcel);
|
|
expect(ServiceProfile.active.hasBookingsEndpoint, isTrue);
|
|
});
|
|
|
|
test('the fixture is unreachable while it is off', () {
|
|
ServiceProfile.setActive(ServiceProfile.milkMan);
|
|
expect(MealRunMock.active, isFalse);
|
|
});
|
|
});
|
|
|
|
test(
|
|
'the fixture is reachable only when asked for, and only on its line',
|
|
() {
|
|
MockBackend.enabled = true;
|
|
|
|
ServiceProfile.setActive(ServiceProfile.milkMan);
|
|
expect(MealRunMock.active, isTrue);
|
|
|
|
// And still not by a parcel rider, whatever else is true.
|
|
ServiceProfile.setActive(ServiceProfile.parcel);
|
|
expect(MealRunMock.active, isFalse);
|
|
},
|
|
);
|
|
}
|