diff options
| author | Craig Jennings <c@cjennings.net> | 2025-11-04 09:09:28 -0600 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-11-04 09:09:28 -0600 |
| commit | d05a8c84310ad3122c1a38f113bd93bca3f7f58a (patch) | |
| tree | 2e4074845979729e8e370f998b8c5dea6e2cb5d4 /tests | |
| parent | 520203cfb54091dae7647a51a5910bb094fd1c4f (diff) | |
feat(emacs): Add asynchronous weather fetching to wttrin
Introduce asynchronous data fetching to the wttrin.el Emacs package.
This enhancement avoids blocking Emacs during data retrieval by
using `url-retrieve` for async calls. The behavior is controlled via
a new customizable variable `wttrin-use-async`. Tests have been
added for the new async behavior to ensure proper functionality.feat:makefile): Add package initialization for Emacs batch
Enhance Makefile with package support by loading and initializing
MELPA archive before validating and compiling, ensuring required
packages are available during these operations.
feat(tests): Add unit tests for `wttrin--display-weather`
Introduce comprehensive tests for `wttrin--display-weather` function
to validate buffer creation, content, keybindings, and error
handling.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test-wttrin--display-weather.el | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/tests/test-wttrin--display-weather.el b/tests/test-wttrin--display-weather.el new file mode 100644 index 0000000..364908f --- /dev/null +++ b/tests/test-wttrin--display-weather.el @@ -0,0 +1,213 @@ +;;; test-wttrin--display-weather.el --- Tests for wttrin--display-weather -*- lexical-binding: t; -*- + +;; Copyright (C) 2025 Craig Jennings + +;;; Commentary: + +;; Unit tests for wttrin--display-weather function. +;; Tests the extracted display logic that formats and shows weather data. + +;;; Code: + +(require 'ert) +(require 'wttrin) +(require 'testutil-wttrin) + +;;; Test Data Fixtures + +(defconst test-wttrin--display-weather-sample-raw-data + " +Weather report: Paris, France + + ┌─────────────┐ + ┌──────────────────────────┐ + ┌──────────────────────────────┬───────────────────────────────────────────┴───────────────────────────────────────┐ + │ Monday └──────────────────────────────────────────────────────────────────────────────────────┤ + │ 2025-11-04 08:00:00 CST + │ + │ Coordinates: 48.8566, 2.3522 + │ + \\ / Partly cloudy + _ /\".-. 22 °C + \\_( ). ↓ 15 km/h + /(___(__) 10 km + 0.0 mm" + "Sample raw weather data with realistic wttr.in structure for testing.") + +;;; Test Setup and Teardown + +(defun test-wttrin--display-weather-setup () + "Setup for display weather tests." + (testutil-wttrin-setup) + ;; Kill any existing weather buffer + (when (get-buffer "*wttr.in*") + (kill-buffer "*wttr.in*"))) + +(defun test-wttrin--display-weather-teardown () + "Teardown for display weather tests." + (testutil-wttrin-teardown) + ;; Clean up weather buffer + (when (get-buffer "*wttr.in*") + (kill-buffer "*wttr.in*"))) + +;;; Normal Cases + +(ert-deftest test-wttrin--display-weather-normal-valid-data-creates-buffer () + "Test that valid weather data creates and displays buffer correctly." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (wttrin--display-weather "Paris, France" test-wttrin--display-weather-sample-raw-data) + + ;; Buffer should exist + (should (get-buffer "*wttr.in*")) + + ;; Buffer should be displayed + (should (get-buffer-window "*wttr.in*")) + + ;; Buffer should have content + (with-current-buffer "*wttr.in*" + (should (> (buffer-size) 0)) + + ;; Buffer should be read-only + (should buffer-read-only) + + ;; Location should be set + (should (equal wttrin--current-location "Paris, France")))) + (test-wttrin--display-weather-teardown))) + +(ert-deftest test-wttrin--display-weather-normal-valid-data-sets-keybindings () + "Test that keybindings are properly set up in weather buffer." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (wttrin--display-weather "London" test-wttrin--display-weather-sample-raw-data) + + (with-current-buffer "*wttr.in*" + ;; Check that keybindings are set (they should be in the local map) + (should (keymapp (current-local-map))) + (should (commandp (lookup-key (current-local-map) "q"))) + (should (commandp (lookup-key (current-local-map) "r"))) + (should (commandp (lookup-key (current-local-map) "g"))))) + (test-wttrin--display-weather-teardown))) + +(ert-deftest test-wttrin--display-weather-normal-valid-data-contains-instructions () + "Test that help instructions are displayed at bottom of buffer." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (wttrin--display-weather "Tokyo" test-wttrin--display-weather-sample-raw-data) + + (with-current-buffer "*wttr.in*" + (goto-char (point-max)) + (forward-line -2) + ;; Should contain help text + (should (search-forward "Press:" nil t)) + (should (search-forward "[g] to query another location" nil t)) + (should (search-forward "[r] to refresh" nil t)) + (should (search-forward "[q] to quit" nil t)))) + (test-wttrin--display-weather-teardown))) + +;;; Boundary Cases + +(ert-deftest test-wttrin--display-weather-boundary-empty-location-name-creates-buffer () + "Test that empty location name still creates buffer." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (wttrin--display-weather "" test-wttrin--display-weather-sample-raw-data) + + ;; Buffer should still be created + (should (get-buffer "*wttr.in*")) + + (with-current-buffer "*wttr.in*" + ;; Location should be set to empty string + (should (equal wttrin--current-location "")))) + (test-wttrin--display-weather-teardown))) + +(ert-deftest test-wttrin--display-weather-boundary-location-with-special-chars-creates-buffer () + "Test that location with special characters creates buffer." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (wttrin--display-weather "São Paulo, BR 🌆" test-wttrin--display-weather-sample-raw-data) + + (should (get-buffer "*wttr.in*")) + + (with-current-buffer "*wttr.in*" + ;; Location with Unicode should be preserved + (should (equal wttrin--current-location "São Paulo, BR 🌆")))) + (test-wttrin--display-weather-teardown))) + +(ert-deftest test-wttrin--display-weather-boundary-empty-string-creates-buffer () + "Test that empty weather string creates buffer without error. +Empty string does not match ERROR pattern, so it's processed as data." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (wttrin--display-weather "Paris" "") + + ;; Empty string is not treated as error, buffer is created + (should (get-buffer "*wttr.in*")) + + (with-current-buffer "*wttr.in*" + ;; Buffer exists but will have minimal/broken content + ;; Just verify it was created and made read-only + (should buffer-read-only))) + (test-wttrin--display-weather-teardown))) + +;;; Error Cases + +(ert-deftest test-wttrin--display-weather-error-nil-raw-string-shows-message () + "Test that nil raw-string displays error message." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + ;; Capture message output + (let ((message-log-max t) + (message-displayed nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (setq message-displayed (apply #'format format-string args))))) + (wttrin--display-weather "InvalidCity" nil) + + ;; Should display error message + (should message-displayed) + (should (string-match-p "Cannot retrieve" message-displayed))))) + (test-wttrin--display-weather-teardown))) + +(ert-deftest test-wttrin--display-weather-error-string-with-error-shows-message () + "Test that weather string containing ERROR shows error message." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + (let ((message-log-max t) + (message-displayed nil)) + (cl-letf (((symbol-function 'message) + (lambda (format-string &rest args) + (setq message-displayed (apply #'format format-string args))))) + (wttrin--display-weather "BadLocation" testutil-wttrin-sample-error-response) + + ;; Should display error message + (should message-displayed) + (should (string-match-p "Cannot retrieve" message-displayed))))) + (test-wttrin--display-weather-teardown))) + +(ert-deftest test-wttrin--display-weather-error-nil-raw-string-no-buffer-created () + "Test that nil raw-string does not create weather buffer." + (test-wttrin--display-weather-setup) + (unwind-protect + (progn + ;; Suppress message output + (cl-letf (((symbol-function 'message) (lambda (&rest _) nil))) + (wttrin--display-weather "InvalidCity" nil) + + ;; Buffer should not be created for error case + ;; (or if it exists from before, it shouldn't be switched to) + ;; This is testing the error path doesn't create/switch to buffer + (should-not (string-match-p "wttr.in" + (buffer-name (current-buffer)))))) + (test-wttrin--display-weather-teardown))) + +(provide 'test-wttrin--display-weather) +;;; test-wttrin--display-weather.el ends here |
