chatgpt-api/test/llms/parse-output.test.ts

244 wiersze
7.2 KiB
TypeScript

import test from 'ava'
import { z } from 'zod'
import {
parseArrayOutput,
parseBooleanOutput,
parseNumberOutput,
parseObjectOutput,
parseOutput
} from '@/llms/parse-output'
test('parseArrayOutput - handles valid arrays correctly', (t) => {
const output1 = parseArrayOutput('[1,2,3]')
const output2 = parseArrayOutput('["a", "b", "c"]')
const output3 = parseArrayOutput('[{"a": 1}, {"b": 2}]')
t.snapshot(output1, 'should return [1, 2, 3] for "[1,2,3]"')
t.snapshot(output2, 'should return ["a", "b", "c"] for "["a", "b", "c"]')
t.snapshot(
output3,
'should return [{"a": 1}, {"b": 2}] for [{"a": 1}, {"b": 2}]'
)
})
test('parseArrayOutput - handles arrays surrounded by text correctly', (t) => {
const output1 = parseArrayOutput('The array is [1,2,3]')
const output2 = parseArrayOutput('Array: ["a", "b", "c"]. That\'s all!')
const output3 = parseArrayOutput(
'This is the array [{"a": 1}, {"b": 2}] in the text'
)
t.snapshot(output1, 'should return [1, 2, 3] for "The array is [1,2,3]"')
t.snapshot(
output2,
'should return ["a", "b", "c"] for "Array: ["a", "b", "c"]. That\'s all!"'
)
t.snapshot(
output3,
'should return [{"a": 1}, {"b": 2}] for "This is the array [{"a": 1}, {"b": 2}] in the text"'
)
})
test('parseArrayOutput - handles and repairs broken JSON arrays correctly', (t) => {
const output1 = parseArrayOutput('[1, "two, 3]')
const output2 = parseArrayOutput('Array: ["a, "b", "c"]. Error here!')
const output3 = parseArrayOutput('Array in text {"arr": ["value1, "value2"]}')
t.snapshot(output1, 'should repair and return [1, "two", 3] for [1, "two, 3]')
t.snapshot(
output2,
'should repair and return ["a", "b", "c"] for Array: ["a, "b", "c"]. Error here!'
)
t.snapshot(
output3,
'should repair and return {"arr": ["value1", "value2"]} for Array in text {"arr": ["value1, "value2"]}'
)
})
test('parseArrayOutput - throws error for invalid arrays', (t) => {
const error = t.throws(
() => {
parseArrayOutput('not a valid array')
},
{ instanceOf: Error }
)
t.snapshot(error?.message)
})
test('parseObjectOutput - handles valid objects correctly', (t) => {
const output1 = parseObjectOutput('{"a":1,"b":2,"c":3}')
const output2 = parseObjectOutput(
'{"name":"John","age":30,"city":"New York"}'
)
t.snapshot(
output1,
'should return {"a":1,"b":2,"c":3} for {"a":1,"b":2,"c":3}'
)
t.snapshot(
output2,
'should return {"name":"John","age":30,"city":"New York"} for {"name":"John","age":30,"city":"New York"}'
)
})
test('parseObjectOutput - handles objects surrounded by text correctly', (t) => {
const output1 = parseObjectOutput('The object is {"a":1,"b":2,"c":3}')
const output2 = parseObjectOutput(
'Object: {"name":"John","age":30,"city":"New York"}. That\'s all!'
)
t.snapshot(
output1,
'should return {"a":1,"b":2,"c":3} for "The object is {"a":1,"b":2,"c":3}"'
)
t.snapshot(
output2,
'should return {"name":"John","age":30,"city":"New York"} for "Object: {"name":"John","age":30,"city":"New York"}. That\'s all!"'
)
})
test('parseObjectOutput - handles and repairs broken JSON objects correctly', (t) => {
const output1 = parseObjectOutput('{"a":1, "b":2, "c":3')
const output2 = parseObjectOutput(
'Object: {"name":"John,"age":30,"city":"New York"}. Error here!'
)
t.snapshot(
output1,
'should repair and return {"a":1, "b":2, "c":3} for {"a":1, "b":2, "c":3'
)
t.snapshot(
output2,
'should repair and return {"name":"John","age":30,"city":"New York"} for Object: {"name":"John,"age":30,"city":"New York"}. Error here!'
)
})
test('parseObjectOutput - handles JSON array of objects', (t) => {
const output = parseObjectOutput('[{"a":1,"b":2},{"c":3,"d":4}]')
t.snapshot(
output,
'should return first object {"a":1,"b":2} for [{"a":1,"b":2},{"c":3,"d":4}]'
)
})
test('parseObjectOutput - throws error for invalid objects', (t) => {
const error = t.throws(
() => {
parseObjectOutput('not a valid object')
},
{ instanceOf: Error }
)
t.snapshot(error?.message)
})
test('parseBooleanOutput - handles `true` outputs correctly', (t) => {
const output1 = parseBooleanOutput('True')
const output2 = parseBooleanOutput('TRUE')
const output3 = parseBooleanOutput('true.')
t.snapshot(output1, 'should return true for "True"')
t.snapshot(output2, 'should return true for "TRUE"')
t.snapshot(output3, 'should return true for "true."')
})
test('parseBooleanOutput - handles `false` outputs correctly', (t) => {
const output1 = parseBooleanOutput('False')
const output2 = parseBooleanOutput('FALSE')
const output3 = parseBooleanOutput('false!')
t.snapshot(output1, 'should return false for "False"')
t.snapshot(output2, 'should return false for "FALSE"')
t.snapshot(output3, 'should return false for "false!"')
})
test('parseBooleanOutput - throws error for invalid outputs', (t) => {
const error = t.throws(
() => {
parseBooleanOutput('NotBooleanValue')
},
{ instanceOf: Error }
)
t.snapshot(error?.message)
})
test('parseNumberOutput - handles integer outputs correctly', (t) => {
const output1 = parseNumberOutput('42', z.number().int())
const output2 = parseNumberOutput(' -5 ', z.number().int())
t.snapshot(output1, 'should return 42 for "42"')
t.snapshot(output2, 'should return -5 for " -5 "')
})
test('parseNumberOutput - handles float outputs correctly', (t) => {
const output1 = parseNumberOutput('42.42', z.number())
const output2 = parseNumberOutput(' -5.5 ', z.number())
t.snapshot(output1, 'should return 42.42 for "42.42"')
t.snapshot(output2, 'should return -5.5 for " -5.5 "')
})
test('parseNumberOutput - throws error for invalid outputs', (t) => {
const error = t.throws(
() => {
parseNumberOutput('NotANumber', z.number())
},
{ instanceOf: Error }
)
t.snapshot(error?.message)
})
test('parseOutput - handles arrays correctly', (t) => {
const arraySchema = z.array(z.number())
const output = '[1, 2, 3]'
const result = parseOutput(output, arraySchema)
t.snapshot(result, 'should parse and return [1, 2, 3] for "[1, 2, 3]"')
})
test('parseOutput - handles objects correctly', (t) => {
const objectSchema = z.object({ a: z.number(), b: z.string() })
const output = '{"a": 1, "b": "two"}'
const result = parseOutput(output, objectSchema)
t.snapshot(
result,
'should parse and return {"a": 1, "b": "two"} for "{"a": 1, "b": "two"}"'
)
})
test('parseOutput - handles booleans correctly', (t) => {
const booleanSchema = z.boolean()
const output = 'True'
const result = parseOutput(output, booleanSchema)
t.snapshot(result, 'should parse and return true for "True"')
})
test('parseOutput - handles numbers correctly', (t) => {
const numberSchema = z.number()
const output = '123.45'
const result = parseOutput(output, numberSchema)
t.snapshot(result, 'should parse and return 123.45 for "123.45"')
})
test('parseOutput - throws error for invalid data', (t) => {
const numberSchema = z.number()
const output = 'not a number'
const error = t.throws(
() => {
parseOutput(output, numberSchema)
},
{ instanceOf: Error }
)
t.snapshot(error?.message)
})