// Copyright 2019 Frédéric Guillot. All rights reserved. // Use of this source code is governed by the Apache 2.0 // license that can be found in the LICENSE file. package atom // import "miniflux.app/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(bytes.NewBufferString(data)) if err != nil { t.Fatal(err) } if feed.Title != "Example Feed" { t.Errorf("Incorrect title, got: %s", feed.Title) } if feed.FeedURL != "" { 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 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(bytes.NewBufferString(data)) if err != nil { t.Fatal(err) } if feed.Title != "https://example.org/" { t.Errorf("Incorrect feed title, got: %s", feed.Title) } } func TestParseEntryWithoutTitle(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(bytes.NewBufferString(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 TestParseFeedURL(t *testing.T) { data := ` Example Feed 2003-12-13T18:30:02Z ` feed, err := Parse(bytes.NewBufferString(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 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(bytes.NewBufferString(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(bytes.NewBufferString(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 TestParseEntryTitleWithHTMLAndCDATA(t *testing.T) { data := ` Example Feed <![CDATA[Test “Test”]]> urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse(bytes.NewBufferString(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) } } func TestParseEntryTitleWithHTML(t *testing.T) { data := ` Example Feed <code>Test</code> Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse(bytes.NewBufferString(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) } } func TestParseEntryTitleWithXHTML(t *testing.T) { data := ` Example Feed <code>Test</code> Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse(bytes.NewBufferString(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) } } func TestParseEntrySummaryWithXHTML(t *testing.T) { data := ` Example Feed <code>Test</code> Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z

Some text.

` feed, err := Parse(bytes.NewBufferString(data)) if err != nil { t.Fatal(err) } if feed.Entries[0].Content != "

Some text.

" { t.Errorf("Incorrect entry content, got: %s", feed.Entries[0].Content) } } func TestParseEntrySummaryWithHTML(t *testing.T) { data := ` Example Feed <code>Test</code> Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text.

]]>
` feed, err := Parse(bytes.NewBufferString(data)) if err != nil { t.Fatal(err) } if feed.Entries[0].Content != "

Some text.

" { t.Errorf("Incorrect entry content, got: %s", feed.Entries[0].Content) } } func TestParseEntrySummaryWithPlainText(t *testing.T) { data := ` Example Feed <code>Test</code> Test urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z ]]> ` feed, err := Parse(bytes.NewBufferString(data)) if err != nil { t.Fatal(err) } if feed.Entries[0].Content != "<Some text.>" { t.Errorf("Incorrect entry content, got: %s", 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(bytes.NewBufferString(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(bytes.NewBufferString(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 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(bytes.NewBufferString(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 TestParseEntryWithPublished(t *testing.T) { data := ` Example Feed urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. ` feed, err := Parse(bytes.NewBufferString(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(bytes.NewBufferString(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(bytes.NewBufferString(data)) if err == nil { t.Error("Parse should returns an error") } } func TestParseWithHTMLEntity(t *testing.T) { data := ` Example   Feed ` feed, err := Parse(bytes.NewBufferString(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(bytes.NewBufferString(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(bytes.NewBufferString(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(bytes.NewBufferString(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 TestParseRepliesLinkRelation(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(bytes.NewBufferString(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) } }