Skip to content
quarry Artifact [ec522835dd]
Login

Artifact [ec522835dd]

Artifact ec522835dddf3de0a8fb100dc1cf7676e51d6c1a3358d53484b124ecc16732da:


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