Files
jiu/client/test/golden/product_detail_golden_test.dart
T
wangjia c7f36b2d72 feat(client): 库存表格列头排序 UI——DsSortHeader 点击循环 升/降/无
- 新组件 DsSortHeader(原型 thead .sh 对照,L1 已登记):未排序淡箭头暗示
  可排,激活 primary + 方向箭头(↑升/↓降)
- 库存屏 5 列(库存/成本价/总价/生产日期/入库时间)接线,排序走服务端
  全局生效(跨分页),点击循环 无→升→降→无
- 原型 inventory.html COLS sort:true + toggleSort 交互 + atoms .sh 样式登记
- 桌面库存 golden 重录 ×3(列头带排序箭头)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 16:45:39 +08:00

121 lines
4.0 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:shared_preferences/shared_preferences.dart';
import 'package:jiu_client/core/models/page_result.dart';
import 'package:jiu_client/models/product.dart';
import 'package:jiu_client/models/inventory.dart';
import 'package:jiu_client/providers/product_provider.dart';
import 'package:jiu_client/providers/inventory_provider.dart';
import 'package:jiu_client/repositories/product_repository.dart';
import 'package:jiu_client/repositories/inventory_repository.dart';
import 'package:jiu_client/screens/products/product_detail_screen.dart';
import '../support/golden_harness.dart';
/// design-distill 阶段4:商品详情「富数据版」golden × 三主题。
/// 验证 3 KPI(当前库存/货值/近30天出库)+ 各仓库分布 + 近期流水(接后端
/// /inventory?product_id + /inventory/logs?product_id 聚合)。
/// 更新基准:flutter test --update-goldens test/golden/product_detail_golden_test.dart
class _FakeProductRepo implements ProductRepository {
@override
Future<Product> getDetail(int id) async => const Product(
id: 1,
code: 'MT-FT-500',
name: '茅台 飞天 53°',
unit: '',
series: '飞天',
spec: '500ml×6',
brand: '茅台',
purchasePrice: 2680,
categoryName: '酱香');
@override
Future<List<({String date, double price})>> getPriceHistory(int id) async =>
const [
(date: '2026-06-12', price: 2680),
(date: '2026-04-20', price: 2620),
(date: '2026-02-08', price: 2700),
(date: '2025-11-15', price: 2580),
];
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class _FakeInvRepo implements InventoryRepository {
@override
Future<PageResult<Inventory>> listInventory({
int? warehouseId,
int? productId,
String? keyword,
String? code,
List<String>? series,
List<String>? spec,
String? status,
String? sortBy,
bool sortAsc = true,
int page = 1,
int pageSize = 50,
}) async =>
const PageResult(data: [
Inventory(id: 1, productId: 1, quantity: 92, warehouseName: '主仓'),
Inventory(id: 2, productId: 1, quantity: 28, warehouseName: '二号仓'),
Inventory(id: 3, productId: 1, quantity: 8, warehouseName: '冷藏库'),
], total: 3, page: 1, pageSize: 1000);
@override
Future<PageResult<InventoryLog>> listLogs({
int? warehouseId,
int? productId,
int page = 1,
int pageSize = 50,
}) async =>
const PageResult(data: [
InventoryLog(
warehouseId: 1,
productId: 1,
direction: 'in',
quantity: 24,
createdAt: '2026-06-20T09:00:00'),
InventoryLog(
warehouseId: 1,
productId: 1,
direction: 'out',
quantity: 12,
createdAt: '2026-06-18T09:00:00'),
InventoryLog(
warehouseId: 2,
productId: 1,
direction: 'out',
quantity: 18,
createdAt: '2026-06-15T09:00:00'),
InventoryLog(
warehouseId: 1,
productId: 1,
direction: 'in',
quantity: 36,
createdAt: '2026-06-12T09:00:00'),
], total: 4, page: 1, pageSize: 100);
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
List<Override> _overrides() => [
productRepositoryProvider.overrideWithValue(_FakeProductRepo()),
inventoryRepositoryProvider.overrideWithValue(_FakeInvRepo()),
];
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
SharedPreferences.setMockInitialValues({});
goldenAcrossThemes(
'product detail 富数据(桌面)',
goldenPrefix: 'product_detail',
child: () => const Scaffold(body: ProductDetailScreen(productId: 1)),
overrides: _overrides,
logical: const Size(1100, 1300),
);
}