Files
MujicaUI/calendar_month_view_test.go
T

172 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package mujica
import (
"fmt"
"testing"
"time"
"github.com/egoist/mygo/ui"
)
type monthProbe struct {
month YearMonth
events []CalendarEvent
opts CalendarMonthViewOptions
opened []string
changes []CalendarChange
days []Date
disabled bool
}
func (p *monthProbe) tester() *ui.Tester {
if p.month.IsZero() {
p.month = YearMonth{2026, time.October}
}
p.opts.Location, p.opts.Today = calTokyo, calendarToday
return ui.NewTester(func(c *ui.Context) {
Use(c, Settings{})
o := p.opts
o.Disabled = p.disabled
r := CalendarMonthView(c, &p.month, p.events, o)
if id, ok := r.Opened(); ok {
p.opened = append(p.opened, id)
}
if ch, ok := r.Changed(); ok {
p.changes = append(p.changes, ch)
}
if d, ok := r.DayChosen(); ok {
p.days = append(p.days, d)
}
}, 1000, 900)
}
func TestCalendarMonthViewOverflowAndPopover(t *testing.T) {
p := &monthProbe{}
for i := range 5 {
p.events = append(p.events, calEvent(fmt.Sprint(i), 14, 8+2*i, 0, 60))
}
tt := p.tester()
if !tt.HasText("+2") || tt.HasText("Event 3") {
t.Fatalf("3 rows then +2 expected: %v", tt.Texts())
}
_ = tt.Click("2 more events")
if !tt.HasText("Event 4") {
t.Fatal("+N should list the hidden events")
}
_ = tt.Click("Event 4, 16:00 – 17:00")
if len(p.opened) != 1 || p.opened[0] != "4" {
t.Fatalf("opened %v", p.opened)
}
}
func TestCalendarMonthViewOverlapSideBySide(t *testing.T) {
p := &monthProbe{events: []CalendarEvent{calEvent("a", 14, 9, 0, 120), calEvent("b", 14, 10, 0, 60), calEvent("c", 14, 15, 0, 60)}}
tt := p.tester()
a, _ := tt.Find("Event a, 09:00 – 11:00")
b, _ := tt.Find("Event b, 10:00 – 11:00")
cc, _ := tt.Find("Event c, 15:00 – 16:00")
if a.Y != b.Y || b.X <= a.X || cc.Y <= a.Y {
t.Fatalf("overlapping events should share a row: %v %v %v", a, b, cc)
}
}
func TestCalendarMonthViewDragAndKeys(t *testing.T) {
p := &monthProbe{events: []CalendarEvent{calEvent("a", 14, 9, 30, 60)}}
tt := p.tester()
chip, _ := tt.Find("Event a, 09:30 – 10:30")
target, _ := tt.Find(datetimeTestLabel(oct(16)))
tt.Press(chip.X+10, chip.Y+5)
for i := 1; i <= 4; i++ {
f := float32(i) / 4
tt.Move(chip.X+10+(target.X+20-chip.X-10)*f, chip.Y+5+(target.Y+40-chip.Y-5)*f)
}
tt.Release(target.X+20, target.Y+40)
want := time.Date(2026, time.October, 16, 9, 30, 0, 0, calTokyo)
if len(p.changes) != 1 || !p.changes[0].Start.Equal(want) || p.changes[0].End.Sub(p.changes[0].Start) != time.Hour {
t.Fatalf("drop gave %+v", p.changes)
}
_ = tt.Click("Event a, 09:30 – 10:30")
tt.Key(ui.Alt, ui.KeyDown)
if len(p.changes) != 2 || !p.changes[1].Start.Equal(time.Date(2026, time.October, 21, 9, 30, 0, 0, calTokyo)) {
t.Fatalf("Alt+Down gave %+v", p.changes)
}
}
func TestCalendarMonthViewDSTGapReported(t *testing.T) {
ny, err := time.LoadLocation("America/New_York")
if err != nil {
t.Fatal(err)
}
ev := CalendarEvent{ID: "g", Title: "Early", Start: time.Date(2026, time.March, 7, 2, 30, 0, 0, ny)}
ev.End = ev.Start.Add(time.Hour)
p := &monthProbe{month: YearMonth{2026, time.March}, events: []CalendarEvent{ev}}
p.opts.Location = ny
tt := ui.NewTester(func(c *ui.Context) {
Use(c, Settings{})
if ch, ok := CalendarMonthView(c, &p.month, p.events, CalendarMonthViewOptions{Location: ny, Today: Date{2026, time.March, 1}}).Changed(); ok {
p.changes = append(p.changes, ch)
}
}, 1000, 900)
_ = tt.Click("Early, 02:30 – 03:30")
tt.Key(ui.Alt, ui.KeyRight)
if len(p.changes) != 0 || !tt.HasText("2026-03-08 02:30 does not exist in America/New_York") {
t.Fatalf("gap not reported: %v", tt.Texts())
}
}
func TestCalendarMonthViewNavigationDayAndDisabled(t *testing.T) {
p := &monthProbe{events: []CalendarEvent{calEvent("a", 14, 9, 0, 60)}}
tt := p.tester()
_ = tt.Click(datetimeTestLabel(oct(20)))
_ = tt.Click("Next month")
if len(p.days) != 1 || p.days[0] != oct(20) || p.month != (YearMonth{2026, time.November}) {
t.Fatalf("day %v month %v", p.days, p.month)
}
p.month, p.disabled = YearMonth{2026, time.October}, true
tt.Frame()
_ = tt.Click("Next month")
_ = tt.Click("Event a, 09:00 – 10:00")
tt.Key(ui.Alt, ui.KeyRight)
if p.month != (YearMonth{2026, time.October}) || len(p.opened) != 0 || len(p.changes) != 0 {
t.Fatal("disabled view reacted")
}
}
func TestCalendarMonthViewLargeDataAndInvalid(t *testing.T) {
p := &monthProbe{}
base := time.Date(2000, 1, 1, 9, 0, 0, 0, calTokyo)
for i := range 100000 {
s := base.Add(time.Duration(i) * 3 * time.Hour)
p.events = append(p.events, CalendarEvent{ID: fmt.Sprint(i), Title: "E", Start: s, End: s.Add(time.Hour)})
}
tt := p.tester()
if n := len(tt.Texts()); n > 800 {
t.Fatalf("built %d labels for one month", n)
}
for _, bad := range []func(){
func() { q := &monthProbe{events: []CalendarEvent{{ID: "x", Start: base, End: base}}}; q.tester() },
func() { q := &monthProbe{opts: CalendarMonthViewOptions{MaxPerDay: -1}}; q.tester() },
} {
func() {
defer func() {
if recover() == nil {
t.Error("expected panic")
}
}()
bad()
}()
}
}
func TestCalendarMonthViewSnapshot(t *testing.T) {
m := YearMonth{2026, time.October}
evs := []CalendarEvent{calEvent("1", 6, 9, 0, 60), calEvent("2", 14, 9, 0, 120), calEvent("3", 14, 10, 0, 30),
calEvent("4", 14, 13, 0, 30), calEvent("5", 14, 15, 0, 30), calEvent("6", 14, 17, 0, 30), calEvent("7", 22, 18, 0, 60)}
evs[1].Color, evs[2].Color, evs[6].Color = EventInfo, EventSuccess, EventWarning
snapshot(t, "calendar_month_view", 900, 860, func(c *ui.Context) {
ui.Column(c).Padding(16).Children(func() {
CalendarMonthView(c, &m, evs, CalendarMonthViewOptions{Location: calTokyo, Today: calendarToday})
})
})
}