Files
doormile_milderapp/test/delivery_shell_smoke_test.dart
Thiru-tenext d7348e253f Miler rider app: surface system, visible design language, backend lifecycle
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>
2026-08-22 05:40:35 +05:30

112 lines
5.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:miler/data/service_profile.dart';
import 'package:miler/helpers/rider_shell.dart';
/// Does the ported delivery dashboard actually *build*?
///
/// ── Why this is worth a test of its own ──
///
/// `delivery_line_test.dart` checks that [riderShell] returns the right widget
/// *type*, which is a cheap assertion: it constructs nothing. The failure this
/// port was most exposed to is one type-checking cannot see — the delivery home
/// page resolves its controller in a **field initialiser**:
///
/// final DeliveryController _deliveryController = Get.find<DeliveryController>();
///
/// GetX keys its container on type, and both lines declare a class called
/// `RiderLogController`, `LogController` and `ProfileController`. So a delivery
/// screen asking for "the" RiderLogController gets nothing unless the *xpress*
/// type was registered — and it throws while the widget is being constructed,
/// before any frame, which a rider sees as a red screen rather than an empty
/// list. See `bootstrapDeliveryLine`.
///
/// Pumping the shell for real is the only thing that catches that.
///
/// ── Why there is no matching test for the parcel shell ──
///
/// The parcel dashboard reads `PickupController` and friends out of the GetX
/// container too, but nothing registers them for it — `main()` does, and tests
/// do not run `main()`. Pumping it here would be testing this file's ability to
/// re-implement `main()`, not the app.
///
/// The delivery shell needs no such scaffolding, and that asymmetry is the
/// point: [riderShell] calls `registerDeliveryLine()` on the way in, precisely
/// because a rider can reach it mid-session by signing out of one line and into
/// the other. This test passing with no setup *is* that guard working — and it
/// is what caught the first version of that call being `async`, which registered
/// nothing before the shell built.
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
// ── What is allowed to have gone wrong ──
//
// One thing, inherited with the markup: Flutter's debug-only complaint that a
// `ListTile` sits inside a coloured `DecoratedBox`, so its ink splash is
// hidden. Cosmetic, debug-only, and present in Xpress-rider before the port.
//
// Filtered at `FlutterError.onError` rather than drained afterwards with
// `takeException`, which returns one exception at a time while the harness
// fails the test on the whole batch. Everything else still reaches the
// default handler and still fails the test — in particular a `Get.find`
// failure or a missing plugin, which would mean the port does not run.
//
// Installed **inside the test body**, not in `setUp`: the test binding
// installs its own reporter when it starts running the body, which is after
// `setUp`, so a handler set there is overwritten before the first pump.
tearDown(() => ServiceProfile.setActive(ServiceProfile.parcel));
testWidgets('the delivery dashboard builds and shows its four tabs', (
tester,
) async {
final reportToHarness = FlutterError.onError;
FlutterError.onError = (details) {
if (details.exceptionAsString().contains(
'ListTile background color or ink splashes',
)) {
return;
}
reportToHarness?.call(details);
};
addTearDown(() => FlutterError.onError = reportToHarness);
SharedPreferences.setMockInitialValues({});
// ── Set directly, not resolved ──
//
// No tenant name or id opens this line any more; only
// `--dart-define=TENANT=delivery` does, and that is a compile-time constant
// a test cannot set. See `delivery_line_test.dart` for why the wire route
// was closed.
//
// What this test is actually for survives that unchanged: it is the guard
// on `registerDeliveryLine()` being **synchronous**. An async version
// returns at its first await, the framework builds the shell in the gap,
// and the home page throws on a controller that is about to exist. Only
// pumping the real shell catches it.
ServiceProfile.setActive(ServiceProfile.delivery);
await tester.pumpWidget(
ScreenUtilInit(
designSize: const Size(390, 844),
builder: (_, _) => MaterialApp(home: riderShell()),
),
);
await tester.pump();
// The ported Xpress-rider bar, verbatim: four fixed tabs, shouted in caps.
// If the controllers had not been registered, none of this would exist —
// the page would have thrown on construction.
expect(find.text('HOME'), findsOneWidget);
expect(find.text('DELIVERIES'), findsOneWidget);
expect(find.text('SUMMARY'), findsOneWidget);
expect(find.text('PROFILE'), findsOneWidget);
// And it is not the parcel bar wearing different words.
expect(find.text('Activity'), findsNothing);
expect(find.text('Bookings'), findsNothing);
});
}