import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:qiangbao_accounting/widgets/avatar.dart'; /// 头像组件的测试。 /// /// 重点是**不崩**和**不留裂图** —— 头像是从后端 /uploads 拉的, /// 文件被删、地址写错、网络断了都会走到 errorBuilder, /// 那时候必须退回默认图标,而不是显示一个裂开的图。 void main() { Widget wrap(Widget child) => MaterialApp(home: Scaffold(body: child)); group('Avatar 兜底', () { testWidgets('assetPath 为 null 时显示默认图标,不发起网络请求', (tester) async { await tester.pumpWidget(wrap(const Avatar(size: 40))); await tester.pump(); // 没有 Image 组件 —— 说明压根没去加载图片 expect(find.byType(Image), findsNothing); expect(tester.takeException(), isNull); }); testWidgets('assetPath 为空串时也走默认图标', (tester) async { await tester.pumpWidget(wrap(const Avatar(assetPath: '', size: 40))); await tester.pump(); expect(find.byType(Image), findsNothing); expect(tester.takeException(), isNull); }); testWidgets('只有空白字符的路径也当没有(后端可能返回 " ")', (tester) async { await tester.pumpWidget(wrap(const Avatar(assetPath: ' ', size: 40))); await tester.pump(); expect(find.byType(Image), findsNothing); expect(tester.takeException(), isNull); }); testWidgets('★ 给了路径就渲染图片,且加载失败时不崩(退回默认图标)', (tester) async { await tester.pumpWidget(wrap( const Avatar(assetPath: 'persona/2026/09/29/x.jpg', size: 40), )); await tester.pump(); expect(find.byType(Image), findsOneWidget); // 测试环境里网络请求必然失败,会走 errorBuilder。 // 这里断言的是「失败被接住了,没有把异常抛到 widget 树」 await tester.pump(const Duration(milliseconds: 100)); expect(tester.takeException(), isNull, reason: '图片加载失败必须被 errorBuilder 接住,不能抛异常'); }); }); group('Avatar 尺寸', () { testWidgets('尺寸按传入值设置(聊天气泡和「我的」页面用不同大小)', (tester) async { await tester.pumpWidget(wrap(const Avatar(size: 36))); await tester.pump(); final container = tester.widget(find.byType(Container).first); final size = container.constraints; expect(size?.maxWidth, 36); expect(size?.maxHeight, 36); }); testWidgets('不同尺寸都不溢出', (tester) async { for (final s in [24.0, 36.0, 40.0, 60.0, 76.0]) { await tester.pumpWidget(wrap(Avatar(size: s))); await tester.pump(); expect(tester.takeException(), isNull, reason: '尺寸 $s 出问题了'); } }); testWidgets('在很窄的容器里也不溢出', (tester) async { await tester.pumpWidget(wrap( const SizedBox(width: 40, height: 40, child: Avatar(size: 36)), )); await tester.pump(); expect(tester.takeException(), isNull); }); }); }