test(apps): 添加 UI Schema 单元测试
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:social_app/core/schemas/ui_schema.dart';
|
||||
|
||||
void main() {
|
||||
group('ui_schema protocol stability', () {
|
||||
test('UiSchemaDocument.fromJson keeps enum fallback defaults', () {
|
||||
final doc = UiSchemaDocument.fromJson({
|
||||
'version': '1.0',
|
||||
'schemaType': 'unknown_type',
|
||||
'status': 'unknown_status',
|
||||
'nodes': const [],
|
||||
});
|
||||
|
||||
expect(doc.schemaType, SchemaType.toolResult);
|
||||
expect(doc.status, UiStatus.info);
|
||||
});
|
||||
|
||||
test('actionSpecFromJson covers known and unknown branches', () {
|
||||
final navigation = actionSpecFromJson({
|
||||
'type': 'navigation',
|
||||
'path': '/calendar/dayweek',
|
||||
'params': {'from': 'home'},
|
||||
});
|
||||
expect(navigation, isA<NavigateAction>());
|
||||
|
||||
final unknown = actionSpecFromJson({'type': 'not_supported'});
|
||||
expect(unknown, isA<EventAction>());
|
||||
expect((unknown as EventAction).event, 'unknown');
|
||||
});
|
||||
|
||||
test('UiNode.fromJson returns text fallback for unknown node type', () {
|
||||
final node = UiNode.fromJson({'type': 'mystery'});
|
||||
|
||||
expect(node, isA<UiTextNode>());
|
||||
expect((node as UiTextNode).content, 'Unknown node type: mystery');
|
||||
});
|
||||
|
||||
test(
|
||||
'buildSuccessDocument and buildErrorDocument keep status semantics',
|
||||
() {
|
||||
final success = buildSuccessDocument(const [
|
||||
UiTextNode(content: 'ok'),
|
||||
], schemaType: SchemaType.agentResponse);
|
||||
final error = buildErrorDocument(const [UiTextNode(content: 'bad')]);
|
||||
|
||||
expect(success.status, UiStatus.success);
|
||||
expect(success.schemaType, SchemaType.agentResponse);
|
||||
expect(success.locale, 'zh-CN');
|
||||
|
||||
expect(error.status, UiStatus.error);
|
||||
expect(error.schemaType, SchemaType.toolResult);
|
||||
expect(error.version, '1.0');
|
||||
},
|
||||
);
|
||||
|
||||
test('UiSchemaDocument round-trip keeps critical fields stable', () {
|
||||
final original = UiSchemaDocument(
|
||||
version: '1.0',
|
||||
schemaType: SchemaType.toolResult,
|
||||
docId: 'doc_1',
|
||||
timestamp: '2026-03-19T10:00:00Z',
|
||||
locale: 'zh-CN',
|
||||
status: UiStatus.success,
|
||||
renderer: const RendererConfig(theme: RendererTheme.light),
|
||||
meta: const DocumentMeta(requestId: 'req_1', toolId: 'tool_1'),
|
||||
nodes: const [
|
||||
UiContainerNode(
|
||||
direction: ContainerDirection.vertical,
|
||||
children: [
|
||||
UiTextNode(content: 'hello', format: TextFormat.markdown),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final encoded = original.toJson();
|
||||
final decoded = UiSchemaDocument.fromJson(encoded);
|
||||
|
||||
expect(decoded.version, '1.0');
|
||||
expect(decoded.schemaType, SchemaType.toolResult);
|
||||
expect(decoded.docId, 'doc_1');
|
||||
expect(decoded.status, UiStatus.success);
|
||||
expect(decoded.renderer?.theme, RendererTheme.light);
|
||||
expect(decoded.nodes, hasLength(1));
|
||||
expect(decoded.nodes.first, isA<UiContainerNode>());
|
||||
});
|
||||
|
||||
test('toJson omits nullable fields as before', () {
|
||||
const action = UiAction(
|
||||
id: 'a1',
|
||||
label: 'open',
|
||||
action: NavigateAction(path: '/settings'),
|
||||
);
|
||||
|
||||
final json = action.toJson();
|
||||
|
||||
expect(json['id'], 'a1');
|
||||
expect(json['label'], 'open');
|
||||
expect(json.containsKey('icon'), false);
|
||||
expect(json.containsKey('style'), false);
|
||||
expect(json.containsKey('confirm'), false);
|
||||
expect((json['action'] as Map<String, dynamic>)['path'], '/settings');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user