aboutsummaryrefslogtreecommitdiff
path: root/tests/test-org-config-table-header.el
blob: 38e73b483f2e096974831d7401320e3c4628087a (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
;;; test-org-config-table-header.el --- In-buffer org table header fontify -*- lexical-binding: t; -*-

;;; Commentary:
;; Org has no in-buffer header-row face -- the whole table uses `org-table'.
;; cj/--org-table-header-row-p, cj/--org-table-first-hline-position, and the
;; font-lock matcher cj/--org-fontify-table-header-matcher (org-config.el) add
;; one: they identify a table's header rows (the non-hline rows above its first
;; hline) so font-lock can prepend `org-table-header' there.  These exercise the
;; detection logic directly against fixture tables, matching the tag-alignment
;; test's pure-logic style.

;;; Code:

(require 'ert)
(require 'org)
(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'org-config)

(defmacro test-org-th--in (content &rest body)
  "Run BODY in a temp org buffer holding CONTENT, hooks suppressed."
  (declare (indent 1))
  `(let ((org-mode-hook nil))
     (with-temp-buffer
       (insert ,content)
       (org-mode)
       (goto-char (point-min))
       ,@body)))

(defun test-org-th--goto (substring)
  "Move point to the beginning of the line containing SUBSTRING."
  (goto-char (point-min))
  (search-forward substring)
  (beginning-of-line))

;; ----- cj/--org-table-header-row-p -----

(ert-deftest test-org-table-header-row-p-header-above-hline ()
  "Normal: a non-hline row above the first hline is a header row."
  (test-org-th--in "| Name | Age |\n|------+-----|\n| Bob | 3 |\n"
    (test-org-th--goto "Name")
    (should (cj/--org-table-header-row-p))))

(ert-deftest test-org-table-header-row-p-body-row-not-header ()
  "Normal: a row below the first hline is not a header row."
  (test-org-th--in "| Name | Age |\n|------+-----|\n| Bob | 3 |\n"
    (test-org-th--goto "Bob")
    (should-not (cj/--org-table-header-row-p))))

(ert-deftest test-org-table-header-row-p-hline-not-header ()
  "Boundary: the hline itself is not a header row."
  (test-org-th--in "| Name | Age |\n|------+-----|\n| Bob | 3 |\n"
    (test-org-th--goto "----")
    (should-not (cj/--org-table-header-row-p))))

(ert-deftest test-org-table-header-row-p-no-hline-no-header ()
  "Boundary: a table with no hline has no header rows."
  (test-org-th--in "| A | B |\n| x | y |\n"
    (test-org-th--goto "A |")
    (should-not (cj/--org-table-header-row-p))))

(ert-deftest test-org-table-header-row-p-multi-row-header ()
  "Boundary: every non-hline row above the first hline is a header row."
  (test-org-th--in "| A | B |\n| C | D |\n|---+---|\n| x | y |\n"
    (test-org-th--goto "A |")
    (should (cj/--org-table-header-row-p))
    (test-org-th--goto "C |")
    (should (cj/--org-table-header-row-p))))

(ert-deftest test-org-table-header-row-p-key-value-first-row-only ()
  "Boundary: hline-after-every-row table -- only the first row is header."
  (test-org-th--in "| Status | draft |\n|--------+-------|\n| Owner | cj |\n|--------+-------|\n"
    (test-org-th--goto "Status")
    (should (cj/--org-table-header-row-p))
    (test-org-th--goto "Owner")
    (should-not (cj/--org-table-header-row-p))))

(ert-deftest test-org-table-header-row-p-non-table-line ()
  "Error: a line that is not in a table is never a header row."
  (test-org-th--in "Just some prose.\n"
    (test-org-th--goto "prose")
    (should-not (cj/--org-table-header-row-p))))

;; ----- cj/--org-table-first-hline-position -----

(ert-deftest test-org-table-first-hline-position-found ()
  "Normal: returns the bol of the first hline in the table."
  (test-org-th--in "| Name | Age |\n|------+-----|\n| Bob | 3 |\n"
    (test-org-th--goto "Name")
    (let ((expected (save-excursion (goto-char (point-min))
                                    (forward-line 1)
                                    (line-beginning-position))))
      (should (equal (cj/--org-table-first-hline-position) expected)))))

(ert-deftest test-org-table-first-hline-position-none ()
  "Boundary: a table with no hline returns nil."
  (test-org-th--in "| A | B |\n| x | y |\n"
    (test-org-th--goto "A |")
    (should-not (cj/--org-table-first-hline-position))))

;; ----- cj/--org-fontify-table-header-matcher -----

(ert-deftest test-org-fontify-table-header-matcher-matches-header-only ()
  "Normal: the matcher sets match data to the header row, then stops."
  (test-org-th--in "| Name | Age |\n|------+-----|\n| Bob | 3 |\n"
    (should (cj/--org-fontify-table-header-matcher (point-max)))
    (should (equal (match-string 0) "| Name | Age |"))
    (should-not (cj/--org-fontify-table-header-matcher (point-max)))))

(ert-deftest test-org-fontify-table-header-matcher-no-header ()
  "Boundary: a table with no hline yields no matches."
  (test-org-th--in "| A | B |\n| x | y |\n"
    (should-not (cj/--org-fontify-table-header-matcher (point-max)))))

(provide 'test-org-config-table-header)
;;; test-org-config-table-header.el ends here