// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. // SPDX-License-Identifier: Apache-2.0 package atom // import "miniflux.app/v2/internal/reader/atom" import ( "bytes" "testing" "time" ) func TestParseAtomSample(t *testing.T) { data := ` Example Feed 2003-12-13T18:30:02Z John Doe urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 Atom-Powered Robots Run Amok urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("http://example.org/feed.xml", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Title != "Example Feed" { t.Errorf("Incorrect title, got: %s", feed.Title) } if feed.FeedURL != "http://example.org/feed.xml" { t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL) } if feed.SiteURL != "http://example.org/" { t.Errorf("Incorrect site URL, got: %s", feed.SiteURL) } if feed.IconURL != "" { t.Errorf("Incorrect icon URL, got: %s", feed.IconURL) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if !feed.Entries[0].Date.Equal(time.Date(2003, time.December, 13, 18, 30, 2, 0, time.UTC)) { t.Errorf("Incorrect entry date, got: %v", feed.Entries[0].Date) } if feed.Entries[0].Hash != "3841e5cf232f5111fc5841e9eba5f4b26d95e7d7124902e0f7272729d65601a6" { t.Errorf("Incorrect entry hash, got: %s", feed.Entries[0].Hash) } if feed.Entries[0].URL != "http://example.org/2003/12/13/atom03" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].CommentsURL != "" { t.Errorf("Incorrect entry Comments URL, got: %s", feed.Entries[0].CommentsURL) } if feed.Entries[0].Title != "Atom-Powered Robots Run Amok" { t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title) } if feed.Entries[0].Content != "Some text." { t.Errorf("Incorrect entry content, got: %s", feed.Entries[0].Content) } if feed.Entries[0].Author != "John Doe" { t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author) } } func TestParseFeedWithoutTitle(t *testing.T) { data := ` 2003-12-13T18:30:02Z ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Title != "https://example.org/" { t.Errorf("Incorrect feed title, got: %s", feed.Title) } } func TestParseEntryWithoutTitleButWithURL(t *testing.T) { data := ` Example Feed 2003-12-13T18:30:02Z John Doe urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != "http://example.org/2003/12/13/atom03" { t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title) } } func TestParseEntryWithoutTitleButWithSummary(t *testing.T) { data := ` Example Feed 2003-12-13T18:30:02Z John Doe urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != "Some text." { t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title) } } func TestParseEntryWithoutTitleButWithXHTMLContent(t *testing.T) { data := ` Example Feed 2003-12-13T18:30:02Z John Doe urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z
AT&T bought by SBC!
` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != "AT&T bought by SBC!" { t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title) } } func TestParseFeedURL(t *testing.T) { data := ` Example Feed 2003-12-13T18:30:02Z ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.SiteURL != "https://example.org/" { t.Errorf("Incorrect site URL, got: %s", feed.SiteURL) } if feed.FeedURL != "https://example.org/feed" { t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL) } } func TestParseFeedWithRelativeURL(t *testing.T) { data := ` Example Feed Test /blog/article.html 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.FeedURL != "https://example.org/blog/atom.xml" { t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL) } if feed.SiteURL != "https://example.org/blog" { t.Errorf("Incorrect site URL, got: %s", feed.SiteURL) } if feed.Entries[0].URL != "https://example.org/blog/article.html" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } } func TestParseEntryWithRelativeURL(t *testing.T) { data := ` Example Feed Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].URL != "http://example.org/something.html" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } } func TestParseEntryURLWithTextHTMLType(t *testing.T) { data := ` Example Feed Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].URL != "http://example.org/something.html" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } } func TestParseEntryURLWithNoRelAndNoType(t *testing.T) { data := ` Example Feed Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].URL != "http://example.org/something.html" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } } func TestParseEntryURLWithAlternateRel(t *testing.T) { data := ` Example Feed Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.net/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].URL != "http://example.org/something.html" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } } func TestParseEntryTitleWithWhitespaces(t *testing.T) { data := ` Example Feed Some Title urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != "Some Title" { t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title) } } func TestParseEntryWithPlainTextTitle(t *testing.T) { data := ` Example Feed AT&T bought by SBC! urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. AT&T bought by SBC! urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } expected := `AT&T bought by SBC!` for i := range 2 { if feed.Entries[i].Title != expected { t.Errorf("Incorrect title for entry #%d, got: %q", i, feed.Entries[i].Title) } } } func TestParseEntryWithHTMLTitle(t *testing.T) { data := ` Example Feed <code>Test</code> Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. <![CDATA[Test “Test”]]> urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. <![CDATA[Entry title with space around CDATA]]> urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != "Test Test" { t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title) } if feed.Entries[1].Title != "Test “Test”" { t.Errorf("Incorrect entry title, got: %q", feed.Entries[1].Title) } if feed.Entries[2].Title != "Entry title with space around CDATA" { t.Errorf("Incorrect entry title, got: %q", feed.Entries[2].Title) } } func TestParseEntryWithXHTMLTitle(t *testing.T) { data := ` Example Feed <div xmlns="http://www.w3.org/1999/xhtml"> This is <b>XHTML</b> content. </div> urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != `This is XHTML content.` { t.Errorf("Incorrect entry title, got: %q", feed.Entries[1].Title) } } func TestParseEntryWithEmptyXHTMLTitle(t *testing.T) { data := ` Example Feed <div xmlns="http://www.w3.org/1999/xhtml"/> urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != `http://example.org/entry` { t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title) } } func TestParseEntryWithXHTMLTitleWithoutDiv(t *testing.T) { data := ` Example Feed test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != `test` { t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title) } } func TestParseEntryWithNumericCharacterReferenceTitle(t *testing.T) { data := ` Example Feed Σ ß urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != "Σ ß" { t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title) } } func TestParseEntryWithDoubleEncodedEntitiesTitle(t *testing.T) { data := ` Example Feed &#39;AT&amp;T&#39; urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Title != `'AT&T'` { t.Errorf("Incorrect entry title, got: %q", feed.Entries[0].Title) } } func TestParseEntryWithXHTMLSummary(t *testing.T) { data := ` Example Feed Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z

Test: std::unique_ptr<S>

` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Content != `

Test: std::unique_ptr<S>

` { t.Errorf("Incorrect entry content, got: %s", feed.Entries[1].Content) } } func TestParseEntryWithHTMLSummary(t *testing.T) { data := ` Example Feed Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z <code>std::unique_ptr&lt;S&gt;</code> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z <code>std::unique_ptr&lt;S&gt;</code> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z std::unique_ptr<S>]]> ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } expected := `std::unique_ptr<S>` for i := range 3 { if feed.Entries[i].Content != expected { t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content) } } } func TestParseEntryWithTextSummary(t *testing.T) { data := ` Example Feed Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&T <S> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&T <S> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&T <S> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z ]]> ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } expected := `AT&T <S>` for i := range 4 { if feed.Entries[i].Content != expected { t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content) } } } func TestParseEntryWithTextContent(t *testing.T) { data := ` Example Feed Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&T <S> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&T <S> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&T <S> Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z ]]> ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } expected := `AT&T <S>` for i := range 4 { if feed.Entries[i].Content != expected { t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content) } } } func TestParseEntryWithHTMLContent(t *testing.T) { data := ` Example Feed Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&amp;T bought <b>by SBC</b>! Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z AT&amp;T bought <b>by SBC</b>! Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z by SBC!]]> ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } expected := `AT&T bought by SBC!` for i := range 3 { if feed.Entries[i].Content != expected { t.Errorf("Incorrect content for entry #%d, got: %q", i, feed.Entries[i].Content) } } } func TestParseEntryWithXHTMLContent(t *testing.T) { data := ` Example Feed Example urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z
AT&T bought by SBC!
` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Content != `AT&T bought by SBC!` { t.Errorf("Incorrect entry content, got: %q", feed.Entries[0].Content) } } func TestParseEntryWithAuthorName(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. Me me@localhost ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Author != "Me" { t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author) } } func TestParseEntryWithoutAuthorName(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. me@localhost ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Author != "me@localhost" { t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author) } } func TestParseEntryWithMultipleAuthors(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. Alice Bob ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Author != "Alice, Bob" { t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author) } } func TestParseEntryWithoutAuthor(t *testing.T) { data := ` Example Feed John Doe urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Author != "John Doe" { t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author) } } func TestParseFeedWithMultipleAuthors(t *testing.T) { data := ` Example Feed Alice Bob urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Author != "Alice, Bob" { t.Errorf("Incorrect entry author, got: %s", feed.Entries[0].Author) } } func TestParseFeedWithoutAuthor(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Entries[0].Author != "" { t.Errorf("Incorrect entry author, got: %q", feed.Entries[0].Author) } } func TestParseEntryWithEnclosures(t *testing.T) { data := ` http://www.example.org/myfeed My Podcast Feed 2005-07-15T12:00:00Z John Doe http://www.example.org/entries/1 Atom 1.0 2005-07-15T12:00:00Z An overview of Atom 1.0

Show Notes

  • 00:01:00 -- Introduction
  • 00:15:00 -- Talking about Atom 1.0
  • 00:30:00 -- Wrapping up
` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if len(feed.Entries[0].Enclosures) != 2 { t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures)) } expectedResults := []struct { url string mimeType string size int64 }{ {"http://www.example.org/myaudiofile.mp3", "audio/mpeg", 1234}, {"http://www.example.org/myaudiofile.torrent", "application/x-bittorrent", 4567}, } for index, enclosure := range feed.Entries[0].Enclosures { if expectedResults[index].url != enclosure.URL { t.Errorf(`Unexpected enclosure URL, got %q instead of %q`, enclosure.URL, expectedResults[index].url) } if expectedResults[index].mimeType != enclosure.MimeType { t.Errorf(`Unexpected enclosure type, got %q instead of %q`, enclosure.MimeType, expectedResults[index].mimeType) } if expectedResults[index].size != enclosure.Size { t.Errorf(`Unexpected enclosure size, got %d instead of %d`, enclosure.Size, expectedResults[index].size) } } } func TestParseEntryWithoutEnclosureURL(t *testing.T) { data := ` http://www.example.org/myfeed My Podcast Feed 2005-07-15T12:00:00Z http://www.example.org/entries/1 Atom 1.0 2005-07-15T12:00:00Z An overview of Atom 1.0 Test ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if len(feed.Entries[0].Enclosures) != 0 { t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures)) } } func TestParseEntryWithPublished(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if !feed.Entries[0].Date.Equal(time.Date(2003, time.December, 13, 18, 30, 2, 0, time.UTC)) { t.Errorf("Incorrect entry date, got: %v", feed.Entries[0].Date) } } func TestParseEntryWithPublishedAndUpdated(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2002-11-12T18:30:02Z 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if !feed.Entries[0].Date.Equal(time.Date(2002, time.November, 12, 18, 30, 2, 0, time.UTC)) { t.Errorf("Incorrect entry date, got: %v", feed.Entries[0].Date) } } func TestParseInvalidXml(t *testing.T) { data := `garbage` _, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err == nil { t.Error("Parse should returns an error") } } func TestParseTitleWithSingleQuote(t *testing.T) { data := ` ' or ’ ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Title != "' or ’" { t.Errorf(`Incorrect title, got: %q`, feed.Title) } } func TestParseTitleWithEncodedSingleQuote(t *testing.T) { data := ` Test's Blog ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Title != "Test's Blog" { t.Errorf(`Incorrect title, got: %q`, feed.Title) } } func TestParseTitleWithSingleQuoteAndHTMLType(t *testing.T) { data := ` O’Hara ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Title != "O’Hara" { t.Errorf(`Incorrect title, got: %q`, feed.Title) } } func TestParseWithHTMLEntity(t *testing.T) { data := ` Example   Feed ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.Title != "Example \u00a0 Feed" { t.Errorf(`Incorrect title, got: %q`, feed.Title) } } func TestParseWithInvalidCharacterEntity(t *testing.T) { data := ` Example Feed ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.SiteURL != "http://example.org/a&b" { t.Errorf(`Incorrect URL, got: %q`, feed.SiteURL) } } func TestParseMediaGroup(t *testing.T) { data := ` http://www.example.org/myfeed My Video Feed 2005-07-15T12:00:00Z http://www.example.org/entries/1 Some Video 2005-07-15T12:00:00Z Another title Some description A website: http://example.org/ ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].Content != `Some description
A website: http://example.org/` { t.Errorf("Incorrect entry content, got: %q", feed.Entries[0].Content) } if len(feed.Entries[0].Enclosures) != 2 { t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures)) } expectedResults := []struct { url string mimeType string size int64 }{ {"https://example.org/thumbnail.jpg", "image/*", 0}, {"https://www.youtube.com/v/abcd", "application/x-shockwave-flash", 0}, } for index, enclosure := range feed.Entries[0].Enclosures { if expectedResults[index].url != enclosure.URL { t.Errorf(`Unexpected enclosure URL, got %q instead of %q`, enclosure.URL, expectedResults[index].url) } if expectedResults[index].mimeType != enclosure.MimeType { t.Errorf(`Unexpected enclosure type, got %q instead of %q`, enclosure.MimeType, expectedResults[index].mimeType) } if expectedResults[index].size != enclosure.Size { t.Errorf(`Unexpected enclosure size, got %d instead of %d`, enclosure.Size, expectedResults[index].size) } } } func TestParseMediaElements(t *testing.T) { data := ` http://www.example.org/myfeed My Video Feed 2005-07-15T12:00:00Z http://www.example.org/entries/1 Some Video 2005-07-15T12:00:00Z Another title Some description A website: http://example.org/ ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].Content != `Some description
A website: http://example.org/` { t.Errorf("Incorrect entry content, got: %q", feed.Entries[0].Content) } if len(feed.Entries[0].Enclosures) != 2 { t.Fatalf("Incorrect number of enclosures, got: %d", len(feed.Entries[0].Enclosures)) } expectedResults := []struct { url string mimeType string size int64 }{ {"https://example.org/thumbnail.jpg", "image/*", 0}, {"https://www.youtube.com/v/abcd", "application/x-shockwave-flash", 0}, } for index, enclosure := range feed.Entries[0].Enclosures { if expectedResults[index].url != enclosure.URL { t.Errorf(`Unexpected enclosure URL, got %q instead of %q`, enclosure.URL, expectedResults[index].url) } if expectedResults[index].mimeType != enclosure.MimeType { t.Errorf(`Unexpected enclosure type, got %q instead of %q`, enclosure.MimeType, expectedResults[index].mimeType) } if expectedResults[index].size != enclosure.Size { t.Errorf(`Unexpected enclosure size, got %d instead of %d`, enclosure.Size, expectedResults[index].size) } } } func TestParseRepliesLinkRelationWithHTMLType(t *testing.T) { data := ` http://www.example.org/myfeed My Example Feed 2005-07-28T12:00:00Z James tag:entries.com,2005:1 My original entry 2006-03-01T12:12:12Z This is my original entry ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].CommentsURL != "http://www.example.org/comments.html" { t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL) } } func TestParseRepliesLinkRelationWithXHTMLType(t *testing.T) { data := ` http://www.example.org/myfeed My Example Feed 2005-07-28T12:00:00Z James tag:entries.com,2005:1 My original entry 2006-03-01T12:12:12Z This is my original entry ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].CommentsURL != "http://www.example.org/comments.xhtml" { t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL) } } func TestParseRepliesLinkRelationWithNoType(t *testing.T) { data := ` http://www.example.org/myfeed My Example Feed 2005-07-28T12:00:00Z James tag:entries.com,2005:1 My original entry 2006-03-01T12:12:12Z This is my original entry ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].CommentsURL != "" { t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL) } } func TestAbsoluteCommentsURL(t *testing.T) { data := ` http://www.example.org/myfeed My Example Feed 2005-07-28T12:00:00Z James tag:entries.com,2005:1 My original entry 2006-03-01T12:12:12Z This is my original entry ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries) != 1 { t.Errorf("Incorrect number of entries, got: %d", len(feed.Entries)) } if feed.Entries[0].URL != "http://www.example.org/entries/1" { t.Errorf("Incorrect entry URL, got: %s", feed.Entries[0].URL) } if feed.Entries[0].CommentsURL != "" { t.Errorf("Incorrect entry comments URL, got: %s", feed.Entries[0].CommentsURL) } } func TestParseFeedWithCategories(t *testing.T) { data := ` Example Feed Alice Bob urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if len(feed.Entries[0].Tags) != 2 { t.Errorf("Incorrect number of tags, got: %d", len(feed.Entries[0].Tags)) } expected := "Tech" result := feed.Entries[0].Tags[0] if result != expected { t.Errorf("Incorrect entry category, got %q instead of %q", result, expected) } expected = "Science" result = feed.Entries[0].Tags[1] if result != expected { t.Errorf("Incorrect entry category, got %q instead of %q", result, expected) } } func TestParseFeedWithIconURL(t *testing.T) { data := ` Example Feed http://example.org/icon.png ` feed, err := Parse("https://example.org/", bytes.NewReader([]byte(data))) if err != nil { t.Fatal(err) } if feed.IconURL != "http://example.org/icon.png" { t.Errorf("Incorrect icon URL, got: %s", feed.IconURL) } }