summaryrefslogtreecommitdiff
path: root/tests/test-wttrin-mode-initialization-order.el
blob: 20adf06ca8e1bd4e9832e00db3be789eea0a4e09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
;;; test-wttrin-mode-initialization-order.el --- Test mode initialization order -*- lexical-binding: t; -*-

;; Copyright (C) 2025 Craig Jennings

;;; Commentary:

;; This test verifies that wttrin--display-weather initializes wttrin-mode
;; BEFORE setting buffer-local variables. This prevents kill-all-local-variables
;; (called by derived modes) from wiping out important state like xterm-color--state.
;;
;; Bug context: On fresh Emacs launch, weather displayed with no colors because
;; xterm-color--state was set buffer-local BEFORE wttrin-mode was called, and
;; wttrin-mode's kill-all-local-variables wiped it out.

;;; Code:

(require 'ert)
(require 'wttrin)
(require 'testutil-wttrin)

(defun test-wttrin-mode-init-setup ()
  "Setup for mode initialization tests."
  (testutil-wttrin-setup)
  (when (get-buffer "*wttr.in*")
    (kill-buffer "*wttr.in*")))

(defun test-wttrin-mode-init-teardown ()
  "Teardown for mode initialization tests."
  (testutil-wttrin-teardown)
  (when (get-buffer "*wttr.in*")
    (kill-buffer "*wttr.in*")))

(ert-deftest test-wttrin-mode-initialization-order-mode-before-buffer-local-vars ()
  "Test that wttrin-mode is activated before setting buffer-local variables.

This test verifies the fix for the color rendering bug where xterm-color--state
was wiped by kill-all-local-variables.

The test strategy:
1. Advise wttrin-mode to record when it's called
2. Advise setq-local to record when buffer-local vars are set
3. Call wttrin--display-weather
4. Verify wttrin-mode was called BEFORE any buffer-local vars were set"
  (test-wttrin-mode-init-setup)
  (unwind-protect
      (let ((mode-called-at nil)
            (first-setq-local-at nil)
            (call-counter 0))

        ;; Advise to track when wttrin-mode is called
        (cl-letf (((symbol-function 'wttrin-mode)
                   (let ((orig-fn (symbol-function 'wttrin-mode)))
                     (lambda ()
                       (setq mode-called-at (cl-incf call-counter))
                       (funcall orig-fn))))

                  ;; Advise to track first buffer-local variable set
                  ((symbol-function 'set)
                   (let ((orig-fn (symbol-function 'set)))
                     (lambda (symbol value)
                       ;; Track xterm-color--state specifically
                       (when (and (eq symbol 'xterm-color--state)
                                  (null first-setq-local-at))
                         (setq first-setq-local-at (cl-incf call-counter)))
                       (funcall orig-fn symbol value)))))

          (wttrin--display-weather "Paris" "Test weather data")

          ;; Verify mode was called
          (should mode-called-at)
          ;; Verify buffer-local var was set
          (should first-setq-local-at)
          ;; Critical: mode must be called BEFORE buffer-local var
          (should (< mode-called-at first-setq-local-at))))

    (test-wttrin-mode-init-teardown)))

(ert-deftest test-wttrin-mode-initialization-order-xterm-color-state-survives ()
  "Test that xterm-color--state remains buffer-local after wttrin--display-weather.

This verifies that the state isn't wiped by kill-all-local-variables."
  (test-wttrin-mode-init-setup)
  (unwind-protect
      (progn
        (wttrin--display-weather "London" "Test data")

        (should (get-buffer "*wttr.in*"))

        (with-current-buffer "*wttr.in*"
          ;; xterm-color--state should be buffer-local
          (should (local-variable-p 'xterm-color--state))
          ;; It should have the correct value
          (should (eq xterm-color--state :char))))

    (test-wttrin-mode-init-teardown)))

(provide 'test-wttrin-mode-initialization-order)
;;; test-wttrin-mode-initialization-order.el ends here