07f7550931
Three defects on the server-rendered pages. /events printed both timestamps in whatever zone the value arrived in. NoticedAt is the bus's local instant; OccurredAt is the store's UTC, or a pubDate internal/rss parsed to UTC. So one row carried two zones and a feed item read hours older than it was, on a page whose hint tells him that column gap is real. /morning printed a plan item's At raw. It is a calendar fact's Ts or a reminder's FireTs, both UTC out of the store, so the same reminder named a different hour here than on /reminders — which does call Local, since V-469. promoteCandidate read the importance select inside `if due != nil`. Confirming a candidate as "срочно" with no deadline threw the word away and the row came back normal with nothing saying why. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kami/maven/internal/ipc"
|
|
)
|
|
|
|
// morningCore serves a canned checklist and day plan.
|
|
type morningCore struct {
|
|
ipc.UnimplementedCoreAPI
|
|
status []ipc.MorningRoutineStatus
|
|
plan ipc.DayPlan
|
|
}
|
|
|
|
func (c *morningCore) MorningStatus(context.Context) ([]ipc.MorningRoutineStatus, error) {
|
|
return c.status, nil
|
|
}
|
|
|
|
func (c *morningCore) DayPlan(context.Context) (ipc.DayPlan, error) { return c.plan, nil }
|
|
|
|
func TestMorningRendersPlanTimesInLocalZone(t *testing.T) {
|
|
// A plan item's At is a calendar fact's Ts or a reminder's FireTs, and the
|
|
// store hands both back as UTC. Printed raw, /morning named an hour for a
|
|
// reminder that /reminders — which does call Local — disagreed with.
|
|
away := awayFromLocal()
|
|
at := time.Date(2026, 8, 1, 9, 0, 0, 0, time.UTC).In(away)
|
|
core := &morningCore{plan: ipc.DayPlan{
|
|
Date: at,
|
|
Items: []ipc.DayPlanItem{{At: at, Text: "выпить таблетки", Kind: "reminder"}},
|
|
}}
|
|
w := httptest.NewRecorder()
|
|
handleMorning(w, httptest.NewRequest(http.MethodGet, "/morning", nil), core)
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200", w.Code)
|
|
}
|
|
body := w.Body.String()
|
|
if !strings.Contains(body, at.Local().Format("15:04")) {
|
|
t.Errorf("plan item not rendered in his clock (%s): %s", at.Local().Format("15:04"), body)
|
|
}
|
|
if strings.Contains(body, at.In(away).Format("15:04")) {
|
|
t.Errorf("plan item rendered in the stored zone: %s", body)
|
|
}
|
|
}
|