feat: refine AI navigation and accessibility recovery
This commit is contained in:
@@ -65,12 +65,12 @@ void main() {
|
||||
).readAsStringSync();
|
||||
final addPage = File('lib/features/add/add_page.dart').readAsStringSync();
|
||||
final chat = File('lib/features/chat/chat_page.dart').readAsStringSync();
|
||||
final companion = File(
|
||||
'lib/features/settings/companion_page.dart',
|
||||
).readAsStringSync();
|
||||
final onboarding = File(
|
||||
'lib/features/onboarding/pages/onboarding_page.dart',
|
||||
).readAsStringSync();
|
||||
final companion = File(
|
||||
'lib/features/settings/companion_page.dart',
|
||||
).readAsStringSync();
|
||||
final onboarding = File(
|
||||
'lib/features/onboarding/pages/onboarding_page.dart',
|
||||
).readAsStringSync();
|
||||
final me = File('lib/features/settings/me_page.dart').readAsStringSync();
|
||||
final report = File(
|
||||
'lib/features/stats/report_page.dart',
|
||||
@@ -79,30 +79,30 @@ void main() {
|
||||
expect(controls, contains(': context.jz.card'));
|
||||
expect(addPage, isNot(contains('selected ? _activeColor : Colors.white')));
|
||||
expect(chat, isNot(contains('isMe ? AppTheme.primary : Colors.white')));
|
||||
expect(
|
||||
companion,
|
||||
isNot(contains('context.jz.aiBackground : Colors.white')),
|
||||
);
|
||||
expect(onboarding, contains(': context.jz.card'));
|
||||
expect(
|
||||
onboarding,
|
||||
isNot(contains('context.jz.aiBackground : Colors.white')),
|
||||
);
|
||||
expect(
|
||||
companion,
|
||||
isNot(contains('context.jz.aiBackground : Colors.white')),
|
||||
);
|
||||
expect(onboarding, contains(': context.jz.card'));
|
||||
expect(
|
||||
onboarding,
|
||||
isNot(contains('context.jz.aiBackground : Colors.white')),
|
||||
);
|
||||
expect(me, isNot(contains('context.jz.primaryBackground : Colors.white')));
|
||||
expect(report, isNot(contains('selected ? Colors.white')));
|
||||
});
|
||||
|
||||
test('首次引导只提交服务端实际返回的 AI 伙伴配置', () {
|
||||
final onboarding = File(
|
||||
'lib/features/onboarding/pages/onboarding_page.dart',
|
||||
).readAsStringSync();
|
||||
|
||||
expect(onboarding, contains('_hasValidCatalogSelection'));
|
||||
expect(onboarding, contains('AI 伙伴配置暂不可用'));
|
||||
expect(onboarding, contains('重新加载'));
|
||||
expect(onboarding, isNot(contains('_fallbackAvatars')));
|
||||
expect(onboarding, isNot(contains('_fallbackPersonas')));
|
||||
});
|
||||
expect(report, isNot(contains('selected ? Colors.white')));
|
||||
});
|
||||
|
||||
test('首次引导只提交服务端实际返回的 AI 伙伴配置', () {
|
||||
final onboarding = File(
|
||||
'lib/features/onboarding/pages/onboarding_page.dart',
|
||||
).readAsStringSync();
|
||||
|
||||
expect(onboarding, contains('_hasValidCatalogSelection'));
|
||||
expect(onboarding, contains('AI 伙伴配置暂不可用'));
|
||||
expect(onboarding, contains('重新加载'));
|
||||
expect(onboarding, isNot(contains('_fallbackAvatars')));
|
||||
expect(onboarding, isNot(contains('_fallbackPersonas')));
|
||||
});
|
||||
|
||||
test('聊天附件只保留拍照和相册导入', () {
|
||||
final source = File('lib/features/chat/chat_page.dart').readAsStringSync();
|
||||
@@ -114,6 +114,49 @@ void main() {
|
||||
expect(source, isNot(contains('ScreenshotChannel.capture')));
|
||||
});
|
||||
|
||||
test('底部导航固定保留 AI 入口且关闭状态在聊天二级页处理', () {
|
||||
final shell = File(
|
||||
'lib/features/home/pages/main_shell.dart',
|
||||
).readAsStringSync();
|
||||
final router = File('lib/app/app.dart').readAsStringSync();
|
||||
final gate = File(
|
||||
'lib/shared/widgets/ai_access_gate.dart',
|
||||
).readAsStringSync();
|
||||
|
||||
expect(shell, isNot(contains('showAiEntry')));
|
||||
expect(shell, contains('_tab(companion.name, AppIcons.chat, 2)'));
|
||||
expect(router, isNot(contains("state.matchedLocation == '/chat'")));
|
||||
expect(gate, contains('AiAccessState.aiDisabled'));
|
||||
expect(gate, contains('AI 功能已关闭'));
|
||||
expect(gate, contains('手动记账和统计不受影响'));
|
||||
});
|
||||
|
||||
test('报告入口归入统计并继承当前周期', () {
|
||||
final stats = File('lib/features/stats/stats_page.dart').readAsStringSync();
|
||||
final report = File(
|
||||
'lib/features/stats/report_page.dart',
|
||||
).readAsStringSync();
|
||||
final me = File('lib/features/settings/me_page.dart').readAsStringSync();
|
||||
|
||||
expect(me, isNot(contains("context.push('/report')")));
|
||||
expect(stats, contains("path: '/report'"));
|
||||
expect(stats, contains("'period': _period"));
|
||||
expect(stats, contains("'date': _anchor.toIso8601String()"));
|
||||
expect(stats, contains('查看完整报告'));
|
||||
expect(report, contains('widget.initialPeriod'));
|
||||
expect(report, contains('widget.initialAnchor'));
|
||||
});
|
||||
|
||||
test('聊天输入为空显示附件加号,有文本时显示发送按钮', () {
|
||||
final chat = File('lib/features/chat/chat_page.dart').readAsStringSync();
|
||||
|
||||
expect(chat, contains("ValueKey('add-attachment')"));
|
||||
expect(chat, contains("ValueKey('send-message')"));
|
||||
expect(chat, contains('child: hasText'));
|
||||
expect(chat, contains("tooltip: '添加附件'"));
|
||||
expect(chat, isNot(contains("'附件'")));
|
||||
});
|
||||
|
||||
test('表情包具备离线缓存、内置兜底和展开刷新', () {
|
||||
final api = File('lib/shared/api/business_api.dart').readAsStringSync();
|
||||
final chat = File('lib/features/chat/chat_page.dart').readAsStringSync();
|
||||
@@ -236,4 +279,40 @@ void main() {
|
||||
expect(source, contains('setRecognitionToggle(key, false)'));
|
||||
expect(source, contains('_BackgroundKeepAliveCard'));
|
||||
});
|
||||
|
||||
test('长期识别组件与系统绑定使用默认进程并支持重连状态', () {
|
||||
final manifest = File(
|
||||
'android/app/src/main/AndroidManifest.xml',
|
||||
).readAsStringSync();
|
||||
final channel = File(
|
||||
'lib/shared/services/screenshot_channel.dart',
|
||||
).readAsStringSync();
|
||||
final activity = File(
|
||||
'android/app/src/main/kotlin/com/nx/miaoji/MainActivity.kt',
|
||||
).readAsStringSync();
|
||||
|
||||
for (final component in [
|
||||
'ScreenshotTileService',
|
||||
'PaymentNotificationListenerService',
|
||||
'ScreenshotAccessibilityService',
|
||||
]) {
|
||||
final declaration = RegExp(
|
||||
'<service\\s+android:name="\\.$component"[\\s\\S]*?</service>',
|
||||
).firstMatch(manifest)?.group(0);
|
||||
expect(declaration, isNotNull);
|
||||
expect(declaration, contains('android:stopWithTask="false"'));
|
||||
expect(declaration, isNot(contains('android:process=')));
|
||||
}
|
||||
final provider = RegExp(
|
||||
'<provider\\s+android:name="\\.RecognitionBridgeProvider"[\\s\\S]*?/>',
|
||||
).firstMatch(manifest)?.group(0);
|
||||
expect(provider, isNotNull);
|
||||
expect(provider, isNot(contains('android:process=')));
|
||||
expect(manifest, contains('android:name=".OneShotProjectionService"'));
|
||||
expect(manifest, contains('android:process=":recognition"'));
|
||||
expect(channel, contains('waitForAccessibilityConnection'));
|
||||
expect(channel, contains('AccessibilityConnectionState.reconnecting'));
|
||||
expect(activity, contains('"reconnecting"'));
|
||||
expect(activity, contains('"disconnected"'));
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user