<feed xmlns='http://www.w3.org/2005/Atom'>
<title>emacs-wttrin/tests, branch main</title>
<subtitle>Emacs frontend for Igor Chubin's wttr.in weather service
</subtitle>
<id>https://git.cjennings.net/emacs-wttrin/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/emacs-wttrin/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/'/>
<updated>2026-05-05T15:06:20+00:00</updated>
<entry>
<title>feat: support t for auto-detect via geolocation in wttrin-favorite-location</title>
<updated>2026-05-05T15:06:20+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-05T15:06:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=541586e3ff0606afcf0581210a62c95f5ee65c71'/>
<id>urn:sha1:541586e3ff0606afcf0581210a62c95f5ee65c71</id>
<content type='text'>
Completes the three-mode configuration the favorite-location feature was always meant to have:

- nil      — disabled (default; unchanged)
- a string — explicit location (unchanged)
- t        — auto-detect via IP geolocation (NEW)

When the user sets `wttrin-favorite-location` to t, wttrin runs the geolocation lookup once on first use and caches the result for the session. Subsequent reads return the cached string. The lookup happens in the background via the existing `wttrin-geolocation-detect`, so Emacs startup is never blocked.

I added two private state vars (`wttrin--resolved-favorite-location`, `wttrin--favorite-location-pending`) and a resolver `wttrin--resolve-favorite-location` that maps the three modes onto a returned string or nil. When t is set and the cache is empty, the resolver kicks off the lookup and returns nil for that call — the next consumer tick after the callback completes gets the cached string. The pending flag prevents duplicate concurrent lookups when several consumers ask during the resolution window.

Five consumer call sites now go through the resolver instead of reading `wttrin-favorite-location` directly: `wttrin--mode-line-fetch-weather`, `wttrin-mode-line-click`, `wttrin-mode-line-force-refresh`, `wttrin--buffer-cache-refresh`, and `wttrin--mode-line-start`. Two display sites (the placeholder and error tooltips) use a new `wttrin--favorite-location-display-name` helper that returns "current location" while a t-mode lookup is pending, instead of showing the literal `t` to the user.

Tests cover the resolver across all three modes, including the pending state, the duplicate-suppression behavior, and detection-failure retry. Existing consumer tests stay green because the resolver returns the bound string unchanged when the variable is a string. One care: the test file requires wttrin-geolocation up front so cl-letf mocks of `wttrin-geolocation-detect` aren't undone by the resolver's lazy require — without that, the first run hit ipapi.co for real.

