Subscribe and post RSS feeds to Bluesky
rss
bluesky
1package rss
2
3import (
4 "context"
5 "net/http"
6 "net/http/httptest"
7 "testing"
8 "time"
9)
10
11func TestFetchLatestItems(t *testing.T) {
12 // Create a test RSS feed
13 testFeed := `<?xml version="1.0" encoding="UTF-8"?>
14<rss version="2.0">
15 <channel>
16 <title>Test Feed</title>
17 <link>https://example.com</link>
18 <description>A test feed</description>
19 <item>
20 <title>Test Item 1</title>
21 <link>https://example.com/item1</link>
22 <description>Description for item 1</description>
23 <guid>item-1</guid>
24 <pubDate>Mon, 02 Jan 2023 15:04:05 GMT</pubDate>
25 </item>
26 <item>
27 <title>Test Item 2</title>
28 <link>https://example.com/item2</link>
29 <description>Description for item 2</description>
30 <guid>item-2</guid>
31 <pubDate>Mon, 02 Jan 2023 16:04:05 GMT</pubDate>
32 </item>
33 <item>
34 <title>Test Item 3</title>
35 <link>https://example.com/item3</link>
36 <description>Description for item 3</description>
37 <guid>item-3</guid>
38 <pubDate>Mon, 02 Jan 2023 17:04:05 GMT</pubDate>
39 </item>
40 </channel>
41</rss>`
42
43 // Create a test server
44 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
45 w.Header().Set("Content-Type", "application/rss+xml")
46 w.WriteHeader(http.StatusOK)
47 w.Write([]byte(testFeed))
48 }))
49 defer server.Close()
50
51 // Create checker
52 checker := NewChecker()
53
54 // Test fetching all items
55 t.Run("FetchAllItems", func(t *testing.T) {
56 items, err := checker.FetchLatestItems(context.Background(), server.URL)
57 if err != nil {
58 t.Fatalf("Failed to fetch items: %v", err)
59 }
60
61 if len(items) != 3 {
62 t.Errorf("Expected 3 items, got %d", len(items))
63 }
64
65 // Check first item
66 if items[0].Title != "Test Item 1" {
67 t.Errorf("Expected title 'Test Item 1', got '%s'", items[0].Title)
68 }
69 if items[0].Link != "https://example.com/item1" {
70 t.Errorf("Expected link 'https://example.com/item1', got '%s'", items[0].Link)
71 }
72 if items[0].GUID != "item-1" {
73 t.Errorf("Expected GUID 'item-1', got '%s'", items[0].GUID)
74 }
75 })
76
77 // Test with context timeout
78 t.Run("ContextTimeout", func(t *testing.T) {
79 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
80 defer cancel()
81
82 time.Sleep(2 * time.Millisecond) // Ensure context is expired
83
84 _, err := checker.FetchLatestItems(ctx, server.URL)
85 if err == nil {
86 t.Error("Expected error with expired context, got nil")
87 }
88 })
89}
90
91func TestFetchLatestItems_InvalidURL(t *testing.T) {
92 checker := NewChecker()
93
94 _, err := checker.FetchLatestItems(context.Background(), "not-a-valid-url")
95 if err == nil {
96 t.Error("Expected error with invalid URL, got nil")
97 }
98}
99
100func TestFetchLatestItems_EmptyFeed(t *testing.T) {
101 emptyFeed := `<?xml version="1.0" encoding="UTF-8"?>
102<rss version="2.0">
103 <channel>
104 <title>Empty Feed</title>
105 <link>https://example.com</link>
106 <description>A feed with no items</description>
107 </channel>
108</rss>`
109
110 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
111 w.Header().Set("Content-Type", "application/rss+xml")
112 w.WriteHeader(http.StatusOK)
113 w.Write([]byte(emptyFeed))
114 }))
115 defer server.Close()
116
117 checker := NewChecker()
118 items, err := checker.FetchLatestItems(context.Background(), server.URL)
119
120 if err != nil {
121 t.Fatalf("Expected no error with empty feed, got: %v", err)
122 }
123
124 if len(items) != 0 {
125 t.Errorf("Expected 0 items, got %d", len(items))
126 }
127}
128
129func TestFeedItem_GUIDFallback(t *testing.T) {
130 // Feed with no GUID, should use link instead
131 feedNoGUID := `<?xml version="1.0" encoding="UTF-8"?>
132<rss version="2.0">
133 <channel>
134 <title>Test Feed</title>
135 <link>https://example.com</link>
136 <description>Test</description>
137 <item>
138 <title>Item Without GUID</title>
139 <link>https://example.com/item-no-guid</link>
140 <description>Description</description>
141 <pubDate>Mon, 02 Jan 2023 15:04:05 GMT</pubDate>
142 </item>
143 </channel>
144</rss>`
145
146 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
147 w.Header().Set("Content-Type", "application/rss+xml")
148 w.WriteHeader(http.StatusOK)
149 w.Write([]byte(feedNoGUID))
150 }))
151 defer server.Close()
152
153 checker := NewChecker()
154 items, err := checker.FetchLatestItems(context.Background(), server.URL)
155
156 if err != nil {
157 t.Fatalf("Failed to fetch items: %v", err)
158 }
159
160 if len(items) != 1 {
161 t.Fatalf("Expected 1 item, got %d", len(items))
162 }
163
164 // GUID should fall back to link
165 if items[0].GUID != "https://example.com/item-no-guid" {
166 t.Errorf("Expected GUID to fallback to link, got '%s'", items[0].GUID)
167 }
168}