Replace the customer app with Doormile CX
Book a pickup, track it to delivery — the rebuilt customer app. - Design language from doormile-screens.html: brand #8F0F06, Manrope + Geist Mono (variable fonts), bordered cards instead of shadows, crimson brand headers, sliding tab indicator, mono for anything read digit by digit. - lib/data (one live API implementation, plus a debug-only offline fake), lib/state, lib/ui (tokens, widgets, screens). - 84 tests, plus a design snapshot harness that renders every screen with the real fonts: flutter test test/design_snapshot_test.dart --run-skipped --update-goldens This replaces the previous app (pubspec 'doormile', app id com.doormile.customer). That tree remains in history at 6c7d656; note its android/app/google-services.json is not carried over, and the application id here is in.doormile.customer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
89
integration_test/book_one_test.dart
Normal file
89
integration_test/book_one_test.dart
Normal file
@@ -0,0 +1,89 @@
|
||||
import 'package:doormile_cx/data/location_service.dart';
|
||||
import 'package:doormile_cx/main.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
/// Drives the real app on the simulator all the way through a booking, then
|
||||
/// holds on the confirmation so it can be photographed from outside.
|
||||
///
|
||||
/// Run against the dev data, which is where any 4-digit code signs in and the
|
||||
/// serviceability / slots / booking all exist without a server:
|
||||
///
|
||||
/// flutter test integration_test/book_one_test.dart \
|
||||
/// -d <simulator> --dart-define=DM_MOCK=true
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
testWidgets('books a pickup to Chennai and lands on the confirmation',
|
||||
(tester) async {
|
||||
// Deterministic pin, so the pickup step never stops on an OS location
|
||||
// dialog and resolves the same way every run.
|
||||
LocationService.instance = FixedLocationService();
|
||||
|
||||
await tester.pumpWidget(const DoormileApp());
|
||||
await tester.pumpAndSettle(const Duration(milliseconds: 400));
|
||||
|
||||
// The app runs continuous animations, so pumpAndSettle would spin forever.
|
||||
// Pump fixed slices instead.
|
||||
Future<void> hold([int ms = 900]) async {
|
||||
await tester.pump();
|
||||
await tester.pump(Duration(milliseconds: ms));
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
}
|
||||
|
||||
// ---- sign in: 9876543210 + any 4-digit code ----------------------------
|
||||
await tester.enterText(find.byType(TextField).first, '9876543210');
|
||||
await hold(300);
|
||||
await tester.tap(find.text('Continue'));
|
||||
await hold();
|
||||
|
||||
final boxes = find.byType(TextField);
|
||||
for (var i = 0; i < 4; i++) {
|
||||
await tester.enterText(boxes.at(i), '1');
|
||||
await tester.pump();
|
||||
}
|
||||
await hold(1200);
|
||||
expect(find.text('Where should we pick up?'), findsOneWidget);
|
||||
debugPrint('DRIVER: signed in, on Home');
|
||||
|
||||
// ---- BOOK → confirm the pin -----------------------------------
|
||||
await tester.tap(find.text('BOOK'));
|
||||
await hold(1200);
|
||||
await tester.tap(find.text('Next'));
|
||||
await hold();
|
||||
expect(find.text('Where are you sending it?'), findsOneWidget);
|
||||
|
||||
// ---- destination: Tamil Nadu ▸ Chennai ---------------------------------
|
||||
await tester.tap(find.text('Tamil Nadu'));
|
||||
await hold();
|
||||
await tester.tap(find.text('Chennai'));
|
||||
await hold();
|
||||
expect(find.text('Chennai, Tamil Nadu'), findsOneWidget);
|
||||
await tester.tap(find.text('Next'));
|
||||
await hold();
|
||||
|
||||
// ---- pickup window -----------------------------------------------------
|
||||
expect(find.text('When should we come?'), findsOneWidget);
|
||||
await tester.tap(find.text('2:00 – 4:00 PM').first);
|
||||
await hold();
|
||||
await tester.tap(find.text('Review booking'));
|
||||
await hold(1200);
|
||||
|
||||
// ---- review → book -----------------------------------------------------
|
||||
expect(find.text('Review pickup details'), findsOneWidget);
|
||||
debugPrint('DRIVER: on review');
|
||||
await tester.tap(find.text('Book Pickup'));
|
||||
await hold(1600);
|
||||
|
||||
// ---- confirmation ------------------------------------------------------
|
||||
expect(find.text('Pickup booked'), findsOneWidget);
|
||||
debugPrint('DRIVER: BOOKED — holding on confirmation');
|
||||
|
||||
// Hold so the confirmation can be photographed from outside the test.
|
||||
for (var i = 0; i < 50; i++) {
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user