From 1b8bf596c569e0483bcac8b244d82f543bfe385f Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 25 Jun 2026 14:38:55 +0800 Subject: [PATCH] =?UTF-8?q?test(client):=20app=20=E5=A4=96=E5=A3=B3?= =?UTF-8?q?=EF=BC=88=E9=A1=B6=E6=A0=8F/=E4=BE=A7=E6=A0=8F/=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=A0=8F=EF=BC=89=E6=95=B4=E5=A3=B3=20golden=20=C3=97?= =?UTF-8?q?=E4=B8=89=E4=B8=BB=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 外壳 chrome 是最显眼的主题面,但各屏 golden 都不含它。本 golden 用 MaterialApp.router + StatefulNavigationShell 渲染整壳(覆盖 auth/shop/license/ update/connectivity/heartbeat,跳过联网首检与心跳避免 Timer 泄漏),锁住 顶栏+侧栏+状态栏随 A/B/C 换色入回归闸。 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01TSKEiHsvauyxYUW2itzUXX --- client/test/golden/app_shell_golden_test.dart | 101 ++++++++++++++++++ client/test/golden/goldens/app_shell_a.png | Bin 0 -> 26217 bytes client/test/golden/goldens/app_shell_b.png | Bin 0 -> 26167 bytes client/test/golden/goldens/app_shell_c.png | Bin 0 -> 26225 bytes 4 files changed, 101 insertions(+) create mode 100644 client/test/golden/app_shell_golden_test.dart create mode 100644 client/test/golden/goldens/app_shell_a.png create mode 100644 client/test/golden/goldens/app_shell_b.png create mode 100644 client/test/golden/goldens/app_shell_c.png diff --git a/client/test/golden/app_shell_golden_test.dart b/client/test/golden/app_shell_golden_test.dart new file mode 100644 index 0000000..71c8cbb --- /dev/null +++ b/client/test/golden/app_shell_golden_test.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:go_router/go_router.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:jiu_client/core/auth/auth_state.dart'; +import 'package:jiu_client/core/theme/themes.dart'; +import 'package:jiu_client/models/shop.dart'; +import 'package:jiu_client/providers/shop_provider.dart'; +import 'package:jiu_client/providers/license_provider.dart'; +import 'package:jiu_client/providers/update_provider.dart'; +import 'package:jiu_client/providers/connectivity_provider.dart'; +import 'package:jiu_client/providers/session_heartbeat.dart'; +import 'package:jiu_client/screens/shell/app_shell.dart'; + +/// design-distill 阶段4:app 外壳(顶栏 + 侧栏 + 内容区)golden × 三主题。 +/// 锁住导航 chrome 随主题换色——这是最显眼的主题面,之前各屏 golden 都不含外壳。 +/// 需 MaterialApp.router(外壳依赖 StatefulNavigationShell),故为自定义 golden。 +/// 更新基准:flutter test --update-goldens test/golden/app_shell_golden_test.dart + +class _FakeAuth extends AuthNotifier { + _FakeAuth() { + state = const AuthState( + user: AuthUser( + accessToken: 't', refreshToken: 'r', id: 1, username: 'wang', + realName: '王经理', shopNo: 'DBZB-001', shopId: 1, role: 'admin'), + ); + } +} + +class _FakeUpdate extends UpdateNotifier { + @override + Future build() async => null; +} + +class _FakeLicense extends LicenseNotifier { + @override + Future build() async => null; +} + +const _shop = ShopInfo( + id: 1, code: 'DBZB-001', name: '鼎昌酒行', + address: '浙江省杭州市', phone: '0571-88886666', managerName: '王经理'); + +List _overrides() => [ + authStateProvider.overrideWith((ref) => _FakeAuth()), + shopInfoProvider.overrideWith((ref) => _shop), + licenseProvider.overrideWith(() => _FakeLicense()), + updateProvider.overrideWith(() => _FakeUpdate()), + // 跳过联网首检 / 不启动心跳,避免后台 Timer 泄漏 + connectivityProvider + .overrideWith((ref) => ConnectivityNotifier(skipInit: true)), + sessionHeartbeatProvider.overrideWith((ref) => SessionHeartbeat(ref)), + appVersionProvider.overrideWith((ref) => 'v1.0.72'), + isReadonlyProvider.overrideWithValue(false), + ]; + +GoRouter _router() => GoRouter( + initialLocation: '/inventory', + routes: [ + StatefulShellRoute.indexedStack( + builder: (ctx, state, shell) => AppShell(navigationShell: shell), + branches: [ + StatefulShellBranch(routes: [ + GoRoute( + path: '/inventory', + builder: (_, __) => const SizedBox.expand()), + ]), + ], + ), + ], + ); + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + SharedPreferences.setMockInitialValues({}); + + for (final theme in const ['a', 'b', 'c']) { + testWidgets('app shell · theme $theme', (tester) async { + tester.view.physicalSize = const Size(2560, 1600); + tester.view.devicePixelRatio = 2.0; + addTearDown(tester.view.resetPhysicalSize); + addTearDown(tester.view.resetDevicePixelRatio); + + await tester.pumpWidget(ProviderScope( + overrides: _overrides(), + child: MaterialApp.router( + debugShowCheckedModeBanner: false, + theme: buildTheme(theme), + routerConfig: _router(), + ), + )); + await tester.pumpAndSettle(); + + await expectLater( + find.byType(MaterialApp), + matchesGoldenFile('goldens/app_shell_$theme.png'), + ); + }); + } +} diff --git a/client/test/golden/goldens/app_shell_a.png b/client/test/golden/goldens/app_shell_a.png new file mode 100644 index 0000000000000000000000000000000000000000..30d2d72579bc4a3efab0624a4c2a8e0efbd9900b GIT binary patch literal 26217 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 literal 0 HcmV?d00001 diff --git a/client/test/golden/goldens/app_shell_b.png b/client/test/golden/goldens/app_shell_b.png new file mode 100644 index 0000000000000000000000000000000000000000..dbd4e3c3ce0ae2a096f1f814c6fcbec8c66b8ca7 GIT binary patch literal 26167 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 kEdK*a?T<*-ALypnS}_QGdNzU8Ho?IVY)I78K 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 O&YjXcnR49t-v0p2$jaUT literal 0 HcmV?d00001