README documents the new mode under "Setting the Favorite Location from IP Geolocation".
</content>
</entry>
<entry>
<title>feat: add wttrin-display-options for wttr.in flag customization (closes #3)</title>
<updated>2026-05-05T14:48:13+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-05T14:48:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=ec00dbe1c03527ec46a0faa20545a7acd382da84'/>
<id>urn:sha1:ec00dbe1c03527ec46a0faa20545a7acd382da84</id>
<content type='text'>
wttr.in accepts single-character flags appended to the URL that control what the report looks like — no Follow line (F), narrow output (n), quiet mode (q), forecast horizon (0/1/2), console-glyph mode (d), and so on. Until now wttrin always used the same default report shape with no way to opt into these.

Added a `wttrin-display-options` defcustom that takes a string of concatenated flags, e.g. "0Fq" for current weather only with no Follow line and no header. The flags get appended to every request via `wttrin--build-url`. The defcustom defaults to nil so existing users see no change.

I excluded `A` and `T` from the recommended set in the docstring since wttrin needs ANSI output for the xterm-color rendering to produce the colored glyphs. The user could still pass them, but the docstring nudges them away.

Tests cover the normal cases (single, multi-flag, with and without unit system), the boundaries (nil and empty string both leave the URL unchanged from baseline, single character works), and a sanity check that the new flags slot in after the always-on `A`. Existing build-url tests stay green because they don't bind the new variable, and the default is nil.

Also added `.claude/` to .gitignore — the scheduled-tasks lockfile from local wakeup scheduling shouldn't be tracked.
</content>
</entry>
<entry>
<title>fix(ci): rewrite mode-init-order test and retry deps install</title>
<updated>2026-05-05T14:37:12+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-05T14:37:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=b83865a65eb744f6d36c1c672a4d83a59d6383f8'/>
<id>urn:sha1:b83865a65eb744f6d36c1c672a4d83a59d6383f8</id>
<content type='text'>
Two CI failures from the first run, neither a real bug in production code.

The Emacs-snapshot job failed on
`test-wttrin-mode-initialization-order-normal-mode-before-buffer-local-vars-calls-mode-first`.
The original test mocked the `set' primitive to detect when
`xterm-color--state' was first set. That worked on the byte-code path some
older Emacs versions used, but `setq-local' doesn't go through the `set'
function on Emacs master, so the mock never fired and the assertion read nil.
The test was already brittle in isolation locally too.

Rewrote the test to use `advice-add :before' on `wttrin-mode' and
`make-local-variable'. Both are ordinary advisable functions, and
`make-local-variable' is on the code path for every form that defines a
buffer-local binding (`setq-local', `defvar-local', etc.) so the observation
holds across Emacs versions. Renamed the test to drop "calls-mode-first"
and use "mode-runs-before-xterm-color-state-binding" since that's what the
new advice actually observes.

The Emacs 26.3 job failed with a transient DNS error from elpa.gnu.org
during `make deps'. Wrapped the install step in a 3-attempt retry with a
15-second backoff so a runner-side network blip doesn't fail the build.
Applied to all three jobs (test, lint, coverage) since they all hit the
same archives.
</content>
</entry>
<entry>
<title>refactor: rename debug-wttrin-* commands to wttrin-debug-* with obsolete aliases</title>
<updated>2026-05-05T10:20:44+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-05T10:20:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=35131cb72c08c657d2a3389338d0c049d57e69bd'/>
<id>urn:sha1:35131cb72c08c657d2a3389338d0c049d57e69bd</id>
<content type='text'>
The four interactive commands in `wttrin-debug.el` used `debug-wttrin-` as their prefix instead of the package's `wttrin-debug-` prefix. package-lint flags this as a convention violation, and it makes M-x discovery slightly less consistent for users.

Renamed:
- `debug-wttrin-show-raw`   -&gt; `wttrin-debug-show-raw`
- `debug-wttrin-enable`     -&gt; `wttrin-debug-enable`
- `debug-wttrin-disable`    -&gt; `wttrin-debug-disable`
- `debug-wttrin-mode-line`  -&gt; `wttrin-debug-mode-line`

The old names stay available as `define-obsolete-function-alias` entries marked since 0.4.0, so anyone with a keybinding or `(call-interactively 'debug-wttrin-enable)` in their config keeps working. The byte-compiler will emit an obsolescence warning to nudge migration. Aliases will be removed in a future release.

Internal caller `wttrin--debug-mode-line-info` now invokes the new name. Test files renamed to match (`test-debug-wttrin-*.el` -&gt; `test-wttrin-debug-*.el`); inside each, ert-deftest names and function calls were updated.

Added `tests/test-wttrin-debug-aliases.el` to verify each old name resolves via `indirect-function` to the new name and carries `byte-obsolete-info` with the expected target and "0.4.0" version.
</content>
</entry>
<entry>
<title>test: cover wttrin-debug.el and expand lint to all source files</title>
<updated>2026-05-05T10:11:55+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-05T10:11:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=ba22e0cc3c81d85b3ee8aaa337d6a388627c3af2'/>
<id>urn:sha1:ba22e0cc3c81d85b3ee8aaa337d6a388627c3af2</id>
<content type='text'>
I added 24 unit tests across six new files for wttrin-debug.el. They cover enable/disable, the debug-log writer, clear-log, show-log, and the mode-line diagnostic dump. That lifts wttrin-debug.el coverage from 27% to 95%, and overall coverage from 84% to 94%. Each function gets Normal / Boundary / Error categories where applicable. Globals like `wttrin-debug` and `wttrin--debug-log` are isolated per test with let-bindings. The dynamic-scope rebinding restores state cleanly at exit.

I expanded the `lint` target to run on all three source files instead of just `wttrin.el`. Checkdoc and elisp-lint run on every file. Package-lint stays scoped to `wttrin.el` because the others aren't standalone packages.

The tricky bit: `elisp-lint-file` re-runs package-lint internally as one of its validators. So the explicit guard alone wasn't enough. The fix binds `elisp-lint-ignored-validators` to include "package-lint" for the secondaries, which suppresses the re-run at the validator level.

I also added `*-autoloads.el` to .gitignore. Eask generates `emacs-wttrin-autoloads.el` during install, and it shouldn't be tracked.

I skipped one function: `wttrin--debug-mode-line-info` is a one-line dispatcher to `debug-wttrin-mode-line`. Testing it would assert the dispatch happened, which only tests Emacs.
</content>
</entry>
<entry>
<title>build: switch Makefile to eask, wire up undercover coverage</title>
<updated>2026-05-05T09:58:34+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-05T09:58:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=6554cb8000a8f471f7c9e050e284f3fc364d5dad'/>
<id>urn:sha1:6554cb8000a8f471f7c9e050e284f3fc364d5dad</id>
<content type='text'>
I wanted a coverage number, so I added an Eask file declaring the runtime dep (xterm-color) plus three dev deps (undercover, package-lint, elisp-lint). The Makefile now runs every test and lint recipe through `eask emacs`. That drops the hand-rolled `(require 'package)` + `add-to-list 'package-archives` boilerplate that was duplicated across six recipes.

I added a `make deps` target that runs `eask install-deps --dev`. I also added a `make coverage` target that loads `tests/run-coverage-file.el` before each unit-test file. Undercover instruments the three source files first, then the test loads pick up the instrumented copy. Per-file results merge into `.coverage/simplecov.json` in simplecov format.

I expanded `validate-parens` and `compile` to cover all three source files instead of just `wttrin.el`. Lint stays scoped to the main file for now.

Coverage right now is 84% overall: wttrin.el 92%, wttrin-geolocation.el 100%, wttrin-debug.el 27%. The debug module is low because only the integration test exercises it. The coverage loop runs unit tests only.
</content>
</entry>
<entry>
<title>test: cover wttrin-geolocation internal helpers</title>
<updated>2026-04-26T23:37:47+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-04-26T23:37:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=439effb54aa8631751a758cb65140800af7e6e63'/>
<id>urn:sha1:439effb54aa8631751a758cb65140800af7e6e63</id>
<content type='text'>
Four pure helpers in wttrin-geolocation.el were exercised only indirectly through the parser tests: --decode-json, --format-city-region, --lookup-provider, and --extract-body. None of them had direct unit coverage. Edge cases like an empty JSON object, a missing-vs-empty city field, an unknown provider symbol, or a missing HTTP body separator weren't locked.

The new file groups all four functions together. Each gets Normal, Boundary, and Error cases per testing.md. Highlights:

- --decode-json: distinguishes nil input, empty string, and malformed JSON, all of which return nil for different reasons.
- --format-city-region: separates "missing key" from "empty string" since the predicate `(and (stringp city) (&gt; (length city) 0) ...)` short-circuits on either.
- --lookup-provider: tests two of the three built-ins plus a `let`-bound synthetic provider, locking the documented extension point on `wttrin-geolocation--providers`.
- --extract-body: real UTF-8 bytes inserted into a temp buffer (mirroring what `url-retrieve` delivers) verify the decoding path. 4xx, 5xx, and missing-separator paths each get their own test.

21 new tests, all green on first run since they characterize existing behavior.
</content>
</entry>
<entry>
<title>refactor: extract wttrin--mode-line-extract-emoji helper</title>
<updated>2026-04-26T23:32:02+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-04-26T23:32:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=38a6a0a745022ed7f0336f7deb121d75f589a916'/>
<id>urn:sha1:38a6a0a745022ed7f0336f7deb121d75f589a916</id>
<content type='text'>
The regex that pulls the emoji character out of a wttr.in mode-line response was inlined inside `wttrin--mode-line-update-display`, mixed in with the render logic. Six tests of the parser couldn't be written without invoking the whole render path.

The new pure helper takes the weather string, runs the regex, and returns either the first non-whitespace character after the colon or "?" as a placeholder. The format-explanation comment that used to sit above the inline code is gone now that the same explanation lives in the helper's docstring. There's no risk of comment and code drifting apart.

Six tests cover Normal (typical response, different emoji), Boundary (no whitespace after colon, multiple whitespace chars), and Error (no colon, empty string).
</content>
</entry>
<entry>
<title>refactor: extract wttrin--mode-line-stale-p helper</title>
<updated>2026-04-26T23:29:27+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-04-26T23:29:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=eabd510c302b43b0b40ee7b92bf5830d345d058d'/>
<id>urn:sha1:eabd510c302b43b0b40ee7b92bf5830d345d058d</id>
<content type='text'>
The staleness check `(&gt; age (* 2 wttrin-mode-line-refresh-interval))` lived in two places, `wttrin--mode-line-tooltip` and `wttrin--mode-line-update-display`, along with the four-line preamble that read the timestamp out of the cache cons and computed age. Centralizing the rule in a single helper means the threshold lives in one spot. That makes it easy to add a `wttrin-mode-line-staleness-threshold` defcustom later if the magic 2× ever needs to be tunable.

The helper takes a cache entry (or nil) and returns t/nil. Five new tests cover Normal (fresh, stale) and Boundary (just below the threshold, just past, nil entry). The boundary tests use 199s and 201s against a 100s refresh interval to lock the strict `&gt;` semantics with comfortable float-time margins.

In `wttrin--mode-line-update-display` the refactor also drops two locals (`timestamp` and `age`) that were no longer used after the helper call replaced the inline calculation. Behavior is unchanged at both call sites.
</content>
</entry>
<entry>
<title>test: regression lock for nil :foreground in --make-emoji-icon</title>
<updated>2026-04-26T22:59:59+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-04-26T22:59:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/emacs-wttrin/commit/?id=8f3c770e062a9aefec17f6b5f4f0a5ed927ac603'/>
<id>urn:sha1:8f3c770e062a9aefec17f6b5f4f0a5ed927ac603</id>
<content type='text'>
When wttrin-mode-line-emoji-font is set and the cache is fresh, --make-emoji-icon was emitting a face plist of the form (:family ... :height 1.0 :foreground nil). Emacs validates faces on every redisplay, so a single fresh-cache state produced hundreds of "Invalid face attribute :foreground nil" warnings in *Messages*.

The new boundary test asserts the face plist omits :foreground entirely when the caller passes nil. The assertion uses plist-member, not plist-get. plist-get returns nil for both a missing key and a present key bound to nil. That's the exact distinction Emacs's redisplay validator cares about.
</content>
</entry>
</feed>
