Files
viettranx e788e621c3 test(contracts): add P1 WS and HTTP API contract tests
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.
2026-04-12 21:44:32 +07:00

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")
}
}