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>
106 lines
3.8 KiB
Dart
106 lines
3.8 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:miler/data/stop_area.dart';
|
|
|
|
/// ── The rule, pinned against the addresses that broke it ──
|
|
///
|
|
/// `areaOf` has been wrong three times, each on a real address from this
|
|
/// tenant, and each fix was verified on a device rather than on a guess. The
|
|
/// cases below are those addresses. A change that shortens or "simplifies"
|
|
/// the rule must survive every one of them.
|
|
void main() {
|
|
String area(String addr) => areaOf({'dropaddress': addr});
|
|
|
|
test('a door number does not take its locality with it', () {
|
|
// The v2 rule dropped any part containing a digit, so this answered with
|
|
// the city — and on a Coimbatore route every stop is in Coimbatore, which
|
|
// is a queue that says nothing. The number is stripped, the name kept.
|
|
expect(area('12 Peelamedu, Coimbatore'), 'Peelamedu');
|
|
});
|
|
|
|
test('the classic comma form still yields the locality', () {
|
|
expect(area('12, SNS Colony, Peelamedu, Coimbatore 641004'), 'Peelamedu');
|
|
});
|
|
|
|
test('a landmark phrase never wins over the name behind it', () {
|
|
// Seen live: the first digit-free part was this whole landmark, printed
|
|
// on every row of the run, wrapped to two lines.
|
|
expect(
|
|
area(
|
|
'Coimbatore Gandhipuram Mofussil Bus Stand, Sathyamurthi Road, '
|
|
'Gandhipuram, Ward 54, West Zone',
|
|
),
|
|
'Gandhipuram',
|
|
);
|
|
});
|
|
|
|
test('a street with a door number is passed over for the area', () {
|
|
expect(
|
|
area('14 Cross Cut Road, Gandhipuram, Coimbatore 641012'),
|
|
'Gandhipuram',
|
|
);
|
|
expect(area('12, Cross Cut Road, Gandhipuram'), 'Gandhipuram');
|
|
});
|
|
|
|
test('a stammered locality is one locality', () {
|
|
// Live: the geocoder writes `Gandhipuram Gandhipuram` as one part, and
|
|
// the queue printed the stutter on every row it headed.
|
|
expect(area('12, Gandhipuram Gandhipuram, Coimbatore'), 'Gandhipuram');
|
|
expect(area('4 Cross, RS Puram RS Puram, Coimbatore'), 'RS Puram');
|
|
});
|
|
|
|
test('Ward 54 is not a place called Ward', () {
|
|
// Stripping digits can leave administrative residue; it must be discarded,
|
|
// not promoted to a one-word name.
|
|
expect(area('Ward 54, Peelamedu, Coimbatore'), 'Peelamedu');
|
|
});
|
|
|
|
test('with no one-word locality, the street beats the city', () {
|
|
// "Race Course" is the locality's actual name here; the city rung would
|
|
// distinguish nothing on a route where every stop ends in Coimbatore.
|
|
expect(area('22 Race Course Road, Coimbatore'), 'Race Course Road');
|
|
// But a bare city with nothing before it is still an honest answer.
|
|
expect(area('Coimbatore'), 'Coimbatore');
|
|
});
|
|
|
|
test('an empty address returns nothing, never a placeholder', () {
|
|
expect(area(''), '');
|
|
expect(areaOf(const {}), '');
|
|
});
|
|
|
|
group('compactAddress', () {
|
|
test('geocoder boilerplate comes off; every place stays', () {
|
|
expect(
|
|
compactAddress(
|
|
'RS Puram RS Puram, Ward 24, West Zone, Perur, Coimbatore South, '
|
|
'Coimbatore, Tamil Nadu, 641002, India',
|
|
),
|
|
'RS Puram, Ward 24, West Zone, Perur, Coimbatore South, Coimbatore',
|
|
);
|
|
});
|
|
|
|
test('a hand-typed address passes through untouched', () {
|
|
expect(
|
|
compactAddress('12, SNS Colony, Peelamedu, Coimbatore 641004'),
|
|
'12, SNS Colony, Peelamedu, Coimbatore 641004',
|
|
);
|
|
});
|
|
|
|
test('an immediate duplicate part collapses', () {
|
|
expect(
|
|
compactAddress('Gandhipuram, Gandhipuram, Coimbatore'),
|
|
'Gandhipuram, Coimbatore',
|
|
);
|
|
});
|
|
});
|
|
|
|
test('a delivery leg prefers the drop; a pickup leg the pickup', () {
|
|
final stop = {
|
|
'pickupaddress': '1 Anna Nagar, Coimbatore',
|
|
'dropaddress': '2 Saibaba Colony, Coimbatore',
|
|
};
|
|
expect(areaOf(stop), 'Saibaba Colony');
|
|
expect(areaOf(stop, preferDrop: false), 'Anna Nagar');
|
|
});
|
|
}
|