summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-wttrin--add-buffer-instructions.el129
-rw-r--r--tests/test-wttrin--process-weather-content.el96
-rw-r--r--tests/test-wttrin--validate-weather-data.el73
3 files changed, 298 insertions, 0 deletions
diff --git a/tests/test-wttrin--add-buffer-instructions.el b/tests/test-wttrin--add-buffer-instructions.el
new file mode 100644
index 0000000..d42d3a0
--- /dev/null
+++ b/tests/test-wttrin--add-buffer-instructions.el
@@ -0,0 +1,129 @@
+;;; test-wttrin--add-buffer-instructions.el --- Tests for wttrin--add-buffer-instructions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2024 Craig Jennings
+
+;;; Commentary:
+;; Unit tests for wttrin--add-buffer-instructions function.
+;; Tests adding user instructions to buffer content.
+
+;;; Code:
+
+(require 'ert)
+(require 'wttrin)
+
+;;; Normal Cases
+
+(ert-deftest test-wttrin--add-buffer-instructions-normal-empty-buffer ()
+ "Test adding instructions to empty buffer."
+ (with-temp-buffer
+ (wttrin--add-buffer-instructions)
+ (should (string= "\n\nPress: [a] for another location [g] to refresh [q] to quit"
+ (buffer-string)))))
+
+(ert-deftest test-wttrin--add-buffer-instructions-normal-with-existing-content ()
+ "Test adding instructions to buffer with existing content."
+ (with-temp-buffer
+ (insert "Weather: Sunny\nTemperature: 20°C")
+ (wttrin--add-buffer-instructions)
+ (should (string= "Weather: Sunny\nTemperature: 20°C\n\nPress: [a] for another location [g] to refresh [q] to quit"
+ (buffer-string)))))
+
+(ert-deftest test-wttrin--add-buffer-instructions-normal-preserves-point ()
+ "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-idempotent-check ()
+ "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 "Press:" by counting matches
+ (let ((count 0))
+ (with-temp-buffer
+ (insert first-result)
+ (goto-char (point-min))
+ (while (search-forward "Press:" 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 "Press:" nil t)
+ (setq count (1+ count))))
+ (should (= 2 count))))))
+
+;;; Boundary Cases
+
+(ert-deftest test-wttrin--add-buffer-instructions-boundary-point-at-beginning ()
+ "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 "Press: [a] for another location [g] to refresh [q] to quit"
+ (buffer-string)))))
+
+(ert-deftest test-wttrin--add-buffer-instructions-boundary-point-in-middle ()
+ "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 "Press: [a] for another location [g] to refresh [q] to quit"
+ (buffer-string)))))
+
+(ert-deftest test-wttrin--add-buffer-instructions-boundary-buffer-with-trailing-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= "Weather\n\n\n\n\nPress: [a] for another location [g] to refresh [q] to quit"
+ (buffer-string)))))
+
+(ert-deftest test-wttrin--add-buffer-instructions-boundary-very-large-buffer ()
+ "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 "Press: \\[a\\] for another location \\[g\\] to refresh \\[q\\] to quit" nil))))
+
+;;; Error Cases
+
+(ert-deftest test-wttrin--add-buffer-instructions-error-read-only-buffer ()
+ "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 ()
+ "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\nPress:")))))
+
+(provide 'test-wttrin--add-buffer-instructions)
+;;; test-wttrin--add-buffer-instructions.el ends here
diff --git a/tests/test-wttrin--process-weather-content.el b/tests/test-wttrin--process-weather-content.el
new file mode 100644
index 0000000..a372f4c
--- /dev/null
+++ b/tests/test-wttrin--process-weather-content.el
@@ -0,0 +1,96 @@
+;;; test-wttrin--process-weather-content.el --- Tests for wttrin--process-weather-content -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2024 Craig Jennings
+
+;;; Commentary:
+;; Unit tests for wttrin--process-weather-content function.
+;; Tests ANSI filtering and removal of verbose Location lines.
+
+;;; Code:
+
+(require 'ert)
+(require 'wttrin)
+(require 'xterm-color)
+
+;;; Normal Cases
+
+(ert-deftest test-wttrin--process-weather-content-normal-plain-text ()
+ "Test processing plain text without ANSI codes or Location lines."
+ (let ((input "Weather: Sunny\nTemperature: 20°C"))
+ (should (string= input (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-normal-removes-location-line ()
+ "Test that Location line with coordinates is removed."
+ (let ((input "Weather: Sunny\n Location: Paris [48.8566, 2.3522]\nTemperature: 20°C")
+ (expected "Weather: Sunny\nTemperature: 20°C"))
+ (should (string= expected (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-normal-multiple-location-lines ()
+ "Test that multiple Location lines are all removed."
+ (let ((input "Location: Paris [48.8566, 2.3522]\nWeather: Sunny\n Location: Test [0, 0]\nTemp: 20°C")
+ (expected "Weather: Sunny\nTemp: 20°C"))
+ (should (string= expected (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-normal-with-ansi-codes ()
+ "Test that ANSI color codes are filtered by xterm-color-filter."
+ ;; xterm-color-filter should process ANSI codes
+ ;; We'll test that the function calls xterm-color-filter by checking
+ ;; that basic ANSI codes are handled (this depends on xterm-color behavior)
+ (let* ((input-with-ansi "\x1b[31mRed Text\x1b[0m\nNormal Text")
+ (result (wttrin--process-weather-content input-with-ansi)))
+ ;; xterm-color-filter adds text properties but returns the text content
+ (should (string-match-p "Red Text" result))
+ (should (string-match-p "Normal Text" result))))
+
+;;; Boundary Cases
+
+(ert-deftest test-wttrin--process-weather-content-boundary-empty-string ()
+ "Test processing empty string."
+ (should (string= "" (wttrin--process-weather-content ""))))
+
+(ert-deftest test-wttrin--process-weather-content-boundary-only-location-line ()
+ "Test processing string with only a Location line removes it."
+ (let ((input " Location: Test [0, 0]\n")
+ (expected ""))
+ ;; Input must have newline for delete-region to work correctly
+ (should (string= expected (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-boundary-location-without-brackets ()
+ "Test that Location line without brackets is not removed (doesn't match pattern)."
+ (let ((input "Location: Paris\nWeather: Sunny"))
+ ;; Pattern requires [coordinates], so this line should remain
+ (should (string-match-p "Location: Paris" (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-boundary-location-case-insensitive ()
+ "Test that 'location' (lowercase) IS removed due to case-insensitive regex."
+ (let ((input "location: test [0, 0]\nWeather: Sunny"))
+ ;; re-search-forward uses case-fold-search (defaults to t)
+ ;; so lowercase 'location' matches 'Location' pattern
+ (should-not (string-match-p "location:" (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-boundary-whitespace-variations ()
+ "Test Location line with various whitespace patterns."
+ (let ((input " Location: Test [1, 2] \nWeather: Sunny")
+ (expected "Weather: Sunny"))
+ (should (string= expected (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-boundary-preserves-non-location-brackets ()
+ "Test that lines with brackets but not Location pattern are preserved."
+ (let ((input "Weather: [Sunny] 20°C\nWind: [Strong]"))
+ (should (string= input (wttrin--process-weather-content input)))))
+
+;;; Error Cases
+
+(ert-deftest test-wttrin--process-weather-content-error-handles-malformed-ansi ()
+ "Test that function handles malformed ANSI codes gracefully."
+ ;; xterm-color-filter should handle this, but we verify no errors occur
+ (let ((input "\x1b[9999mInvalid ANSI\nNormal text"))
+ (should (stringp (wttrin--process-weather-content input)))))
+
+(ert-deftest test-wttrin--process-weather-content-error-very-long-line ()
+ "Test processing very long line without errors."
+ (let ((long-line (make-string 10000 ?x)))
+ (should (string= long-line (wttrin--process-weather-content long-line)))))
+
+(provide 'test-wttrin--process-weather-content)
+;;; test-wttrin--process-weather-content.el ends here
diff --git a/tests/test-wttrin--validate-weather-data.el b/tests/test-wttrin--validate-weather-data.el
new file mode 100644
index 0000000..651fb5c
--- /dev/null
+++ b/tests/test-wttrin--validate-weather-data.el
@@ -0,0 +1,73 @@
+;;; test-wttrin--validate-weather-data.el --- Tests for wttrin--validate-weather-data -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2024 Craig Jennings
+
+;;; Commentary:
+;; Unit tests for wttrin--validate-weather-data function.
+;; Tests validation of weather data strings for errors and nil values.
+
+;;; Code:
+
+(require 'ert)
+(require 'wttrin)
+
+;;; Normal Cases
+
+(ert-deftest test-wttrin--validate-weather-data-normal-valid-weather-string ()
+ "Test that valid weather data string is accepted."
+ (let ((valid-weather "Weather: 20°C\nCondition: Sunny\nWind: 10 km/h"))
+ (should (wttrin--validate-weather-data valid-weather))))
+
+(ert-deftest test-wttrin--validate-weather-data-normal-multiline-weather ()
+ "Test that multiline weather data is accepted."
+ (let ((weather "┌─────────────┐\n│ Weather │\n│ 20°C │\n└─────────────┘"))
+ (should (wttrin--validate-weather-data weather))))
+
+(ert-deftest test-wttrin--validate-weather-data-normal-weather-with-unicode ()
+ "Test that weather data with Unicode characters is accepted."
+ (let ((weather "Temperature: 20°C ☀️\nWind: 15 km/h 💨"))
+ (should (wttrin--validate-weather-data weather))))
+
+;;; Boundary Cases
+
+(ert-deftest test-wttrin--validate-weather-data-boundary-empty-string ()
+ "Test that empty string is considered valid (though unusual)."
+ (should (wttrin--validate-weather-data "")))
+
+(ert-deftest test-wttrin--validate-weather-data-boundary-whitespace-only ()
+ "Test that whitespace-only string is considered valid."
+ (should (wttrin--validate-weather-data " \n \t ")))
+
+(ert-deftest test-wttrin--validate-weather-data-boundary-single-character ()
+ "Test that single character string is valid."
+ (should (wttrin--validate-weather-data "x")))
+
+(ert-deftest test-wttrin--validate-weather-data-boundary-error-lowercase ()
+ "Test that lowercase 'error' is rejected (case-insensitive matching)."
+ ;; string-match uses case-fold-search which defaults to t in Emacs
+ (should-not (wttrin--validate-weather-data "error: connection failed")))
+
+(ert-deftest test-wttrin--validate-weather-data-boundary-error-in-middle ()
+ "Test that 'ERROR' anywhere in string causes rejection."
+ (should-not (wttrin--validate-weather-data "Weather: ERROR occurred while fetching")))
+
+;;; Error Cases
+
+(ert-deftest test-wttrin--validate-weather-data-error-nil-string ()
+ "Test that nil string is rejected."
+ (should-not (wttrin--validate-weather-data nil)))
+
+(ert-deftest test-wttrin--validate-weather-data-error-uppercase-error ()
+ "Test that string containing 'ERROR' is rejected."
+ (should-not (wttrin--validate-weather-data "ERROR: Unable to fetch weather")))
+
+(ert-deftest test-wttrin--validate-weather-data-error-error-at-start ()
+ "Test that 'ERROR' at start of string causes rejection."
+ (should-not (wttrin--validate-weather-data "ERROR 404")))
+
+(ert-deftest test-wttrin--validate-weather-data-error-error-at-end ()
+ "Test that 'ERROR' at end of string causes rejection."
+ (should-not (wttrin--validate-weather-data "Network ERROR")))
+
+(provide 'test-wttrin--validate-weather-data)
+;;; test-wttrin--validate-weather-data.el ends here