package main import ( "os" "path/filepath" "strings" "testing" "time" ) var when = time.Date(2026, 8, 27, 12, 0, 0, 0, time.UTC) // A directory gets a generated name: writing into ~/photos/weather is more // useful than refusing, and two days do not overwrite each other. func TestResolveOutIntoADirectory(t *testing.T) { dir := t.TempDir() got, err := resolveOut(dir, "Krakow, PL", when, "svg") if err != nil { t.Fatal(err) } want := filepath.Join(dir, "krakow-pl-2026-08-27.svg") if got != want { t.Fatalf("got %q, want %q", got, want) } // A different day must not collide with the first. other, _ := resolveOut(dir, "Krakow, PL", when.AddDate(0, 0, 1), "svg") if other == got { t.Error("two days produced the same filename") } } func TestResolveOutCreatesATrailingSlashDirectory(t *testing.T) { dir := filepath.Join(t.TempDir(), "photos", "weather") + string(os.PathSeparator) got, err := resolveOut(dir, "Krakow, PL", when, "svg") if err != nil { t.Fatal(err) } if fi, err := os.Stat(filepath.Dir(got)); err != nil || !fi.IsDir() { t.Fatalf("directory was not created: %v", err) } } // "-o weather" should not produce an extensionless file no viewer will open. func TestResolveOutAddsTheExtensionToABareName(t *testing.T) { base := filepath.Join(t.TempDir(), "weather") got, err := resolveOut(base, "Krakow, PL", when, "svg") if err != nil { t.Fatal(err) } if !strings.HasSuffix(got, ".svg") { t.Fatalf("got %q, want a .svg suffix", got) } } // An explicit extension is respected, whatever the format's default. func TestResolveOutKeepsAnExplicitExtension(t *testing.T) { base := filepath.Join(t.TempDir(), "chart.png") got, _ := resolveOut(base, "Krakow, PL", when, "svg") if got != base { t.Fatalf("got %q, want %q unchanged", got, base) } } func TestSlug(t *testing.T) { for in, want := range map[string]string{ "Krakow, PL": "krakow-pl", "Tarnów, PL": "tarnow-pl", "Zbylitowska Góra": "zbylitowska-gora", "Gdańsk": "gdansk", "Łódź": "lodz", " spaced out ": "spaced-out", "50.0617,19.9373": "50-0617-19-9373", "!!!": "", } { if got := slug(in); got != want { t.Errorf("slug(%q) = %q, want %q", in, got, want) } } } // A slug must never contain a path separator, or -o would write outside the // directory it was given. func TestSlugCannotEscapeADirectory(t *testing.T) { for _, nasty := range []string{"../../etc/passwd", "a/b", `c\d`} { got := slug(nasty) if strings.ContainsAny(got, `/\`) || strings.Contains(got, "..") { t.Errorf("slug(%q) = %q, which can escape the directory", nasty, got) } } }