all repos

rss-tools @ 97e6bf5

get rss feed from sources that(i need and) dont provide one

rss-tools/app/atom_test.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
update feed generator, 1 month ago
1
package app
2
3
import (
4
	"bytes"
5
	"encoding/xml"
6
	"net/http"
7
	"net/http/httptest"
8
	"strings"
9
	"testing"
10
	"time"
11
12
	"olexsmir.xyz/x/is"
13
)
14
15
func TestFeedBuilderAddEntryDefaults(t *testing.T) {
16
	feed := NewFeed("test", "feed-id")
17
	feed.AddEntry(FeedEntry{Title: "entry", Content: "body"})
18
19
	is.Equal(t, 1, len(feed.f.Entries))
20
	entry := feed.f.Entries[0]
21
	is.NotEqual(t, "", entry.ID)
22
	is.NotEqual(t, "", entry.Updated)
23
}
24
25
func TestFeedBuilderBytesAndWriteTo(t *testing.T) {
26
	updated := time.Date(2026, 4, 20, 12, 30, 0, 0, time.UTC)
27
	feed := NewFeed("test", "feed-id", WithFeedSubtitle("subtitle")).AddText("entry", "content", updated)
28
29
	raw, err := feed.Bytes()
30
	is.Err(t, err, nil)
31
	if !bytes.Contains(raw, []byte("<subtitle>subtitle</subtitle>")) {
32
		t.Fatalf("expected subtitle in serialized feed")
33
	}
34
35
	var parsed AtomFeed
36
	is.Err(t, xml.Unmarshal(raw, &parsed), nil)
37
	is.Equal(t, "test", parsed.Title)
38
}
39
40
func TestFeedBuilderRender(t *testing.T) {
41
	r := httptest.NewRecorder()
42
	err := NewFeed("test", "feed-id").
43
		Add("entry", "entry-id", "content", time.Date(2026, 4, 20, 8, 0, 0, 0, time.UTC)).
44
		Render(r)
45
	is.Err(t, err, nil)
46
47
	is.Equal(t, http.StatusOK, r.Code)
48
	if got := r.Header().Get("Content-Type"); !strings.Contains(got, "application/atom+xml") {
49
		t.Fatalf("unexpected content type: %q", got)
50
	}
51
}
52
53
func TestFeedEntryTextContent(t *testing.T) {
54
	feed := NewFeed("test", "feed-id").
55
		AddEntry(FeedEntry{
56
			Title:       "text entry",
57
			Content:     "plain text content",
58
			ContentType: "text",
59
			Updated:     time.Date(2026, 4, 20, 12, 0, 0, 0, time.UTC),
60
		})
61
62
	raw, err := feed.Bytes()
63
	is.Err(t, err, nil)
64
	if !strings.Contains(string(raw), `<content type="text">plain text content</content>`) {
65
		t.Fatalf("expected text content with type attribute in serialized feed")
66
	}
67
68
	var parsed AtomFeed
69
	is.Err(t, xml.Unmarshal(raw, &parsed), nil)
70
	is.Equal(t, 1, len(parsed.Entries))
71
72
	entry := parsed.Entries[0]
73
	is.Equal(t, "text", entry.Content.Type)
74
	is.Equal(t, "plain text content", entry.Content.Value)
75
}
76
77
func TestFeedEntryHtmlContent(t *testing.T) {
78
	htmlContent := "<p>Hello <strong>World</strong></p>"
79
	feed := NewFeed("test", "feed-id").
80
		AddEntry(FeedEntry{
81
			Title:       "html entry",
82
			Content:     htmlContent,
83
			ContentType: "html",
84
			Updated:     time.Date(2026, 4, 20, 12, 0, 0, 0, time.UTC),
85
		})
86
87
	raw, err := feed.Bytes()
88
	is.Err(t, err, nil)
89
	if !strings.Contains(string(raw), `<content type="html">`) {
90
		t.Fatalf("expected HTML content with type='html' attribute in serialized feed")
91
	}
92
93
	var parsed AtomFeed
94
	is.Err(t, xml.Unmarshal(raw, &parsed), nil)
95
	is.Equal(t, 1, len(parsed.Entries))
96
97
	entry := parsed.Entries[0]
98
	is.Equal(t, "html", entry.Content.Type)
99
	is.Equal(t, htmlContent, entry.Content.Value)
100
}
101
102
func TestFeedMultipleEntriesWithMixedContentTypes(t *testing.T) {
103
	updated := time.Date(2026, 4, 20, 12, 0, 0, 0, time.UTC)
104
	feed := NewFeed("test", "feed-id").
105
		AddEntry(FeedEntry{
106
			Title:       "text entry",
107
			Content:     "plain text",
108
			ContentType: "text",
109
			Updated:     updated,
110
		}).
111
		AddEntry(FeedEntry{
112
			Title:       "html entry",
113
			Content:     "<p>html content</p>",
114
			ContentType: "html",
115
			Updated:     updated,
116
		}).
117
		AddEntry(FeedEntry{
118
			Title:   "default entry",
119
			Content: "default content",
120
			Updated: updated,
121
		})
122
123
	raw, err := feed.Bytes()
124
	is.Err(t, err, nil)
125
126
	var parsed AtomFeed
127
	is.Err(t, xml.Unmarshal(raw, &parsed), nil)
128
	is.Equal(t, 3, len(parsed.Entries))
129
130
	tests := []struct {
131
		name         string
132
		expectedType string
133
		expectedText string
134
	}{
135
		{"text entry", "text", "plain text"},
136
		{"html entry", "html", "<p>html content</p>"},
137
		{"default entry", "text", "default content"},
138
	}
139
	for i, tc := range tests {
140
		is.Equal(t, tc.name, parsed.Entries[i].Title)
141
		is.Equal(t, tc.expectedText, parsed.Entries[i].Content.Value)
142
		is.Equal(t, tc.expectedType, parsed.Entries[i].Content.Type)
143
	}
144
}