@Tags(['shots']) library; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_test/flutter_test.dart'; import 'support/golden_fonts.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:miler/data/service_profile.dart'; import 'package:miler/views/Dashboard/home/trip.dart'; import 'package:miler/views/Dashboard/home/trip_progress_rail.dart'; // `card.dart` is a `part of` this library, so [PickupCard] comes through it. import 'package:miler/views/Dashboard/pickups/pickups.dart'; import 'package:miler/views/helpers/constants/Colorconstants.dart'; import 'package:miler/views/helpers/constants/Font_constant.dart'; /// Visual harness for the Deliveries tab's two public pieces. /// /// `_MyPickupsState` cannot be pumped — Get, SharedPreferences, Geolocator and /// a 3s poll — and the queue's three quieter tiers (`_NextCard`, `_LaterRow`, /// `_SkippedRow`) are private to `card.dart`. What is reachable is exactly the /// pair the redesign is about: [TripProgressRail], which is the head of the /// screen, and [PickupCard], which is the one live card under it. /// /// The rail is shot at four route lengths because the documented gap against it /// is that "a 21-stop route overflows it" — a claim about layout, which is /// answerable by looking. Run with `--update-goldens`. void main() { setUpAll(() async { // Same reasoning as `home_shots_test`: a golden rendered without the app's // own family is a picture of the fallback, and Poppins ships one file per // weight so each has to be registered under the family by hand. await loadGoldenFonts(); }); tearDown(() { Get.reset(); ServiceProfile.setActive(ServiceProfile.parcel); }); Map drop( String id, String customer, { String status = 'picked', String label = '', }) => { 'orderid': id, 'tripid': 'T1', 'type': 'delivery', 'pickupcustomer': customer, 'name': customer, 'sourcename': 'DailyGrubs RS Puram Kitchen', 'kitchenid': 'K1', 'kitchenname': 'DailyGrubs RS Puram Kitchen', 'pickupaddress': '4 Cross, RS Puram, Coimbatore 641002', 'dropaddress': '12, SNS Colony, Peelamedu, Coimbatore 641004', 'deliveryaddress': '12, SNS Colony, Peelamedu, Coimbatore 641004', 'orderstatus': status, 'pickupcontactno': '9787698259', 'deliverycontactno': '9787698259', if (label.isNotEmpty) 'baglabel': label, 'Quantity': 1, 'pickuplat': 11.0168, 'pickuplon': 76.9558, 'droplat': 11.0208, 'droplon': 76.9598, }; Future frame( WidgetTester tester, String name, Widget child, { double height = 400, double width = 390, }) async { ServiceProfile.setActive(ServiceProfile.milkMan); SharedPreferences.setMockInitialValues({'userid': 1}); tester.view.physicalSize = Size(width * 3, height * 3); tester.view.devicePixelRatio = 3.0; addTearDown(tester.view.reset); await tester.pumpWidget( ScreenUtilInit( // Design size == surface, so `.w`/`.h` are both exactly 1 and the shot // does not lie about spacing. See the note in `home_shots_test`. designSize: Size(width, height), builder: (_, _) => MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( backgroundColor: ColorConstants.daylightSurface, body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(vertical: 12), child: child, ), ), ), ), ), ); await tester.pumpAndSettle(); await expectLater( find.byType(MaterialApp), matchesGoldenFile('shots/deliveries_$name.png'), ); } /// A route of [total] stops with [done] delivered and the rider standing at /// the next one — the shape the rail is actually asked to draw mid-round. List route(int total, {int done = 0}) => [ for (var i = 0; i < total; i++) if (i < done) StopProgress.done else if (i == done) StopProgress.current else StopProgress.pending, ]; group('the route rail', () { testWidgets('a short round lays out across the full width', (tester) async { await frame( tester, 'rail_short', TripProgressRail( progress: route(5, done: 2), slotLabel: 'Trip 1 · 10:00 AM – 1:00 PM', remaining: const Duration(minutes: 74), ), height: 150, ); }); testWidgets('the documented 21-stop round', (tester) async { await frame( tester, 'rail_21', TripProgressRail( progress: route(21, done: 6), slotLabel: 'Trip 1 · 10:00 AM – 1:00 PM', remaining: const Duration(minutes: 110), ), height: 150, ); }); testWidgets('nothing delivered yet — the whole load still aboard', ( tester, ) async { await frame( tester, 'rail_21_fresh', TripProgressRail( progress: route(21), slotLabel: 'Trip 1 · 10:00 AM – 1:00 PM', remaining: const Duration(minutes: 130), ), height: 150, ); }); testWidgets('a 320pt phone at 1.3x text scale', (tester) async { await frame( tester, 'rail_21_small', MediaQuery( data: const MediaQueryData(textScaler: TextScaler.linear(1.3)), child: TripProgressRail( progress: route(21, done: 6), slotLabel: 'Trip 1 · 10:00 AM – 1:00 PM', remaining: const Duration(minutes: 110), ), ), height: 170, width: 320, ); }); }); group('the live card', () { testWidgets('picked, waiting to be taken out', (tester) async { await frame( tester, 'card_picked', PickupCard( item: drop('D1', 'Joe Mathew', label: 'DG-8'), displayStep: 7, distanceMeters: 1100, label: 'DG-8', collectedIds: const {'D1'}, ), height: 320, ); }); testWidgets('active — the rider has set off', (tester) async { await frame( tester, 'card_active', PickupCard( item: drop('D1', 'Joe Mathew', label: 'DG-8'), displayStep: 7, distanceMeters: 1100, label: 'DG-8', collectedIds: const {'D1'}, outForDeliveryIds: const {'D1'}, ), height: 320, ); }); }); }