diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-13 13:04:10 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-13 13:04:10 +0200 |
| commit | e14a7db4ffe3c4e0f15f6b37a980501a8d74d26b (patch) | |
| tree | 670ef0897839871a64d3a3bb2e17e242e7d6c385 /internal/i18n/i18n_test.go | |
| download | prognosis-e14a7db4ffe3c4e0f15f6b37a980501a8d74d26b.tar.gz prognosis-e14a7db4ffe3c4e0f15f6b37a980501a8d74d26b.zip | |
Initial commit: prognosis, the Go implementation
An hour-by-hour forecast for the terminal, with official IMGW warnings for
Polish locations. Replaces the Python version, whose cache file format it
keeps so the two can coexist until this reaches parity.
Open-Meteo provides the forecast, geocoding and pollen; GUGiK turns
coordinates into a TERYT powiat code; IMGW supplies the warnings, filtered
to that powiat rather than the whole country. Only the two lookups that
never change are cached. Forecasts never are.
Silence is never allowed to read as all-clear: "no warnings in force" and
"the check failed" are reported as distinct states.
Place names are resolved without guessing. A name matching several places
is refused with a numbered list carrying each candidate's region and
coordinates, and -pick N chooses one and remembers it. A stray positional
beside -l is an error, so an unquoted "Wiry, PL" cannot silently resolve to
somewhere else.
The cache is written one entry per line with sorted keys, and treated as
disposable but not worthless: an entry that will not parse is skipped and
the rest kept, and a file that will not parse at all is moved to
cache.json.bad rather than overwritten.
No third-party dependencies. `make ci` is the gate: gofmt clean, vet, tests.
Diffstat (limited to 'internal/i18n/i18n_test.go')
| -rw-r--r-- | internal/i18n/i18n_test.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/internal/i18n/i18n_test.go b/internal/i18n/i18n_test.go new file mode 100644 index 0000000..2a6a617 --- /dev/null +++ b/internal/i18n/i18n_test.go @@ -0,0 +1,88 @@ +package i18n + +import ( + "testing" + "time" + + "github.com/lukaszkasprzak/prognosis/internal/config" +) + +func TestForFallsBackToEnglish(t *testing.T) { + if For("klingon").Lang() != EN { + t.Fatal("an unknown language must degrade to English, not to empty strings") + } + if For("pl").Lang() != PL { + t.Fatal("pl must resolve to the Polish catalogue") + } +} + +// Every catalogue must cover every column, or a table in that language would +// silently fall back to the internal column name. +func TestEveryLanguageCoversEveryColumn(t *testing.T) { + for _, lang := range []Lang{EN, PL} { + c := For(string(lang)) + for _, col := range config.ValidColumns() { + if _, ok := c.headers[col]; !ok { + t.Errorf("%s: no header for column %q", lang, col) + } + } + } +} + +// The WMO codes must match across languages: a code described in English but +// not Polish would print "code 71" to a Polish reader. +func TestConditionCoverageMatchesAcrossLanguages(t *testing.T) { + en, pl := For("en"), For("pl") + for code := range en.conditions { + if _, ok := pl.conditions[code]; !ok { + t.Errorf("code %d described in English but not Polish", code) + } + } + for code := range pl.conditions { + if _, ok := en.conditions[code]; !ok { + t.Errorf("code %d described in Polish but not English", code) + } + } +} + +func TestWordAndSpeciesCoverageMatches(t *testing.T) { + en, pl := For("en"), For("pl") + for k := range en.words { + if _, ok := pl.words[k]; !ok { + t.Errorf("word %q missing from Polish", k) + } + } + for _, s := range config.AllSpecies { + if _, ok := en.species[s]; !ok { + t.Errorf("species %q missing from English", s) + } + if _, ok := pl.species[s]; !ok { + t.Errorf("species %q missing from Polish", s) + } + } + for _, b := range []string{"none", "low", "medium", "high", "very high"} { + if en.Band(b) == b && b != "none" && b != "low" && b != "medium" && b != "high" && b != "very high" { + t.Errorf("band %q missing from English", b) + } + if pl.Band(b) == b { + t.Errorf("band %q not translated to Polish", b) + } + } +} + +func TestUnknownCodeIsVisible(t *testing.T) { + got := For("en").Condition(4242) + if got != "code 4242" { + t.Fatalf("unknown codes must be visible, got %q", got) + } +} + +func TestDate(t *testing.T) { + d := time.Date(2026, 8, 10, 13, 0, 0, 0, time.UTC) // a Monday + if got, want := For("en").Date(d), "Mon 10 Aug"; got != want { + t.Errorf("en date = %q, want %q", got, want) + } + if got, want := For("pl").Date(d), "pn 10 sie"; got != want { + t.Errorf("pl date = %q, want %q", got, want) + } +} |
