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> list({ String? status, String? startDate, String? endDate, String? keyword, Map? detail, int page = 1, int pageSize = 20, }) async { listCalls++; lastKeyword = keyword; return const PageResult( 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.delayed(const Duration(milliseconds: 120)); expect(repo.listCalls, 1); // 过了防抖窗口 → 合并成 1 次,关键词取最后一个 await Future.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.delayed(const Duration(milliseconds: 400)); expect(repo.listCalls, 2); expect(repo.lastKeyword, '茅台'); // 再次搜索完全相同的关键词 → 直接 return,不发请求 notifier.setKeyword('茅台'); await Future.delayed(const Duration(milliseconds: 400)); expect(repo.listCalls, 2); }); }