// Author: fruit.com.cn // 验证个人数据图标、无障碍入口与多语言窄屏布局。 import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/core/theme/app_dimens.dart'; import 'package:fruitshorts/core/theme/app_theme.dart'; import 'package:fruitshorts/l10n/app_localizations.dart'; import 'package:fruitshorts/pages/mine/widgets/mine_stat_icon.dart'; import 'package:fruitshorts/pages/mine/widgets/mine_stats_panel.dart'; const _coinsKey = Key('mine-stat-coins'); const _historyKey = Key('mine-stat-watch-records'); const _favoritesKey = Key('mine-stat-favorites'); const _locales = [Locale('zh'), Locale('en'), Locale('id')]; const _widths = [320.0, 390.0]; const _scales = [1.0, 2.0]; const _screenHeight = 600.0; const _largeBalance = 123456789; const _historyTotal = 57; const _favoritesTotal = 23; void main() { _responsiveTests(); _interactionTests(); } void _responsiveTests() { for (final locale in _locales) { for (final width in _widths) { for (final scale in _scales) { testWidgets( 'should_fit_three_columns_when_${locale.languageCode}_${width}_scale_$scale', (tester) async { await _pumpPanel( tester, locale: locale, width: width, scale: scale, ); final cells = [_coinsKey, _historyKey, _favoritesKey]; final positions = cells .map((key) => tester.getTopLeft(find.byKey(key))) .toList(); expect(positions.map((point) => point.dy).toSet(), hasLength(1)); expect(positions.map((point) => point.dx).toSet(), hasLength(3)); for (final key in cells) { final size = tester.getSize(find.byKey(key)); expect(size.width, greaterThanOrEqualTo(AppDimens.tapTarget)); expect(size.height, greaterThanOrEqualTo(AppDimens.tapTarget)); } expect(tester.takeException(), isNull); }, ); } } } } void _interactionTests() { testWidgets( 'should_render_distinct_vector_icons_when_statistics_are_visible', (tester) async { await _pumpPanel(tester); final icons = tester.widgetList(find.byType(MineStatIcon)); expect(icons.map((icon) => icon.type), MineStatIconType.values); for (final icon in icons) { expect( tester.getSize(find.byKey(icon.key!)), const Size.square(AppDimens.mineStatsIcon), ); } }, ); testWidgets('should_forward_each_action_once_when_statistics_are_tapped', ( tester, ) async { final opened = []; await _pumpPanel( tester, actions: MineStatsActions( onWallet: () => opened.add(MineStatIconType.coins), onHistory: () => opened.add(MineStatIconType.history), onFavorites: () => opened.add(MineStatIconType.favorites), ), ); for (final key in [_coinsKey, _historyKey, _favoritesKey]) { await tester.tap(find.byKey(key)); await tester.pump(); } expect(opened, MineStatIconType.values); }); testWidgets( 'should_announce_label_value_and_action_when_using_screen_reader', (tester) async { await _pumpPanel(tester); final semantics = tester.ensureSemantics(); final coinSemantics = find.byWidgetPredicate( (widget) => widget is Semantics && widget.properties.label == 'Coin balance', ); try { expect( tester.getSemantics(coinSemantics), matchesSemantics( label: 'Coin balance', value: '123,456,789', isButton: true, hasTapAction: true, ), ); } finally { semantics.dispose(); } }, ); } Future _pumpPanel( WidgetTester tester, { Locale locale = const Locale('en'), double width = 390, double scale = 1, MineStatsActions? actions, }) async { tester.view.physicalSize = Size(width, _screenHeight); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); await tester.pumpWidget( MaterialApp( theme: AppTheme.dark(), locale: locale, supportedLocales: AppLocalizations.supportedLocales, localizationsDelegates: AppLocalizations.localizationsDelegates, builder: (context, child) => MediaQuery( data: MediaQuery.of( context, ).copyWith(textScaler: TextScaler.linear(scale)), child: child!, ), home: Scaffold( body: Padding( padding: const EdgeInsets.all(AppDimens.pageHorizontal), child: MineStatsPanel( coinBalance: _largeBalance, watchRecordCount: _historyTotal, favoriteCount: _favoritesTotal, actions: actions ?? MineStatsActions( onWallet: () {}, onHistory: () {}, onFavorites: () {}, ), ), ), ), ), ); await tester.pumpAndSettle(); }