- Garden and plant dialogs keep centimeters as the source of truth (LengthField in lib/units.ts): a no-change Save no longer rewrites 900 cm as 899.922 or a 45 cm spacing as 44.958, bumping versions and writing bogus history entries on the way. - The UI stamps every date with the browser's local day (lib/dates.ts). Journal notes already did; plop placement, fill and removal now do too, so a 9 pm placement isn't "planted tomorrow". The fill endpoint gained an optional plantedAt; API and agent callers still default to UTC today. - Removing an object that holds plants asks first and says how many go with it. An empty one still goes straight away (one Undo restores it). - The expanded plant card's action row wraps instead of clipping "Delete". - Monogram lettering switches to a dark ink on pale marker colors (garlic, cabbage, marigold) instead of near-white on near-white. - Copy-as-plan proposes the next free year and warns when the typed name already exists, so two gardens can't both read as "the 2027 plan". - Plan cards show the base name with a "2027 plan" tag, so the year — the point of the name — survives truncation. - A rejected model spec now says which model and why: a wrapped ErrInvalidInput's reason reaches the client as the 400's message, and the Settings field shows it inline instead of toasting "invalid input". Also defuses a clock bomb in TestRemainingReturnsWhenAPlantingIsRemoved, which only passed while the real date was before 2026-08-01. Co-Authored-By: Claude Fable 5 <[email protected]>
31 lines
888 B
Go
31 lines
888 B
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"gitea.stevedudenhoeffer.com/steve/pansy/internal/domain"
|
|
)
|
|
|
|
// TestInputMessage: the bare sentinel stays generic; a wrapped reason reaches
|
|
// the person without the "invalid input: " prefix in front of it.
|
|
func TestInputMessage(t *testing.T) {
|
|
cases := []struct {
|
|
err error
|
|
want string
|
|
}{
|
|
{domain.ErrInvalidInput, "invalid input"},
|
|
{fmt.Errorf("%w: chat model %q: unknown provider", domain.ErrInvalidInput, "nonesuch/model"), `chat model "nonesuch/model": unknown provider`},
|
|
{fmt.Errorf("loading: %w", domain.ErrInvalidInput), "loading: invalid input"},
|
|
}
|
|
for _, c := range cases {
|
|
if !errors.Is(c.err, domain.ErrInvalidInput) {
|
|
t.Fatalf("%v should still be an ErrInvalidInput", c.err)
|
|
}
|
|
if got := inputMessage(c.err); got != c.want {
|
|
t.Errorf("inputMessage(%v) = %q, want %q", c.err, got, c.want)
|
|
}
|
|
}
|
|
}
|