110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"task/internal/sqlite"
|
|
"task/internal/ticket"
|
|
)
|
|
|
|
func TestProjectReportFilters(t *testing.T) {
|
|
db, err := sqlite.Open(filepath.Join(t.TempDir(), "t.db"), []byte("secret"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
if _, err := db.CreateUser("admin", "pass", true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
srv := New(db)
|
|
handler := srv.Handler()
|
|
|
|
loginBody, _ := json.Marshal(map[string]string{"username": "admin", "password": "pass"})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader(loginBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("login %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
cookie := rec.Result().Cookies()[0]
|
|
|
|
createBody, _ := json.Marshal(map[string]string{"name": "Demo"})
|
|
req = httptest.NewRequest(http.MethodPost, "/api/v1/projects", bytes.NewReader(createBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.AddCookie(cookie)
|
|
rec = httptest.NewRecorder()
|
|
handler.ServeHTTP(rec, req)
|
|
var proj map[string]any
|
|
_ = json.Unmarshal(rec.Body.Bytes(), &proj)
|
|
pid, _ := proj["id"].(string)
|
|
|
|
ticketBody, _ := json.Marshal(map[string]string{"title": "Work"})
|
|
req = httptest.NewRequest(http.MethodPost, "/api/v1/projects/"+pid+"/tickets", bytes.NewReader(ticketBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.AddCookie(cookie)
|
|
rec = httptest.NewRecorder()
|
|
handler.ServeHTTP(rec, req)
|
|
var tk map[string]any
|
|
_ = json.Unmarshal(rec.Body.Bytes(), &tk)
|
|
tid, _ := tk["id"].(string)
|
|
|
|
day := time.Date(2026, 10, 18, 14, 0, 0, 0, time.Local)
|
|
_, err = srv.Times.Create(ticket.TimeEntry{
|
|
TicketID: tid,
|
|
ProjectID: pid,
|
|
Start: day,
|
|
End: day.Add(45 * time.Minute),
|
|
Duration: 45 * time.Minute,
|
|
Source: ticket.SourceManual,
|
|
Note: "filtered",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
other := time.Date(2026, 9, 1, 10, 0, 0, 0, time.Local)
|
|
_, err = srv.Times.Create(ticket.TimeEntry{
|
|
TicketID: tid,
|
|
ProjectID: pid,
|
|
Start: other,
|
|
End: other.Add(time.Hour),
|
|
Duration: time.Hour,
|
|
Source: ticket.SourceManual,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
url := "/api/v1/projects/" + pid + "/report?groupBy=ticket&from=2026-10-18&to=2026-10-18&ticketId=" + tid
|
|
req = httptest.NewRequest(http.MethodGet, url, nil)
|
|
req.AddCookie(cookie)
|
|
rec = httptest.NewRecorder()
|
|
handler.ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("report %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
var out struct {
|
|
EntryCount int `json:"entryCount"`
|
|
TotalDurationNs int64 `json:"totalDurationNs"`
|
|
Entries []ticket.TimeEntry `json:"entries"`
|
|
}
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if out.EntryCount != 1 || len(out.Entries) != 1 {
|
|
t.Fatalf("want 1 entry, got count=%d entries=%d", out.EntryCount, len(out.Entries))
|
|
}
|
|
if out.TotalDurationNs != int64(45*time.Minute) {
|
|
t.Fatalf("total=%d", out.TotalDurationNs)
|
|
}
|
|
if out.Entries[0].Note != "filtered" {
|
|
t.Fatalf("note=%q", out.Entries[0].Note)
|
|
}
|
|
}
|