tinyrelayfile
tinyrelay/internal/daemon/social_protocol_test.go/

internal/daemon/social_protocol_test.go raw
1package daemon
2
3import (
4 "context"
5 "encoding/json"
6 "strings"
7 "testing"
8
9 "github.com/FelineStateMachine/tinyrelay/internal/event"
10 "github.com/FelineStateMachine/tinyrelay/internal/storage"
11)
12
13// These fixtures use the wire shapes from NIP-10 and NIP-22 rather than the
14// relay's internal metadata vocabulary. They are intentionally signed and
15// executed through the tenant RPC so filtering, moderation and visibility are
16// exercised together.
17func TestSocialProtocolReferencesAndVisibility(t *testing.T) {
18 _, tenant := testTenant(t)
19 owner := tenant.Policy().Owner
20 authorSecret := strings.Repeat("1", 63) + "2"
21 commenterSecret := strings.Repeat("3", 63) + "4"
22 note := signedEvent(t, authorSecret, 1, 500, nil, "root note")
23 reply := signedEvent(t, commenterSecret, 1, 501, [][]string{{"e", note.ID, "", "root", note.PubKey}}, "reply")
24 nested := signedEvent(t, authorSecret, 1, 502, [][]string{{"e", note.ID, "", "root", note.PubKey}, {"e", reply.ID, "", "reply", reply.PubKey}}, "nested")
25 article := signedEvent(t, authorSecret, 30023, 600, [][]string{{"d", "essay:edition"}, {"title", "Current"}}, "article")
26 address := "30023:" + article.PubKey + ":essay:edition"
27 articleComment := signedEvent(t, commenterSecret, 1111, 601, [][]string{
28 {"A", address}, {"K", "30023"}, {"P", article.PubKey},
29 {"a", address}, {"k", "30023"}, {"p", article.PubKey},
30 }, "article comment")
31 reaction := signedEvent(t, commenterSecret, 7, 602, [][]string{{"e", article.ID}, {"a", address}}, "")
32 unrelated := signedEvent(t, commenterSecret, 1111, 603, [][]string{{"E", strings.Repeat("f", 64)}, {"K", "30023"}}, "unrelated")
33 for _, row := range []event.Event{note, reply, nested, article, articleComment, reaction, unrelated} {
34 if _, err := tenant.store.Save(context.Background(), row, storage.SaveOptions{Now: row.CreatedAt, SearchMode: tenant.Policy().Features.Search}); err != nil {
35 t.Fatal(err)
36 }
37 }
38 value, err := tenant.Execute(context.Background(), owner, "browsesocial", []json.RawMessage{rawJSON(map[string]any{"limit": 20})})
39 if err != nil {
40 t.Fatal(err)
41 }
42 items := value.(map[string]any)["items"].([]socialItem)
43 if len(items) != 2 || items[0].Address != address || items[1].ID != note.ID {
44 t.Fatalf("feed roots = %#v", items)
45 }
46 if items[0].ReplyCount != 1 || len(items[0].Reactions) != 1 || items[0].Reactions[0].Content != "+" {
47 t.Fatalf("article folding = %#v", items[0])
48 }
49 detail, err := tenant.Execute(context.Background(), owner, "browsesocialthread", []json.RawMessage{rawJSON(map[string]any{"id": nested.ID, "limit": 20})})
50 if err != nil {
51 t.Fatal(err)
52 }
53 selected := detail.(map[string]any)["post"].(socialItem)
54 if selected.ParentID != reply.ID || selected.RootID != note.ID {
55 t.Fatalf("thread metadata = %#v", selected)
56 }
57 rootDetail, err := tenant.Execute(context.Background(), owner, "browsesocialthread", []json.RawMessage{rawJSON(map[string]any{"id": note.ID})})
58 if err != nil {
59 t.Fatal(err)
60 }
61 comments := rootDetail.(map[string]any)["comments"].([]socialItem)
62 if len(comments) != 2 || comments[0].ParentID != reply.ID {
63 t.Fatalf("root conversation = %#v", comments)
64 }
65 articleDetail, err := tenant.Execute(context.Background(), owner, "browsesocialthread", []json.RawMessage{rawJSON(map[string]any{"address": address, "limit": 20})})
66 if err != nil {
67 t.Fatal(err)
68 }
69 if len(articleDetail.(map[string]any)["comments"].([]socialItem)) != 1 {
70 t.Fatal("article comment missing")
71 }
72}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs