// 功能描述:验证一级页面保留入口、游客数据边界、筛选及刷新错误恢复。 // 版本:1.0.0 import 'package:flutter/material.dart'; import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; import 'package:go_router/go_router.dart'; import 'package:user_app/domain/models/client_models.dart'; import 'package:user_app/domain/models/order_summary.dart'; import 'package:user_app/ui/features/home/home_page.dart'; import 'package:user_app/ui/features/shop/shop_page.dart'; import 'package:user_app/ui/core/async_content.dart'; import 'package:user_app/ui/core/text_entry_dialog.dart'; import '../support/a1_fixture.dart'; void main() { testWidgets('刷新失败保留上次数据,较迟的旧请求不覆盖新数据', (tester) async { final key = GlobalKey>(); final pending = >[]; await tester.pumpWidget( MaterialApp( home: Scaffold( body: AsyncContent( key: key, load: () { final c = Completer(); pending.add(c); return c.future; }, builder: (_, value) => ListView(children: [Text(value)]), ), ), ), ); pending[0].complete('初始数据'); await tester.pumpAndSettle(); final first = key.currentState!.refresh(); final second = key.currentState!.refresh(); pending[2].complete('最新数据'); await second; await tester.pump(); pending[1].complete('旧请求结果'); await first; await tester.pump(); expect(find.text('最新数据'), findsOneWidget); expect(find.text('旧请求结果'), findsNothing); final failure = key.currentState!.refresh(); pending[3].completeError(Exception('offline')); await failure; await tester.pumpAndSettle(); expect(find.text('最新数据'), findsOneWidget); expect(find.textContaining('刷新失败,当前显示上次数据'), findsOneWidget); }); testWidgets('输入弹窗关闭动画期间控制器有效,空值阻止提交', (tester) async { String? result; await tester.pumpWidget( MaterialApp( home: Builder( builder: (context) => Scaffold( body: TextButton( onPressed: () async { result = await showDialog( context: context, builder: (_) => const TextEntryDialog(title: '新增地址', label: '详细地址', action: '保存'), ); }, child: const Text('打开'), ), ), ), ), ); await tester.tap(find.text('打开')); await tester.pumpAndSettle(); await tester.tap(find.text('保存')); await tester.pump(); expect(find.text('请填写详细地址'), findsOneWidget); await tester.enterText(find.byType(TextField), '测试地址'); await tester.tap(find.text('保存')); await tester.pump(); await tester.pumpAndSettle(); expect(result, '测试地址'); expect(tester.takeException(), isNull); }); testWidgets('游客首页不读取个人归属并保留设备入口', (tester) async { final source = A1FixtureRepository(); await tester.pumpWidget(MaterialApp(home: HomePage(repository: source, authenticated: false))); await tester.pumpAndSettle(); expect(source.relationCalls, 0); await tester.ensureVisible(find.text('扫码添加')); await tester.tap(find.text('扫码添加')); await tester.pumpAndSettle(); expect(find.textContaining('该功能暂未开放'), findsOneWidget); expect(find.text('85%'), findsNothing); }); testWidgets('首页真实入口可进入设备页且未接入入口明确提示', (tester) async { final source = A1FixtureRepository(); final router = GoRouter( initialLocation: '/home', routes: [ GoRoute( path: '/home', builder: (_, _) => HomePage(repository: source), ), GoRoute( path: '/devices', builder: (_, _) => const Scaffold(body: Text('设备页已打开')), ), ], ); addTearDown(router.dispose); await tester.pumpWidget(MaterialApp.router(routerConfig: router)); await tester.pumpAndSettle(); expect(find.text('查看设备状态与告警记录'), findsOneWidget); expect(find.text('查看气瓶使用与检测信息'), findsOneWidget); await tester.tap(find.text('查看详情')); await tester.pumpAndSettle(); expect(find.text('设备页已打开'), findsOneWidget); }); testWidgets('首次加载失败可重试恢复真实内容', (tester) async { final source = A1FixtureRepository()..fail = true; await tester.pumpWidget(MaterialApp(home: HomePage(repository: source))); await tester.pumpAndSettle(); expect(find.text('加载失败'), findsOneWidget); source.fail = false; await tester.tap(find.text('重新加载')); await tester.pumpAndSettle(); expect(find.text('当前服务归属'), findsOneWidget); }); testWidgets('商城搜索与分类联动并显示空结果', (tester) async { await tester.pumpWidget(MaterialApp(home: ShopPage(repository: A1FixtureRepository()))); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), '报警'); await tester.pumpAndSettle(); expect(find.text('燃气报警器'), findsOneWidget); expect(find.text('15kg家用液化气'), findsNothing); await tester.enterText(find.byType(TextField), '不存在'); await tester.pumpAndSettle(); expect(find.textContaining('暂无符合条件'), findsOneWidget); }); test('旧响应缺少 allowed_actions 时不从状态码推测权限', () { final order = OrderSummary.fromRecord( const ClientRecord(identity: 'o', title: '', subtitle: '', status: 16, raw: {}), ); expect(order.actions, isEmpty); expect(order.amount, isNull); }); }