Datepickers on native time.Time / lagoon.Date fields, file uploads on materials, readings and class sessions managed from the course form (course_id made nullable).
88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
package models_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/lagoon"
|
|
"git.golem15.com/jakub/sm-bm-plugin/models"
|
|
)
|
|
|
|
func TestParseDateTimeForms(t *testing.T) {
|
|
want := time.Date(2026, 10, 3, 6, 0, 0, 0, time.UTC)
|
|
for _, in := range []string{
|
|
"2026-10-03T08:00:00+02:00",
|
|
"2026-10-03T06:00:00Z",
|
|
"2026-10-03 08:00",
|
|
"2026-10-03T08:00",
|
|
" 2026-10-03 08:00:00 ",
|
|
} {
|
|
got, err := models.ParseDateTime(in)
|
|
if err != nil {
|
|
t.Errorf("ParseDateTime(%q): %v", in, err)
|
|
continue
|
|
}
|
|
if !got.Equal(want) {
|
|
t.Errorf("ParseDateTime(%q) = %v, want %v", in, got, want)
|
|
}
|
|
}
|
|
// Winter time: a wall-clock time in December is UTC+1.
|
|
got, err := models.ParseDateTime("2026-12-01 08:00")
|
|
if err != nil || !got.Equal(time.Date(2026, 12, 1, 7, 0, 0, 0, time.UTC)) {
|
|
t.Errorf("winter wall clock = %v, %v", got, err)
|
|
}
|
|
for _, bad := range []string{"", "tomorrow", "2026-13-01 08:00", "2026-10-03"} {
|
|
if _, err := models.ParseDateTime(bad); err == nil {
|
|
t.Errorf("ParseDateTime(%q) accepted", bad)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseDateAndFormat(t *testing.T) {
|
|
d, err := models.ParseDate(" 2026-10-03 ")
|
|
if err != nil || d.String() != "2026-10-03" {
|
|
t.Errorf("ParseDate = %v, %v", d, err)
|
|
}
|
|
if _, err := models.ParseDate("03.10.2026"); err == nil {
|
|
t.Error("a non-ISO date was accepted")
|
|
}
|
|
got := models.FormatDateTime(time.Date(2026, 10, 3, 6, 0, 0, 0, time.UTC))
|
|
if got != "2026-10-03T08:00:00+02:00" {
|
|
t.Errorf("FormatDateTime = %q, want the Warsaw RFC 3339 form", got)
|
|
}
|
|
}
|
|
|
|
func TestTemporalErrors(t *testing.T) {
|
|
at := func(h int) time.Time { return time.Date(2026, 10, 3, h, 0, 0, 0, models.Location) }
|
|
s := &models.ClassSession{StartsAt: at(10), EndsAt: at(9)}
|
|
if errs := s.TemporalErrors(); len(errs["ends_at"]) != 1 {
|
|
t.Errorf("end before start: %v", errs)
|
|
}
|
|
if errs := (&models.ClassSession{StartsAt: at(8), EndsAt: at(10)}).TemporalErrors(); errs != nil {
|
|
t.Errorf("valid session: %v", errs)
|
|
}
|
|
// Missing times are the required rules' job, not an order error.
|
|
if errs := (&models.ClassSession{}).TemporalErrors(); errs != nil {
|
|
t.Errorf("empty session: %v", errs)
|
|
}
|
|
m := &models.Meeting{StartsOn: lagoon.NewDate(2026, 10, 4), EndsOn: lagoon.NewDate(2026, 10, 3)}
|
|
if errs := m.TemporalErrors(); len(errs["ends_on"]) != 1 {
|
|
t.Errorf("meeting order: %v", errs)
|
|
}
|
|
ok := &models.Meeting{StartsOn: lagoon.NewDate(2026, 10, 3), EndsOn: lagoon.NewDate(2026, 10, 4)}
|
|
if errs := ok.TemporalErrors(); errs != nil {
|
|
t.Errorf("valid meeting: %v", errs)
|
|
}
|
|
}
|
|
|
|
func TestBeforeSaveBlanksOptionalText(t *testing.T) {
|
|
empty, space := "", " "
|
|
c := &models.Course{Code: &empty, Lecturer: &space}
|
|
if err := c.BeforeSave(nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Code != nil || c.Lecturer != nil {
|
|
t.Errorf("blank text kept: %v %v", c.Code, c.Lecturer)
|
|
}
|
|
}
|