M entry.go => entry.go +0 -2
@@ 54,8 54,6 @@ func (e Entries) Swap(i, j int) {
type EntryV1 struct {
FeedPath string `bare:"feedPath"`
ID string `bare:"id"`
- Read bool `bare:"read"`
- Favorite bool `bare:"favorite"`
Title Text `bare:"title"`
Content Text `bare:"content"`
Published Timestamp `bare:"published"`
M entry_test.go => entry_test.go +33 -11
@@ 6,26 6,39 @@ import (
"time"
)
-func testEntries(t *testing.T, expected, actual Entries) {
+func testEntryList(t *testing.T, expected, actual []string) {
if len(expected) != len(actual) {
t.Errorf("Expected %d entries, actual %d entries", len(expected), len(actual))
}
for i := 0; i < len(expected); i++ {
- r := actual[i].(*EntryV1)
- e := expected[i].(*EntryV1)
+ r := actual[i]
+ e := expected[i]
+ if r != e {
+ t.Errorf("Expected %s, actual %s", e, r)
+ }
+ }
+}
+
+func testEntries(t *testing.T, expected, actual map[string]Entry) {
+ if len(expected) != len(actual) {
+ t.Errorf("Expected %d entries, actual %d entries", len(expected), len(actual))
+ }
+
+ for k, ev := range expected {
+ rv, ok := actual[k]
+ if !ok {
+ t.Errorf("expected key %s not found", k)
+ }
+
+ r := rv.(*EntryV1)
+ e := ev.(*EntryV1)
if r.FeedPath != e.FeedPath {
t.Errorf("Expected %s, actual %s", e.FeedPath, r.FeedPath)
}
if r.ID != e.ID {
t.Errorf("Expected %s, actual %s", e.ID, r.ID)
}
- if r.Read != e.Read {
- t.Errorf("Expected %t, actual %t", e.Read, r.Read)
- }
- if r.Favorite != e.Favorite {
- t.Errorf("Expected %t, actual %t", e.Favorite, r.Favorite)
- }
if r.Published != e.Published {
t.Errorf("Expected %v, actual %v", e.Published, r.Published)
}
@@ 64,12 77,21 @@ func getEntries() Entries {
return Entries{a}
}
+func getEntryList() []string {
+ e := getEntries()
+
+ r := make([]string, len(e))
+ for i, a := range e {
+ r[i] = a.(*EntryV1).ID
+ }
+
+ return r
+}
+
func getEntry() Entry {
e := EntryV1{
FeedPath: "https://example.com/feed.xml",
ID: "urn:uuid:603bb616-7ae6-4413-83ec-a8cffbdd148e",
- Read: true,
- Favorite: true,
Title: getText(),
Content: getText(),
Published: ToTimestamp(time.Now()),
M feed.go => feed.go +34 -4
@@ 7,6 7,16 @@ import (
"git.sr.ht/~sircmpwn/go-bare"
)
+// FeedType is an enumerated type for Feed
+type FeedType uint
+
+const (
+ // RSS denotes the feed as RSS
+ RSS FeedType = iota
+ // ATOM denotes the feed as ATOM
+ ATOM
+)
+
// Feed type contains elements from RSS Channel & Atom Feed
type Feed interface {
bare.Union
@@ 55,16 65,36 @@ func (f Feeds) Swap(i, j int) {
type FeedV1 struct {
Path string `bare:"path"`
ID string `bare:"id"`
- IsAtom bool `bare:"isAtom"`
+ FeedType FeedType `bare:"feedType"`
Title Text `bare:"title"`
Updated Timestamp `bare:"updated"`
- Entries Entries `bare:"entries"`
Authors Persons `bare:"authors"`
Links Links `bare:"links"`
- Generator *string `bare:"generator,omitempty"`
- Description *Text `bare:"description,omitempty"`
+ Entries []string `bare:"entries"`
+ Generator *string `bare:"generator"`
+ Description *Text `bare:"description"`
}
// IsUnion function is necessary to make the type compatible with the Union
// interface
func (t FeedV1) IsUnion() {}
+
+// String converts the enumerated value to a string. "RSS" is default.
+func (t FeedType) String() string {
+ switch t {
+ case ATOM:
+ return "ATOM"
+ default:
+ return "RSS"
+ }
+}
+
+// ToFeedType converts a string to the enumerated value. RSS is default.
+func ToFeedType(t string) FeedType {
+ switch t {
+ case "ATOM":
+ return ATOM
+ default:
+ return RSS
+ }
+}
M feed_test.go => feed_test.go +34 -11
@@ 6,14 6,19 @@ import (
"time"
)
-func testFeeds(t *testing.T, expected, actual Feeds) {
+func testFeeds(t *testing.T, expected, actual map[string]Feed) {
if len(expected) != len(actual) {
t.Errorf("Expected %d feeds, actual %d feeds", len(expected), len(actual))
}
- for i := 0; i < len(expected); i++ {
- r := actual[i].(*FeedV1)
- e := expected[i].(*FeedV1)
+ for k, ev := range expected {
+ rv, ok := actual[k]
+ if !ok {
+ t.Errorf("expected key %s not found", k)
+ }
+
+ r := rv.(*FeedV1)
+ e := ev.(*FeedV1)
if e.Path != r.Path {
t.Errorf("Expected %s, actual %s", e.Path, r.Path)
}
@@ 29,8 34,8 @@ func testFeeds(t *testing.T, expected, actual Feeds) {
t.Errorf("Expected %s, actual %s", *e.Generator, *r.Generator)
}
}
- if r.IsAtom != e.IsAtom {
- t.Errorf("Expected %t, actual %t", e.IsAtom, r.IsAtom)
+ if r.FeedType != e.FeedType {
+ t.Errorf("Expected %d, actual %d", e.FeedType, r.FeedType)
}
if r.Updated != e.Updated {
t.Errorf("Expected %v, actual %v", e.Updated, r.Updated)
@@ 48,7 53,7 @@ func testFeeds(t *testing.T, expected, actual Feeds) {
testText(t, e.Title, r.Title)
testPersons(t, e.Authors, r.Authors)
testLinks(t, e.Links, r.Links)
- testEntries(t, e.Entries, r.Entries)
+ testEntryList(t, e.Entries, r.Entries)
}
}
@@ 71,9 76,13 @@ func TestFeedSort(t *testing.T) {
}
}
-func getFeeds() Feeds {
+func getFeeds() map[string]Feed {
+ m := make(map[string]Feed)
+
fd := getFeed("test title")
- return Feeds{fd}
+ m[fd.(*FeedV1).Path] = fd
+
+ return m
}
func getFeed(title string) Feed {
@@ 83,16 92,30 @@ func getFeed(title string) Feed {
Path: "https://example.com/feed.xml",
ID: "urn:uuid:22fea9cf-095c-4634-95f5-d0b72f99944f",
Generator: &gen,
- IsAtom: true,
+ FeedType: ATOM,
Title: getText(),
Updated: ToTimestamp(time.Now()),
Description: &desc,
Links: getLinks(),
Authors: getPersons(),
- Entries: getEntries(),
+ Entries: getEntryList(),
}
f.Title.Value = title
var fd Feed = &f
return fd
}
+
+func TestFeedType(t *testing.T) {
+ e := RSS
+ a := ToFeedType(e.String())
+ if e != a {
+ t.Errorf("Expected %d, actual %d", e, a)
+ }
+
+ e = ATOM
+ a = ToFeedType(e.String())
+ if e != a {
+ t.Errorf("Expected %d, actual %d", e, a)
+ }
+}
M link.go => link.go +1 -2
@@ 6,8 6,7 @@ type Links []Link
// Link contains info needed for any link
type Link struct {
URL string `bare:"url"`
- Type string `bare:"type"`
+ LinkType string `bare:"linkType"`
Rel string `bare:"rel"`
Length int `bare:"length"`
- Position *int `bare:"position,omitempty"`
}
M link_test.go => link_test.go +4 -16
@@ 10,8 10,8 @@ func testLinks(t *testing.T, expected, actual Links) {
if expected[j].URL != actual[j].URL {
t.Errorf("Expected %s, actual %s", expected[j].URL, actual[j].URL)
}
- if expected[j].Type != actual[j].Type {
- t.Errorf("Expected %s, actual %s", expected[j].Type, actual[j].Type)
+ if expected[j].LinkType != actual[j].LinkType {
+ t.Errorf("Expected %s, actual %s", expected[j].LinkType, actual[j].LinkType)
}
if expected[j].Rel != actual[j].Rel {
t.Errorf("Expected %s, actual %s", expected[j].Rel, actual[j].Rel)
@@ 19,34 19,22 @@ func testLinks(t *testing.T, expected, actual Links) {
if expected[j].Length != actual[j].Length {
t.Errorf("Expected %d, actual %d", expected[j].Length, actual[j].Length)
}
- if actual[j].Position != expected[j].Position {
- if expected[j].Position == nil {
- t.Errorf("Expected nil, actual %d", *actual[j].Position)
- } else if actual[j].Position == nil {
- t.Errorf("Expected %d, actual nil", *expected[j].Position)
- } else if *actual[j].Position != *expected[j].Position {
- t.Errorf("Expected %d, actual %d", *expected[j].Position, *actual[j].Position)
- }
- }
}
}
func getLinks() Links {
- pos := 1000000
a := Link{
URL: "https://example.com/entry.mp3",
- Type: "audio/mp3",
+ LinkType: "audio/mp3",
Rel: "enclosure",
Length: 50416767,
- Position: &pos,
}
b := Link{
URL: "https://example.com/feed.xml",
- Type: "plain/html",
+ LinkType: "plain/html",
Rel: "self",
Length: 123,
- Position: nil,
}
return Links{a, b}
M message.go => message.go +6 -3
@@ 9,9 9,12 @@ import (
// Message is the first version of the spec
type Message struct {
- Generator string `bare:"generator"`
- Created Timestamp `bare:"created"`
- Feeds Feeds `bare:"feeds"`
+ Generator string `bare:"generator"`
+ Created Timestamp `bare:"created"`
+ Feeds map[string]Feed `bare:"feeds"`
+ Entries map[string]Entry `bare:"entries"`
+ Unread map[string]int64 `bare:"unread"`
+ Favorite map[string]Timestamp `bare:"favorite"`
}
// Bytes will return the barefeed as a slice of bytes
M message_test.go => message_test.go +1 -0
@@ 13,6 13,7 @@ func testMessage(t *testing.T, expected, actual Message) {
t.Errorf("Expected %s, actual %s", expected.Generator, actual.Generator)
}
testFeeds(t, expected.Feeds, actual.Feeds)
+ testEntries(t, expected.Entries, actual.Entries)
}
func getMessage() Message {
M person.go => person.go +2 -2
@@ 6,6 6,6 @@ type Persons []Person
// Person contains info needed for authors
type Person struct {
Name string `bare:"name"`
- Email *string `bare:"email,omitempty"`
- URI *string `bare:"uri,omitempty"`
+ Email *string `bare:"email"`
+ URI *string `bare:"uri"`
}
M text.go => text.go +38 -2
@@ 1,7 1,43 @@
package barefeed
+// TextType is an enumerated type for Text
+type TextType uint
+
+const (
+ // TEXT denotes the text as plain text
+ TEXT TextType = iota
+ // HTML denotes the text as entity escaped html
+ HTML
+ // XHTML denotes the text as inline xhtml, wrapped in a div element
+ XHTML
+)
+
// Text contains info needed for any text
type Text struct {
- Type string `bare:"type"`
- Value string `bare:"value"`
+ Value string `bare:"value"`
+ TextType TextType `bare:"textType"`
+}
+
+// String converts the enumerated value to a string. "TEXT" is default.
+func (t TextType) String() string {
+ switch t {
+ case HTML:
+ return "HTML"
+ case XHTML:
+ return "XHTML"
+ default:
+ return "TEXT"
+ }
+}
+
+// ToTextType converts a string to the enumerated value. TEXT is default.
+func ToTextType(t string) TextType {
+ switch t {
+ case "HTML":
+ return HTML
+ case "XHTML":
+ return XHTML
+ default:
+ return TEXT
+ }
}
M text_test.go => text_test.go +24 -4
@@ 5,8 5,8 @@ import (
)
func testText(t *testing.T, expected, actual Text) {
- if expected.Type != actual.Type {
- t.Errorf("Expected %s, actual %s", expected.Type, actual.Type)
+ if expected.TextType != actual.TextType {
+ t.Errorf("Expected %d, actual %d", expected.TextType, actual.TextType)
}
if expected.Value != actual.Value {
t.Errorf("Expected %s, actual %s", expected.Value, actual.Value)
@@ 15,7 15,27 @@ func testText(t *testing.T, expected, actual Text) {
func getText() Text {
return Text{
- Type: "html",
- Value: "<p>This is a test</p>",
+ TextType: HTML,
+ Value: "<p>This is a test</p>",
+ }
+}
+
+func TestTextType(t *testing.T) {
+ e := TEXT
+ a := ToTextType(e.String())
+ if e != a {
+ t.Errorf("Expected %d, actual %d", e, a)
+ }
+
+ e = HTML
+ a = ToTextType(e.String())
+ if e != a {
+ t.Errorf("Expected %d, actual %d", e, a)
+ }
+
+ e = XHTML
+ a = ToTextType(e.String())
+ if e != a {
+ t.Errorf("Expected %d, actual %d", e, a)
}
}