diff options
Diffstat (limited to 'tests/test-pearl-convert.el')
| -rw-r--r-- | tests/test-pearl-convert.el | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/tests/test-pearl-convert.el b/tests/test-pearl-convert.el new file mode 100644 index 0000000..4125e22 --- /dev/null +++ b/tests/test-pearl-convert.el @@ -0,0 +1,172 @@ +;;; test-pearl-convert.el --- Tests for the markdown->org conversion -*- lexical-binding: t; -*- + +;; Copyright (C) 2026 Craig Jennings + +;; Author: Craig Jennings <c@cjennings.net> + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Tests for `pearl--md-to-org' and `pearl--md-line-to-org' -- +;; the pure-elisp markdown->org conversion tier. Cover each supported +;; construct (links, inline code, bold, underscore italics, headings, bullets, +;; fenced code), the heading-safety guard, and literal pass-through. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) + +;;; inline conversion + +(ert-deftest test-pearl-convert-link () + "A markdown link becomes an org link with url and label swapped." + (should (string= "see [[https://x.y][the docs]] now" + (pearl--md-line-to-org "see [the docs](https://x.y) now")))) + +(ert-deftest test-pearl-convert-inline-code () + "Inline code backticks become org verbatim tildes." + (should (string= "call ~foo()~ here" + (pearl--md-line-to-org "call `foo()` here")))) + +(ert-deftest test-pearl-convert-bold () + "Markdown bold becomes org bold." + (should (string= "a *strong* word" (pearl--md-line-to-org "a **strong** word")))) + +(ert-deftest test-pearl-convert-italic-underscore () + "Underscore italics become org italics, but identifiers are left alone." + (should (string= "an /emphatic/ point" + (pearl--md-line-to-org "an _emphatic_ point"))) + (should (string= "the foo_bar_baz name" + (pearl--md-line-to-org "the foo_bar_baz name")))) + +;;; line / block conversion + +(ert-deftest test-pearl-convert-heading-to-bold () + "A markdown heading becomes a bold line, never an org heading." + (let ((out (pearl--md-to-org "## Big Heading"))) + (should (string= "*Big Heading*" out)) + (should-not (string-match-p "^\\*+ " out)))) + +(ert-deftest test-pearl-convert-bullets () + "Markdown `*' and `+' bullets become org `-' bullets." + (should (string= "- one\n- two" + (pearl--md-to-org "* one\n+ two")))) + +(ert-deftest test-pearl-convert-fenced-code () + "A fenced code block becomes a src block, verbatim inside." + (should (string= "#+begin_src elisp\n(+ 1 2)\n#+end_src" + (pearl--md-to-org "```elisp\n(+ 1 2)\n```")))) + +(ert-deftest test-pearl-convert-code-block-is-verbatim () + "Inline markup inside a fenced block is not converted." + (let ((out (pearl--md-to-org "```\n**not bold** here\n```"))) + (should (string-match-p "\\*\\*not bold\\*\\*" out)))) + +(ert-deftest test-pearl-convert-guards-heading-line () + "A non-bullet line that Org would read as a heading is space-guarded." + (let ((out (pearl--md-to-org "** looks like a heading"))) + (should-not (string-match-p "^\\*+ " out)) + (should (string-prefix-p " " out)))) + +(ert-deftest test-pearl-convert-passes-through-plain-and-tables () + "Plain text and unsupported constructs (tables) pass through unchanged." + (should (string= "just some text" (pearl--md-to-org "just some text"))) + (should (string= "| a | b |\n|---|---|" + (pearl--md-to-org "| a | b |\n|---|---|")))) + +(ert-deftest test-pearl-convert-empty () + "An empty or nil description converts to the empty string." + (should (string= "" (pearl--md-to-org ""))) + (should (string= "" (pearl--md-to-org nil)))) + +;;; org -> markdown (the push direction) + +(ert-deftest test-pearl-org-to-md-link () + "An org link becomes a markdown link with label and url swapped back." + (should (string= "see [the docs](https://x.y) now" + (pearl--org-line-to-md "see [[https://x.y][the docs]] now")))) + +(ert-deftest test-pearl-org-to-md-bare-link () + "An org link with no description becomes the bare url." + (should (string= "visit https://x.y" + (pearl--org-line-to-md "visit [[https://x.y]]")))) + +(ert-deftest test-pearl-org-to-md-inline-code () + "Org verbatim tildes become markdown backticks." + (should (string= "call `foo()` here" + (pearl--org-line-to-md "call ~foo()~ here")))) + +(ert-deftest test-pearl-org-to-md-bold () + "Org bold becomes markdown bold." + (should (string= "a **strong** word" (pearl--org-line-to-md "a *strong* word")))) + +(ert-deftest test-pearl-org-to-md-italic () + "Org italics become underscore italics, but paths are left alone." + (should (string= "an _emphatic_ point" + (pearl--org-line-to-md "an /emphatic/ point"))) + (should (string= "the /usr/local/bin path" + (pearl--org-line-to-md "the /usr/local/bin path")))) + +(ert-deftest test-pearl-org-to-md-fenced-code () + "An org src block becomes a fenced code block, language preserved." + (should (string= "```elisp\n(+ 1 2)\n```" + (pearl--org-to-md "#+begin_src elisp\n(+ 1 2)\n#+end_src")))) + +(ert-deftest test-pearl-org-to-md-code-block-is-verbatim () + "Org markup inside a src block is not converted back." + (let ((out (pearl--org-to-md "#+begin_src\n*not bold* here\n#+end_src"))) + (should (string-match-p "\\*not bold\\* here" out)))) + +(ert-deftest test-pearl-org-to-md-quote-block () + "An org quote block becomes markdown blockquote lines." + (should (string= "> a quote\n> second line" + (pearl--org-to-md + "#+begin_quote\na quote\nsecond line\n#+end_quote")))) + +(ert-deftest test-pearl-org-to-md-checkbox-case () + "Org uppercase checkbox marks normalize to markdown lowercase." + (should (string= "- [ ] todo\n- [x] done" + (pearl--org-to-md "- [ ] todo\n- [X] done")))) + +(ert-deftest test-pearl-org-to-md-empty () + "An empty or nil body converts to the empty string." + (should (string= "" (pearl--org-to-md ""))) + (should (string= "" (pearl--org-to-md nil)))) + +(ert-deftest test-pearl-org-to-md-passes-through-tables () + "Tables and unsupported constructs pass through unchanged." + (should (string= "| a | b |\n|---|---|" + (pearl--org-to-md "| a | b |\n|---|---|")))) + +;;; round-trip: org-to-md inverts md-to-org for the supported subset + +(ert-deftest test-pearl-convert-roundtrip-identity () + "For the cleanly-supported constructs, org->md(md->org(x)) == x. +Markdown headings and single-asterisk italics are intentionally lossy (see +the conversion-tier docstring) and are excluded here." + (dolist (md '("a **strong** word" + "call `foo()` here" + "an _emphatic_ point" + "see [the docs](https://x.y) now" + "- one\n- two\n- three" + "1. first\n2. second" + "- [ ] todo\n- [x] done" + "```elisp\n(+ 1 2)\n```" + "just some plain prose" + "| a | b |\n|---|---|")) + (should (string= md (pearl--org-to-md (pearl--md-to-org md)))))) + +(provide 'test-pearl-convert) +;;; test-pearl-convert.el ends here |
