refactor(ai): enhance AI trace integration and OCR normalization
- Add FlyerTraceSupplement type for AI trace metadata - Implement getFlyerTraceSupplements method to fetch trace supplements - Update AiTraceService to include prompt/rawOutput and counters in flyer traces - Add persistFlyerTrace method to FlyerImportService for trace persistence - Enhance AiFlyerParserService to return structured trace data with prompts and retries - Update FlyerNormalizerService with OCR typo fixes for cheese variants and spröd bakad firre - Improve Flutter admin panel with selectable text, warnings display, and tooltips - Add comprehensive tests for AI trace supplements and normalization rules
This commit is contained in:
@@ -54,6 +54,8 @@ Widget _buildPanelApp(AdminRepository repo) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
final veryLargeOutput = '{"payload":"${List.filled(13050, 'x').join()}"}';
|
||||
|
||||
final flyerItem = AdminAiTraceListItem(
|
||||
id: 'flyer-101',
|
||||
source: AdminAiTraceSource.flyer,
|
||||
@@ -68,7 +70,7 @@ void main() {
|
||||
warningsCount: 2,
|
||||
hasPrompt: true,
|
||||
hasOutput: true,
|
||||
error: null,
|
||||
error: 'Det finns 2 varningar i detaljvyn.',
|
||||
);
|
||||
|
||||
final flyerDetail = AdminAiTraceDetail(
|
||||
@@ -84,16 +86,11 @@ void main() {
|
||||
durationMs: 1880,
|
||||
retryCount: 1,
|
||||
chunkCount: 3,
|
||||
warnings: const ['parse:low_confidence'],
|
||||
warnings: const ['parse:low_confidence', 'match:no_match'],
|
||||
error: null,
|
||||
prompt: 'Prompttext exempel',
|
||||
rawOutput: '{"ok":true}',
|
||||
normalizedOutput: const {
|
||||
'sessionId': 101,
|
||||
'items': [
|
||||
{'rawName': 'Tomat'}
|
||||
],
|
||||
},
|
||||
rawOutput: veryLargeOutput,
|
||||
normalizedOutput: null,
|
||||
summary: const {'itemCount': 1},
|
||||
);
|
||||
|
||||
@@ -180,7 +177,7 @@ void main() {
|
||||
expect(find.text('willys-v20.pdf'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Prompt and output render and copy actions show snackbars',
|
||||
testWidgets('Prompt/output are selectable and warning details are visible',
|
||||
(tester) async {
|
||||
await tester.binding.setSurfaceSize(const Size(1400, 1200));
|
||||
final fakeRepo = _FakeAdminRepository(
|
||||
@@ -200,6 +197,9 @@ void main() {
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
expect(find.text('Sammanfattning'), findsOneWidget);
|
||||
expect(find.text('Varningar (2)'), findsOneWidget);
|
||||
expect(find.text('parse:low_confidence'), findsOneWidget);
|
||||
expect(find.text('match:no_match'), findsOneWidget);
|
||||
final detailScroll = find.byType(Scrollable).last;
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('Model Output'),
|
||||
@@ -209,12 +209,19 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Model Output'), findsOneWidget);
|
||||
expect(find.textContaining('"sessionId": 101'), findsOneWidget);
|
||||
expect(find.byType(SelectableText), findsWidgets);
|
||||
expect(find.text('Visa hela outputen'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Visa hela outputen'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Visa mindre'), findsOneWidget);
|
||||
|
||||
final copyPrompt = find.byTooltip('Kopiera');
|
||||
final copyOutput = find.byTooltip('Kopiera JSON');
|
||||
final copyWarnings = find.byTooltip('Kopiera alla varningar');
|
||||
expect(copyPrompt, findsOneWidget);
|
||||
expect(copyOutput, findsOneWidget);
|
||||
expect(copyWarnings, findsOneWidget);
|
||||
|
||||
await tester.tap(copyPrompt);
|
||||
await tester.pumpAndSettle();
|
||||
@@ -224,6 +231,10 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(tester.takeException(), isNull);
|
||||
|
||||
await tester.tap(copyWarnings);
|
||||
await tester.pumpAndSettle();
|
||||
expect(tester.takeException(), isNull);
|
||||
|
||||
addTearDown(() => tester.binding.setSurfaceSize(null));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user