100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package basic
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestDatetime_Execute_Normal covers default, formatted and zone-shifted output.
|
|
func TestDatetime_Execute_Normal(t *testing.T) {
|
|
t.Parallel()
|
|
c := datetime{}
|
|
|
|
t.Run("default", func(t *testing.T) {
|
|
t.Parallel()
|
|
got, err := run(t, c, nil)
|
|
assertNoErr(t, err)
|
|
m := mapResult(t, got)
|
|
if fieldString(t, m, "timezone") != "UTC" {
|
|
t.Fatalf("timezone = %v, want UTC", m["timezone"])
|
|
}
|
|
if fieldString(t, m, "format") != time.RFC3339 {
|
|
t.Fatalf("format = %v, want RFC3339", m["format"])
|
|
}
|
|
if _, err := time.Parse(time.RFC3339, fieldString(t, m, "now")); err != nil {
|
|
t.Fatalf("now %q is not RFC3339: %v", m["now"], err)
|
|
}
|
|
if fieldInt64(t, m, "unix") <= 0 {
|
|
t.Fatalf("unix = %v, want positive", m["unix"])
|
|
}
|
|
})
|
|
|
|
t.Run("custom format", func(t *testing.T) {
|
|
t.Parallel()
|
|
got, err := run(t, c, map[string]any{"format": "2006-01-02"})
|
|
assertNoErr(t, err)
|
|
m := mapResult(t, got)
|
|
if len(fieldString(t, m, "now")) != 10 {
|
|
t.Fatalf("now = %v, want 10-char date", m["now"])
|
|
}
|
|
})
|
|
|
|
t.Run("non-UTC zone", func(t *testing.T) {
|
|
t.Parallel()
|
|
if _, err := time.LoadLocation("Asia/Shanghai"); err != nil {
|
|
t.Skipf("tzdata not available: %v", err)
|
|
}
|
|
got, err := run(t, c, map[string]any{"timezone": "Asia/Shanghai"})
|
|
assertNoErr(t, err)
|
|
m := mapResult(t, got)
|
|
if fieldString(t, m, "timezone") != "Asia/Shanghai" {
|
|
t.Fatalf("timezone = %v, want Asia/Shanghai", m["timezone"])
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestDatetime_Execute_Errors covers invalid zones and overlong inputs.
|
|
func TestDatetime_Execute_Errors(t *testing.T) {
|
|
t.Parallel()
|
|
c := datetime{}
|
|
cases := []struct {
|
|
name string
|
|
args map[string]any
|
|
target error
|
|
}{
|
|
{name: "invalid zone", args: map[string]any{"timezone": "Not/AZone"}, target: nil},
|
|
{name: "zone too long", args: map[string]any{"timezone": string(make([]byte, 65))}, target: ErrInvalidArgument},
|
|
{name: "layout too long", args: map[string]any{"format": string(make([]byte, 129))}, target: ErrInvalidArgument},
|
|
{name: "non-string timezone", args: map[string]any{"timezone": 123}, target: ErrInvalidArgument},
|
|
}
|
|
for _, tc := range cases {
|
|
tc := tc
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := run(t, c, tc.args)
|
|
if err == nil {
|
|
t.Fatalf("want error, got nil")
|
|
}
|
|
if tc.target != nil {
|
|
assertIs(t, err, tc.target)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestDatetime_Schema verifies the JSON Schema contract.
|
|
func TestDatetime_Schema(t *testing.T) {
|
|
t.Parallel()
|
|
p, err := datetime{}.Parameters()
|
|
assertNoErr(t, err)
|
|
if _, ok := p["required"].([]any); ok {
|
|
t.Fatalf("datetime schema should have no required fields")
|
|
}
|
|
props := p["properties"].(map[string]any)
|
|
for _, field := range []string{"format", "timezone"} {
|
|
if props[field].(map[string]any)["type"] != "string" {
|
|
t.Fatalf("%s type should be string", field)
|
|
}
|
|
}
|
|
}
|