Files
jiu/client/test/golden/app_shell_golden_test.dart
T
wangjia 6238b86dcb feat(client): 登录/注册页照原型重建,ds 真相源组件族统一全部屏
- 登录/注册(login.html/register.html 1:1):两栏卡片+品牌渐变面板+主题小衣服
  pill(onSurface 变体)+记住我(记录并预填最近账号)+原型式 toast 校验;
  登录 fidelity 1.4–2.1% 三主题全绿;注册暂不入闸(少 门店编号/兑换券 字段,
  已记 CONTRACT,screens.mjs 留存根)
- ds 原子补齐:DsToast(.toast 单例)/DsCheck(.check/.agree)/DsButton lg 档/
  DsSelect 替换全部旧 DropdownButton/DsField label 在上/DsInput 后缀与密码形态
- 全屏统一:对话框按钮全 DsButton、盒式输入主题钉死(visualDensity.standard、
  h38、InputDecorationTheme 渗漏修复)、图标全 lucide、JetBrains Mono 三端同源、
  BrandMark 真相源 logo、只读模式写操作全量守卫(WriteGuard+DsToast)
- 出入库列表:版式对齐原型(卡片对齐+搜索框居中)、KPI 近30天滚动、结清后
  失效财务应收应付表;商品编辑抽屉介绍库改搜索下拉、图片双击全屏预览
- 删除旧 UI 死代码:DataTableCard/FormDialog/PageScaffold/SearchChip/
  SelectProductDialog/tabStateProvider
- golden/fidelity:stock-in/out 补注册(9%)、login 入册(8%)、goldens 全量重打;
  修复 pubspec flutter_web_plugins 非法声明(CI pub get 阻断)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-03 09:58:14 +08:00

129 lines
4.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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';
import 'package:jiu_client/widgets/app_status_bar.dart';
import '../support/golden_harness.dart';
/// design-distill 阶段4app 外壳(顶栏两级品牌 + 主题器 + 通知铃 + 分组侧栏 + 状态栏)
/// golden × 三主题。照原型 shell.js/statusbar.js 重建后的回归基准 + 与原型保真比对基准。
/// 与原型对齐:门店=鼎晟酒行/DSJH-001、用户=王经理(管理员)、版本 v1.0.72、库存页激活。
/// 更新基准: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: 'DSJH-001',
shopId: 1,
role: 'admin'),
);
}
}
class _FakeUpdate extends UpdateNotifier {
@override
Future<AppUpdateInfo?> build() async => null;
}
class _FakeLicense extends LicenseNotifier {
@override
Future<LicenseInfo?> build() async => null;
}
const _shop = ShopInfo(
id: 1,
code: 'DSJH-001',
name: '鼎晟酒行',
address: '浙江省杭州市',
phone: '0571-88886666',
managerName: '王经理');
List<Override> _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),
];
// 外壳 nav 引用 9 个分支序号(入/出库·库存·财务·往来·基础数据·设备·设置·关于)。
// 全部空白内容,仅供外壳渲染;初始定位库存(index 2)以匹配原型激活态。
StatefulShellBranch _branch(String path) => StatefulShellBranch(routes: [
GoRoute(path: path, builder: (_, __) => const SizedBox.expand()),
]);
GoRouter _router() => GoRouter(
initialLocation: '/inventory',
routes: [
StatefulShellRoute.indexedStack(
builder: (ctx, state, shell) => AppShell(navigationShell: shell),
branches: [
_branch('/stock-in'),
_branch('/stock-out'),
_branch('/inventory'),
_branch('/finance'),
_branch('/partners'),
_branch('/products'),
_branch('/devices'),
_branch('/settings'),
_branch('/about'),
],
),
],
);
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
SharedPreferences.setMockInitialValues({});
// 冻结状态栏时钟,确定化 golden(关走字,避免像素抖动 / pending timer)。
AppStatusBar.clock = () => DateTime(2026, 7, 13, 9, 30, 15);
AppStatusBar.ticking = false;
for (final theme in const ['a', 'b', 'c']) {
testWidgets('app shell · theme $theme', (tester) async {
await ensureGoldenFonts();
tester.view.physicalSize = const Size(2560, 1800); // 1280×900 @2x
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: withGoldenFont(buildTheme(theme)),
routerConfig: _router(),
),
));
await tester.pumpAndSettle();
await expectLater(
find.byType(MaterialApp),
matchesGoldenFile('goldens/app_shell_$theme.png'),
);
});
}
}