本次提交包含多项迭代优化和问题修复: 1. 新增缩略图图片组件、数字格式化工具类,补充多语言翻译类型与本地化支持 2. 优化底部导航栏主题色统一使用动态accent色值 3. 修复多处图表动画、路由跳转、API请求相关问题 4. 简化服务器公告文案,调整默认分屏状态为关闭 5. 新增安卓/iOS桌面快捷方式配置 6. 重构多处状态管理类使用SafeNotifierInit统一异常保护 7. 替换硬编码蓝色为主题色,更新版本号获取方式为动态读取 8. 优化缓存预加载逻辑,移除无用代码 9. 调整默认设置项,优化用户体验细节
146 lines
6.3 KiB
Dart
146 lines
6.3 KiB
Dart
/// ============================================================
|
||
/// 闲言APP — ToolApiService 单元测试
|
||
/// 创建时间: 2026-05-31
|
||
/// 更新时间: 2026-05-31
|
||
/// 作用: 使用 mocktail 测试工具API服务层
|
||
/// 上次更新: 初始创建,覆盖核心API方法签名和SearchType集成
|
||
/// ============================================================
|
||
|
||
import 'package:flutter_test/flutter_test.dart';
|
||
import 'package:xianyan/features/discover/models/search_type.dart';
|
||
import 'package:xianyan/features/discover/models/tool_item.dart';
|
||
import 'package:xianyan/features/discover/services/tool_api_service.dart';
|
||
|
||
void main() {
|
||
group('ToolApiService', () {
|
||
test('hanziSearch 参数正确传递 SearchType.value', () {
|
||
for (final type in SearchType.forApi(SearchApiType.hanziSearch)) {
|
||
expect(type.value, isNotEmpty);
|
||
expect(type.isSupportedBy(SearchApiType.hanziSearch), isTrue);
|
||
}
|
||
});
|
||
|
||
test('searchAll 参数正确传递 SearchType.value', () {
|
||
for (final type in SearchType.forApi(SearchApiType.searchAll)) {
|
||
expect(type.value, isNotEmpty);
|
||
expect(type.isSupportedBy(SearchApiType.searchAll), isTrue);
|
||
}
|
||
});
|
||
|
||
test('defaultTools 中 listType 与 SearchType.apiType 一致', () {
|
||
final listTools = defaultTools.where(
|
||
(t) => t.navConfig?.type == ToolNavType.list && t.navConfig?.searchType != null,
|
||
);
|
||
|
||
for (final tool in listTools) {
|
||
final config = tool.navConfig!;
|
||
final searchType = config.searchType!;
|
||
final listType = config.listType;
|
||
|
||
if (listType == 'hanzi_search') {
|
||
expect(
|
||
searchType.apiType,
|
||
SearchApiType.hanziSearch,
|
||
reason: '${tool.id} 使用 hanzi_search 但 SearchType.${searchType.name} 的 apiType 不是 hanziSearch',
|
||
);
|
||
} else if (listType == 'searchall') {
|
||
expect(
|
||
searchType.apiType,
|
||
SearchApiType.searchAll,
|
||
reason: '${tool.id} 使用 searchall 但 SearchType.${searchType.name} 的 apiType 不是 searchAll',
|
||
);
|
||
}
|
||
}
|
||
});
|
||
|
||
test('defaultTools 中每个 list 工具的 searchType 不为 null', () {
|
||
final listTools = defaultTools.where(
|
||
(t) => t.navConfig?.type == ToolNavType.list,
|
||
);
|
||
|
||
for (final tool in listTools) {
|
||
final config = tool.navConfig!;
|
||
if (config.listType == 'hanzi_search' || config.listType == 'searchall') {
|
||
expect(
|
||
config.searchType,
|
||
isNotNull,
|
||
reason: '${tool.id} 使用 ${config.listType} 但 searchType 为 null',
|
||
);
|
||
}
|
||
}
|
||
});
|
||
|
||
test('hanziSearch 接口支持的 type 值覆盖所有 hanziSearch 工具', () {
|
||
final hanziValues = SearchType.valuesForApi(SearchApiType.hanziSearch);
|
||
final hanziTools = defaultTools.where(
|
||
(t) => t.navConfig?.listType == 'hanzi_search' && t.navConfig?.searchType != null,
|
||
);
|
||
|
||
for (final tool in hanziTools) {
|
||
expect(
|
||
hanziValues.contains(tool.navConfig!.searchType!.value),
|
||
isTrue,
|
||
reason: '${tool.id} 的 searchType value "${tool.navConfig!.searchType!.value}" 不在 hanziSearch 支持列表中',
|
||
);
|
||
}
|
||
});
|
||
|
||
test('searchAll 接口支持的 type 值覆盖所有 searchAll 工具', () {
|
||
final searchAllValues = SearchType.valuesForApi(SearchApiType.searchAll);
|
||
final searchAllTools = defaultTools.where(
|
||
(t) => t.navConfig?.listType == 'searchall' && t.navConfig?.searchType != null,
|
||
);
|
||
|
||
for (final tool in searchAllTools) {
|
||
expect(
|
||
searchAllValues.contains(tool.navConfig!.searchType!.value),
|
||
isTrue,
|
||
reason: '${tool.id} 的 searchType value "${tool.navConfig!.searchType!.value}" 不在 searchAll 支持列表中',
|
||
);
|
||
}
|
||
});
|
||
|
||
test('ToolApiService 静态方法存在且可调用', () {
|
||
expect(() => ToolApiService.hanziSearch, isA<Function>());
|
||
expect(() => ToolApiService.searchAll, isA<Function>());
|
||
expect(() => ToolApiService.hanziZi, isA<Function>());
|
||
expect(() => ToolApiService.bishun, isA<Function>());
|
||
expect(() => ToolApiService.zuci, isA<Function>());
|
||
expect(() => ToolApiService.cidian, isA<Function>());
|
||
expect(() => ToolApiService.chengyu, isA<Function>());
|
||
expect(() => ToolApiService.jinyici, isA<Function>());
|
||
expect(() => ToolApiService.fanyici, isA<Function>());
|
||
expect(() => ToolApiService.juzi, isA<Function>());
|
||
expect(() => ToolApiService.nick, isA<Function>());
|
||
expect(() => ToolApiService.barcode, isA<Function>());
|
||
expect(() => ToolApiService.unitConvert, isA<Function>());
|
||
expect(() => ToolApiService.danci, isA<Function>());
|
||
expect(() => ToolApiService.suoxie, isA<Function>());
|
||
expect(() => ToolApiService.dailyRecommend, isA<Function>());
|
||
expect(() => ToolApiService.dailyPoetry, isA<Function>());
|
||
expect(() => ToolApiService.dailyChengyu, isA<Function>());
|
||
expect(() => ToolApiService.dailyWisdom, isA<Function>());
|
||
expect(() => ToolApiService.dailyStory, isA<Function>());
|
||
expect(() => ToolApiService.chinaColors, isA<Function>());
|
||
expect(() => ToolApiService.hitokotoRandom, isA<Function>());
|
||
expect(() => ToolApiService.hitokotoSearch, isA<Function>());
|
||
expect(() => ToolApiService.hitokotoCategories, isA<Function>());
|
||
expect(() => ToolApiService.hitokotoHot, isA<Function>());
|
||
expect(() => ToolApiService.hitokotoDetail, isA<Function>());
|
||
expect(() => ToolApiService.searchSuggest, isA<Function>());
|
||
expect(() => ToolApiService.hotRead, isA<Function>());
|
||
expect(() => ToolApiService.jiufangSearch, isA<Function>());
|
||
expect(() => ToolApiService.siteSearch, isA<Function>());
|
||
expect(() => ToolApiService.healthCheck, isA<Function>());
|
||
expect(() => ToolApiService.ocrRecognize, isA<Function>());
|
||
expect(() => ToolApiService.fetchStatsOverview, isA<Function>());
|
||
expect(() => ToolApiService.fetchStatsTrend, isA<Function>());
|
||
expect(() => ToolApiService.fetchHotTools, isA<Function>());
|
||
expect(() => ToolApiService.fetchHotArticles, isA<Function>());
|
||
expect(() => ToolApiService.fetchContentStats, isA<Function>());
|
||
expect(() => ToolApiService.fetchUserActivity, isA<Function>());
|
||
expect(() => ToolApiService.fetchApiUsage, isA<Function>());
|
||
});
|
||
});
|
||
}
|