event item
This commit is contained in:
parent
f4936d4547
commit
a95202247a
|
@ -1 +1,2 @@
|
||||||
test.db*
|
test.db*
|
||||||
|
plannersync
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go-mod.ewintr.nl/planner/item"
|
||||||
"go-mod.ewintr.nl/planner/sync/client"
|
"go-mod.ewintr.nl/planner/sync/client"
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.21.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/lib/pq v1.10.9 // indirect
|
github.com/lib/pq v1.10.9 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,5 +1,7 @@
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package item
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventBody struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Start time.Time `json:"start"`
|
||||||
|
End time.Time `json:"end"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EventBody) MarshalJSON() ([]byte, error) {
|
||||||
|
type Alias EventBody
|
||||||
|
return json.Marshal(&struct {
|
||||||
|
Start string `json:"start"`
|
||||||
|
End string `json:"end"`
|
||||||
|
*Alias
|
||||||
|
}{
|
||||||
|
Start: e.Start.UTC().Format(time.RFC3339),
|
||||||
|
End: e.End.UTC().Format(time.RFC3339),
|
||||||
|
Alias: (*Alias)(&e),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
EventBody
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEvent(i Item) (Event, error) {
|
||||||
|
if i.Kind != KindEvent {
|
||||||
|
return Event{}, fmt.Errorf("item is not an event")
|
||||||
|
}
|
||||||
|
|
||||||
|
var e Event
|
||||||
|
if err := json.Unmarshal([]byte(i.Body), &e); err != nil {
|
||||||
|
return Event{}, fmt.Errorf("could not unmarshal item body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.ID = i.ID
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Event) Item() (Item, error) {
|
||||||
|
body, err := json.Marshal(EventBody{
|
||||||
|
Title: e.Title,
|
||||||
|
Start: e.Start,
|
||||||
|
End: e.End,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return Item{}, fmt.Errorf("could not marshal event to json")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Item{
|
||||||
|
ID: e.ID,
|
||||||
|
Kind: KindEvent,
|
||||||
|
Body: string(body),
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
package item_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"go-mod.ewintr.nl/planner/item"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewEvent(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
it item.Item
|
||||||
|
expEvent item.Event
|
||||||
|
expErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "wrong kind",
|
||||||
|
it: item.Item{
|
||||||
|
ID: "a",
|
||||||
|
Kind: item.KindTask,
|
||||||
|
Body: `{
|
||||||
|
"title":"title",
|
||||||
|
"start":"2024-09-20T08:00:00Z",
|
||||||
|
"end":"2024-09-20T10:00:00Z"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
expErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid json",
|
||||||
|
it: item.Item{
|
||||||
|
ID: "a",
|
||||||
|
Kind: item.KindEvent,
|
||||||
|
Body: `{"id":"a"`,
|
||||||
|
},
|
||||||
|
expErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid",
|
||||||
|
it: item.Item{
|
||||||
|
ID: "a",
|
||||||
|
Kind: item.KindEvent,
|
||||||
|
Body: `{
|
||||||
|
"title":"title",
|
||||||
|
"start":"2024-09-20T08:00:00Z",
|
||||||
|
"end":"2024-09-20T10:00:00Z"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
expEvent: item.Event{
|
||||||
|
ID: "a",
|
||||||
|
EventBody: item.EventBody{
|
||||||
|
Title: "title",
|
||||||
|
Start: time.Date(2024, 9, 20, 8, 0, 0, 0, time.UTC),
|
||||||
|
End: time.Date(2024, 9, 20, 10, 0, 0, 0, time.UTC),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
actEvent, actErr := item.NewEvent(tc.it)
|
||||||
|
if tc.expErr != (actErr != nil) {
|
||||||
|
t.Errorf("exp nil, got %v", actErr)
|
||||||
|
}
|
||||||
|
if tc.expErr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tc.expEvent, actEvent); diff != "" {
|
||||||
|
t.Errorf("(exp +, got -)\n%s", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEventItem(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
event item.Event
|
||||||
|
expItem item.Item
|
||||||
|
expErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
expItem: item.Item{
|
||||||
|
Kind: item.KindEvent,
|
||||||
|
Updated: time.Time{},
|
||||||
|
Body: `{"start":"0001-01-01T00:00:00Z","end":"0001-01-01T00:00:00Z","title":""}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal",
|
||||||
|
event: item.Event{
|
||||||
|
ID: "a",
|
||||||
|
EventBody: item.EventBody{
|
||||||
|
Title: "title",
|
||||||
|
Start: time.Date(2024, 9, 23, 8, 0, 0, 0, time.UTC),
|
||||||
|
End: time.Date(2024, 9, 23, 10, 0, 0, 0, time.UTC),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expItem: item.Item{
|
||||||
|
ID: "a",
|
||||||
|
Kind: item.KindEvent,
|
||||||
|
Updated: time.Time{},
|
||||||
|
Body: `{"start":"2024-09-23T08:00:00Z","end":"2024-09-23T10:00:00Z","title":"title"}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
actItem, actErr := tc.event.Item()
|
||||||
|
if tc.expErr != (actErr != nil) {
|
||||||
|
t.Errorf("exp nil, got %v", actErr)
|
||||||
|
}
|
||||||
|
if tc.expErr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tc.expItem, actItem); diff != "" {
|
||||||
|
t.Errorf("(exp+, got -)\n%s", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServerServeHTTP(t *testing.T) {
|
func TestServerServeHTTP(t *testing.T) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMemoryItem(t *testing.T) {
|
func TestMemoryItem(t *testing.T) {
|
||||||
|
@ -87,14 +87,14 @@ func TestMemoryItem(t *testing.T) {
|
||||||
})
|
})
|
||||||
expItems := []item.Item{t1, t2}
|
expItems := []item.Item{t1, t2}
|
||||||
sort.Slice(expItems, func(i, j int) bool {
|
sort.Slice(expItems, func(i, j int) bool {
|
||||||
return expItems[i].ID < actItems[j].ID
|
return expItems[i].ID < expItems[j].ID
|
||||||
})
|
})
|
||||||
|
|
||||||
if actItems[0].ID != t1.ID {
|
if actItems[0].ID != expItems[0].ID {
|
||||||
t.Errorf("exp %v, got %v", actItems[0].ID, t1.ID)
|
t.Errorf("exp %v, got %v", actItems[0].ID, expItems[0].ID)
|
||||||
}
|
}
|
||||||
if actItems[1].ID != t2.ID {
|
if actItems[1].ID != expItems[1].ID {
|
||||||
t.Errorf("exp %v, got %v", actItems[1].ID, t2.ID)
|
t.Errorf("exp %v, got %v", actItems[1].ID, expItems[1].ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log("select kind")
|
t.Log("select kind")
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/sync/item"
|
"go-mod.ewintr.nl/planner/item"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in New Issue