This commit is contained in:
1 parent
34336b9bd1
commit
333b1cf370
16 files changed
+2079
-130
No files matched your search
@@ -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();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user