feat(mine): 重做我的页会员卡与功能宫格布局
This commit is contained in:
1 parent
e7399fa3fd
commit
53e8c924a6
12 files changed
+1969
-513
No files matched your search
@@ -0,0 +1,168 @@
|
||||
// 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<MineStatIcon>(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 = <MineStatIconType>[];
|
||||
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<void> _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();
|
||||
}
|
||||
Reference in new issue
Block a user