mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 22:15:47 +00:00
WS contract tests: - connect: verify response schema (protocol, role, user_id, tenant_id, is_owner, server) - agents.list: verify agents array with required fields (id, agent_key, display_name) HTTP contract tests: - /v1/chat/completions: verify OpenAI-compatible response (id, object, choices, usage) Tests require CONTRACT_TEST_WS_URL, CONTRACT_TEST_HTTP_URL, CONTRACT_TEST_TOKEN env vars.
72 lines
2.0 KiB
Go
72 lines
2.0 KiB
Go
//go:build integration
|
|
|
|
package http_api
|
|
|
|
import "testing"
|
|
|
|
// CONTRACT: /v1/chat/completions response MUST match OpenAI format.
|
|
func TestContract_HTTP_ChatCompletions(t *testing.T) {
|
|
baseURL, token := getTestServer(t)
|
|
client := newHTTPClient(baseURL, token)
|
|
|
|
resp := client.post(t, "/v1/chat/completions", map[string]any{
|
|
"model": "test",
|
|
"messages": []map[string]any{
|
|
{"role": "user", "content": "Say hello in one word"},
|
|
},
|
|
})
|
|
|
|
// Required OpenAI-compatible fields
|
|
assertField(t, resp, "id", "string")
|
|
assertField(t, resp, "object", "string")
|
|
assertField(t, resp, "created", "number")
|
|
assertField(t, resp, "model", "string")
|
|
assertField(t, resp, "choices", "array")
|
|
|
|
// Verify choices structure
|
|
choices, ok := resp["choices"].([]any)
|
|
if !ok || len(choices) == 0 {
|
|
t.Error("CONTRACT VIOLATION: choices must be non-empty array")
|
|
return
|
|
}
|
|
|
|
choice, ok := choices[0].(map[string]any)
|
|
if !ok {
|
|
t.Error("CONTRACT VIOLATION: choices[0] is not an object")
|
|
return
|
|
}
|
|
|
|
assertField(t, choice, "index", "number")
|
|
assertField(t, choice, "message", "object")
|
|
assertField(t, choice, "finish_reason", "string")
|
|
|
|
message, ok := choice["message"].(map[string]any)
|
|
if !ok {
|
|
t.Error("CONTRACT VIOLATION: choice.message is not an object")
|
|
return
|
|
}
|
|
|
|
assertField(t, message, "role", "string")
|
|
assertField(t, message, "content", "string")
|
|
}
|
|
|
|
// CONTRACT: /v1/chat/completions MUST include usage when available.
|
|
func TestContract_HTTP_ChatCompletions_Usage(t *testing.T) {
|
|
baseURL, token := getTestServer(t)
|
|
client := newHTTPClient(baseURL, token)
|
|
|
|
resp := client.post(t, "/v1/chat/completions", map[string]any{
|
|
"model": "test",
|
|
"messages": []map[string]any{
|
|
{"role": "user", "content": "Hi"},
|
|
},
|
|
})
|
|
|
|
// Usage is optional but if present must have correct structure
|
|
if usage, ok := resp["usage"].(map[string]any); ok {
|
|
assertField(t, usage, "prompt_tokens", "number")
|
|
assertField(t, usage, "completion_tokens", "number")
|
|
assertField(t, usage, "total_tokens", "number")
|
|
}
|
|
}
|