rss email digests over ssh because you're a cool kid
herald.dunkirk.sh
go
rss
rss-reader
ssh
charm
1package email
2
3import (
4 "strings"
5 "testing"
6 "time"
7)
8
9func TestRenderDigest_HTMLNotEscaped(t *testing.T) {
10 // Create test data with HTML content
11 data := &DigestData{
12 ConfigName: "Test Config",
13 TotalItems: 1,
14 FeedGroups: []FeedGroup{
15 {
16 FeedName: "Test Feed",
17 FeedURL: "https://example.com/feed",
18 Items: []FeedItem{
19 {
20 Title: "Test Article",
21 Link: "https://example.com/article",
22 Content: "<p>This is a <strong>test</strong> article with <a href='https://example.com'>a link</a>.</p>",
23 Published: time.Now(),
24 },
25 },
26 },
27 },
28 }
29
30 // Render with inline mode enabled
31 htmlOutput, _, err := RenderDigest(data, true, 30, false, false)
32 if err != nil {
33 t.Fatalf("RenderDigest failed: %v", err)
34 }
35
36 // Debug: print actual output
37 t.Logf("HTML Output:\n%s", htmlOutput)
38
39 // Verify HTML is NOT escaped (should contain actual tags, not < entities)
40 if strings.Contains(htmlOutput, "<p>") {
41 t.Error("HTML is being escaped - found <p> instead of <p>")
42 }
43 if strings.Contains(htmlOutput, "<strong>") {
44 t.Error("HTML is being escaped - found <strong> instead of <strong>")
45 }
46
47 // Verify HTML tags are present (not escaped)
48 if !strings.Contains(htmlOutput, "<p>This is a <strong>test</strong>") {
49 t.Error("HTML tags are not being rendered - content appears to be escaped")
50 }
51}
52
53func TestRenderDigest_UnsafeHTMLStripped(t *testing.T) {
54 // Create test data with unsafe HTML content
55 data := &DigestData{
56 ConfigName: "Test Config",
57 TotalItems: 1,
58 FeedGroups: []FeedGroup{
59 {
60 FeedName: "Test Feed",
61 FeedURL: "https://example.com/feed",
62 Items: []FeedItem{
63 {
64 Title: "Test Article",
65 Link: "https://example.com/article",
66 Content: "<p>Safe content</p><script>alert('xss')</script><p style='color:red'>No styles</p>",
67 Published: time.Now(),
68 },
69 },
70 },
71 },
72 }
73
74 // Render with inline mode enabled
75 htmlOutput, _, err := RenderDigest(data, true, 30, false, false)
76 if err != nil {
77 t.Fatalf("RenderDigest failed: %v", err)
78 }
79
80 // Debug: print actual output
81 t.Logf("HTML Output:\n%s", htmlOutput)
82
83 // Verify script tags are removed
84 if strings.Contains(htmlOutput, "<script>") {
85 t.Error("Unsafe <script> tags were not stripped")
86 }
87 if strings.Contains(htmlOutput, "alert('xss')") {
88 t.Error("Script content was not removed")
89 }
90
91 // Verify safe content remains
92 if !strings.Contains(htmlOutput, "<p>Safe content</p>") {
93 t.Error("Safe HTML content was incorrectly removed")
94 }
95}
96
97func TestRenderDigest_TextOutputNoHTMLTags(t *testing.T) {
98 // Create test data with HTML content
99 data := &DigestData{
100 ConfigName: "Test Config",
101 TotalItems: 1,
102 FeedGroups: []FeedGroup{
103 {
104 FeedName: "Test Feed",
105 FeedURL: "https://example.com/feed",
106 Items: []FeedItem{
107 {
108 Title: "Test Article",
109 Link: "https://example.com/article",
110 Content: "<article><p>This is a <strong>test</strong> article with <a href='https://example.com'>a link</a>.</p></article>",
111 Published: time.Now(),
112 },
113 },
114 },
115 },
116 }
117
118 // Render with inline mode enabled
119 _, textOutput, err := RenderDigest(data, true, 30, false, false)
120 if err != nil {
121 t.Fatalf("RenderDigest failed: %v", err)
122 }
123
124 // Verify text output does NOT contain HTML tags
125 htmlTags := []string{"<article>", "<p>", "<strong>", "<a href", "</article>", "</p>", "</strong>", "</a>"}
126 for _, tag := range htmlTags {
127 if strings.Contains(textOutput, tag) {
128 t.Errorf("Text output contains HTML tag %q - should be stripped", tag)
129 }
130 }
131
132 // Verify the actual text content is present
133 if !strings.Contains(textOutput, "This is a test article with a link") {
134 t.Error("Text content was not preserved after HTML stripping")
135 }
136}
137
138func TestRenderDigest_CodeBlockFormatting(t *testing.T) {
139 data := &DigestData{
140 ConfigName: "Test Config",
141 TotalItems: 1,
142 FeedGroups: []FeedGroup{
143 {
144 FeedName: "Test Feed",
145 FeedURL: "https://example.com/feed",
146 Items: []FeedItem{
147 {
148 Title: "Test Article",
149 Link: "https://example.com/article",
150 Content: `<p>Code example:</p><pre><span class="c1"># comment</span>
151echo hello</pre><p>Done.</p>`,
152 Published: time.Now(),
153 },
154 },
155 },
156 },
157 }
158
159 htmlOutput, textOutput, err := RenderDigest(data, true, 30, false, false)
160 if err != nil {
161 t.Fatalf("RenderDigest failed: %v", err)
162 }
163
164 // HTML: verify code block has styling
165 if !strings.Contains(htmlOutput, `<pre style="background-color:#f5f5f5`) {
166 t.Error("HTML code block missing styling")
167 }
168
169 // HTML: verify syntax highlighting spans are stripped
170 if strings.Contains(htmlOutput, `class="c1"`) {
171 t.Error("Syntax highlighting classes should be stripped")
172 }
173
174 // Text: verify code is indented
175 if !strings.Contains(textOutput, " # comment") {
176 t.Error("Text code block should be indented with 4 spaces")
177 }
178
179 // Text: verify no HTML tags in code block
180 if strings.Contains(textOutput, "<span") || strings.Contains(textOutput, "<pre") {
181 t.Error("Text output should not contain HTML tags")
182 }
183}