You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
3.6 KiB
70 lines
3.6 KiB
import 'package:eaimar/data/services/bailian_multimodal_service.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
/// Dart 版与原生版百炼客户端之间的**共用契约**。
|
|
///
|
|
/// 耳机唤醒走原生(`BailianDialogClient.swift/.kt`),手机麦按住说话走 Dart
|
|
/// ([BailianMultimodalService])。两条路必须连到同一个百炼应用、带同一套
|
|
/// MCP 工具名——对不上不会报任何错,只表现为「用耳机问和在 App 里问,
|
|
/// 助手的能力不一样」。
|
|
///
|
|
/// 原生那份的配置是**从 Dart 传下去**的(apiKey / appId / workspaceId /
|
|
/// mcpAuthTools 都走 start 的参数),所以只要这几个解析入口是共用的,
|
|
/// 两边就不会漂。这个测试钉的就是「它们确实是共用的、且是 public」。
|
|
void main() {
|
|
test('配置解析是 static 且两条链路共用', () {
|
|
// 这三个函数是原生客户端唯一的取值来源(见 BailianNativeDialog.start)。
|
|
// 改成实例私有 getter 会让原生那边不得不再抄一份解析逻辑。
|
|
expect(BailianMultimodalService.resolveApiKey, isA<Function>());
|
|
expect(BailianMultimodalService.resolveAppId, isA<Function>());
|
|
expect(BailianMultimodalService.resolveWorkspaceId, isA<Function>());
|
|
});
|
|
|
|
test('覆盖为空时回退到默认 app/workspace,不会变成空串', () {
|
|
// 空串会让握手带着空 app_id 发出去,服务端只回一句含糊的 task-failed
|
|
expect(BailianMultimodalService.resolveAppId('').isNotEmpty, isTrue);
|
|
expect(BailianMultimodalService.resolveAppId(' ').isNotEmpty, isTrue);
|
|
expect(BailianMultimodalService.resolveWorkspaceId('').isNotEmpty, isTrue);
|
|
expect(BailianMultimodalService.resolveWorkspaceId(' ').isNotEmpty, isTrue);
|
|
});
|
|
|
|
test('显式覆盖优先于全局配置', () {
|
|
// 两个 agent(EMAI / EaiCar 车载助手)用的是百炼里不同的应用,
|
|
// 覆盖失效会让车载香薰唤醒到 EMAI 上去
|
|
expect(BailianMultimodalService.resolveAppId('app-x'), 'app-x');
|
|
expect(BailianMultimodalService.resolveWorkspaceId('ws-x'), 'ws-x');
|
|
});
|
|
|
|
test('EMAI 带位置和日期,未登记的应用不带', () {
|
|
final emai = BailianMultimodalService.resolveAppId();
|
|
expect(BailianMultimodalService.wantsClientContext(emai), isTrue);
|
|
expect(BailianMultimodalService.wantsClientContext('not-an-app'), isFalse);
|
|
|
|
final ctx = BailianMultimodalService.promptContext(emai);
|
|
expect(ctx, isNotNull);
|
|
expect(ctx!['location'], '未知');
|
|
expect(
|
|
ctx['date'],
|
|
matches(RegExp(r'^\d{4}年\d{1,2}月\d{1,2}日 星期[一二三四五六日] \d{2}:\d{2}$')),
|
|
);
|
|
expect(ctx.containsKey('clientLocation'), isFalse);
|
|
expect(BailianMultimodalService.promptContext('not-an-app'), isNull);
|
|
});
|
|
|
|
test('登记进 clientContextAppIds 的应用也带位置和日期', () {
|
|
const id = 'mm_test_context';
|
|
BailianMultimodalService.clientContextAppIds.add(id);
|
|
addTearDown(() => BailianMultimodalService.clientContextAppIds.remove(id));
|
|
expect(BailianMultimodalService.wantsClientContext(id), isTrue);
|
|
expect(BailianMultimodalService.promptContext(id)?['location'], '未知');
|
|
});
|
|
|
|
test('MCP 工具名只有一份,且非空', () {
|
|
// 原生不再抄一份:服务端新增需要身份的工具时只改这里。
|
|
// 漏了那个工具永远「身份校验失败」,而且客户端不报任何错。
|
|
const tools = BailianMultimodalService.mcpAuthTools;
|
|
expect(tools, isNotEmpty);
|
|
expect(tools.toSet().length, tools.length, reason: '工具名不能重复');
|
|
expect(tools.every((t) => t.trim().isNotEmpty), isTrue);
|
|
});
|
|
}
|
|
|