a3a722689e
- 列表重建:KPI 卡、状态+时间列、操作改眼睛开右侧详情抽屉、重置右置 - 详情抽屉(order_detail_drawer) 100% 还原原型 + SelectionArea 可选中复制 - 详细搜索弹窗:ComboSearchField/滚轮日期、字段重构、白底盒子按钮 - 工具栏:搜索框×清除+占位精简、供应商/客户下拉取全部、状态菜单收窄 - 加载不白屏(半透明遮罩)、输入框与下拉等高、windows/macOS 默认窗口尺寸调大 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
84 lines
2.8 KiB
Dart
84 lines
2.8 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:jiu_client/core/api/api_client.dart';
|
|
import 'package:jiu_client/core/models/page_result.dart';
|
|
import 'package:jiu_client/models/stock_in.dart';
|
|
import 'package:jiu_client/providers/stock_in_provider.dart';
|
|
import 'package:jiu_client/repositories/stock_in_repository.dart';
|
|
|
|
/// 统计 list() 调用次数与最后一次关键词的假仓库,用于验证搜索限流。
|
|
class _CountingStockInRepo extends StockInRepository {
|
|
int listCalls = 0;
|
|
String? lastKeyword;
|
|
|
|
_CountingStockInRepo() : super(ApiClient(token: 't'));
|
|
|
|
@override
|
|
Future<PageResult<StockInOrder>> list({
|
|
String? status,
|
|
String? startDate,
|
|
String? endDate,
|
|
String? keyword,
|
|
Map<String, String>? detail,
|
|
int page = 1,
|
|
int pageSize = 20,
|
|
}) async {
|
|
listCalls++;
|
|
lastKeyword = keyword;
|
|
return const PageResult<StockInOrder>(
|
|
data: [], total: 0, page: 1, pageSize: 20);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
test('setKeyword 防抖:350ms 内连发只触发最后一次', () async {
|
|
final repo = _CountingStockInRepo();
|
|
final container = ProviderContainer(
|
|
overrides: [stockInRepositoryProvider.overrideWithValue(repo)],
|
|
);
|
|
addTearDown(container.dispose);
|
|
|
|
// 初次 build 自动拉一次列表
|
|
await container.read(stockInListProvider.future);
|
|
expect(repo.listCalls, 1);
|
|
|
|
final notifier = container.read(stockInListProvider.notifier);
|
|
|
|
// 350ms 内连发三个不同关键词
|
|
notifier.setKeyword('茅');
|
|
notifier.setKeyword('茅台');
|
|
notifier.setKeyword('飞天茅台');
|
|
|
|
// 防抖窗口未到 → 不应有新请求
|
|
await Future<void>.delayed(const Duration(milliseconds: 120));
|
|
expect(repo.listCalls, 1);
|
|
|
|
// 过了防抖窗口 → 合并成 1 次,关键词取最后一个
|
|
await Future<void>.delayed(const Duration(milliseconds: 350));
|
|
expect(repo.listCalls, 2);
|
|
expect(repo.lastKeyword, '飞天茅台');
|
|
});
|
|
|
|
test('setKeyword 去重:相同关键词不重复查询', () async {
|
|
final repo = _CountingStockInRepo();
|
|
final container = ProviderContainer(
|
|
overrides: [stockInRepositoryProvider.overrideWithValue(repo)],
|
|
);
|
|
addTearDown(container.dispose);
|
|
|
|
await container.read(stockInListProvider.future);
|
|
final notifier = container.read(stockInListProvider.notifier);
|
|
|
|
// 首次搜索「茅台」
|
|
notifier.setKeyword('茅台');
|
|
await Future<void>.delayed(const Duration(milliseconds: 400));
|
|
expect(repo.listCalls, 2);
|
|
expect(repo.lastKeyword, '茅台');
|
|
|
|
// 再次搜索完全相同的关键词 → 直接 return,不发请求
|
|
notifier.setKeyword('茅台');
|
|
await Future<void>.delayed(const Duration(milliseconds: 400));
|
|
expect(repo.listCalls, 2);
|
|
});
|
|
}
|