Files
biz_xfj_cloud/test/sub_screen/reservation_query_widget_test.dart
T
2026-08-09 14:45:18 +08:00

269 lines
8.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:forui/forui.dart';
import 'package:pj_supermarket_cloud/common/models/page/reservation_menu_page_models.dart';
import 'package:pj_supermarket_cloud/common/widgets/app/reservation_schedule_card.dart';
import 'package:pj_supermarket_cloud/sub_screen/common/models/reservation_query_display_models.dart';
import 'package:pj_supermarket_cloud/sub_screen/common/utils/reservation_query_coordinator.dart';
import 'package:pj_supermarket_cloud/sub_screen/page/reservation_query_display.dart';
void main() {
testWidgets('午餐预约卡只补齐基础三餐,不生成夜间餐占位', (tester) async {
ReservationMenuMealData? verifiedMeal;
const day = ReservationMenuDayData(
date: '2026-07-24',
meals: [
ReservationMenuMealData(
hourType: 'NOONING',
title: '午餐',
items: ['香菇滑鸡'],
orderIds: [1001],
),
],
);
await tester.pumpWidget(
MaterialApp(
home: FTheme(
data: FThemes.zinc.light,
child: Center(
child: SizedBox(
width: 420,
height: 420,
child: ReservationScheduleCard(
day: day,
verificationEnabled: true,
onVerify: (meal) => verifiedMeal = meal,
),
),
),
),
),
);
for (final title in const ['早餐', '午餐', '晚餐']) {
expect(find.text(title), findsOneWidget);
}
expect(find.text('夜间餐'), findsNothing);
expect(find.text('未预定'), findsNWidgets(2));
expect(find.text('核销'), findsOneWidget);
final verificationVisual = tester.getSize(
find.byKey(const ValueKey('reservation-verification-visual-2')),
);
final verificationTarget = tester.getSize(
find.byKey(const ValueKey('reservation-verification-target-2')),
);
expect(verificationVisual.height, 36);
expect(verificationTarget.height, 48);
expect(verificationTarget.width, greaterThan(verificationVisual.width));
await tester.tap(find.text('核销'));
expect(verifiedMeal?.title, '午餐');
});
testWidgets('后端返回夜间餐时正常追加展示', (tester) async {
const day = ReservationMenuDayData(
date: '2026-07-24',
meals: [
ReservationMenuMealData(
hourType: 'LATE_NIGHT',
title: '夜间餐',
items: ['牛肉面'],
),
],
);
await tester.pumpWidget(
MaterialApp(
home: FTheme(
data: FThemes.zinc.light,
child: const Center(
child: SizedBox(
width: 420,
height: 420,
child: ReservationScheduleCard(day: day),
),
),
),
),
);
expect(find.text('夜间餐'), findsOneWidget);
expect(find.text('牛肉面'), findsOneWidget);
final lateNightText = tester.renderObject<RenderParagraph>(
find.byKey(const ValueKey('reservation-meal-title-4')),
);
expect(lateNightText.maxLines, 1);
expect(lateNightText.didExceedMaxLines, isFalse);
});
testWidgets('关闭核销配置时预约餐段仍显示查询详情入口', (tester) async {
ReservationMenuMealData? selectedMeal;
const day = ReservationMenuDayData(
date: '2026-07-24',
meals: [
ReservationMenuMealData(
hourType: '2',
title: '午餐',
items: ['小青菜'],
orderIds: [1001],
),
],
);
await tester.pumpWidget(
MaterialApp(
home: FTheme(
data: FThemes.zinc.light,
child: Center(
child: SizedBox(
width: 420,
height: 420,
child: ReservationScheduleCard(
day: day,
onVerify: (meal) => selectedMeal = meal,
),
),
),
),
),
);
expect(find.text('核销'), findsNothing);
expect(find.text('查询详情'), findsOneWidget);
await tester.tap(find.text('查询详情'));
expect(selectedMeal?.title, '午餐');
});
testWidgets('窄卡片中的查询详情保持紧凑且菜名不再逐字换行', (tester) async {
const day = ReservationMenuDayData(
date: '2026-07-24',
meals: [
ReservationMenuMealData(
hourType: '2',
title: '午餐',
items: ['小青菜'],
orderIds: [1001],
),
],
);
await tester.pumpWidget(
MaterialApp(
home: FTheme(
data: FThemes.zinc.light,
child: const Center(
child: SizedBox(
width: 220,
height: 420,
child: ReservationScheduleCard(
day: day,
),
),
),
),
),
);
expect(tester.takeException(), isNull);
final itemText = tester.renderObject<RenderParagraph>(
find.text('小青菜'),
);
final detailVisual = tester.getSize(
find.byKey(const ValueKey('reservation-verification-visual-2')),
);
expect(itemText.maxLines, 1);
expect(itemText.didExceedMaxLines, isFalse);
expect(itemText.size.height, lessThan(24));
expect(detailVisual.width, lessThanOrEqualTo(70));
expect(detailVisual.height, 30);
});
for (final size in [const Size(1920, 1080), const Size(1280, 720)]) {
testWidgets('${size.width.toInt()}x${size.height.toInt()} 七种预约状态无布局异常',
(tester) async {
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
for (final scenario in ReservationQueryDisplayScenario.values) {
final coordinator = ReservationQueryCoordinator(
initialState: ReservationQueryDisplayState.demo(
scenario,
now: DateTime(2026, 7, 24, 8),
),
);
await tester.pumpWidget(
MaterialApp(
debugShowCheckedModeBanner: false,
home: FTheme(
data: FThemes.zinc.light,
child: ReservationQueryDisplayPage(coordinator: coordinator),
),
),
);
await tester.pump();
expect(
find.byKey(ValueKey('reservation-scenario-${scenario.name}')),
findsOneWidget,
);
expect(tester.takeException(), isNull);
if (scenario == ReservationQueryDisplayScenario.success) {
expect(find.byType(ReservationScheduleCard), findsNWidgets(10));
expect(find.text('张*明 · 三年级二班'), findsOneWidget);
expect(find.text('张小明'), findsNothing);
expect(find.byKey(const ValueKey('reservation-page-indicator')),
findsOneWidget);
}
await tester.pumpWidget(const SizedBox.shrink());
coordinator.dispose();
}
});
}
testWidgets('持续人脸副屏同时保留实时预览、预约菜单和十秒倒计时', (tester) async {
tester.view.physicalSize = const Size(1920, 1080);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final state = ReservationQueryDisplayState.demo(
ReservationQueryDisplayScenario.success,
now: DateTime(2026, 8, 7, 10),
).copyWith(
remainingSeconds: 10,
continuousFaceRecognition: true,
);
final coordinator = ReservationQueryCoordinator(initialState: state);
await tester.pumpWidget(
MaterialApp(
debugShowCheckedModeBanner: false,
home: FTheme(
data: FThemes.zinc.light,
child: ReservationQueryDisplayPage(coordinator: coordinator),
),
),
);
await tester.pump();
expect(
find.byKey(const ValueKey('sub-reservation-live-face-preview')),
findsOneWidget,
);
expect(find.byType(ReservationScheduleCard), findsNWidgets(10));
expect(find.text('预约结果展示中'), findsOneWidget);
expect(find.textContaining('10 秒后识别下一位'), findsOneWidget);
expect(tester.takeException(), isNull);
await tester.pumpWidget(const SizedBox.shrink());
coordinator.dispose();
});
}