Refactored, added comprehensive testing.
All checks were successful
Release / release (push) Successful in 3m17s

This commit is contained in:
Jay
2025-10-26 23:23:43 -04:00
parent ec32b75267
commit 1936f055e2
61 changed files with 4678 additions and 769 deletions

159
api/parse_test.go Normal file
View File

@@ -0,0 +1,159 @@
package api
import (
"os"
"testing"
"git.wisehodl.dev/jay/aicli/config"
"github.com/stretchr/testify/assert"
)
func TestParseResponse(t *testing.T) {
tests := []struct {
name string
body string
protocol config.APIProtocol
want string
wantErr bool
errContains string
}{
{
name: "openai success",
body: `{"choices":[{"message":{"content":"This is the response text."}}]}`,
protocol: config.ProtocolOpenAI,
want: "This is the response text.",
},
{
name: "openai empty choices",
body: `{"choices":[]}`,
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "empty choices array",
},
{
name: "openai no choices field",
body: `{"result":"ok"}`,
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "no choices in response",
},
{
name: "openai invalid choice format",
body: `{"choices":["invalid"]}`,
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "invalid choice format",
},
{
name: "openai no message field",
body: `{"choices":[{"text":"wrong structure"}]}`,
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "no message in choice",
},
{
name: "openai no content field",
body: `{"choices":[{"message":{"role":"assistant"}}]}`,
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "no content in message",
},
{
name: "ollama success",
body: `{"response":"This is the Ollama response."}`,
protocol: config.ProtocolOllama,
want: "This is the Ollama response.",
},
{
name: "ollama no response field",
body: `{"model":"llama3"}`,
protocol: config.ProtocolOllama,
wantErr: true,
errContains: "no response field in ollama response",
},
{
name: "malformed json",
body: `{invalid json`,
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "parse response",
},
{
name: "openai multiline content",
body: `{"choices":[{"message":{"content":"Line 1\nLine 2\nLine 3"}}]}`,
protocol: config.ProtocolOpenAI,
want: "Line 1\nLine 2\nLine 3",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseResponse([]byte(tt.body), tt.protocol)
if tt.wantErr {
assert.Error(t, err)
if tt.errContains != "" {
assert.Contains(t, err.Error(), tt.errContains)
}
return
}
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
func TestParseResponseWithTestdata(t *testing.T) {
tests := []struct {
name string
file string
protocol config.APIProtocol
want string
wantErr bool
errContains string
}{
{
name: "openai success from file",
file: "testdata/openai_success.json",
protocol: config.ProtocolOpenAI,
want: "This is the response text.",
},
{
name: "openai empty choices from file",
file: "testdata/openai_empty_choices.json",
protocol: config.ProtocolOpenAI,
wantErr: true,
errContains: "empty choices array",
},
{
name: "ollama success from file",
file: "testdata/ollama_success.json",
protocol: config.ProtocolOllama,
want: "This is the Ollama response.",
},
{
name: "ollama no response from file",
file: "testdata/ollama_no_response.json",
protocol: config.ProtocolOllama,
wantErr: true,
errContains: "no response field",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
body, err := os.ReadFile(tt.file)
assert.NoError(t, err, "failed to read test file")
got, err := parseResponse(body, tt.protocol)
if tt.wantErr {
assert.Error(t, err)
if tt.errContains != "" {
assert.Contains(t, err.Error(), tt.errContains)
}
return
}
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}