200 lines
7.2 KiB
Dart
200 lines
7.2 KiB
Dart
import 'dart:convert';
|
|
|
|
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/views/Dashboard/activity/activity_page.dart';
|
|
import 'package:miler/views/Dashboard/home/homepage.dart';
|
|
import 'package:miler/views/Dashboard/profile/Profilepage.dart';
|
|
import 'package:miler/views/helpers/constants/Colorconstants.dart';
|
|
|
|
/// ── A day's work is a list, not a stack of cards ──
|
|
///
|
|
/// Every finished stop was a filled, rounded card with 12pt of air under it,
|
|
/// and inside each one a *second*, white panel holding the three figures. So the
|
|
/// page came down the screen as grey slabs with white slabs punched into them —
|
|
/// the card-inside-card shape, repeated once per stop — and on top of that every
|
|
/// row opened with a 40pt green disc that was identical on all of them.
|
|
///
|
|
/// Finished stops are all the same kind of thing, arriving in one order, read by
|
|
/// scanning down. That is a list, and a list is separated by rules.
|
|
void main() {
|
|
String day(DateTime t) =>
|
|
'${t.year}-${t.month.toString().padLeft(2, '0')}-'
|
|
'${t.day.toString().padLeft(2, '0')}';
|
|
|
|
Map<String, dynamic> finished(
|
|
String id,
|
|
String name,
|
|
String address, {
|
|
required String type,
|
|
double cash = 0,
|
|
int minsAgo = 30,
|
|
}) {
|
|
final now = DateTime.now();
|
|
final at = now.subtract(Duration(minutes: minsAgo));
|
|
return {
|
|
'orderid': id,
|
|
'type': type,
|
|
'pickupcustomer': name,
|
|
'pickupaddress': address,
|
|
'orderstatus': 'picked',
|
|
'completedday': day(now),
|
|
'completedat': at.toIso8601String(),
|
|
'startedat': at.subtract(const Duration(minutes: 14)).toIso8601String(),
|
|
if (cash > 0) 'collectionamt': '$cash',
|
|
'proof': {if (cash > 0) 'amountcollected': cash},
|
|
};
|
|
}
|
|
|
|
Future<void> pumpActivity(WidgetTester tester) async {
|
|
SharedPreferences.setMockInitialValues({
|
|
'userId': 1,
|
|
'completed_bookings': jsonEncode([
|
|
finished(
|
|
'DM240817',
|
|
'Sundar Textiles',
|
|
'78, Cross Cut Road, Gandhipuram, Coimbatore',
|
|
type: 'combined',
|
|
cash: 2450,
|
|
minsAgo: 22,
|
|
),
|
|
finished(
|
|
'DM240816',
|
|
'Green Leaf Grocers',
|
|
'29, Kovaipudur Main Road, Coimbatore',
|
|
type: 'delivery',
|
|
minsAgo: 68,
|
|
),
|
|
]),
|
|
});
|
|
|
|
tester.view.physicalSize = const Size(390 * 3, 844 * 3);
|
|
tester.view.devicePixelRatio = 3.0;
|
|
addTearDown(tester.view.reset);
|
|
|
|
await tester.pumpWidget(
|
|
ScreenUtilInit(
|
|
designSize: const Size(390, 844),
|
|
builder: (_, _) => const MaterialApp(home: ActivityPage()),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
|
}
|
|
|
|
testWidgets('a finished stop is not a card', (tester) async {
|
|
await pumpActivity(tester);
|
|
expect(find.text('Sundar Textiles'), findsOneWidget);
|
|
|
|
// `cardSurface` was the row fill and `pureSurface` the fill of the figure
|
|
// panel nested inside it. Neither may come back: on a white page a filled
|
|
// row is a box round a list item, and a filled panel inside a filled row is
|
|
// the shape this page was rebuilt to remove.
|
|
final fills = tester
|
|
.widgetList<Container>(find.byType(Container))
|
|
.map((c) => c.decoration)
|
|
.whereType<BoxDecoration>()
|
|
.map((d) => d.color)
|
|
.toList();
|
|
|
|
expect(fills, isNot(contains(ColorConstants.cardSurface)));
|
|
});
|
|
|
|
testWidgets('the figures line up across rows, not just within one', (
|
|
tester,
|
|
) async {
|
|
await pumpActivity(tester);
|
|
|
|
// The point of three fixed columns is comparing one stop against the next.
|
|
// While every row sat in its own padded card that only held *inside* a row;
|
|
// sharing the page margin is what makes column two of one stop sit directly
|
|
// above column two of the one below.
|
|
final captions = tester.widgetList<Text>(find.text('COLLECTED')).toList();
|
|
expect(captions.length, 2);
|
|
|
|
final rects = [
|
|
for (var i = 0; i < 2; i++) tester.getRect(find.text('COLLECTED').at(i)),
|
|
];
|
|
expect(rects[0].left, closeTo(rects[1].left, 0.5));
|
|
|
|
// Column one starts flush with the stop name above it — no card inset.
|
|
final time = tester.getRect(find.text('TIME').first);
|
|
final name = tester.getRect(find.text('Sundar Textiles'));
|
|
expect(time.left, closeTo(name.left, 0.5));
|
|
});
|
|
|
|
testWidgets('the stop type is a dotted word, not a filled tag', (
|
|
tester,
|
|
) async {
|
|
await pumpActivity(tester);
|
|
|
|
// Two tinted rectangles under every address — the type and the order id —
|
|
// were the loudest things on a row whose subject is the figures below them.
|
|
expect(find.text('Pickup & Delivery'), findsOneWidget);
|
|
// `P&D` is `chipLabel`, which only ever reached this page through the
|
|
// filled tag. (`badgeLabel` still appears inside the collapsed detail,
|
|
// which `AnimatedCrossFade` builds either way — that one is a field value,
|
|
// not a mark.)
|
|
expect(find.text('P&D'), findsNothing);
|
|
|
|
final label = tester.widget<Text>(find.text('Pickup & Delivery'));
|
|
expect(label.style!.color, ColorConstants.combinedAccent);
|
|
|
|
// The reference stays copyable, in grey, without claiming any rank.
|
|
final id = tester.widget<Text>(find.text('#DM240817'));
|
|
expect(id.style!.color, ColorConstants.secondaryText);
|
|
});
|
|
|
|
testWidgets('column captions are readable, not disabled-grey', (
|
|
tester,
|
|
) async {
|
|
await pumpActivity(tester);
|
|
|
|
// #C7C7CC is a disabled-control colour. It measured about 1.9:1 on the
|
|
// white page, which made the three words naming the columns the least
|
|
// readable text on a screen used outdoors.
|
|
for (final caption in const ['TIME', 'RIDDEN', 'COLLECTED']) {
|
|
final text = tester.widget<Text>(find.text(caption).first);
|
|
expect(text.style!.color, ColorConstants.secondaryText);
|
|
expect(text.style!.color, isNot(ColorConstants.disabledFill));
|
|
}
|
|
});
|
|
|
|
testWidgets('the four tabs agree on what colour the paper is', (
|
|
tester,
|
|
) async {
|
|
// Account was on `surface` (#FCF9F8, a warm off-white) while Home and
|
|
// Activity were on `pureSurface`. Bookings hides its background under
|
|
// cards; Account is bare rows, so the whole tab read a shade dirtier.
|
|
Color? bgOf(Widget page) {
|
|
final scaffolds = <Scaffold>[];
|
|
void visit(Element e) {
|
|
final w = e.widget;
|
|
if (w is Scaffold) scaffolds.add(w);
|
|
e.visitChildren(visit);
|
|
}
|
|
|
|
WidgetsBinding.instance.rootElement!.visitChildren(visit);
|
|
return scaffolds.isEmpty ? null : scaffolds.first.backgroundColor;
|
|
}
|
|
|
|
SharedPreferences.setMockInitialValues({'userId': 1});
|
|
tester.view.physicalSize = const Size(390 * 3, 844 * 3);
|
|
tester.view.devicePixelRatio = 3.0;
|
|
addTearDown(tester.view.reset);
|
|
|
|
for (final page in <Widget>[const ActivityPage(), const ProfilePage()]) {
|
|
await tester.pumpWidget(
|
|
ScreenUtilInit(
|
|
designSize: const Size(390, 844),
|
|
builder: (_, _) => MaterialApp(home: page),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
expect(bgOf(page), ColorConstants.pureSurface);
|
|
}
|
|
});
|
|
}
|