Add configuration and CLI foundation
This commit is contained in:
@@ -5,6 +5,10 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/app"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
||||
)
|
||||
|
||||
func TestRunHelpLongFlag(t *testing.T) {
|
||||
@@ -16,8 +20,8 @@ func TestRunHelpLongFlag(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(stdout.String(), "Usage:") {
|
||||
t.Fatalf("help output missing usage:\n%s", stdout.String())
|
||||
if !strings.Contains(stdout.String(), "generate daily") {
|
||||
t.Fatalf("help output missing generate command:\n%s", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,21 +34,159 @@ func TestRunHelpShortFlag(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(stdout.String(), "weatherreporter --help") {
|
||||
t.Fatalf("help output missing root help command:\n%s", stdout.String())
|
||||
if !strings.Contains(stdout.String(), "weatherreporter run evening") {
|
||||
t.Fatalf("help output missing run command:\n%s", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunUnknownArgument(t *testing.T) {
|
||||
func TestRunUnknownCommand(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
err := Run(context.Background(), []string{"generate"}, &stdout, &stderr)
|
||||
err := Run(context.Background(), []string{"inspect"}, &stdout, &stderr)
|
||||
if err == nil {
|
||||
t.Fatal("Run() error = nil, want unknown argument error")
|
||||
t.Fatal("Run() error = nil, want unknown command error")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), `unknown argument "generate"`) {
|
||||
t.Fatalf("Run() error = %q, want unknown argument message", err.Error())
|
||||
if !strings.Contains(err.Error(), `unknown command "inspect"`) {
|
||||
t.Fatalf("Run() error = %q, want unknown command message", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunGenerateReturnsNotImplementedAfterResolution(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
err := runner.Run(context.Background(), []string{"generate", "tomorrow", "--units", "metric"}, &stdout, &stderr)
|
||||
if err == nil {
|
||||
t.Fatal("Run() error = nil, want app not implemented error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "generate is not implemented") {
|
||||
t.Fatalf("Run() error = %q, want app not implemented error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateCommands(t *testing.T) {
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
want app.ReportKind
|
||||
}{
|
||||
{name: "daily", args: []string{"daily", "--date", "2026-05-29"}, want: app.ReportDaily},
|
||||
{name: "tomorrow", args: []string{"tomorrow"}, want: app.ReportTomorrow},
|
||||
{name: "three-day", args: []string{"three-day"}, want: app.ReportThreeDay},
|
||||
{name: "weekend", args: []string{"weekend"}, want: app.ReportWeekend},
|
||||
{name: "storm", args: []string{"storm", "--start", "2026-05-29T18:00", "--end", "2026-05-30T06:00"}, want: app.ReportStorm},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, err := runner.resolveGenerate(tt.args)
|
||||
if err != nil {
|
||||
t.Fatalf("resolveGenerate() error = %v", err)
|
||||
}
|
||||
if req.Report != tt.want {
|
||||
t.Fatalf("Report = %q, want %q", req.Report, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateDailyDefaultsDateInConfiguredTimezone(t *testing.T) {
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
req, err := runner.resolveGenerate([]string{"daily"})
|
||||
if err != nil {
|
||||
t.Fatalf("resolveGenerate() error = %v", err)
|
||||
}
|
||||
|
||||
if got := req.Date.Format(timeutil.DateLayout); got != "2026-05-29" {
|
||||
t.Fatalf("Date = %s, want 2026-05-29", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateAppliesSharedFlags(t *testing.T) {
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
req, err := runner.resolveGenerate([]string{"daily", "--units", "metric", "--tz", "UTC", "--out", "./daily.md"})
|
||||
if err != nil {
|
||||
t.Fatalf("resolveGenerate() error = %v", err)
|
||||
}
|
||||
|
||||
if req.Config.WeatherAPI.Units != "metric" {
|
||||
t.Fatalf("Units = %q, want metric", req.Config.WeatherAPI.Units)
|
||||
}
|
||||
if req.Config.WeatherAPI.Timezone != "UTC" {
|
||||
t.Fatalf("Timezone = %q, want UTC", req.Config.WeatherAPI.Timezone)
|
||||
}
|
||||
if req.OutputPath != "./daily.md" {
|
||||
t.Fatalf("OutputPath = %q, want ./daily.md", req.OutputPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateStormRequiresStartAndEnd(t *testing.T) {
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runner.resolveGenerate([]string{"storm", "--start", "2026-05-29T18:00"})
|
||||
if err == nil {
|
||||
t.Fatal("resolveGenerate() error = nil, want missing end error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "requires --end") {
|
||||
t.Fatalf("error = %q, want missing end", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGenerateStormParsesRFC3339(t *testing.T) {
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
req, err := runner.resolveGenerate([]string{
|
||||
"storm",
|
||||
"--start", "2026-05-29T18:00:00-05:00",
|
||||
"--end", "2026-05-30T06:00:00-05:00",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("resolveGenerate() error = %v", err)
|
||||
}
|
||||
if !req.StormEnd.After(req.StormStart) {
|
||||
t.Fatalf("StormEnd = %s, want after %s", req.StormEnd, req.StormStart)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveRunCommands(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
want app.BatchKind
|
||||
}{
|
||||
{name: "morning", args: []string{"morning"}, want: app.BatchMorning},
|
||||
{name: "evening", args: []string{"evening", "--tz", "UTC"}, want: app.BatchEvening},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, err := resolveRun(tt.args)
|
||||
if err != nil {
|
||||
t.Fatalf("resolveRun() error = %v", err)
|
||||
}
|
||||
if req.Batch != tt.want {
|
||||
t.Fatalf("Batch = %q, want %q", req.Batch, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveRunRejectsOutputFlag(t *testing.T) {
|
||||
_, err := resolveRun([]string{"morning", "--out", "./report.md"})
|
||||
if err == nil {
|
||||
t.Fatal("resolveRun() error = nil, want flag error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "flag provided but not defined") {
|
||||
t.Fatalf("error = %q, want undefined flag error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func fixedClock() timeutil.Clock {
|
||||
return timeutil.FixedClock{Time: time.Date(2026, 5, 29, 12, 0, 0, 0, time.UTC)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user