package api
import (
"context"
"errors"
"testing"
"time"
"craftdesign.group/quarry/internal/chat"
"craftdesign.group/quarry/internal/ops"
)
// A channel whose newest rows are its own edits and deletes, sharing
// the stream with another channel (#379).
func limitRig(t *testing.T) *ops.Registry {
t.Helper()
at := time.Now().UTC().Format(time.RFC3339Nano)
m := func(seq uint64, kind, text string, ref uint64) chat.Message {
return chat.Message{Seq: seq, Kind: kind, Text: text, Ref: ref, User: "jva", At: at}
}
fc := &fakeChat{
msgs: []chat.Message{
m(10, chat.KindMsg, "one", 0), m(11, chat.KindMsg, "two", 0), m(12, chat.KindMsg, "elsewhere", 0),
m(13, chat.KindMsg, "three", 0), m(14, chat.KindEdit, "three, edited", 13), m(15, chat.KindDel, "", 11),
m(16, chat.KindEdit, "three, again", 13),
},
codes: []string{"codeXYZ", "codeXYZ", "other", "codeXYZ", "codeXYZ", "codeXYZ", "codeXYZ"},
}
r := ops.NewRegistry()
repos := testRepos(wikiIndex(t))
mustRepo(t, repos, "test").Code = "codeXYZ"
if err := RegisterAll(r, Deps{Version: "v", Repos: repos, Chat: fc}); err != nil {
t.Fatal(err)
}
return r
}
func TestChatLimitCountsMessagesNotRows(t *testing.T) {
r := limitRig(t)
// A deleted message stays as its placeholder (empty text); the edit
// and delete rows themselves are not messages.
for limit, want := range map[int][]string{1: {"three, again"}, 2: {"", "three, again"}, 3: {"one", "", "three, again"}} {
got, err := r.Invoke(context.Background(), "chat.history", chatHistoryIn{Repo: "test", Limit: limit})
if err != nil {
t.Fatal(err)
}
h := got.(chatHistoryOut)
var texts []string
for _, m := range h.Messages {
texts = append(texts, m.Text)
}
if len(texts) != len(want) || texts[len(texts)-1] != want[len(want)-1] || texts[0] != want[0] {
t.Errorf("FAIL: limit=%d gave %q, want %q", limit, texts, want)
}
}
// Paging from limit=1 reaches the older message and nothing is lost.
got, _ := r.Invoke(context.Background(), "chat.history", chatHistoryIn{Repo: "test", Limit: 1})
next := got.(chatHistoryOut).Next
got, err := r.Invoke(context.Background(), "chat.history", chatHistoryIn{Repo: "test", Limit: 1, Before: next})
if err != nil {
t.Fatal(err)
}
// (Whether 11 reads as deleted here is the paging edge chat.history
// records: its delete row is on the newer page.)
if h := got.(chatHistoryOut); len(h.Messages) != 1 || h.Messages[0].Seq != 11 {
t.Errorf("FAIL: the next page holds %+v, want message 11", h.Messages)
}
}
func TestChatGetAnswers404ForWhatIsNotThisChannelsMessage(t *testing.T) {
r := limitRig(t)
for _, seq := range []uint64{12, 14, 15} { // another channel's, an edit row, a delete row
if _, err := r.Invoke(context.Background(), "chat.get", chatGetIn{Repo: "test", Seq: seq}); !errors.Is(err, ops.ErrNotFound) {
t.Errorf("FAIL: chat.get(%d) = %v, want not found", seq, err)
}
}
got, err := r.Invoke(context.Background(), "chat.get", chatGetIn{Repo: "test", Seq: 11})
if err != nil {
t.Fatal(err)
}
if g := got.(chatGetOut); g.Message.Seq != 11 || !g.Message.Deleted {
t.Errorf("FAIL: a deleted message of this channel reads %+v", g.Message)
}
}