clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/tinyagent
tinyrelay / internal / daemon / room_edit_history_test.go
room_edit_history_test.go 3.8K
1package daemon23import (4 "strconv"5 "testing"6 "time"78 "github.com/FelineStateMachine/tinyrelay/internal/event"9 "github.com/FelineStateMachine/tinyrelay/internal/relay"10)1112func TestBrowseThreadReturnsNewestAuthorEditsOutsideCursor(t *testing.T) {13 h := newRoomHarness(t)14 h.must("alice", event.KIND_CREATE_GROUP, [][]string{{"h", "general"}}, "")15 root := h.must("alice", event.KIND_THREAD, [][]string{{"h", "general"}}, "original root")16 reply := h.must("bob", event.KIND_THREAD_REPLY, [][]string{{"h", "general"}, {"e", root.ID}}, "original reply")1718 cursor := collaborationCursor(collaborationItemFrom(reply))1920 publishAt := func(who string, createdAt int64, target event.Event, content string) event.Event {21 e := h.sign(who, event.KIND_CONTENT_EDIT, [][]string{{"h", "general"}, {"e", target.ID}}, content)22 e.CreatedAt = createdAt23 if err := event.Sign(&e, h.secrets[who]); err != nil {24 t.Fatal(err)25 }26 if _, err := h.tenant.router.Publish(h.ctx, e, relay.Session{PubKeys: []string{h.keys[who]}, RelayURL: h.tenant.RelayURL()}); err != nil {27 t.Fatal(err)28 }29 return e30 }31 old := publishAt("alice", time.Now().Unix()+1, root, "root v1")32 newest := publishAt("alice", old.CreatedAt+1, root, "root v2")33 replyEdit := publishAt("bob", newest.CreatedAt+1, reply, "reply v1")3435 page, err := h.browse("bob", "browsethread", map[string]any{"id": "general", "event": root.ID, "cursor": cursor, "limit": 1})36 if err != nil {37 t.Fatal(err)38 }39 edits, ok := page["edits"].([]any)40 if !ok {41 t.Fatalf("edits = %#v", page["edits"])42 }43 found := map[string]bool{}44 for _, raw := range edits {45 row := raw.(map[string]any)46 found[row["id"].(string)] = true47 }48 if !found[newest.ID] || found[replyEdit.ID] || found[old.ID] {49 t.Fatalf("edits = %#v, want newest visible root only", edits)50 }5152 forged := h.sign("alice", event.KIND_CONTENT_EDIT, [][]string{{"h", "general"}, {"e", reply.ID}}, "wrong author")53 // The target belongs to Bob, so the author filter must exclude this edit.54 if _, err := h.tenant.router.Publish(h.ctx, forged, relay.Session{PubKeys: []string{h.keys["alice"]}, RelayURL: h.tenant.RelayURL()}); err != nil {55 t.Fatal(err)56 }57 page, err = h.browse("bob", "browsethread", map[string]any{"id": "general", "event": root.ID})58 if err != nil {59 t.Fatal(err)60 }61 found = map[string]bool{}62 for _, raw := range page["edits"].([]any) {63 found[raw.(map[string]any)["id"].(string)] = true64 if raw.(map[string]any)["content"] == "wrong author" {65 t.Fatal("forged edit was returned")66 }67 }68 if !found[replyEdit.ID] || !found[newest.ID] {69 t.Fatalf("unpaged edits = %#v, want root and reply", page["edits"])70 }71}7273func TestRoomEditsKeepIndependentTargetsAndUseLastReference(t *testing.T) {74 h := newRoomHarness(t)75 h.must("alice", event.KIND_CREATE_GROUP, [][]string{{"h", "general"}}, "")76 first := h.must("alice", event.KIND_CHAT, [][]string{{"h", "general"}}, "first")77 second := h.must("alice", event.KIND_CHAT, [][]string{{"h", "general"}}, "second")78 wanted := h.must("alice", event.KIND_CONTENT_EDIT, [][]string{{"h", "general"}, {"e", first.ID}}, "first replacement")79 var latest event.Event80 for i := 0; i < 105; i++ {81 // The first reference is context; only the last reference is edited.82 latest = signedEvent(t, h.secrets["alice"], event.KIND_CONTENT_EDIT, first.CreatedAt+int64(i)+1, [][]string{{"h", "general"}, {"e", first.ID}, {"e", second.ID}}, "second replacement "+strconv.Itoa(i))83 if err := publishAs(t, h.tenant, latest); err != nil {84 t.Fatal(err)85 }86 }87 edits, err := h.tenant.roomEdits(h.ctx, h.keys["alice"], "general", []event.Event{first, second})88 if err != nil {89 t.Fatal(err)90 }91 found := map[string]bool{}92 for _, edit := range edits {93 found[edit.ID] = true94 }95 if len(edits) != 2 || !found[wanted.ID] || !found[latest.ID] {96 t.Fatalf("lost independent target edit: %+v", edits)97 }98}