package labeler import ( "strings" "testing" "time" comatproto "github.com/bluesky-social/indigo/api/atproto" ) // TestLabelToLexicon checks the wire-format conversion populates the indigo lexicon // fields (which is what's serialized into both the WS frame and the queryLabels JSON). func TestLabelToLexicon(t *testing.T) { now := time.Date(2026, 3, 22, 10, 0, 0, 0, time.UTC) exp := time.Date(2026, 4, 22, 10, 0, 0, 0, time.UTC) label := Label{ ID: 1, Src: "did:plc:abc", URI: "at://did:plc:abc/io.atcr.manifest/sha256-123", CID: "bafyabc", Val: "!takedown", Cts: now, Exp: &exp, Ver: LabelVersion, Sig: []byte{0x01, 0x02, 0x03}, SubjectDID: "did:plc:abc", SubjectRepo: "myimage", } lex := labelToLexicon(&label) if lex.Src != label.Src { t.Errorf("Src = %q", lex.Src) } if lex.Uri != label.URI { t.Errorf("Uri = %q", lex.Uri) } if lex.Cid == nil || *lex.Cid != "bafyabc" { t.Errorf("Cid = %v", lex.Cid) } if lex.Cts != "2026-03-22T10:00:00Z" { t.Errorf("Cts = %q", lex.Cts) } if lex.Exp == nil || *lex.Exp != "2026-04-22T10:00:00Z" { t.Errorf("Exp = %v", lex.Exp) } if len(lex.Sig) != 3 { t.Errorf("Sig length = %d, want 3", len(lex.Sig)) } } func TestPatternToLike(t *testing.T) { tests := []struct { in string want string wantErr bool }{ {"at://did:plc:abc/foo", "at://did:plc:abc/foo", false}, {"at://did:plc:abc/*", "at://did:plc:abc/%", false}, {"at://did:plc:abc%/foo", `at://did:plc:abc\%/foo`, false}, {"at://did:plc:abc_/foo", `at://did:plc:abc\_/foo`, false}, {"at://*/foo", "", true}, } for _, tt := range tests { t.Run(tt.in, func(t *testing.T) { got, err := patternToLike(tt.in) if tt.wantErr { if err == nil { t.Errorf("expected error, got %q", got) } return } if err != nil { t.Fatalf("unexpected err: %v", err) } if got != tt.want { t.Errorf("patternToLike(%q) = %q, want %q", tt.in, got, tt.want) } }) } } // TestFrameLabels exercises the CBOR framing — produces non-empty bytes whose first // byte is a CBOR map header and whose body contains the labels payload keys. func TestFrameLabels(t *testing.T) { now := time.Date(2026, 3, 22, 10, 0, 0, 0, time.UTC) l := &Label{ Src: "did:plc:abc", URI: "at://did:plc:abc", Val: "!takedown", Cts: now, Ver: LabelVersion, Sig: []byte("sig-bytes"), } frame, err := frameLabels(42, []*comatproto.LabelDefs_Label{labelToLexicon(l)}) if err != nil { t.Fatalf("frame: %v", err) } if len(frame) < 2 { t.Fatalf("frame too short: %d bytes", len(frame)) } if frame[0]&0xe0 != 0xa0 { t.Errorf("first byte %#x is not a CBOR map header", frame[0]) } if !strings.Contains(string(frame), "labels") || !strings.Contains(string(frame), "seq") { t.Errorf("frame missing expected keys") } }