update ai insight to give reasoning for the insight
CI / lint-and-test (push) Canceled after 0s

This commit is contained in:
Alberto-Audrix committed 2026-08-27 14:26:19 +07:00
1 parent 34336b9bd1
commit 333b1cf370
16 files changed
+2079 -130

No files matched your search

+55
View File
@@ -0,0 +1,55 @@
import { describe, it, expect } from 'vitest';
import { parseAiResult } from '../insightParse.ts';
/**
* The multi-line insight format (PENYEBAB / TINDAKAN) is what broke this:
* qwen2.5 writes those line breaks as literal newlines inside the JSON string,
* which `JSON.parse` rejects outright. A valid answer was being discarded and
* the card showed "Respons AI tidak dapat diproses".
*/
describe('parseAiResult — model JSON that is not quite JSON', () => {
it('accepts literal newlines inside a string value', () => {
const raw = `{"kesimpulan":"Mortalitas 9,1% di atas standar.","insight":"PENYEBAB:
1. Suhu 34°C di hari 12-15. [Terbukti dari data]
TINDAKAN:
1. Turunkan suhu ke 28°C."}`;
const parsed = parseAiResult(raw);
expect(parsed).not.toBeNull();
expect(parsed?.kesimpulan).toBe('Mortalitas 9,1% di atas standar.');
// The line breaks must SURVIVE — the card renders them with
// `whitespace-pre-line`, so collapsing them would flatten the format.
expect(parsed?.insight.split('\n')).toHaveLength(4);
expect(parsed?.insight).toContain('PENYEBAB:');
expect(parsed?.insight).toContain('TINDAKAN:');
});
it('accepts tabs and carriage returns inside a string value', () => {
const parsed = parseAiResult('{"kesimpulan":"a\tb","insight":"c\r\nd"}');
expect(parsed?.kesimpulan).toBe('a\tb');
expect(parsed?.insight).toContain('c');
expect(parsed?.insight).toContain('d');
});
it('leaves already-escaped newlines alone', () => {
const parsed = parseAiResult('{"kesimpulan":"satu\\ndua","insight":"tiga"}');
expect(parsed?.kesimpulan).toBe('satu\ndua');
});
it('does not confuse an escaped quote for the end of a string', () => {
const raw = '{"kesimpulan":"dia bilang \\"panas\\" sekali","insight":"x\ny"}';
const parsed = parseAiResult(raw);
expect(parsed?.kesimpulan).toBe('dia bilang "panas" sekali');
expect(parsed?.insight).toBe('x\ny');
});
it('still handles a code fence around the object', () => {
const parsed = parseAiResult('```json\n{"kesimpulan":"a","insight":"b\nc"}\n```');
expect(parsed?.kesimpulan).toBe('a');
expect(parsed?.insight).toBe('b\nc');
});
it('returns null when there is no object at all', () => {
expect(parseAiResult('maaf, saya tidak bisa menjawab')).toBeNull();
});
});