diff options
Diffstat (limited to '.ai/scripts/tests')
| -rw-r--r-- | .ai/scripts/tests/lint-org-cli.bats | 18 | ||||
| -rw-r--r-- | .ai/scripts/tests/task-review-staleness.bats | 53 | ||||
| -rw-r--r-- | .ai/scripts/tests/test-lint-org.el | 23 | ||||
| -rw-r--r-- | .ai/scripts/tests/test-wrap-org-table.el | 42 |
4 files changed, 134 insertions, 2 deletions
diff --git a/.ai/scripts/tests/lint-org-cli.bats b/.ai/scripts/tests/lint-org-cli.bats index d457696..b9faef6 100644 --- a/.ai/scripts/tests/lint-org-cli.bats +++ b/.ai/scripts/tests/lint-org-cli.bats @@ -20,6 +20,24 @@ teardown() { [[ "$output" == *"lint-org: file="* ]] } +@test "lint-org.el default invocation is report-only — file untouched" { + # bare #+begin_src is a mechanical fix (→ #+begin_example) that the old + # default applied on disk; a linter reports, it doesn't write + printf '* H\n\n#+begin_src\nx\n#+end_src\n' > "$TMPFILE" + before="$(cat "$TMPFILE")" + run emacs --batch -q -l "$SCRIPTS_DIR/lint-org.el" "$TMPFILE" + [ "$status" -eq 0 ] + [[ "$output" == *"would-fix"* ]] + [ "$(cat "$TMPFILE")" = "$before" ] +} + +@test "lint-org.el --fix applies mechanical fixes on disk" { + printf '* H\n\n#+begin_src\nx\n#+end_src\n' > "$TMPFILE" + run emacs --batch -q -l "$SCRIPTS_DIR/lint-org.el" --fix "$TMPFILE" + [ "$status" -eq 0 ] + grep -q '#+begin_example' "$TMPFILE" +} + @test "wrap-org-table.el loads and runs without -L on the load path" { run emacs --batch -q -l "$SCRIPTS_DIR/wrap-org-table.el" --width=120 "$TMPFILE" [ "$status" -eq 0 ] diff --git a/.ai/scripts/tests/task-review-staleness.bats b/.ai/scripts/tests/task-review-staleness.bats index 488b023..79aad79 100644 --- a/.ai/scripts/tests/task-review-staleness.bats +++ b/.ai/scripts/tests/task-review-staleness.bats @@ -49,6 +49,16 @@ task_unreviewed() { printf '** %s [#%s] %s\nBody.\n\n' "$keyword" "$prio" "$title" >> "$TODO" } +# Emit a qualifying task whose LAST_REVIEWED is an org-native inactive +# timestamp — [YYYY-MM-DD Day] — matching the CREATED:/CLOSED: cookies that +# sit in the same drawer. The date is derived from an ISO date via `date`. +task_reviewed_org() { + local keyword="$1" prio="$2" title="$3" isodate="$4" + local org="[$(date -d "$isodate" '+%F %a')]" + printf '** %s [#%s] %s\n:PROPERTIES:\n:LAST_REVIEWED: %s\n:END:\nBody.\n\n' \ + "$keyword" "$prio" "$title" "$org" >> "$TODO" +} + # ---- Normal cases ---------------------------------------------------- @test "staleness: empty file reports zero" { @@ -85,6 +95,20 @@ task_unreviewed() { [ "$output" = "2" ] } +@test "staleness: org-native bracketed LAST_REVIEWED parses — recent is fresh" { + task_reviewed_org TODO A "Reviewed five days ago, org stamp" "$D5" + run bash "$SCRIPT" "$TODO" 30 + [ "$status" -eq 0 ] + [ "$output" = "0" ] +} + +@test "staleness: org-native bracketed LAST_REVIEWED parses — old is stale" { + task_reviewed_org TODO A "Reviewed forty days ago, org stamp" "$D40" + run bash "$SCRIPT" "$TODO" 30 + [ "$status" -eq 0 ] + [ "$output" = "1" ] +} + # ---- Boundary cases -------------------------------------------------- @test "staleness: age exactly equal to threshold is fresh" { @@ -136,9 +160,23 @@ task_unreviewed() { [ "$output" = "0" ] } -@test "staleness: malformed LAST_REVIEWED is treated as stale" { +@test "staleness: malformed LAST_REVIEWED warns to stderr and is not counted" { task_reviewed TODO A "Bad date" "not-a-date" - run bash "$SCRIPT" "$TODO" 30 + # stdout carries only the count — the malformed stamp is not folded in. + run bash -c "bash '$SCRIPT' '$TODO' 30 2>/dev/null" + [ "$status" -eq 0 ] + [ "$output" = "0" ] + # stderr carries the loud warning naming the offending value. + run bash -c "bash '$SCRIPT' '$TODO' 30 2>&1 1>/dev/null" + [ "$status" -eq 0 ] + [[ "$output" == *"not-a-date"* ]] + [[ "$output" == *"LAST_REVIEWED"* ]] +} + +@test "staleness: malformed stamp is excluded while real stale tasks still count" { + task_reviewed TODO A "Real stale" "$D40" + task_reviewed TODO B "Broken stamp" "garbage" + run bash -c "bash '$SCRIPT' '$TODO' 30 2>/dev/null" [ "$status" -eq 0 ] [ "$output" = "1" ] } @@ -161,6 +199,17 @@ task_unreviewed() { [[ "${lines[2]}" == *"Reviewed recently"* ]] } +@test "staleness --list: org-native bracketed stamp sorts by its real date" { + task_reviewed TODO A "Bare recent" "$D5" + task_reviewed_org TODO B "Org-stamped old" "$D40" + run bash "$SCRIPT" --list "$TODO" 10 + [ "$status" -eq 0 ] + # The org-bracketed old stamp must sort ahead of the bare recent one — + # proof it parsed to a real date rather than falling to 0000-00-00. + [[ "${lines[0]}" == *"Org-stamped old"* ]] + [[ "${lines[1]}" == *"Bare recent"* ]] +} + @test "staleness --list: takes only the requested count" { task_unreviewed TODO A "First" task_reviewed TODO B "Second" "$D40" diff --git a/.ai/scripts/tests/test-lint-org.el b/.ai/scripts/tests/test-lint-org.el index d14879f..8e3e190 100644 --- a/.ai/scripts/tests/test-lint-org.el +++ b/.ai/scripts/tests/test-lint-org.el @@ -620,6 +620,29 @@ followups file on the next run." ;;; --------------------------------------------------------------------------- ;;; org-table-standard check (width budget + rules between rows) +(ert-deftest lo-table-inside-example-block-not-flagged () + "Pipe-led ASCII art inside an example block is not a table; no judgment." + (let* ((run (lo-test--run + "* H\n\n#+begin_example\n| client |----->| server |\n| box | | box |\n#+end_example\n" + 1 t)) + (judgments (lo-test--judgments (plist-get run :issues)))) + (should-not (memq 'org-table-standard (lo-test--checkers judgments))))) + +(ert-deftest lo-table-inside-src-block-not-flagged () + "Shell pipes inside a src block are not a table; no judgment." + (let* ((run (lo-test--run + "* H\n\n#+begin_src sh\n| sort\n| uniq -c\n#+end_src\n" 1 t)) + (judgments (lo-test--judgments (plist-get run :issues)))) + (should-not (memq 'org-table-standard (lo-test--checkers judgments))))) + +(ert-deftest lo-real-table-after-block-still-flagged () + "Block safety must not mask a genuine violation later in the file." + (let* ((run (lo-test--run + "* H\n\n#+begin_example\n| art |\n#+end_example\n\n| a | b |\n| 1 | 2 |\n" + 1 t)) + (judgments (lo-test--judgments (plist-get run :issues)))) + (should (memq 'org-table-standard (lo-test--checkers judgments))))) + (ert-deftest lo-table-over-budget-emits-judgment () "A table line rendering wider than 120 surfaces as an org-table-standard judgment." (let* ((wide (make-string 130 ?x)) diff --git a/.ai/scripts/tests/test-wrap-org-table.el b/.ai/scripts/tests/test-wrap-org-table.el index 8d1ecb6..0b3b375 100644 --- a/.ai/scripts/tests/test-wrap-org-table.el +++ b/.ai/scripts/tests/test-wrap-org-table.el @@ -186,3 +186,45 @@ (should (string-match-p "Prose before\\." content)) (should (string-match-p "Prose after\\." content)))) (delete-file file)))) + +;;; --------------------------------------------------------------------------- +;;; block safety — pipe lines inside #+begin_/#+end_ blocks are never tables + +(defconst wot-test--block-content + "#+begin_example +| client |----->| server | +| box | | box | +#+end_example +" + "An example block whose ASCII-art lines start with pipes.") + +(defun wot-test--process-content (content budget) + "Write CONTENT to a temp file, run `wot-process-file' at BUDGET, return result." + (let ((file (make-temp-file "wot-test" nil ".org"))) + (unwind-protect + (progn + (with-temp-file file (insert content)) + (wot-process-file file budget) + (with-temp-buffer (insert-file-contents file) (buffer-string))) + (delete-file file)))) + +(ert-deftest wot-process-file-leaves-example-block-byte-identical () + (let ((content (concat "* Diagram\n\n" wot-test--block-content))) + (should (equal (wot-test--process-content content 120) content)))) + +(ert-deftest wot-process-file-reformats-table-but-not-block () + (let* ((content (concat "* Doc\n\n" wot-test--block-content "\n" + wot-test--wide-input)) + (result (wot-test--process-content content 40))) + (should (string-match-p (regexp-quote wot-test--block-content) result)) + (should (string-match-p (regexp-quote wot-test--wide-expected) result)))) + +(ert-deftest wot-process-file-skips-pipes-in-src-block () + (let ((content "* Pipeline\n\n#+begin_src sh\n| sort\n| uniq -c\n#+end_src\n")) + (should (equal (wot-test--process-content content 120) content)))) + +(ert-deftest wot-process-file-literal-inner-end-marker-stays-in-block () + "A literal #+end_src quoted inside an example block must not close it." + (let ((content (concat "* Doc\n\n#+begin_example\n#+begin_src sh\nx\n" + "#+end_src\n| art |----| art |\n#+end_example\n"))) + (should (equal (wot-test--process-content content 120) content)))) |
