[Markdown] Tools for working with agents.
1
;;; ste-lint-tests.el --- Tests for the STE linter -*- lexical-binding: t; -*-
2
3
;;; Commentary:
4
5
;; These tests lint small Org texts in temporary buffers and files. Run them
6
;; with the runner script in this directory:
7
;;
8
;; ./run-tests.sh
9
10
;;; Code:
11
12
(require 'ert)
13
(require 'ste-lint)
14
15
;;; Helpers
16
17
(defun ste-lint-tests--findings (text)
18
"Return the findings of the Org TEXT as (CATEGORY MATCH LINE) lists."
19
(let ((file (make-temp-file "ste-lint-" nil ".org" text)))
20
(unwind-protect
21
(mapcar (lambda (entry)
22
(let ((finding (nth 2 entry)))
23
(list (ste-lint-finding-category finding)
24
(ste-lint-finding-match finding)
25
(nth 0 entry))))
26
(ste-lint-file file))
27
(delete-file file))))
28
29
(defun ste-lint-tests--categories (text)
30
"Return the categories of the findings of the Org TEXT."
31
(mapcar #'car (ste-lint-tests--findings text)))
32
33
(defun ste-lint-tests--words (count)
34
"Return a sentence of COUNT words that ends with a period."
35
(concat (mapconcat (lambda (_) "word") (number-sequence 1 count) " ") "."))
36
37
;;; Rules
38
39
(ert-deftest ste-lint-test-contraction ()
40
(should (equal (ste-lint-tests--findings "We can't stop.\n")
41
'(("contraction" "can't" 1))))
42
(should (equal (ste-lint-tests--categories "We don’t stop.\n")
43
'("contraction"))))
44
45
(ert-deftest ste-lint-test-possessive-is-not-contraction ()
46
(should (null (ste-lint-tests--findings "The user's file is open.\n"))))
47
48
(ert-deftest ste-lint-test-latin-abbreviation-ignores-case ()
49
(should (equal (ste-lint-tests--findings "Use a tool, E.g. a linter.\n")
50
'(("latin-abbreviation" "E.g." 1)))))
51
52
(ert-deftest ste-lint-test-semicolon-and-idiom ()
53
(should (equal (ste-lint-tests--categories "Stop it; start it.\n")
54
'("semicolon")))
55
(should (null (ste-lint-tests--findings "Read the TL;DR first.\n"))))
56
57
(ert-deftest ste-lint-test-substitution ()
58
(should (equal (ste-lint-tests--findings "Utilize the tool.\n")
59
'(("wordy-phrase" "Utilize" 1)))))
60
61
(ert-deftest ste-lint-test-phrase-across-line-break ()
62
(should (equal (ste-lint-tests--findings
63
"Read the file in order\n to see the rules.\n")
64
'(("wordy-phrase" "in order to" 1)))))
65
66
(ert-deftest ste-lint-test-instruction-mood ()
67
(should (equal (ste-lint-tests--categories "You should run the script.\n")
68
'("instruction-mood"))))
69
70
;;; Prose selection
71
72
(ert-deftest ste-lint-test-inline-markup-is-masked ()
73
(should (null (ste-lint-tests--findings
74
"Run =don't;= and ~a;b~ at <2026-10-05 Mon>.\n"))))
75
76
(ert-deftest ste-lint-test-link-label-is-linted-and-target-is-not ()
77
(should (null (ste-lint-tests--findings
78
"Read [[https://a.example/x;y][the page]] now.\n")))
79
(should (equal (ste-lint-tests--categories
80
"Read [[https://a.example/x][the page; now]].\n")
81
'("semicolon"))))
82
83
(ert-deftest ste-lint-test-non-prose-elements-are-skipped ()
84
(should (null (ste-lint-tests--findings
85
(concat "#+TITLE: Don't; skip\n"
86
"* Plain title\n"
87
"SCHEDULED: <2026-10-05 Mon>\n"
88
":PROPERTIES:\n:ID: a;b\n:END:\n"
89
":LOGBOOK:\n- Note: don't; skip.\n:END:\n"
90
"#+BEGIN_SRC sh\necho \"don't;\"\n#+END_SRC\n"
91
"#+BEGIN_EXAMPLE\ndon't;\n#+END_EXAMPLE\n"
92
"#+BEGIN_QUOTE\nHe said don't.\n#+END_QUOTE\n"
93
"| don't; | cell |\n"
94
"# don't; comment\n")))))
95
96
(ert-deftest ste-lint-test-headline-title-only ()
97
(should (equal (ste-lint-tests--findings
98
"* TODO [#A] Don't wait [1/2] :he:\n")
99
'(("contraction" "Don't" 1)))))
100
101
(ert-deftest ste-lint-test-headline-has-no-length-limit ()
102
(should (null (ste-lint-tests--findings
103
(concat "* " (ste-lint-tests--words 30) "\n")))))
104
105
;;; Sentence length
106
107
(ert-deftest ste-lint-test-sentence-length-description ()
108
(should (null (ste-lint-tests--findings
109
(concat (ste-lint-tests--words 25) "\n"))))
110
(should (equal (ste-lint-tests--findings
111
(concat "Intro.\n" (ste-lint-tests--words 26) "\n"))
112
'(("sentence-length" "26 words" 2)))))
113
114
(ert-deftest ste-lint-test-sentence-length-spans-lines ()
115
(let ((text (replace-regexp-in-string
116
" word word word word word word word word "
117
"\nword word word word word word word word\n"
118
(ste-lint-tests--words 30) t t)))
119
(should (equal (ste-lint-tests--categories (concat text "\n"))
120
'("sentence-length")))))
121
122
(ert-deftest ste-lint-test-sentence-length-procedure ()
123
(should (equal (ste-lint-tests--categories
124
(concat "1. " (ste-lint-tests--words 21) "\n"))
125
'("sentence-length")))
126
(should (null (ste-lint-tests--findings
127
(concat "- " (ste-lint-tests--words 21) "\n")))))
128
129
(ert-deftest ste-lint-test-masked-code-counts-as-one-word ()
130
(should (null (ste-lint-tests--findings
131
(concat (ste-lint-tests--words 24) " =a b c d e=.\n")))))
132
133
;;; Positions and entry points
134
135
(ert-deftest ste-lint-test-exact-position ()
136
(let ((file (make-temp-file "ste-lint-" nil ".org"
137
"First line.\nThe tool can't run.\n")))
138
(unwind-protect
139
(let ((entry (car (ste-lint-file file))))
140
(should (equal (list (nth 0 entry) (nth 1 entry)) '(2 10))))
141
(delete-file file))))
142
143
(ert-deftest ste-lint-test-flymake-backend ()
144
(with-temp-buffer
145
(let ((org-mode-hook nil))
146
(org-mode))
147
(insert "We can't stop.\nUtilize the tool.\n")
148
(let (diagnostics)
149
(ste-lint-flymake (lambda (reported) (setq diagnostics reported)))
150
(should (equal (mapcar #'flymake-diagnostic-type diagnostics)
151
'(:error :warning)))
152
(should (equal (buffer-substring
153
(flymake-diagnostic-beg (car diagnostics))
154
(flymake-diagnostic-end (car diagnostics)))
155
"can't")))))
156
157
(provide 'ste-lint-tests)
158
159
;;; ste-lint-tests.el ends here
160