Files
simplexcalc/internal/api/chats_test.go
T
clawbot f53b666119
check / check (push) Successful in 1m5s
HTTP API: a chat's recent messages, and sending a message (closes #5)
`GET /api/v1/chats/{id}/messages?count=N` returns a chat's recent messages, oldest first (`count` 1 to 100, default 20), and `POST` to the same path sends a text message and returns it once the chat client has taken it. Both answer `404` for any id the chats list does not show, looked up in the same contact list. The message record is defined once, for the webhooks to reuse.

Disclosures: items are read five at a time, because one item can be many times its text and 100 at once could pass the 16 MiB read limit; text too long gets `413`, a contact who deleted the chat `409` (unverified for one still connecting); a query the server cannot read gets its own `400`.

Model: opus-5-5
2026-09-29 07:33:36 +02:00

65 lines
2.1 KiB
Go

package api_test
import (
"net/http"
"testing"
"sneak.berlin/go/simplexcalc/internal/simplex"
)
// TestChats: the chats are the bot's contacts, ordered by id, deleted
// ones marked, and the chat client is asked for the bot's user with a
// deadline.
func TestChats(t *testing.T) {
t.Parallel()
client := &fakeClient{contacts: []simplex.Contact{
{ContactID: 3, Profile: simplex.Profile{DisplayName: "bob"}, Status: "deleted"},
{ContactID: 2, Profile: simplex.Profile{DisplayName: "alice"}, Status: "active"},
}}
rec := request(t, newAPI(credential, client), http.MethodGet, chatsPath, bearer)
want := `{"chats":[{"id":2,"display_name":"alice","contact_deleted":false},` +
`{"id":3,"display_name":"bob","contact_deleted":true}]}` + "\n"
if rec.Code != http.StatusOK || rec.Body.String() != want {
t.Errorf("response = %d %q, want 200 %q", rec.Code, rec.Body.String(), want)
}
if got := rec.Header().Get("Content-Type"); got != "application/json" {
t.Errorf("Content-Type = %q, want application/json", got)
}
if client.userID != 1 || !client.hadDeadline {
t.Errorf("the chat client was asked for user %d, deadline %v; "+
"want user 1 with a deadline", client.userID, client.hadDeadline)
}
}
// TestNoChats: no contacts is an empty list, not null.
func TestNoChats(t *testing.T) {
t.Parallel()
rec := request(t, newAPI(credential, &fakeClient{}),
http.MethodGet, chatsPath, bearer)
want := `{"chats":[]}` + "\n"
if rec.Code != http.StatusOK || rec.Body.String() != want {
t.Errorf("response = %d %q, want 200 %q", rec.Code, rec.Body.String(), want)
}
}
// TestChatsFailure: when the chat client fails, the response says so
// in a chosen sentence, never in the error's own text.
func TestChatsFailure(t *testing.T) {
t.Parallel()
rec := request(t, newAPI(credential, &fakeClient{contactsErr: errChat}),
http.MethodGet, chatsPath, bearer)
want := `{"error":"the chats could not be read"}` + "\n"
if rec.Code != http.StatusInternalServerError || rec.Body.String() != want {
t.Errorf("response = %d %q, want 500 %q", rec.Code, rec.Body.String(), want)
}
}