Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions consume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"os"
"reflect"
"strings"
"testing"

"github.com/kr/pretty"
Expand Down Expand Up @@ -403,3 +404,37 @@ func TestAtomUnmarshal(t *testing.T) {
t.Error("object was not unmarshalled correctly")
}
}

func TestRssFeedLanguageSerialization(t *testing.T) {
// Case 1: No language set (empty)
feed := &RssFeed{
Title: "Test Feed",
Link: "http://example.com",
Description: "Test Description",
}

// Marshal just the feed (channel)
bytes, err := xml.Marshal(feed)
if err != nil {
t.Fatalf("Failed to marshal feed without language: %v", err)
}
xmlStr := string(bytes)

if strings.Contains(xmlStr, "<language>") {
t.Errorf("Expected no <language> tag when empty, but found: %s", xmlStr)
}

// Case 2: Language set to "en"
feed.Language = "en"

bytes, err = xml.Marshal(feed)
if err != nil {
t.Fatalf("Failed to marshal feed with language: %v", err)
}
xmlStr = string(bytes)

expected := "<language>en</language>"
if !strings.Contains(xmlStr, expected) {
t.Errorf("Expected %q in output, got: %s", expected, xmlStr)
}
}
21 changes: 21 additions & 0 deletions language.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package feeds

import (
"encoding/xml"
"errors"
"regexp"
)

var iso639Regex = regexp.MustCompile(`^[a-z]{2,3}(-[a-zA-Z0-9-]+)?$`)

type ISO639Code string

func (c ISO639Code) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c == "" {
return nil
}
if !iso639Regex.MatchString(string(c)) {
return errors.New("invalid ISO 639 code")
}
return e.EncodeElement(string(c), start)
}
85 changes: 85 additions & 0 deletions language_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package feeds

import (
"encoding/xml"
"testing"
)

type LanguageTestStruct struct {
XMLName xml.Name `xml:"test"`
Language ISO639Code `xml:"language"`
}

func TestISO639CodeMarshalXML(t *testing.T) {
tests := []struct {
name string
code ISO639Code
wantXML string
wantErr bool
}{
{
name: "valid code en",
code: "en",
wantXML: "<test><language>en</language></test>",
wantErr: false,
},
{
name: "valid code de",
code: "de",
wantXML: "<test><language>de</language></test>",
wantErr: false,
},
{
name: "valid code de-AT",
code: "de-AT",
wantXML: "<test><language>de-AT</language></test>",
wantErr: false,
},
{
name: "valid code en-us",
code: "en-us",
wantXML: "<test><language>en-us</language></test>",
wantErr: false,
},
{
name: "valid code eng",
code: "eng",
wantXML: "<test><language>eng</language></test>",
wantErr: false,
},
{
name: "invalid code case",
code: "EN",
wantXML: "",
wantErr: true,
},
{
name: "invalid code numeric",
code: "12",
wantXML: "",
wantErr: true,
},
{
name: "empty code",
code: "",
wantXML: "<test></test>",
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := LanguageTestStruct{Language: tt.code}
bytes, err := xml.Marshal(s)
if (err != nil) != tt.wantErr {
t.Errorf("MarshalXML() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
if string(bytes) != tt.wantXML {
t.Errorf("MarshalXML() got = %s, want %s", string(bytes), tt.wantXML)
}
}
})
}
}
43 changes: 22 additions & 21 deletions rss.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,35 @@ type RssTextInput struct {
}

type RssFeed struct {
XMLName xml.Name `xml:"channel"`
Title string `xml:"title"` // required
Link string `xml:"link"` // required
Description string `xml:"description"` // required
Language string `xml:"language,omitempty"`
Copyright string `xml:"copyright,omitempty"`
ManagingEditor string `xml:"managingEditor,omitempty"` // Author used
WebMaster string `xml:"webMaster,omitempty"`
PubDate string `xml:"pubDate,omitempty"` // created or updated
LastBuildDate string `xml:"lastBuildDate,omitempty"` // updated used
Category string `xml:"category,omitempty"`
Generator string `xml:"generator,omitempty"`
Docs string `xml:"docs,omitempty"`
Cloud string `xml:"cloud,omitempty"`
Ttl int `xml:"ttl,omitempty"`
Rating string `xml:"rating,omitempty"`
SkipHours string `xml:"skipHours,omitempty"`
SkipDays string `xml:"skipDays,omitempty"`
XMLName xml.Name `xml:"channel"`
Title string `xml:"title"` // required
Link string `xml:"link"` // required
Description string `xml:"description"` // required
Language ISO639Code `xml:"language,omitempty"`
Copyright string `xml:"copyright,omitempty"`
ManagingEditor string `xml:"managingEditor,omitempty"` // Author used
WebMaster string `xml:"webMaster,omitempty"`
PubDate string `xml:"pubDate,omitempty"` // created or updated
LastBuildDate string `xml:"lastBuildDate,omitempty"` // updated used
Category string `xml:"category,omitempty"`
Generator string `xml:"generator,omitempty"`
Docs string `xml:"docs,omitempty"`
Cloud string `xml:"cloud,omitempty"`
Ttl int `xml:"ttl,omitempty"`
Rating string `xml:"rating,omitempty"`
SkipHours string `xml:"skipHours,omitempty"`
SkipDays string `xml:"skipDays,omitempty"`
Image *RssImage
TextInput *RssTextInput
Items []*RssItem `xml:"item"`
}

type RssItem struct {
XMLName xml.Name `xml:"item"`
Title string `xml:"title"` // required
Link string `xml:"link"` // required
Description string `xml:"description"` // required
Title string `xml:"title"` // required
Link string `xml:"link"` // required
Description string `xml:"description"` // required
Language string `xml:"language,omitempty"` //
Content *RssContent
Author string `xml:"author,omitempty"`
Category string `xml:"category,omitempty"`
Expand Down
1 change: 0 additions & 1 deletion to-implement.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@
<itunes:owner>
<itunes:subtitle>
<itunes:summary>
<language>
```
Loading