Add Sort function to Feed.

Fixes #54 and #55
This commit is contained in:
Kamil Kisiel
2018-08-17 23:01:44 -07:00
parent 96fc32f661
commit 5f6928813b
2 changed files with 234 additions and 0 deletions
+9
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"encoding/xml"
"io"
"sort"
"time"
)
@@ -134,3 +135,11 @@ func (f *Feed) WriteJSON(w io.Writer) error {
e.SetIndent("", " ")
return e.Encode(feed)
}
// Sort sorts the Items in the feed with the given less function.
func (f *Feed) Sort(less func(a, b *Item) bool) {
lessFunc := func(i, j int) bool {
return less(f.Items[i], f.Items[j])
}
sort.SliceStable(f.Items, lessFunc)
}
+225
View File
@@ -255,3 +255,228 @@ func TestFeed(t *testing.T) {
t.Errorf("JSON not what was expected. Got:\n||%s||\n\nExpected:\n||%s||\n", got, jsonOutput)
}
}
var atomOutputSorted = `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom">
<title>jmoiron.net blog</title>
<id>http://jmoiron.net/blog</id>
<updated>2013-01-16T21:52:35-05:00</updated>
<rights>This work is copyright © Benjamin Button</rights>
<subtitle>discussion about tech, footie, photos</subtitle>
<link href="http://jmoiron.net/blog"></link>
<author>
<name>Jason Moiron</name>
<email>jmoiron@jmoiron.net</email>
</author>
<entry>
<title>Limiting Concurrency in Go</title>
<updated>2013-01-18T21:52:35-05:00</updated>
<id>tag:jmoiron.net,2013-01-18:/blog/limiting-concurrency-in-go/</id>
<link href="http://jmoiron.net/blog/limiting-concurrency-in-go/" rel="alternate"></link>
<summary type="html"></summary>
</entry>
<entry>
<title>Logic-less Template Redux</title>
<updated>2013-01-17T21:52:35-05:00</updated>
<id>tag:jmoiron.net,2013-01-17:/blog/logicless-template-redux/</id>
<link href="http://jmoiron.net/blog/logicless-template-redux/" rel="alternate"></link>
<summary type="html"></summary>
</entry>
<entry>
<title>Idiomatic Code Reuse in Go</title>
<updated>2013-01-17T09:52:35-05:00</updated>
<id>tag:jmoiron.net,2013-01-17:/blog/idiomatic-code-reuse-in-go/</id>
<link href="http://jmoiron.net/blog/idiomatic-code-reuse-in-go/" rel="alternate"></link>
<summary type="html"></summary>
</entry>
<entry>
<title>Never Gonna Give You Up Mp3</title>
<updated>2013-01-17T07:52:35-05:00</updated>
<id>tag:example.com,2013-01-17:/RickRoll.mp3</id>
<link href="http://example.com/RickRoll.mp3" rel="alternate"></link>
<summary type="html"></summary>
</entry>
<entry>
<title>String formatting in Go</title>
<updated>2013-01-16T21:52:35-05:00</updated>
<id>tag:example.com,2013-01-16:/strings</id>
<link href="http://example.com/strings" rel="alternate"></link>
<summary type="html"></summary>
</entry>
</feed>`
var rssOutputSorted = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>jmoiron.net blog</title>
<link>http://jmoiron.net/blog</link>
<description>discussion about tech, footie, photos</description>
<copyright>This work is copyright © Benjamin Button</copyright>
<managingEditor>jmoiron@jmoiron.net (Jason Moiron)</managingEditor>
<pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate>
<item>
<title>Limiting Concurrency in Go</title>
<link>http://jmoiron.net/blog/limiting-concurrency-in-go/</link>
<description></description>
<pubDate>Fri, 18 Jan 2013 21:52:35 -0500</pubDate>
</item>
<item>
<title>Logic-less Template Redux</title>
<link>http://jmoiron.net/blog/logicless-template-redux/</link>
<description></description>
<pubDate>Thu, 17 Jan 2013 21:52:35 -0500</pubDate>
</item>
<item>
<title>Idiomatic Code Reuse in Go</title>
<link>http://jmoiron.net/blog/idiomatic-code-reuse-in-go/</link>
<description></description>
<pubDate>Thu, 17 Jan 2013 09:52:35 -0500</pubDate>
</item>
<item>
<title>Never Gonna Give You Up Mp3</title>
<link>http://example.com/RickRoll.mp3</link>
<description></description>
<pubDate>Thu, 17 Jan 2013 07:52:35 -0500</pubDate>
</item>
<item>
<title>String formatting in Go</title>
<link>http://example.com/strings</link>
<description></description>
<pubDate>Wed, 16 Jan 2013 21:52:35 -0500</pubDate>
</item>
</channel>
</rss>`
var jsonOutputSorted = `{
"version": "https://jsonfeed.org/version/1",
"title": "jmoiron.net blog",
"home_page_url": "http://jmoiron.net/blog",
"description": "discussion about tech, footie, photos",
"author": {
"name": "Jason Moiron"
},
"items": [
{
"id": "",
"url": "http://jmoiron.net/blog/limiting-concurrency-in-go/",
"title": "Limiting Concurrency in Go",
"date_published": "2013-01-18T21:52:35-05:00"
},
{
"id": "",
"url": "http://jmoiron.net/blog/logicless-template-redux/",
"title": "Logic-less Template Redux",
"date_published": "2013-01-17T21:52:35-05:00"
},
{
"id": "",
"url": "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/",
"title": "Idiomatic Code Reuse in Go",
"date_published": "2013-01-17T09:52:35-05:00"
},
{
"id": "",
"url": "http://example.com/RickRoll.mp3",
"title": "Never Gonna Give You Up Mp3",
"date_published": "2013-01-17T07:52:35-05:00"
},
{
"id": "",
"url": "http://example.com/strings",
"title": "String formatting in Go",
"date_published": "2013-01-16T21:52:35-05:00"
}
]
}`
func TestFeedSorted(t *testing.T) {
now, err := time.Parse(time.RFC3339, "2013-01-16T21:52:35-05:00")
if err != nil {
t.Error(err)
}
tz := time.FixedZone("EST", -5*60*60)
now = now.In(tz)
feed := &Feed{
Title: "jmoiron.net blog",
Link: &Link{Href: "http://jmoiron.net/blog"},
Description: "discussion about tech, footie, photos",
Author: &Author{Name: "Jason Moiron", Email: "jmoiron@jmoiron.net"},
Created: now,
Copyright: "This work is copyright © Benjamin Button",
}
feed.Items = []*Item{
{
Title: "Limiting Concurrency in Go",
Link: &Link{Href: "http://jmoiron.net/blog/limiting-concurrency-in-go/"},
Created: now.Add(time.Duration(time.Hour * 48)),
},
{
Title: "Logic-less Template Redux",
Link: &Link{Href: "http://jmoiron.net/blog/logicless-template-redux/"},
Created: now.Add(time.Duration(time.Hour * 24)),
},
{
Title: "Idiomatic Code Reuse in Go",
Link: &Link{Href: "http://jmoiron.net/blog/idiomatic-code-reuse-in-go/"},
Created: now.Add(time.Duration(time.Hour * 12)),
},
{
Title: "Never Gonna Give You Up Mp3",
Link: &Link{Href: "http://example.com/RickRoll.mp3"},
Created: now.Add(time.Duration(time.Hour * 10)),
},
{
Title: "String formatting in Go",
Link: &Link{Href: "http://example.com/strings"},
Created: now,
}}
feed.Sort(func(a, b *Item) bool {
return a.Created.After(b.Created)
})
atom, err := feed.ToAtom()
if err != nil {
t.Errorf("unexpected error encoding Atom: %v", err)
}
if atom != atomOutputSorted {
t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", atom, atomOutputSorted)
}
var buf bytes.Buffer
if err := feed.WriteAtom(&buf); err != nil {
t.Errorf("unexpected error writing Atom: %v", err)
}
if got := buf.String(); got != atomOutputSorted {
t.Errorf("Atom not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, atomOutputSorted)
}
rss, err := feed.ToRss()
if err != nil {
t.Errorf("unexpected error encoding RSS: %v", err)
}
if rss != rssOutputSorted {
t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", rss, rssOutputSorted)
}
buf.Reset()
if err := feed.WriteRss(&buf); err != nil {
t.Errorf("unexpected error writing RSS: %v", err)
}
if got := buf.String(); got != rssOutputSorted {
t.Errorf("Rss not what was expected. Got:\n%s\n\nExpected:\n%s\n", got, rssOutputSorted)
}
json, err := feed.ToJSON()
if err != nil {
t.Errorf("unexpected error encoding JSON: %v", err)
}
if json != jsonOutputSorted {
t.Errorf("JSON not what was expected. Got:\n%s\n\nExpected:\n%s\n", json, jsonOutputSorted)
}
buf.Reset()
if err := feed.WriteJSON(&buf); err != nil {
t.Errorf("unexpected error writing JSON: %v", err)
}
if got := buf.String(); got != jsonOutputSorted+"\n" { //json.Encode appends a newline after the JSON output: https://github.com/golang/go/commit/6f25f1d4c901417af1da65e41992d71c30f64f8f#diff-50848cbd686f250623a2ef6ddb07e157
t.Errorf("JSON not what was expected. Got:\n||%s||\n\nExpected:\n||%s||\n", got, jsonOutputSorted)
}
}