rss email digests over ssh because you're a cool kid herald.dunkirk.sh
go rss rss-reader ssh charm
at main 257 lines 6.0 kB view raw
1package config 2 3import ( 4 "testing" 5) 6 7func TestParse_Empty(t *testing.T) { 8 cfg, err := Parse("") 9 if err != nil { 10 t.Fatalf("Parse(\"\") failed: %v", err) 11 } 12 if cfg == nil { 13 t.Fatal("expected non-nil config") 14 } 15 if !cfg.Digest { 16 t.Error("expected Digest default to be true") 17 } 18 if cfg.Inline { 19 t.Error("expected Inline default to be false") 20 } 21 if len(cfg.Feeds) != 0 { 22 t.Errorf("expected 0 feeds, got %d", len(cfg.Feeds)) 23 } 24} 25 26func TestParse_Comments(t *testing.T) { 27 input := ` 28# This is a comment 29# Another comment 30 31=: email test@example.com 32` 33 cfg, err := Parse(input) 34 if err != nil { 35 t.Fatalf("Parse failed: %v", err) 36 } 37 if cfg.Email != "test@example.com" { 38 t.Errorf("expected email test@example.com, got %s", cfg.Email) 39 } 40} 41 42func TestParse_EmailDirective(t *testing.T) { 43 input := "=: email user@example.com" 44 cfg, err := Parse(input) 45 if err != nil { 46 t.Fatalf("Parse failed: %v", err) 47 } 48 if cfg.Email != "user@example.com" { 49 t.Errorf("expected email user@example.com, got %s", cfg.Email) 50 } 51} 52 53func TestParse_CronDirective(t *testing.T) { 54 input := "=: cron 0 8 * * *" 55 cfg, err := Parse(input) 56 if err != nil { 57 t.Fatalf("Parse failed: %v", err) 58 } 59 if cfg.CronExpr != "0 8 * * *" { 60 t.Errorf("expected cron '0 8 * * *', got %s", cfg.CronExpr) 61 } 62} 63 64func TestParse_DigestDirective(t *testing.T) { 65 tests := []struct { 66 input string 67 expected bool 68 }{ 69 {"=: digest true", true}, 70 {"=: digest false", false}, 71 {"=: digest 1", true}, 72 {"=: digest 0", false}, 73 {"=: digest invalid", true}, // default 74 } 75 76 for _, tt := range tests { 77 cfg, err := Parse(tt.input) 78 if err != nil { 79 t.Fatalf("Parse(%q) failed: %v", tt.input, err) 80 } 81 if cfg.Digest != tt.expected { 82 t.Errorf("Parse(%q): expected Digest=%v, got %v", tt.input, tt.expected, cfg.Digest) 83 } 84 } 85} 86 87func TestParse_InlineDirective(t *testing.T) { 88 tests := []struct { 89 input string 90 expected bool 91 }{ 92 {"=: inline true", true}, 93 {"=: inline false", false}, 94 {"=: inline 1", true}, 95 {"=: inline 0", false}, 96 {"=: inline invalid", false}, // default 97 } 98 99 for _, tt := range tests { 100 cfg, err := Parse(tt.input) 101 if err != nil { 102 t.Fatalf("Parse(%q) failed: %v", tt.input, err) 103 } 104 if cfg.Inline != tt.expected { 105 t.Errorf("Parse(%q): expected Inline=%v, got %v", tt.input, tt.expected, cfg.Inline) 106 } 107 } 108} 109 110func TestParse_FeedWithoutName(t *testing.T) { 111 input := "=> https://example.com/feed.xml" 112 cfg, err := Parse(input) 113 if err != nil { 114 t.Fatalf("Parse failed: %v", err) 115 } 116 if len(cfg.Feeds) != 1 { 117 t.Fatalf("expected 1 feed, got %d", len(cfg.Feeds)) 118 } 119 if cfg.Feeds[0].URL != "https://example.com/feed.xml" { 120 t.Errorf("expected URL https://example.com/feed.xml, got %s", cfg.Feeds[0].URL) 121 } 122 if cfg.Feeds[0].Name != "" { 123 t.Errorf("expected empty name, got %s", cfg.Feeds[0].Name) 124 } 125} 126 127func TestParse_FeedWithName(t *testing.T) { 128 input := `=> https://example.com/feed.xml "Example Feed"` 129 cfg, err := Parse(input) 130 if err != nil { 131 t.Fatalf("Parse failed: %v", err) 132 } 133 if len(cfg.Feeds) != 1 { 134 t.Fatalf("expected 1 feed, got %d", len(cfg.Feeds)) 135 } 136 if cfg.Feeds[0].URL != "https://example.com/feed.xml" { 137 t.Errorf("expected URL https://example.com/feed.xml, got %s", cfg.Feeds[0].URL) 138 } 139 if cfg.Feeds[0].Name != "Example Feed" { 140 t.Errorf("expected name 'Example Feed', got %s", cfg.Feeds[0].Name) 141 } 142} 143 144func TestParse_MultipleFeeds(t *testing.T) { 145 input := ` 146=> https://feed1.com/rss 147=> https://feed2.com/atom "Feed Two" 148=> https://feed3.com/json "Feed Three" 149` 150 cfg, err := Parse(input) 151 if err != nil { 152 t.Fatalf("Parse failed: %v", err) 153 } 154 if len(cfg.Feeds) != 3 { 155 t.Fatalf("expected 3 feeds, got %d", len(cfg.Feeds)) 156 } 157 158 if cfg.Feeds[0].URL != "https://feed1.com/rss" { 159 t.Errorf("feed[0] URL wrong: %s", cfg.Feeds[0].URL) 160 } 161 if cfg.Feeds[0].Name != "" { 162 t.Errorf("feed[0] should have empty name, got %s", cfg.Feeds[0].Name) 163 } 164 165 if cfg.Feeds[1].URL != "https://feed2.com/atom" { 166 t.Errorf("feed[1] URL wrong: %s", cfg.Feeds[1].URL) 167 } 168 if cfg.Feeds[1].Name != "Feed Two" { 169 t.Errorf("feed[1] name wrong: %s", cfg.Feeds[1].Name) 170 } 171 172 if cfg.Feeds[2].Name != "Feed Three" { 173 t.Errorf("feed[2] name wrong: %s", cfg.Feeds[2].Name) 174 } 175} 176 177func TestParse_CompleteConfig(t *testing.T) { 178 input := ` 179# My feed configuration 180=: email user@example.com 181=: cron 0 9 * * * 182=: digest true 183=: inline false 184 185=> https://blog.example.com/feed.xml "Example Blog" 186=> https://news.example.com/rss 187` 188 cfg, err := Parse(input) 189 if err != nil { 190 t.Fatalf("Parse failed: %v", err) 191 } 192 193 if cfg.Email != "user@example.com" { 194 t.Errorf("email wrong: %s", cfg.Email) 195 } 196 if cfg.CronExpr != "0 9 * * *" { 197 t.Errorf("cron wrong: %s", cfg.CronExpr) 198 } 199 if !cfg.Digest { 200 t.Error("digest should be true") 201 } 202 if cfg.Inline { 203 t.Error("inline should be false") 204 } 205 if len(cfg.Feeds) != 2 { 206 t.Fatalf("expected 2 feeds, got %d", len(cfg.Feeds)) 207 } 208} 209 210func TestParse_CaseInsensitiveDirectives(t *testing.T) { 211 input := ` 212=: EMAIL test@example.com 213=: CRON 0 8 * * * 214=: DIGEST false 215=: INLINE true 216` 217 cfg, err := Parse(input) 218 if err != nil { 219 t.Fatalf("Parse failed: %v", err) 220 } 221 if cfg.Email != "test@example.com" { 222 t.Error("EMAIL directive not parsed") 223 } 224 if cfg.CronExpr != "0 8 * * *" { 225 t.Error("CRON directive not parsed") 226 } 227 if cfg.Digest { 228 t.Error("DIGEST directive not parsed") 229 } 230 if !cfg.Inline { 231 t.Error("INLINE directive not parsed") 232 } 233} 234 235func TestParseBool(t *testing.T) { 236 tests := []struct { 237 input string 238 defaultVal bool 239 expected bool 240 }{ 241 {"true", false, true}, 242 {"false", true, false}, 243 {"1", false, true}, 244 {"0", true, false}, 245 {"yes", false, false}, // invalid, returns default 246 {"no", true, true}, // invalid, returns default 247 {"", false, false}, // invalid, returns default 248 {"invalid", true, true}, // invalid, returns default 249 } 250 251 for _, tt := range tests { 252 result := parseBool(tt.input, tt.defaultVal) 253 if result != tt.expected { 254 t.Errorf("parseBool(%q, %v) = %v, expected %v", tt.input, tt.defaultVal, result, tt.expected) 255 } 256 } 257}