check / check (push) Successful in 1m5s
`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
65 lines
2.1 KiB
Go
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)
|
|
}
|
|
}
|