import 'package:eaimar/data/models/appconfig_model.dart'; import 'package:flutter_test/flutter_test.dart'; /// `user_getappconfig` 响应的契约测试:服务端少下发字段、下发 null, /// 客户端都要能解出来,而不是整个 fromJson 抛 TypeError。 void main() { test('完整响应正常解析', () { final resp = UserGetAppConfigResp.fromJson({ 'env': {'AGENT_TYPE': 'default'}, 'agents': [ { 'id': 'a1', 'name': 'Emma', 'avatarUrl': '', 'description': '', 'tag': '', 'isOnline': true, 'voice': 'v', 'welcomeMessage': null, 'voiceWelcomeMessage': null, 'systemPrompt': 'hi', 'tools': null, } ], 'mcps': { 'm': {'servername': 'm', 'url': 'u', 'type': 1, 'tools': ''} }, 'products': [ { 'id': 45091, 'factoryid': 1, 'devicetype': 0, 'devicename': 'Echo-one', 'productimage': null, 'version': '0.0.3', 'isforceupdate': false, 'iscontinuouschat': null, 'wakeupenable': null, 'broadcastpeertranslate': null, 'updatedescription': null, 'updatepackageaddress': null, } ], }); expect(resp.products.single.devicename, 'Echo-one'); expect(resp.agents.single.systemPrompt, 'hi'); expect(resp.mcps['m']!.type, 1); }); test('顶层键缺失时给空集合,不抛', () { final resp = UserGetAppConfigResp.fromJson({}); expect(resp.env, isEmpty); expect(resp.agents, isEmpty); expect(resp.mcps, isEmpty); expect(resp.products, isEmpty); }); test('产品缺 devicetype / factoryid / devicename 时用默认值', () { final p = DBProduct.fromJson({'id': 1, 'version': '1.0.0'}); expect(p.devicetype, 0); expect(p.factoryid, 0); expect(p.devicename, ''); expect(p.version, '1.0.0'); expect(p.updateonmismatch, isNull); }); test('agent 缺非空字段时用默认值', () { final a = DBAgent.fromJson({'id': 'x'}); expect(a.name, ''); expect(a.isOnline, isFalse); expect(a.voice, ''); }); thirdSvcTests(); } void thirdSvcTests() { group('thirdsvcs', () { test('v3 形状能解析,字段是 map', () { final resp = UserGetAppConfigResp.fromJson({ 'env': {}, 'thirdsvcs': [ { 'id': 'stt_azure', 'name': '微软 Azure 语音', 'provider': 'azure', 'categories': '1', 'fields': {'subscription_key': 'k', 'region': 'southeastasia'}, }, // 空 map 字面量在 Dart 里会推断成 Map,生成代码按 Map 强转会炸; // 真实响应经 jsonDecode 出来就是 Map,这里显式标类型只是让测试字面量与之一致。 {'id': 'mcp_x', 'name': 'x', 'provider': '', 'categories': '10,11', 'fields': {}}, ], }); expect(resp.thirdsvcs.length, 2); expect(resp.thirdsvcs.first.fields['region'], 'southeastasia'); }); test('走明文 v1 时没有 thirdsvcs 键 → 空列表,不抛', () { final resp = UserGetAppConfigResp.fromJson({'env': {'A': '1'}}); expect(resp.thirdsvcs, isEmpty); expect(resp.env['A'], '1'); }); test('hasCategory 按逗号拆分整项比对,1 不会命中 10/11', () { final s = ThirdSvc(id: 'x', name: '', provider: '', categories: '10,11', fields: {}); expect(s.hasCategory(1), isFalse); expect(s.hasCategory(10), isTrue); expect(s.hasCategory(11), isTrue); }); test('条目缺字段时用默认值', () { final resp = UserGetAppConfigResp.fromJson({'thirdsvcs': [{'id': 'only_id'}]}); expect(resp.thirdsvcs.single.id, 'only_id'); expect(resp.thirdsvcs.single.fields, isEmpty); }); }); }