Files
doormile_milderapp/test/tenantname_unblocks_test.dart
2026-08-28 11:13:15 +05:30

102 lines
4.2 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:miler/data/service_profile.dart';
/// ─────────────────────────────────────────────────────────────────────────
/// WHAT `tenantname` ON THE LOGIN IS WORTH
///
/// The backend gates `MILER_COLLECTED_STATE_ENABLED` on every hyperlocal rider
/// having a **Start delivery** button, because with the flag on a parcel with
/// nobody to release it sits at `Collected_By_Miler` forever.
///
/// That button is not a build flag. It is [ServiceProfile.deliversToCustomer],
/// resolved per-login from the rider's tenant — so the question is not *which
/// build is installed* but *does this rider resolve to the milk-run profile*.
///
/// ── Two ways to answer, and only one of them scales ──
///
/// ```
/// by id a hardcoded set, {13} today. A client whose id we were never
/// told falls through to logistics and gets no button.
/// by name matched against `tenantname`, checked FIRST. `dailygrubs` is
/// already on the list, so the client resolves with no release.
/// ```
///
/// `tenantname` is not deployed yet, which is the whole of the risk: every
/// hyperlocal tenant that is not id 13 is currently a strand waiting for the
/// flag to be turned on. These pin both halves — that the name is sufficient
/// on its own, and what happens without it.
/// ─────────────────────────────────────────────────────────────────────────
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
tearDown(() => ServiceProfile.setActive(ServiceProfile.parcel));
test(
'the name alone puts a DailyGrubs rider on the milk-run profile',
() async {
// Deliberately no tenant id: this is a client whose id this app has never
// been told, which is exactly the case the id set cannot cover.
SharedPreferences.setMockInitialValues({
TenantController.kTenantName: 'DailyGrubs',
});
final profile = await resolveServiceProfile();
expect(profile, ServiceProfile.milkMan);
expect(
profile.deliversToCustomer,
isTrue,
reason: 'this is the flag that renders Start delivery',
);
},
);
test('case and spacing do not decide a rider\'s day', () async {
for (final spelling in const [
'dailygrubs',
'DAILYGRUBS',
' DailyGrubs ',
// How a human actually types a client name into a tenant record. Each of
// these used to miss, and a miss is a rider with no Start delivery button
// and a parcel stranded at `Collected_By_Miler`.
'Daily Grubs',
'daily-grubs',
'DAILY_GRUBS',
]) {
SharedPreferences.setMockInitialValues({
TenantController.kTenantName: spelling,
});
expect(
await resolveServiceProfile(),
ServiceProfile.milkMan,
reason: '"$spelling" did not resolve',
);
}
});
test('without it, an unrecognised tenant falls back to logistics', () async {
// The strand: flag on, newest build installed, no button to press, and the
// parcel stays at `Collected_By_Miler` because nothing can release it.
SharedPreferences.setMockInitialValues({TenantController.kTenantId: 17});
final profile = await resolveServiceProfile();
expect(profile, ServiceProfile.parcel);
expect(profile.deliversToCustomer, isFalse);
});
test('the name decides when the id says nothing', () async {
// Belt and braces: a hyperlocal client sitting on an id this app has not
// been told about must still resolve from its name.
//
// Note 17 is *unlisted*, not contradictory — an id this build knows wins,
// see `tenant_mode_test.dart`. This is the fall-through, which is the whole
// reason a new client needs no release.
SharedPreferences.setMockInitialValues({
TenantController.kTenantName: 'DailyGrubs',
TenantController.kTenantId: 17,
});
expect(await resolveServiceProfile(), ServiceProfile.milkMan);
});
}