summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2025-11-21 08:43:19 -0800
committerCraig Jennings <c@cjennings.net>2025-11-21 08:43:19 -0800
commit1752c6e58906721a47afc56e357b7fb1c0c8a5a1 (patch)
treed7ea54fa3831c198c96d85eb4a17de7b41d30f75 /tests
parent42e3fd284600c84c4158bee6bb0092eba99bece5 (diff)
feat(org-noter): implement custom org-noter workflow
Implemented custom org-noter workflow with F6 keybinding: - Creates notes files as org-roam nodes in org-roam-directory - Title prompt with pre-slugified default, notes-on-{slug}.org format - F6 toggles notes window visibility when session active - Preserves PDF fit setting on toggle - Deferred org-roam integration to prevent PDF open hang Also fixed: quick-sdcv quit binding, calendar-sync sentinel buffer error Added 30 ERT tests for title-to-slug and template generation functions
Diffstat (limited to 'tests')
-rw-r--r--tests/test-org-noter--generate-notes-template.el109
-rw-r--r--tests/test-org-noter--title-to-slug.el100
2 files changed, 209 insertions, 0 deletions
diff --git a/tests/test-org-noter--generate-notes-template.el b/tests/test-org-noter--generate-notes-template.el
new file mode 100644
index 00000000..df545ccf
--- /dev/null
+++ b/tests/test-org-noter--generate-notes-template.el
@@ -0,0 +1,109 @@
+;;; test-org-noter--generate-notes-template.el --- Tests for cj/org-noter--generate-notes-template -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; ERT tests for the generate-notes-template function used in org-noter workflow.
+;; Tests cover normal, boundary, and error cases.
+
+;;; Code:
+
+(require 'ert)
+(require 'org-noter-config)
+
+;;; Test Helpers
+
+(defun test-org-noter--template-has-property (template property value)
+ "Check if TEMPLATE contains PROPERTY with VALUE in properties drawer."
+ (string-match-p (format ":%s: %s" property (regexp-quote value)) template))
+
+(defun test-org-noter--template-has-keyword (template keyword value)
+ "Check if TEMPLATE contains #+KEYWORD: VALUE."
+ (string-match-p (format "#\\+%s: %s" keyword (regexp-quote value)) template))
+
+;;; Normal Cases
+
+(ert-deftest test-org-noter--generate-notes-template-normal-basic ()
+ "Normal case: Basic template generation."
+ (let ((template (cj/org-noter--generate-notes-template "Test Book" "/path/to/book.pdf")))
+ (should (stringp template))
+ (should (string-match-p ":PROPERTIES:" template))
+ (should (string-match-p ":END:" template))
+ (should (string-match-p "\\* Notes" template))))
+
+(ert-deftest test-org-noter--generate-notes-template-normal-has-id ()
+ "Normal case: Template has ID property."
+ (let ((template (cj/org-noter--generate-notes-template "Test Book" "/path/to/book.pdf")))
+ (should (string-match-p ":ID: [a-f0-9-]+" template))))
+
+(ert-deftest test-org-noter--generate-notes-template-normal-has-noter-document ()
+ "Normal case: Template has NOTER_DOCUMENT property."
+ (let ((template (cj/org-noter--generate-notes-template "Test Book" "/path/to/book.pdf")))
+ (should (test-org-noter--template-has-property template "NOTER_DOCUMENT" "/path/to/book.pdf"))))
+
+(ert-deftest test-org-noter--generate-notes-template-normal-has-roam-refs ()
+ "Normal case: Template has ROAM_REFS property."
+ (let ((template (cj/org-noter--generate-notes-template "Test Book" "/path/to/book.pdf")))
+ (should (test-org-noter--template-has-property template "ROAM_REFS" "/path/to/book.pdf"))))
+
+(ert-deftest test-org-noter--generate-notes-template-normal-has-title ()
+ "Normal case: Template has title with book name."
+ (let ((template (cj/org-noter--generate-notes-template "The Great Gatsby" "/books/gatsby.epub")))
+ (should (test-org-noter--template-has-keyword template "title" "Notes on The Great Gatsby"))))
+
+(ert-deftest test-org-noter--generate-notes-template-normal-has-filetags ()
+ "Normal case: Template has ReadingNotes filetag."
+ (let ((template (cj/org-noter--generate-notes-template "Test Book" "/path/to/book.pdf")))
+ (should (test-org-noter--template-has-keyword template "FILETAGS" ":ReadingNotes:"))))
+
+(ert-deftest test-org-noter--generate-notes-template-normal-has-category ()
+ "Normal case: Template has CATEGORY set to book title."
+ (let ((template (cj/org-noter--generate-notes-template "Clean Code" "/books/clean-code.pdf")))
+ (should (test-org-noter--template-has-keyword template "CATEGORY" "Clean Code"))))
+
+;;; Boundary Cases
+
+(ert-deftest test-org-noter--generate-notes-template-boundary-long-title ()
+ "Boundary case: Very long title."
+ (let* ((long-title "This Is An Incredibly Long Book Title That Goes On And On")
+ (template (cj/org-noter--generate-notes-template long-title "/books/long.pdf")))
+ (should (test-org-noter--template-has-keyword template "title" (format "Notes on %s" long-title)))
+ (should (test-org-noter--template-has-keyword template "CATEGORY" long-title))))
+
+(ert-deftest test-org-noter--generate-notes-template-boundary-special-chars-in-title ()
+ "Boundary case: Special characters in title."
+ (let ((template (cj/org-noter--generate-notes-template "C++: A Guide" "/books/cpp.pdf")))
+ (should (test-org-noter--template-has-keyword template "title" "Notes on C++: A Guide"))))
+
+(ert-deftest test-org-noter--generate-notes-template-boundary-special-chars-in-path ()
+ "Boundary case: Special characters in path."
+ (let ((template (cj/org-noter--generate-notes-template "Test" "/path/with spaces/book.pdf")))
+ (should (test-org-noter--template-has-property template "NOTER_DOCUMENT" "/path/with spaces/book.pdf"))))
+
+(ert-deftest test-org-noter--generate-notes-template-boundary-epub-path ()
+ "Boundary case: EPUB file path."
+ (let ((template (cj/org-noter--generate-notes-template "Novel" "/library/novel.epub")))
+ (should (test-org-noter--template-has-property template "NOTER_DOCUMENT" "/library/novel.epub"))))
+
+;;; Structure Tests
+
+(ert-deftest test-org-noter--generate-notes-template-structure-properties-first ()
+ "Structure: Properties drawer comes first."
+ (let ((template (cj/org-noter--generate-notes-template "Test" "/path.pdf")))
+ (should (string-match "\\`:PROPERTIES:" template))))
+
+(ert-deftest test-org-noter--generate-notes-template-structure-notes-heading ()
+ "Structure: Has Notes heading for content."
+ (let ((template (cj/org-noter--generate-notes-template "Test" "/path.pdf")))
+ (should (string-match-p "^\\* Notes$" template))))
+
+(ert-deftest test-org-noter--generate-notes-template-structure-unique-ids ()
+ "Structure: Each call generates unique ID."
+ (let ((template1 (cj/org-noter--generate-notes-template "Test1" "/path1.pdf"))
+ (template2 (cj/org-noter--generate-notes-template "Test2" "/path2.pdf")))
+ (string-match ":ID: \\([a-f0-9-]+\\)" template1)
+ (let ((id1 (match-string 1 template1)))
+ (string-match ":ID: \\([a-f0-9-]+\\)" template2)
+ (let ((id2 (match-string 1 template2)))
+ (should-not (equal id1 id2))))))
+
+(provide 'test-org-noter--generate-notes-template)
+;;; test-org-noter--generate-notes-template.el ends here
diff --git a/tests/test-org-noter--title-to-slug.el b/tests/test-org-noter--title-to-slug.el
new file mode 100644
index 00000000..b6880cf6
--- /dev/null
+++ b/tests/test-org-noter--title-to-slug.el
@@ -0,0 +1,100 @@
+;;; test-org-noter--title-to-slug.el --- Tests for cj/org-noter--title-to-slug -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; ERT tests for the title-to-slug function used in org-noter workflow.
+;; Tests cover normal, boundary, and error cases.
+
+;;; Code:
+
+(require 'ert)
+(require 'org-noter-config)
+
+;;; Normal Cases
+
+(ert-deftest test-org-noter--title-to-slug-normal-simple-title ()
+ "Normal case: Simple title with spaces."
+ (should (equal (cj/org-noter--title-to-slug "The Pragmatic Programmer")
+ "the-pragmatic-programmer")))
+
+(ert-deftest test-org-noter--title-to-slug-normal-single-word ()
+ "Normal case: Single word title."
+ (should (equal (cj/org-noter--title-to-slug "Dune")
+ "dune")))
+
+(ert-deftest test-org-noter--title-to-slug-normal-with-numbers ()
+ "Normal case: Title with numbers."
+ (should (equal (cj/org-noter--title-to-slug "1984 by George Orwell")
+ "1984-by-george-orwell")))
+
+(ert-deftest test-org-noter--title-to-slug-normal-mixed-case ()
+ "Normal case: Title with mixed case."
+ (should (equal (cj/org-noter--title-to-slug "SICP Structure and Interpretation")
+ "sicp-structure-and-interpretation")))
+
+;;; Boundary Cases
+
+(ert-deftest test-org-noter--title-to-slug-boundary-special-chars ()
+ "Boundary case: Title with special characters."
+ (should (equal (cj/org-noter--title-to-slug "C++: The Complete Guide")
+ "c-the-complete-guide")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-punctuation ()
+ "Boundary case: Title with punctuation."
+ (should (equal (cj/org-noter--title-to-slug "Why's (Poignant) Guide to Ruby")
+ "why-s-poignant-guide-to-ruby")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-leading-special ()
+ "Boundary case: Title starting with special character."
+ (should (equal (cj/org-noter--title-to-slug "...And Then There Were None")
+ "and-then-there-were-none")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-trailing-special ()
+ "Boundary case: Title ending with special character."
+ (should (equal (cj/org-noter--title-to-slug "What Is This Thing Called Love?")
+ "what-is-this-thing-called-love")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-multiple-spaces ()
+ "Boundary case: Title with multiple consecutive spaces."
+ (should (equal (cj/org-noter--title-to-slug "The Great Gatsby")
+ "the-great-gatsby")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-underscores ()
+ "Boundary case: Title with underscores."
+ (should (equal (cj/org-noter--title-to-slug "file_name_example")
+ "file-name-example")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-hyphens ()
+ "Boundary case: Title with existing hyphens."
+ (should (equal (cj/org-noter--title-to-slug "Self-Reliance")
+ "self-reliance")))
+
+(ert-deftest test-org-noter--title-to-slug-boundary-all-numbers ()
+ "Boundary case: Title that is all numbers."
+ (should (equal (cj/org-noter--title-to-slug "2001")
+ "2001")))
+
+;;; Edge Cases
+
+(ert-deftest test-org-noter--title-to-slug-edge-empty-string ()
+ "Edge case: Empty string."
+ (should (equal (cj/org-noter--title-to-slug "")
+ "")))
+
+(ert-deftest test-org-noter--title-to-slug-edge-only-special-chars ()
+ "Edge case: Only special characters."
+ (should (equal (cj/org-noter--title-to-slug "!@#$%^&*()")
+ "")))
+
+(ert-deftest test-org-noter--title-to-slug-edge-unicode ()
+ "Edge case: Title with unicode characters."
+ (should (equal (cj/org-noter--title-to-slug "Café au Lait")
+ "caf-au-lait")))
+
+(ert-deftest test-org-noter--title-to-slug-edge-long-title ()
+ "Edge case: Very long title."
+ (let ((long-title "The Absolutely Incredibly Long Title of This Book That Goes On and On"))
+ (should (equal (cj/org-noter--title-to-slug long-title)
+ "the-absolutely-incredibly-long-title-of-this-book-that-goes-on-and-on"))))
+
+(provide 'test-org-noter--title-to-slug)
+;;; test-org-noter--title-to-slug.el ends here