Files
Aq-Accounting-Flutter/test/ai_persona_test.dart
T
2026-09-28 17:16:34 +08:00

139 lines
4.4 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:qiangbao_accounting/models/ai_persona.dart';
/// AiPersonaItem 的解析与预览测试。
///
/// 重点是**不崩**:服务端字段缺失(老版本后端、网络截断)时 fromJson
/// 不能抛异常,否则整个配置页会白屏。
void main() {
group('AiPersonaItem 解析', () {
test('完整字段正常解析', () {
final item = AiPersonaItem.fromJson({
'id': 5,
'name': '花花',
'systemPrompt': '你是助手。',
'promptLength': 6,
'isDefault': false,
'editable': true,
'defaultPrompt': null,
});
expect(item.id, 5);
expect(item.name, '花花');
expect(item.systemPrompt, '你是助手。');
expect(item.promptLength, 6);
expect(item.isDefault, isFalse);
expect(item.editable, isTrue);
expect(item.defaultPrompt, isNull);
});
test('默认项:id 为 null、不可编辑、带 defaultPrompt', () {
final item = AiPersonaItem.fromJson({
'id': null,
'name': '默认人设',
'systemPrompt': '内置文本',
'isDefault': true,
'editable': false,
'defaultPrompt': '内置文本',
});
expect(item.id, isNull);
expect(item.isDefault, isTrue);
expect(item.editable, isFalse);
expect(item.defaultPrompt, '内置文本');
});
test('★ 字段全缺也不抛异常(老后端 / 网络截断)', () {
final item = AiPersonaItem.fromJson(const {});
expect(item.id, isNull);
expect(item.name, '未命名');
expect(item.systemPrompt, '');
expect(item.promptLength, 0);
expect(item.isDefault, isFalse);
// editable 默认 true —— 缺字段时倾向「让用户能改」,而不是锁死
expect(item.editable, isTrue);
expect(item.defaultPrompt, isNull);
});
test('selectionKey:默认项是 -1,具体项是它的 id', () {
final def = AiPersonaItem.fromJson({'id': null, 'isDefault': true});
final mine = AiPersonaItem.fromJson({'id': 42});
expect(def.selectionKey, -1);
expect(mine.selectionKey, 42);
});
test('defaultPrompt 为空串时归一成 null(不能拿空串去判断「有没有」)', () {
final item = AiPersonaItem.fromJson({'id': 1, 'defaultPrompt': ''});
expect(item.defaultPrompt, isNull);
});
test('promptLength 缺失时按 0,不会让界面显示 null', () {
final item = AiPersonaItem.fromJson({'id': 1});
expect(item.promptLength, 0);
});
});
group('preview(列表里的两行预览)', () {
test('短文本原样返回', () {
final item = AiPersonaItem.fromJson({
'id': 1,
'systemPrompt': '你是助手。',
});
expect(item.preview, '你是助手。');
});
test('换行被压成空格 —— 否则列表项会被撑成好几行', () {
final item = AiPersonaItem.fromJson({
'id': 1,
'systemPrompt': '第一行\n第二行\n\n第三行',
});
expect(item.preview, '第一行 第二行 第三行');
expect(item.preview.contains('\n'), isFalse);
});
test('连续空白(含缩进)被压成一个空格', () {
final item = AiPersonaItem.fromJson({
'id': 1,
'systemPrompt': '甲 乙\t丙',
});
expect(item.preview, '甲 乙 丙');
});
test('超长文本截断并加省略号', () {
final long = '啊' * 100;
final item = AiPersonaItem.fromJson({'id': 1, 'systemPrompt': long});
expect(item.preview.length, 51); // 50 + 省略号
expect(item.preview.endsWith('…'), isTrue);
});
test('刚好 50 字不截断', () {
final exact = '啊' * 50;
final item = AiPersonaItem.fromJson({'id': 1, 'systemPrompt': exact});
expect(item.preview, exact);
expect(item.preview.endsWith('…'), isFalse);
});
test('空提示词不会崩', () {
final item = AiPersonaItem.fromJson({'id': 1, 'systemPrompt': ''});
expect(item.preview, '');
});
test('只有空白字符时预览是空的', () {
final item = AiPersonaItem.fromJson({'id': 1, 'systemPrompt': ' \n\t '});
expect(item.preview, '');
});
test('首尾空白被去掉', () {
final item = AiPersonaItem.fromJson({
'id': 1,
'systemPrompt': ' 你是助手。 ',
});
expect(item.preview, '你是助手。');
});
});
}