diff --git a/ChangeLog b/ChangeLog index 22b86137..6b3d64e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2025-11-12 Mats Lidell + +* test/MANIFEST: Add hywiki-yki-tests.el plus older tests missing from + MANIFEST: hproperty-test.el, hypb-ert-tests.el and hywiki-tests.el. + +* test/hywiki-yki-tests.el: Add hywiki yank, kill and insert tests. + 2025-11-11 Mats Lidell * test/hpath-tests.el (hpath:path-at-point-finds-path-when-unbalanced-quote-on-same-line): diff --git a/test/MANIFEST b/test/MANIFEST index 042808d6..d60a830c 100644 --- a/test/MANIFEST +++ b/test/MANIFEST @@ -10,6 +10,7 @@ hibtypes-tests.el - unit test for hib-kbd hmouse-drv-tests.el - hmouse-drv unit tests hmouse-info-tests.el - hmouse-info unit tests hpath-tests.el - unit tests for hpath +hproperty-tests.el - hproperty tests hsettings-tests.el - unit tests for hsettings hsys-org-tests.el - hsys-org tests hui-mini-tests.el - hui-mini tests @@ -21,10 +22,13 @@ hy-test-coverage.el - provide test coverage information hy-test-dependencies.el - Hyperbole test dependencies hy-test-helpers.el - unit test helpers hycontrol-tests.el - hycontrol unit tests +hypb-ert-tests.el - hypb-ert tests hypb-tests.el - tests for hypb.el utility functions hyperbole-tests.el - tests for hyperbole.el hyrolo-tests.el - unit tests for hyrolo.el hywconfig-tests.el - tests for hyperbole window configuration management +hywiki-tests.el - hywiki tests +hywiki-yki-tests.el - hywiki yank, kill and insert tests kcell-tests.el - test for kcells in Koutlines kexport-tests.el - test exporting Koutlines to file types kimport-tests.el - test importing file types to Koutlines diff --git a/test/hywiki-tests.el b/test/hywiki-tests.el index 7f70163a..eed39b51 100644 --- a/test/hywiki-tests.el +++ b/test/hywiki-tests.el @@ -1417,7 +1417,7 @@ named WikiReferent with a non-page referent type." ;; Command (defun hywiki-tests--command (wikiword) - "Test command." + "Verify WIKIWORD is WikiReferent." (interactive) (should (string= "WikiReferent" wikiword))) diff --git a/test/hywiki-yki-tests.el b/test/hywiki-yki-tests.el new file mode 100644 index 00000000..938c8923 --- /dev/null +++ b/test/hywiki-yki-tests.el @@ -0,0 +1,274 @@ +;;; hywiki-yki.tests --- Yank, kill and insert tests for hywiki -*- lexical-binding: t; -*- +;; +;; Author: Mats Lidell +;; +;; Orig-Date: 13-Jul-25 at 19:50:37 +;; Last-Mod: 11-Nov-25 at 17:21:42 by Mats Lidell +;; +;; SPDX-License-Identifier: GPL-3.0-or-later +;; +;; Copyright (C) 2025 Free Software Foundation, Inc. +;; See the "../HY-COPY" file for license information. +;; +;; This file is part of GNU Hyperbole. + +;;; Commentary: +;; +;; Development area for new hywiki-tests and their support functions. +;; Will eventually, when finished, be moved into "hywiki-test.el" or +;; maybe stay as here in a separate file!? + +;;; Code: + +(require 'ert) +(require 'el-mock) +(require 'ert-x) +(require 'hy-test-helpers) +(require 'hywiki) + +(require 'hywiki-tests) ;; For functions and variables in hywiki-tests + +;; The testing idea here is based on functions in simple-test.el add +;; support for also marking highlighted words in buffers using the +;; same idea with point-tag and mark-tag also for start and end of +;; highlighted regions. Note that for setting the highlighted areas +;; hywiki-mode is used. The tag notation is not used for that. It is +;; only used for the verification. + +(defconst hywiki-test--point-char "^") +(defconst hywiki-test--highlight-start-char "<") +(defconst hywiki-test--highlight-end-char ">") + +(defun hywiki-test--insert-chars (positions) + "Insert in string representation of current buffer start, end and point chars. +POSITIONS is a list of cons cells (START . END) with beginning of string +at index 1. For every highlighted word in the buffer a +`hywiki-test--highlight-start-char' and +`hywiki-test--highlight-end-char' surrounding the highlighted word is +inserted. Finally a `hywiki-test--point-char' is inserted where point is." + (let* ((buffer-string (buffer-substring-no-properties (point-min) (point-max))) + (current-point (point)) + ;; Convert 1-based positions to 0-based for string operations + ;; Note: Emacs ranges are (start . end) where end is exclusive + (zero-based-positions (mapcar (lambda (pos) + (cons (1- (car pos)) (1- (cdr pos)))) + (or positions '()))) + ;; Sort ranges in reverse order for right-to-left processing + (sorted-positions (sort zero-based-positions + (lambda (a b) (> (car a) (car b))))) + (result buffer-string)) + + ;; First, process all ranges from right to left + (dolist (pos sorted-positions) + (let* ((start (car pos)) + (end (cdr pos)) + (before (substring result 0 start)) + (middle (substring result start end)) + (after (substring result end))) + + (setq result (concat before hywiki-test--highlight-start-char middle hywiki-test--highlight-end-char after)))) + + ;; Then insert point char adjusting for inserted chars. + (let* ((point-pos (1- current-point)) + (tags-before-point 0)) + + ;; Count characters and check if point is within ranges + (dolist (pos zero-based-positions) + (let ((range-start (car pos)) + (range-end (cdr pos))) + (cond + ((and (> point-pos range-start) (< point-pos range-end)) + (setq tags-before-point (+ tags-before-point (length hywiki-test--highlight-start-char)))) + ((<= range-end point-pos) + (setq tags-before-point (+ tags-before-point + (length hywiki-test--highlight-start-char) + (length hywiki-test--highlight-end-char))))))) + + ;; Insert point char at adjusted position + (let* ((adjusted-point (+ point-pos tags-before-point)) + (before (substring result 0 adjusted-point)) + (after (substring result adjusted-point))) + (setq result (concat before hywiki-test--point-char after)))) + + result)) + +(ert-deftest hywiki-test--insert--test () + "Verify `hywiki-test--insert-chars'." + (with-temp-buffer + (insert "Hello World\n") + (goto-char 6) + (should (string= (hywiki-test--insert-chars nil) + "Hello^ World\n")) + (should (string= (hywiki-test--insert-chars '((1 . 6) (7 . 12))) + "^ \n")) + (goto-char 5) + (should (string= (hywiki-test--insert-chars '((1 . 6) (7 . 12))) + " \n")))) + +(defun hywiki-test--insert (string) + "Command to insert a STRING at point." + (interactive "s: ") + (dolist (c (string-to-list string)) + (hywiki-tests--command-execute #'self-insert-command 1 c))) + +(defun hywiki-test--insert-with-point (string) + "Insert STRING and return new POINT pos given by `hywiki-test--point-char'. +The point char is not inserted." + (interactive "s: ") + (let ((pos (point))) + (dolist (c (string-to-list string) pos) + (if (equal (char-to-string c) hywiki-test--point-char) + (setq pos (point)) + (hywiki-tests--command-execute #'self-insert-command 1 c))))) + +(defun hywiki-test--set-buffer-text-with-point-and-highlight (description) + "Set the current buffer's text, point and mark according to DESCRIPTION. + +Erase current buffer and insert DESCRIPTION. Set point to the first +occurrence of `hywiki-test--point-char' in the buffer, removing it. If +there is no `hywiki-test--point-char', set point to the beginning of the +buffer. + +End the insertion of text by turning on hywiki-mode and perform a dummy +command to get the pre- and post-hooks executed. This creates the +highlighting overlays we want to test." + (erase-buffer) + (hywiki-mode 1) + (goto-char (hywiki-test--insert-with-point description))) + +(defun hywiki-test--get-buffer-text-with-point-and-highlight () + "An inverse of `hywiki-test--set-buffer-text-with-point-and-highlight'. +Inserts tags for highlighted areas as well as point." + (hywiki-test--insert-chars (hywiki-get-reference-positions))) + +(ert-deftest hywiki--verify-get-buffer-text-with-point-and-highlight-compact () + "Verify proper highlighting after different editing actions. +Actions can be move, insertion, killing and deletion. + +Each test is constructed as three phases: + +* First phase, pre:, empties the buffer from any previous test and then + prepares the text and sets the point. Hywiki-mode is activated in the + prepare phase in order to set any initial + highlighting. + +* The second phase performs some action. It can be insertion, killing + or deletion. The action should call the pre- and post-command-hooks + in order for the highlighting overlays to be constructed. + +* The third phase, post:, does a verification. A representation of the + `buffer-string' as a string is constructed where chars are used for + point, and start and stop of the highlighting with angle brackets. + That is then compared to the expected string." + (skip-unless (not noninteractive)) ; Only works in interactive mode for now + (hywiki-tests--preserve-hywiki-mode + (let* ((hywiki-directory (make-temp-file "hywiki" t)) + (wikiHi (cdr (hywiki-add-page "Hi"))) + (wikiHo (cdr (hywiki-add-page "Ho"))) + (wikiWord (cdr (hywiki-add-page "WikiWord"))) + (hywiki-tests--with-face-test t)) + (cl-flet* ((pre: (start) + (hywiki-test--set-buffer-text-with-point-and-highlight start)) + (exec: (cmd &rest args) + (apply #'hywiki-tests--command-execute cmd args)) + (del: (str) + (exec: #'delete-region (point) (+ (point) (length str)))) + (post: (stop) + (should (string= stop (hywiki-test--get-buffer-text-with-point-and-highlight))))) + (unwind-protect + (progn + (ert-info ("1" :prefix "Verify point, no highlighting:") + (pre: "hej^hopp") + (post: "hej^hopp")) + (ert-info ("2" :prefix "Verify point, no highlighting: ") + (pre: "hej^hopp") + (forward-char 1) + (post: "hejh^opp")) + (ert-info ("3" :prefix "Verify highlighting: ") + (pre: "^Hi") + (post: "^")) + (ert-info ("4" :prefix "Verify highlighting: ") + (pre: "Hi^Ho") + (hywiki-test--insert "\"text\"") + (post: "Hi\"text\"^")) + (ert-info ("5" :prefix "Verify highlighting: ") + (pre: "Hi^Ho") + (hywiki-test--insert " \"text\"") + (post: " \"text\"^")) + + ;; PASS: WikiWord -> highlight {WikiWord} after delete + (ert-info ("6" :prefix "Verify highlighting: ") + (pre: "Wiki^delete-regionWord") + (del: "delete-region") + (post: "")) + + ;; PASS: Wiki#secWord -> no highlight after adding "tion" + (ert-info ("7" :prefix "Verify highlighting: ") + (pre: "Wiki#sec^tionWord") + (del: "tion") + (post: "Wiki#sec^Word")) + + ;; PASS: Wiki<#section>Word -> highlight {WikiWord} after delete of "#section" + (ert-info ("8" :prefix "Verify highlighting: ") + (pre: "Wiki^#sectionWord") + (del: "#section") + (post: "")) + + ;; PASS: WikiWord -> dehighlight "WikiWord" + (ert-info ("8" :prefix "Verify highlighting: ") + (pre: "WikiWo^kill-wordrd") + (del: "kill-word") + (post: "")) + + ;; PASS: "WikiWord#section with spaces" -> shrink highlight + ;; to {WikiWord#section} with this operation: + ;; "WikiWord#section with spaces" + (ert-info ("9" :prefix "Verify highlighting: ") + (pre: "^\"WikiWord#section with spaces\"") + (exec: #'delete-char 1) + (post: "^ with spaces\"")) + + ;; PASS: "WikiWord#section" -> no + ;; highlight change "{WikiWord#section} + (ert-info ("10" :prefix "Verify highlighting: ") + (pre: "\"WikiWord#section\"^") + (exec: #'backward-delete-char-untabify 1) + (post: "\"^")) + + ;; PASS: "WikiWord#section with spaces" + ;; -> shrink highlight to "{WikiWord#section} with spaces + (ert-info ("11" :prefix "Verify highlighting: ") + (pre: "\"WikiWord#section with spaces\"^") + (exec: #'backward-delete-char-untabify 1) + (post: "\" with spaces^")) + + ;; PASS: WikiWord abc WikiWord + (ert-info ("12" :prefix "Verify highlighting: ") + (pre: "WikiWord ^abc WikiWord") + (del: "abc ") + (post: " ^")) + + ;; PASS: WikiWord abc WikiWord + (ert-info ("13" :prefix "Verify highlighting: ") + (pre: "WikiWord ^abc WikiWord") + (del: "abc") + (post: " ^ ")) + + ;; PASS: WikiWord abc abc WikiWord + (ert-info ("14" :prefix "Verify highlighting: ") + (pre: "WikiWord ^abc abc WikiWord") + (del: "abc abc ") + (post: " ^")) + + ;; PASS: WikiWord abc WikiWord + (ert-info ("15" :prefix "Verify highlighting: ") + (pre: "WikiWord ^ abc WikiWord") + (del: " abc") + (post: " ^ "))) + + (hy-delete-files-and-buffers (list wikiHi wikiHo wikiWord)) + (hywiki-tests--delete-hywiki-dir-and-buffer hywiki-directory)))))) + +(provide 'hywiki-yki-tests) + +;;; hywiki-yki-tests.el ends here