;;; test-wttrin--add-buffer-instructions.el --- Tests for wttrin--add-buffer-instructions -*- lexical-binding: t; -*- ;; Copyright (C) 2024-2026 Craig Jennings ;;; Commentary: ;; Unit tests for wttrin--add-buffer-instructions function. ;; Tests adding user instructions to buffer content. ;;; Code: (require 'ert) (require 'wttrin) (require 'testutil-wttrin) ;;; Setup and Teardown (defun test-wttrin--expected-footer () "Return the footer string `wttrin--add-buffer-instructions' should produce. Width 23 is pinned here as a literal, independent of the production constant, so the test fails if the visible layout drifts." (concat "\n\n" (format "%-23s%s" "This view" "Saved locations") "\n" (format "%-23s%s" "[a] another" "[s] save") "\n" (format "%-23s%s" "[g] refresh" "[d] make default") "\n" (format "%-23s%s" "[q] quit" "[r] rename") "\n" (format "%-23s%s" "" "[x] remove"))) (defun test-wttrin--add-buffer-instructions-setup () "Setup for add-buffer-instructions tests." (testutil-wttrin-setup)) (defun test-wttrin--add-buffer-instructions-teardown () "Teardown for add-buffer-instructions tests." (testutil-wttrin-teardown)) ;;; Normal Cases (ert-deftest test-wttrin--add-buffer-instructions-normal-empty-buffer-adds-instructions () "Test adding instructions to empty buffer." (with-temp-buffer (wttrin--add-buffer-instructions) (should (string= (test-wttrin--expected-footer) (buffer-string))))) (ert-deftest test-wttrin--add-buffer-instructions-normal-with-existing-content-appends-instructions () "Test adding instructions to buffer with existing content." (with-temp-buffer (insert "Weather: Sunny\nTemperature: 20°C") (wttrin--add-buffer-instructions) (should (string= (concat "Weather: Sunny\nTemperature: 20°C" (test-wttrin--expected-footer)) (buffer-string))))) (ert-deftest test-wttrin--add-buffer-instructions-normal-preserves-point-moves-to-end () "Test that point is moved to end after adding instructions." (with-temp-buffer (insert "Some content") (goto-char (point-min)) (wttrin--add-buffer-instructions) (should (= (point) (point-max))))) (ert-deftest test-wttrin--add-buffer-instructions-normal-called-twice-adds-instructions-twice () "Test that calling function twice adds instructions twice (not idempotent)." (with-temp-buffer (insert "Weather") (wttrin--add-buffer-instructions) (let ((first-result (buffer-string))) (wttrin--add-buffer-instructions) ;; Should add instructions again, not check if they already exist (should-not (string= first-result (buffer-string))) ;; Check for two occurrences of the header by counting matches (let ((count 0)) (with-temp-buffer (insert first-result) (goto-char (point-min)) (while (search-forward "This view" nil t) (setq count (1+ count)))) ;; After first call, should have 1 occurrence (should (= 1 count))) ;; After second call, check for 2 occurrences (let ((count 0)) (save-excursion (goto-char (point-min)) (while (search-forward "This view" nil t) (setq count (1+ count)))) (should (= 2 count)))))) (ert-deftest test-wttrin--add-buffer-instructions-normal-key-chords-carry-key-face () "Bracketed key chords are styled with `wttrin-key'." (with-temp-buffer (wttrin--add-buffer-instructions) (goto-char (point-min)) (search-forward "[a]") ;; point is just after the closing bracket; the bracket char is part ;; of the "[a]" segment (should (eq (get-text-property (1- (point)) 'face) 'wttrin-key)))) (ert-deftest test-wttrin--add-buffer-instructions-normal-prose-carries-instructions-face () "The footer prose is styled with `wttrin-instructions'." (with-temp-buffer (wttrin--add-buffer-instructions) (goto-char (point-min)) (search-forward "another") (should (eq (get-text-property (1- (point)) 'face) 'wttrin-instructions)))) ;;; Boundary Cases (ert-deftest test-wttrin--add-buffer-instructions-boundary-point-at-beginning-appends-at-end () "Test adding instructions when point is at beginning of buffer." (with-temp-buffer (insert "Weather data here") (goto-char (point-min)) (wttrin--add-buffer-instructions) (should (string-suffix-p "[x] remove" (buffer-string))))) (ert-deftest test-wttrin--add-buffer-instructions-boundary-point-in-middle-appends-at-end () "Test adding instructions when point is in middle of buffer." (with-temp-buffer (insert "Line 1\nLine 2\nLine 3") (goto-char (point-min)) (forward-line 1) (wttrin--add-buffer-instructions) (should (string-suffix-p "[x] remove" (buffer-string))))) (ert-deftest test-wttrin--add-buffer-instructions-boundary-trailing-newlines-preserves-newlines () "Test adding instructions to buffer that already ends with newlines." (with-temp-buffer (insert "Weather\n\n\n") (wttrin--add-buffer-instructions) (should (string= (concat "Weather\n\n\n" (test-wttrin--expected-footer)) (buffer-string))))) (ert-deftest test-wttrin--add-buffer-instructions-boundary-very-large-buffer-appends-at-end () "Test adding instructions to large buffer." (with-temp-buffer (insert (make-string 10000 ?x)) (wttrin--add-buffer-instructions) (goto-char (point-max)) (should (looking-back "\\[x\\] remove" nil)))) ;;; Error Cases (ert-deftest test-wttrin--add-buffer-instructions-error-read-only-buffer-signals-error () "Test that function signals error when buffer is read-only." (with-temp-buffer (insert "Some content") (read-only-mode 1) (should-error (wttrin--add-buffer-instructions) :type 'buffer-read-only))) (ert-deftest test-wttrin--add-buffer-instructions-error-narrowed-buffer-adds-at-narrowed-end () "Test adding instructions to narrowed buffer adds at narrowed end." (with-temp-buffer (insert "Line 1\nLine 2\nLine 3\nLine 4") (goto-char (point-min)) (forward-line 1) (let ((start (point))) (forward-line 1) (narrow-to-region start (point)) (wttrin--add-buffer-instructions) ;; Instructions should be added at end of narrowed region (widen) (goto-char start) (forward-line 1) (should (looking-at-p "\n\nThis view"))))) (provide 'test-wttrin--add-buffer-instructions) ;;; test-wttrin--add-buffer-instructions.el ends here