Files
jizhi/frontend/test/widget_test.dart
T
2026-07-24 23:11:20 +08:00

140 lines
4.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:miaoji_zhang/features/ai_mode/pages/ai_mode_page.dart';
import 'package:miaoji_zhang/features/auth/pages/login_page.dart';
import 'package:miaoji_zhang/features/settings/me_page.dart';
import 'package:miaoji_zhang/shared/api/business_api.dart';
import 'package:miaoji_zhang/shared/theme/app_theme.dart';
import 'package:miaoji_zhang/shared/widgets/ai_access_gate.dart';
import 'package:miaoji_zhang/shared/widgets/app_controls.dart';
import 'package:miaoji_zhang/shared/widgets/async_error_view.dart';
import 'package:miaoji_zhang/shared/widgets/brand_logo.dart';
void main() {
testWidgets('错误状态无需真实 API 即可重试', (tester) async {
var retries = 0;
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: Scaffold(
body: AsyncErrorView(
message: '网络开小差了',
onRetry: () async => retries++,
),
),
),
);
expect(find.text('网络开小差了'), findsOneWidget);
await tester.tap(find.text('重试'));
await tester.pump();
expect(retries, 1);
});
testWidgets('全 AI 模式预算条展示未设置状态并可进入设置', (tester) async {
var taps = 0;
final data = BudgetsData.fromJson({'total': null, 'categories': []});
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: Scaffold(
body: AiBudgetStrip(data: data, onTap: () => taps++),
),
),
);
expect(find.text('本月还没设置预算'), findsOneWidget);
expect(find.text('去设置'), findsOneWidget);
await tester.tap(find.byType(AiBudgetStrip));
expect(taps, 1);
});
testWidgets('全 AI 模式预算条明确展示超支金额', (tester) async {
final data = BudgetsData.fromJson({
'total': {
'categoryId': null,
'categoryName': null,
'categoryIcon': null,
'amount': 1000,
'spent': 1250,
'isRecurring': false,
},
'categories': [],
});
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: Scaffold(
body: AiBudgetStrip(data: data, onTap: () {}),
),
),
);
expect(find.text('已超 ¥250'), findsOneWidget);
expect(find.text('已用 ¥1250'), findsOneWidget);
expect(find.text('总额 ¥1000'), findsOneWidget);
});
testWidgets('登录与启动页共用的新品牌图标可加载', (tester) async {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: const Scaffold(body: Center(child: BrandLogo(size: 64))),
),
);
await tester.pumpAndSettle();
expect(find.byType(BrandLogo), findsOneWidget);
expect(tester.takeException(), isNull);
});
testWidgets('登录页合规入口只展示协议和隐私政策', (tester) async {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: const Scaffold(body: LoginLegalLinks()),
),
);
expect(find.text('用户协议'), findsOneWidget);
expect(find.text('隐私政策'), findsOneWidget);
expect(find.text('权限用途'), findsNothing);
expect(find.text('第三方 SDK'), findsNothing);
});
testWidgets('游客本地状态是信息卡而不是禁用开关', (tester) async {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: const Scaffold(body: GuestLocalStatusCard()),
),
);
expect(find.text('本机保存中'), findsOneWidget);
expect(find.text('游客模式'), findsOneWidget);
expect(find.byType(JzSwitchTile), findsNothing);
});
testWidgets('游客 AI 页面只展示登录引导', (tester) async {
var actions = 0;
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light,
home: Scaffold(
body: AiAccessGate(
state: AiAccessState.guest,
onAction: () async => actions++,
),
),
),
);
await tester.pumpAndSettle();
expect(find.text('登录后使用 AI 助手'), findsOneWidget);
expect(find.text('登录后使用'), findsOneWidget);
await tester.tap(find.text('登录后使用'));
await tester.pump();
expect(actions, 1);
});
}