test(client): 出入库状态多选语义与默认仓库填充回归用例

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-14 11:14:32 +08:00
parent f555b99565
commit 9f620e9fc7
3 changed files with 603 additions and 0 deletions
+120
View File
@@ -2,13 +2,18 @@ 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/api/api_client.dart';
import 'package:jiu_client/core/auth/auth_state.dart';
import 'package:jiu_client/core/theme/themes.dart';
import 'package:jiu_client/models/product_option.dart';
import 'package:jiu_client/models/stock_in.dart';
import 'package:jiu_client/models/warehouse.dart';
import 'package:jiu_client/providers/stock_in_provider.dart';
import 'package:jiu_client/providers/warehouse_provider.dart';
import 'package:jiu_client/providers/product_option_provider.dart';
import 'package:jiu_client/repositories/stock_in_repository.dart';
import 'package:jiu_client/screens/stock_in/stock_in_form_screen.dart';
import 'package:jiu_client/widgets/ds/grid_combo_cell.dart';
class _FakeWarehouses extends WarehouseListNotifier {
@override
@@ -16,6 +21,23 @@ class _FakeWarehouses extends WarehouseListNotifier {
const [Warehouse(id: 1, name: '主仓', isDefault: true)];
}
/// 可配置仓库列表的假 notifier(T5 默认仓填充回归用)。
class _ConfigurableWarehouses extends WarehouseListNotifier {
final List<Warehouse> _list;
_ConfigurableWarehouses(this._list);
@override
Future<List<Warehouse>> build() async => _list;
}
/// 编辑模式假仓库:get() 返回固定单据(供 _loadEditOrder 消费)。
class _FakeStockInRepoForEdit extends StockInRepository {
final StockInOrder order;
_FakeStockInRepoForEdit(this.order) : super(ApiClient(token: 't'));
@override
Future<StockInOrder> get(int id) async => order;
}
class _FakeNames extends ProductNameListNotifier {
@override
Future<List<ProductNameOption>> build() async => const [
@@ -85,4 +107,102 @@ void main() {
expect(find.text('选择商品名称'), findsNothing,
reason: 'hint should be replaced by the picked name');
});
// ── T5:新建入库单默认填充默认仓库(2026-07-14)──────────────────────
//
// _initWarehouseDefault 语义:仓库列表加载完成后,
// isDefault 的仓 优先;无默认时仅剩 1 个仓才取它;否则保持未选(null)。
// 编辑模式不受影响(_loadEditOrder 已从单据自身仓库回填)。
int? _warehouseSelectedId(WidgetTester tester) => tester
.widgetList<GridComboCell>(find.byType(GridComboCell))
.firstWhere((c) => c.hint == '选择仓库…')
.selectedId;
Future<void> _pumpForm(WidgetTester tester, List<Override> overrides,
{int? editOrderId}) async {
tester.view.physicalSize = const Size(1400, 1000);
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.resetPhysicalSize);
await tester.pumpWidget(ProviderScope(
overrides: overrides,
child: MaterialApp(
theme: buildTheme('a'),
home: Scaffold(body: StockInFormScreen(editOrderId: editOrderId)),
),
));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
// _initWarehouseDefault / _loadEditOrder 都是异步(await provider.future),
// 多 pump 几拍确保 setState 落地。
await tester.pump(const Duration(milliseconds: 100));
}
testWidgets('新建入库单:有默认仓(isDefault=true)时自动选中默认仓',
(tester) async {
await _pumpForm(tester, [
warehouseListProvider.overrideWith(() => _FakeWarehouses()), // 主仓 isDefault
productNameListProvider.overrideWith(() => _FakeNames()),
productSeriesListProvider.overrideWith(() => _FakeSeries()),
productSpecListProvider.overrideWith(() => _FakeSpecs()),
isReadonlyProvider.overrideWithValue(false),
]);
expect(_warehouseSelectedId(tester), 1);
});
testWidgets('新建入库单:无默认仓且多仓时保持未选', (tester) async {
await _pumpForm(tester, [
warehouseListProvider.overrideWith(() => _ConfigurableWarehouses(const [
Warehouse(id: 1, name: '主仓', isDefault: false),
Warehouse(id: 2, name: '分仓', isDefault: false),
])),
productNameListProvider.overrideWith(() => _FakeNames()),
productSeriesListProvider.overrideWith(() => _FakeSeries()),
productSpecListProvider.overrideWith(() => _FakeSpecs()),
isReadonlyProvider.overrideWithValue(false),
]);
expect(_warehouseSelectedId(tester), isNull);
});
testWidgets('新建入库单:无默认仓但仅有 1 个仓时自动选中该仓', (tester) async {
await _pumpForm(tester, [
warehouseListProvider.overrideWith(() => _ConfigurableWarehouses(const [
Warehouse(id: 7, name: '唯一仓', isDefault: false),
])),
productNameListProvider.overrideWith(() => _FakeNames()),
productSeriesListProvider.overrideWith(() => _FakeSeries()),
productSpecListProvider.overrideWith(() => _FakeSpecs()),
isReadonlyProvider.overrideWithValue(false),
]);
expect(_warehouseSelectedId(tester), 7);
});
testWidgets('编辑模式:不被默认仓覆盖,仍显示单据原仓库', (tester) async {
const order = StockInOrder(
id: 99,
orderNo: 'SI2024010099',
warehouseId: 2, // 单据原仓库 = 分仓(非默认仓)
status: 'draft',
items: [],
);
await _pumpForm(
tester,
[
// 主仓(id=1isDefault=true,若默认仓填充逻辑误在编辑模式生效会把它选中,
// 但单据自身仓库是 id=2,回归断言二者不一致时以单据为准。
warehouseListProvider.overrideWith(() => _ConfigurableWarehouses(const [
Warehouse(id: 1, name: '主仓', isDefault: true),
Warehouse(id: 2, name: '分仓', isDefault: false),
])),
stockInRepositoryProvider
.overrideWithValue(_FakeStockInRepoForEdit(order)),
productNameListProvider.overrideWith(() => _FakeNames()),
productSeriesListProvider.overrideWith(() => _FakeSeries()),
productSpecListProvider.overrideWith(() => _FakeSpecs()),
isReadonlyProvider.overrideWithValue(false),
],
editOrderId: 99,
);
expect(_warehouseSelectedId(tester), 2);
});
}