1package tinyclient23import (4 "strings"5 "testing"6)78func TestSocialBodyRendersMarkdownAndMedia(t *testing.T) {9 row := map[string]any{10 "kind": "30023",11 "content": "# Hello\n\nA **note** with a table:\n\n| one | two |\n| --- | --- |\n| a | b |\n\n",12 "tags": [][]string{{"imeta", "url https://cdn.example.test/sun.png", "m image/png", "alt sunset"}},13 }14 got := string(socialBody(row))15 for _, want := range []string{"<h1>Hello</h1>", "<strong>note</strong>", "data-markdown-table", "<img", `alt="sunset"`, `loading="lazy"`} {16 if !strings.Contains(got, want) {17 t.Errorf("social body missing %q: %s", want, got)18 }19 }20 if strings.Count(got, "sun.png") != 1 {21 t.Fatalf("media should have one image: %s", got)22 }23}2425func TestSocialBodySupportsMediaTypesAndIgnoresCode(t *testing.T) {26 row := map[string]any{27 "kind": "1",28 "content": "https://cdn.example.test/clip.mp4\n\nhttps://cdn.example.test/song.mp3\n\n```\nhttps://cdn.example.test/hidden.png\n```",29 "tags": [][]string{{"imeta", "url https://cdn.example.test/clip.mp4", "m video/mp4"}, {"imeta", "url https://cdn.example.test/song.mp3", "m audio/mpeg"}, {"imeta", "url https://cdn.example.test/hidden.png", "m image/png"}},30 }31 got := string(socialBody(row))32 if !strings.Contains(got, `<video controls`) || !strings.Contains(got, `<audio controls`) {33 t.Fatalf("native media missing: %s", got)34 }35 if !strings.Contains(got, "hidden.png") || strings.Contains(got, "<iframe") {36 t.Fatalf("code or iframe leaked into media: %s", got)37 }38}3940func TestSocialNoteIsPlaintext(t *testing.T) {41 got := string(socialBody(map[string]any{"kind": "1", "content": "**literal**\nhttps://cdn.example.test/note.png", "tags": [][]string{{"imeta", "url https://cdn.example.test/note.png", "m image/png"}}}))42 if strings.Contains(got, "<strong>") || !strings.Contains(got, "**literal**") || !strings.Contains(got, "<img") {43 t.Fatalf("note rendering = %s", got)44 }45}4647func TestSocialMediaSkipsInlineAndFencedCode(t *testing.T) {48 url := "https://cdn.example.test/hidden.png"49 row := map[string]any{"kind": "30023", "content": "``\n\n````\n\n````", "tags": [][]string{{"imeta", "url " + url, "m image/png"}}}50 got := string(socialBody(row))51 if strings.Contains(got, "<img") || strings.Contains(got, "<figure") {52 t.Fatalf("code media was embedded: %s", got)53 }54 if !strings.Contains(got, "hidden.png") {55 t.Fatalf("code source missing: %s", got)56 }57}5859func TestSocialBodyEscapesUnsafeContent(t *testing.T) {60 got := string(socialBody(map[string]any{"content": `<script>alert(1)</script> [x](javascript:alert(1)) https://cdn.example.test/a.svg`, "tags": [][]string{{"imeta", "url https://cdn.example.test/a.svg", "m image/svg+xml"}}}))61 if strings.Contains(got, "<script") || strings.Contains(got, `href="javascript:`) || strings.Contains(got, "<iframe") {62 t.Fatalf("unsafe social markup: %s", got)63 }64 if !strings.Contains(got, "a.svg") {65 t.Fatalf("safe media link missing: %s", got)66 }67}6869func TestSocialPreviewAndMediaURL(t *testing.T) {70 if got := socialPreview(map[string]any{"content": "hello\nworld"}); got != "hello world" {71 t.Fatalf("preview = %q", got)72 }73 if got := socialMediaURL("javascript:alert(1)"); got != "" {74 t.Fatalf("unsafe URL = %q", got)75 }76 if got := socialMediaURL("https://example.test/a?x=1"); got != "https://example.test/a?x=1" {77 t.Fatalf("safe URL = %q", got)78 }79}8081func TestSocialArticleMediaWithoutMetadata(t *testing.T) {82 got := string(socialBody(map[string]any{"kind": 30023, "content": "\n\n[Watch](https://cdn.test/a.mp4)\n\nhttps://cdn.test/a.mp3"}))83 for _, want := range []string{`<img src="https://cdn.test/a.jpg"`, `alt="Cover"`, `<video controls`, `<audio controls`} {84 if !strings.Contains(got, want) {85 t.Errorf("missing %s: %s", want, got)86 }87 }88 if strings.Contains(got, "!Cover") || strings.Contains(got, "<p><figure") {89 t.Fatal(got)90 }91}92func TestSocialNoteImageWithoutMetadataAndInvalidClientMIME(t *testing.T) {93 for _, tags := range [][][]string{nil, {{"imeta", "url https://cdn.test/a.jpg", "m jpeg"}}} {94 got := string(socialBody(map[string]any{"kind": 1, "content": "A photo\nhttps://cdn.test/a.jpg", "tags": tags}))95 if !strings.Contains(got, `<img src="https://cdn.test/a.jpg"`) {96 t.Fatal(got)97 }98 }99}100func TestSocialMediaTokenCannotBeForgedInCode(t *testing.T) {101 raw := "https://cdn.test/a.png"102 got := string(socialBody(map[string]any{"kind": 30023, "content": "`" + socialMediaToken(raw) + "`\n\n"}))103 if strings.Count(got, "<img") != 1 || !strings.Contains(got, "<code>"+socialMediaToken(raw)+"</code>") {104 t.Fatal(got)105 }106}107108func TestSocialMediaReservesValidMetadataDimensions(t *testing.T) {109 for _, dimension := range []string{"1170x1613", "1170.0x1613.0"} {110 got := string(socialBody(map[string]any{"kind": 1, "content": "https://cdn.test/a.jpg", "tags": [][]string{{"imeta", "url https://cdn.test/a.jpg", "m image/jpeg", "dim " + dimension}}}))111 if !strings.Contains(got, `width="1170" height="1613"`) {112 t.Fatal(got)113 }114 }115 for _, dimension := range []string{"0x3", "NaNx3", "1e90x3", `1" onload="bad`} {116 got := string(socialBody(map[string]any{"kind": 1, "content": "https://cdn.test/a.jpg", "tags": [][]string{{"imeta", "url https://cdn.test/a.jpg", "m image/jpeg", "dim " + dimension}}}))117 if strings.Contains(got, "width=") || strings.Contains(got, "onload=") {118 t.Fatal(got)119 }120 }121}