blob: 9d6e2f0a51846bd78971a0e58c7d11a70a95f839 [file] [log] [blame]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"slices"
"strings"
"testing"
"time"
"golang.org/x/oscar/internal/actions"
"golang.org/x/oscar/internal/storage"
"golang.org/x/oscar/internal/testutil"
"rsc.io/ordered"
)
func TestTimeOrDuration(t *testing.T) {
for _, test := range []struct {
endpoint endpoint
wantTime time.Time
wantDur time.Duration
}{
{
endpoint: endpoint{Radio: "fixed"},
wantTime: time.Time{},
},
{
endpoint: endpoint{Radio: "date", Date: "2018-01-02T09:11"},
wantTime: time.Date(2018, 1, 2, 9, 11, 0, 0, time.Local),
},
{
endpoint: endpoint{Radio: "dur", DurNum: "3", DurUnit: "hours"},
wantDur: 3 * time.Hour,
},
} {
gotTime, gotDur, err := test.endpoint.timeOrDuration(time.Local)
if err != nil {
t.Fatal(err)
}
if !gotTime.Equal(test.wantTime) || gotDur != test.wantDur {
t.Errorf("%+v: got (%s, %s), want (%s, %s)",
test.endpoint, gotTime, gotDur, test.wantTime, test.wantDur)
}
}
}
func TestTimes(t *testing.T) {
dt := func(year int, month time.Month, day, hour, minute int) time.Time {
return time.Date(year, month, day, hour, minute, 0, 0, time.Local)
}
now := dt(2024, 9, 10, 0, 0)
for _, test := range []struct {
start, end endpoint
wantStart, wantEnd time.Time
}{
{
start: endpoint{Radio: "fixed"},
end: endpoint{Radio: "fixed"},
wantStart: time.Time{},
wantEnd: now,
},
{
start: endpoint{Radio: "dur", DurNum: "1", DurUnit: "hours"},
end: endpoint{Radio: "date", Date: "2001-11-12T04:00"},
wantStart: dt(2001, 11, 12, 3, 0),
wantEnd: dt(2001, 11, 12, 4, 0),
},
{
start: endpoint{Radio: "date", Date: "2001-11-12T04:00"},
end: endpoint{Radio: "dur", DurNum: "1", DurUnit: "hours"},
wantStart: dt(2001, 11, 12, 4, 0),
wantEnd: dt(2001, 11, 12, 5, 0),
},
{
start: endpoint{Radio: "date", Date: "2001-11-12T04:00"},
end: endpoint{Radio: "date", Date: "2002-01-02T11:21"},
wantStart: dt(2001, 11, 12, 4, 0),
wantEnd: dt(2002, 1, 2, 11, 21),
},
} {
gotStart, gotEnd, err := times(test.start, test.end, now, time.Local)
if err != nil {
t.Fatal(err)
}
if !gotStart.Equal(test.wantStart) || !gotEnd.Equal(test.wantEnd) {
t.Errorf("times(%+v, %+v):\ngot (%s, %s)\nwant (%s, %s)",
test.start, test.end, gotStart, gotEnd, test.wantStart, test.wantEnd)
}
}
}
func TestActionTemplate(t *testing.T) {
page := actionLogPage{
Start: endpoint{DurNum: "3", DurUnit: "days"},
StartTime: "whatevs",
Entries: []*actions.Entry{
{
Created: time.Now(),
Key: ordered.Encode("P", 22),
Action: []byte(`{"Project": "P", "Issue":22, "Fix": "fix"}`),
},
},
}
page.setCommonPage()
b, err := Exec(actionLogPageTmpl, &page)
if err != nil {
t.Fatal(err)
}
got := string(b)
wants := []string{
`<option value="days" selected>days</option>`,
`Project`,
`Issue`,
}
for _, w := range wants {
if !strings.Contains(got, w) {
t.Errorf("did not find %q", w)
}
}
if t.Failed() {
t.Log(got)
}
}
type testActioner struct {
actions.Actioner
}
func (testActioner) Run(context.Context, []byte) ([]byte, error) { return nil, nil }
func TestActionsBetween(t *testing.T) {
db := storage.MemDB()
g := &Gaby{slog: testutil.Slogger(t), db: db}
before := actions.Register("actionlog", testActioner{})
start := time.Now()
before(db, []byte{1}, nil, false)
end := time.Now()
time.Sleep(100 * time.Millisecond)
before(db, []byte{2}, nil, false)
got := g.actionsBetween(start, end, func(*actions.Entry) bool { return true })
if len(got) != 1 {
t.Errorf("got %d entries, want 1", len(got))
}
}
func TestActionFilter(t *testing.T) {
entries := []*actions.Entry{
{Kind: "a", Error: ""},
{Kind: "b", Error: ""},
{Kind: "a", Error: "a bad error"},
{Kind: "a", Error: "meh"},
{Kind: "b", Error: "bad"},
{Kind: "a", ApprovalRequired: true},
{Kind: "b", ApprovalRequired: true},
}
applyFilter := func(f func(*actions.Entry) bool) []*actions.Entry {
var res []*actions.Entry
for _, e := range entries {
if f(e) {
res = append(res, e)
}
}
return res
}
for _, tc := range []struct {
in string
want func(*actions.Entry) bool
}{
{"", func(*actions.Entry) bool { return true }},
{
"Kind=a",
func(e *actions.Entry) bool { return e.Kind == "a" },
},
{
"Kind=a Error:bad",
func(e *actions.Entry) bool {
return e.Kind == "a" && strings.Contains(e.Error, "bad")
},
},
{
"ApprovalRequired=true",
func(e *actions.Entry) bool { return e.ApprovalRequired },
},
{
"ApprovalRequired=true OR Kind=b",
func(e *actions.Entry) bool {
return e.ApprovalRequired || e.Kind == "b"
},
},
} {
gotf, err := newFilter(tc.in)
if err != nil {
t.Fatal(err)
}
got := applyFilter(gotf)
want := applyFilter(tc.want)
if !slices.Equal(got, want) {
t.Errorf("%q:\ngot %v\nwant %v", tc.in, got, want)
}
}
}