Compare commits

...

2 Commits

Author SHA1 Message Date
c6d8fee715 Add a unit test for Time Trackers
Some checks failed
CI / test (push) Has been cancelled
2025-06-20 16:13:22 +02:00
34a94fa269 Refactor APIClient, start to add support for time trackers 2025-06-20 16:12:48 +02:00
2 changed files with 98 additions and 13 deletions

View File

@ -3,6 +3,7 @@ package mite
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"time"
@ -56,7 +57,7 @@ func (p Project) GetName() string { return p.Name + " (" + p.CustomerName + ")"
func (a APIClient) GetProjects() (Projects, error) {
// GET /projects.json
p := APIProjects{}
err := get(a.domain, a.apiKey, "/projects.json", &p)
err := a.get("/projects.json", &p)
if err != nil {
return nil, err
}
@ -98,7 +99,7 @@ func (c Customer) GetName() string { return c.Name }
func (a APIClient) GetCustomers() (Customers, error) {
// GET /customers.json
p := apiCustomers{}
err := get(a.domain, a.apiKey, "/customers.json", &p)
err := a.get("/customers.json", &p)
if err != nil {
return nil, err
}
@ -142,7 +143,7 @@ func (s Service) GetName() string {
func (a APIClient) GetServices() (Services, error) {
// GET /services.json
p := apiServices{}
err := get(a.domain, a.apiKey, "/services.json", &p)
err := a.get("/services.json", &p)
if err != nil {
return nil, err
}
@ -215,7 +216,7 @@ func (a APIClient) GetTimeEntries(from, to time.Time) (TimeEntries, error) {
p := apiTimeEntry{}
u := fmt.Sprintf("/time_entries.json?from=%s&to=%s", from.Format(time.DateOnly), to.Format(time.DateOnly))
err := get(a.domain, a.apiKey, u, &p)
err := a.get(u, &p)
if err != nil {
return nil, err
}
@ -253,23 +254,62 @@ func (a APIClient) AddTimeEntry(date string, minutes int, notes string, projectI
req.RequestTimeEntryHolder.ProjectID = projectId
req.RequestTimeEntryHolder.ServiceID = serviceId
err := post(a.domain, a.apiKey, "/time_entries.json", req)
err := a.post("/time_entries.json", req)
return err
}
func post(domain, apiKey, path string, data any) error {
type apiTimeTrackerEntry struct {
TimeTrackerHolder timeTrackerHolder `json:"tracker"`
}
type timeTrackerHolder struct {
TrackingTimeEntry *TrackingTimeEntry `json:"tracking_time_entry"`
}
type TrackingTimeEntry struct {
ID int `json:"id"`
Minutes int `json:"minutes"`
Since time.Time `json:"since"`
}
// {
// "tracker": {
// "tracking_time_entry": {
// "id": 36135321,
// "minutes": 247,
// "since": "2015-10-15T17:05:04+02:00"
// }
// }
// }
var ErrNoTracker = errors.New("no time tracker running")
// GetTimeTracker gets the current running time tracker. If no tracker is
// running, the error returned will be ErrNoTracker
func (a APIClient) GetTimeTracker() (TrackingTimeEntry, error) {
r := apiTimeTrackerEntry{}
err := a.get("/tracker.json", &r)
if err != nil {
return TrackingTimeEntry{}, err
}
if r.TimeTrackerHolder.TrackingTimeEntry == nil {
return TrackingTimeEntry{}, ErrNoTracker
}
return *r.TimeTrackerHolder.TrackingTimeEntry, nil
}
func (a APIClient) post(path string, data any) error {
b, err := json.Marshal(data)
if err != nil {
return err
}
req, err := http.NewRequest("POST", baseurl(domain, path), bytes.NewBuffer(b))
req, err := http.NewRequest("POST", baseurl(a.domain, path), bytes.NewBuffer(b))
if err != nil {
return err
}
req.Header.Add("X-MiteApiKey", apiKey)
req.Header.Add("X-MiteApiKey", a.apiKey)
req.Header.Add("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
@ -285,12 +325,12 @@ func post(domain, apiKey, path string, data any) error {
}
func get(domain, apiKey, path string, data any) error {
req, err := http.NewRequest("GET", baseurl(domain, path), nil)
func (a APIClient) get(path string, data any) error {
req, err := http.NewRequest("GET", baseurl(a.domain, path), nil)
if err != nil {
return err
}
req.Header.Add("X-MiteApiKey", apiKey)
req.Header.Add("X-MiteApiKey", a.apiKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
@ -305,7 +345,6 @@ func get(domain, apiKey, path string, data any) error {
return err
}
return nil
}
func baseurl(domain, path string) string {

46
mite/mite_test.go Normal file
View File

@ -0,0 +1,46 @@
package mite
import (
"encoding/json"
"testing"
)
func TestUnmarshalTimeTracking(t *testing.T) {
trackerOn := []byte(`
{
"tracker": {
"tracking_time_entry": {
"id": 36135321,
"minutes": 247,
"since": "2015-10-15T17:05:04+02:00"
}
}
}`)
trackerOff := []byte(`{
"tracker": {}
}`)
off := apiTimeTrackerEntry{}
err := json.Unmarshal(trackerOff, &off)
if err != nil {
t.Error(err)
} else {
if off.TimeTrackerHolder.TrackingTimeEntry != nil {
t.Error("expected nil, but is not")
}
}
on := apiTimeTrackerEntry{}
err = json.Unmarshal(trackerOn, &on)
if err != nil {
t.Error(err)
} else {
if on.TimeTrackerHolder.TrackingTimeEntry == nil {
t.Error("expected note nil, but is not")
} else {
if on.TimeTrackerHolder.TrackingTimeEntry.ID != 36135321 {
t.Error("bad unmarshal?")
}
}
}
}