From ea5636c51361b86d132d647ee3548d208394878e Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 4 Apr 2026 12:26:16 -0500 Subject: test: add 50 tests for untested functions; fix nil crash in save-debug-data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 11 new test files covering wttrin--save-debug-data, wttrin--buffer-cache-refresh, wttrin--mode-line-stop, wttrin--mode-line-start, wttrin-query, wttrin-requery-force, wttrin-mode-line-click, wttrin-mode-line-force-refresh, wttrin-fetch-raw-string, wttrin-clear-cache, and wttrin-requery. Fix bug in wttrin--save-debug-data where nil raw-string caused (insert nil) crash — reachable when debug mode is on and fetch fails. Refactor wttrin-requery: extract wttrin--requery-location so the core kill-buffer-and-query logic is testable without mocking completing-read. 267 tests total (was 217), all passing. --- tests/test-wttrin--mode-line-start.el | 157 ++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 tests/test-wttrin--mode-line-start.el (limited to 'tests/test-wttrin--mode-line-start.el') diff --git a/tests/test-wttrin--mode-line-start.el b/tests/test-wttrin--mode-line-start.el new file mode 100644 index 0000000..e97c185 --- /dev/null +++ b/tests/test-wttrin--mode-line-start.el @@ -0,0 +1,157 @@ +;;; test-wttrin--mode-line-start.el --- Tests for wttrin--mode-line-start -*- lexical-binding: t; -*- + +;; Copyright (C) 2025 Craig Jennings + +;;; Commentary: + +;; Unit tests for wttrin--mode-line-start function. +;; Tests that starting mode-line display sets up placeholder, timers, and scheduling. + +;;; Code: + +(require 'ert) +(require 'wttrin) +(require 'testutil-wttrin) + +;;; Setup and Teardown + +(defun test-wttrin--mode-line-start-setup () + "Setup for mode-line-start tests." + (testutil-wttrin-setup) + (setq wttrin-mode-line-string nil) + (setq wttrin--mode-line-cache nil) + (setq wttrin--mode-line-timer nil) + (setq wttrin--buffer-refresh-timer nil)) + +(defun test-wttrin--mode-line-start-teardown () + "Teardown for mode-line-start tests." + (testutil-wttrin-teardown) + (when (timerp wttrin--mode-line-timer) + (cancel-timer wttrin--mode-line-timer)) + (when (timerp wttrin--buffer-refresh-timer) + (cancel-timer wttrin--buffer-refresh-timer)) + (setq wttrin-mode-line-string nil) + (setq wttrin--mode-line-cache nil) + (setq wttrin--mode-line-timer nil) + (setq wttrin--buffer-refresh-timer nil)) + +;;; Normal Cases + +(ert-deftest test-wttrin--mode-line-start-normal-shows-placeholder-immediately () + "Starting mode-line should show the hourglass placeholder right away." + (test-wttrin--mode-line-start-setup) + (unwind-protect + (let ((wttrin-favorite-location "Paris") + (wttrin-mode-line-emoji-font nil)) + ;; Mock run-at-time so no real timers fire + (cl-letf (((symbol-function 'run-at-time) + (lambda (_time _repeat _func) (list 'mock-timer)))) + (wttrin--mode-line-start) + ;; Placeholder should be visible + (should wttrin-mode-line-string) + (should (string-match-p "⏳" (substring-no-properties wttrin-mode-line-string))))) + (test-wttrin--mode-line-start-teardown))) + +(ert-deftest test-wttrin--mode-line-start-normal-schedules-delayed-initial-fetch () + "Initial weather fetch should be scheduled after startup-delay seconds." + (test-wttrin--mode-line-start-setup) + (unwind-protect + (let ((wttrin-favorite-location "Paris") + (wttrin-mode-line-startup-delay 5) + (scheduled-calls nil)) + (cl-letf (((symbol-function 'run-at-time) + (lambda (time repeat func) + (push (list :time time :repeat repeat :func func) scheduled-calls) + (list 'mock-timer)))) + (wttrin--mode-line-start) + ;; One of the calls should be the delayed initial fetch + (let ((initial-fetch (seq-find (lambda (call) + (and (= (plist-get call :time) 5) + (null (plist-get call :repeat)))) + scheduled-calls))) + (should initial-fetch) + (should (eq (plist-get initial-fetch :func) + #'wttrin--mode-line-fetch-weather))))) + (test-wttrin--mode-line-start-teardown))) + +(ert-deftest test-wttrin--mode-line-start-normal-creates-repeating-mode-line-timer () + "A repeating timer should be created for periodic mode-line refresh." + (test-wttrin--mode-line-start-setup) + (unwind-protect + (let ((wttrin-favorite-location "Paris") + (wttrin-mode-line-refresh-interval 3600) + (scheduled-calls nil)) + (cl-letf (((symbol-function 'run-at-time) + (lambda (time repeat func) + (push (list :time time :repeat repeat :func func) scheduled-calls) + (list 'mock-timer)))) + (wttrin--mode-line-start) + ;; Should have a repeating timer for mode-line fetch + (let ((repeating-fetch (seq-find (lambda (call) + (and (equal (plist-get call :repeat) 3600) + (eq (plist-get call :func) + #'wttrin--mode-line-fetch-weather))) + scheduled-calls))) + (should repeating-fetch)))) + (test-wttrin--mode-line-start-teardown))) + +(ert-deftest test-wttrin--mode-line-start-normal-creates-buffer-refresh-timer () + "A repeating timer should be created for periodic buffer cache refresh." + (test-wttrin--mode-line-start-setup) + (unwind-protect + (let ((wttrin-favorite-location "Paris") + (wttrin-refresh-interval 3600) + (scheduled-calls nil)) + (cl-letf (((symbol-function 'run-at-time) + (lambda (time repeat func) + (push (list :time time :repeat repeat :func func) scheduled-calls) + (list 'mock-timer)))) + (wttrin--mode-line-start) + ;; Should have a repeating timer for buffer cache refresh + (let ((buffer-refresh (seq-find (lambda (call) + (and (equal (plist-get call :repeat) 3600) + (eq (plist-get call :func) + #'wttrin--buffer-cache-refresh))) + scheduled-calls))) + (should buffer-refresh)))) + (test-wttrin--mode-line-start-teardown))) + +;;; Boundary Cases + +(ert-deftest test-wttrin--mode-line-start-boundary-nil-location-skips-setup () + "When no favorite location is set, no timers or placeholder should be created." + (test-wttrin--mode-line-start-setup) + (unwind-protect + (let ((wttrin-favorite-location nil) + (run-at-time-called nil)) + (cl-letf (((symbol-function 'run-at-time) + (lambda (_time _repeat _func) + (setq run-at-time-called t) + (list 'mock-timer)))) + (wttrin--mode-line-start) + (should-not run-at-time-called) + (should-not wttrin-mode-line-string) + (should-not wttrin--mode-line-timer))) + (test-wttrin--mode-line-start-teardown))) + +(ert-deftest test-wttrin--mode-line-start-boundary-cancels-existing-timers () + "Starting when timers already exist should cancel old timers before creating new ones." + (test-wttrin--mode-line-start-setup) + (unwind-protect + (let ((wttrin-favorite-location "Paris") + (cancelled-timers nil)) + ;; Create fake existing timers + (setq wttrin--mode-line-timer (run-at-time 99999 nil #'ignore)) + (setq wttrin--buffer-refresh-timer (run-at-time 99999 nil #'ignore)) + (let ((old-ml-timer wttrin--mode-line-timer) + (old-buf-timer wttrin--buffer-refresh-timer)) + (cl-letf (((symbol-function 'run-at-time) + (lambda (_time _repeat _func) (list 'mock-timer)))) + (wttrin--mode-line-start) + ;; Old timers should have been replaced + (should-not (eq wttrin--mode-line-timer old-ml-timer)) + (should-not (eq wttrin--buffer-refresh-timer old-buf-timer))))) + (test-wttrin--mode-line-start-teardown))) + +(provide 'test-wttrin--mode-line-start) +;;; test-wttrin--mode-line-start.el ends here -- cgit v1.2.3