prop/test/microwaveprop/markdown_test.exs
Graham McIntire 0429c9dbab
fix(docs): render API reference bullets correctly + tighter reading column
Two issues made docs/api hard to read:

1. The site's custom Markdown parser only recognized `- ` bullets,
   so the README's `* ` bullets rendered as a single run-on paragraph
   with literal asterisks. Extended the parser (and tests) to accept
   the full CommonMark bullet set: `-`, `*`, `+`.

2. The shared .markdown-content container is 88rem wide. Comfortable
   for /algo's wide tables but uncomfortable for monospace prose,
   which prefers ~80ch. Added a .api-docs modifier class on the
   /docs/api page that drops max-width to 60rem, allows table
   cells to wrap, and slightly downsizes headings.
2026-05-09 09:46:45 -05:00

187 lines
5 KiB
Elixir

defmodule Microwaveprop.MarkdownTest do
use ExUnit.Case, async: true
alias Microwaveprop.Markdown
describe "headings" do
test "renders h1" do
assert Markdown.to_html!("# Hello") =~ "<h1>Hello</h1>"
end
test "renders h2 through h6" do
for level <- 2..6 do
hashes = String.duplicate("#", level)
assert Markdown.to_html!("#{hashes} Title") =~ "<h#{level}>Title</h#{level}>"
end
end
test "caps at h6 for excessive hashes" do
assert Markdown.to_html!("####### Too many") =~ "<h6>"
end
end
describe "paragraphs" do
test "renders simple paragraph" do
assert Markdown.to_html!("Hello world") =~ "<p>Hello world</p>"
end
test "joins multi-line paragraphs" do
result = Markdown.to_html!("Line one\nLine two")
assert result =~ "<p>Line one Line two</p>"
end
test "separates paragraphs by blank lines" do
result = Markdown.to_html!("Para one\n\nPara two")
assert result =~ "<p>Para one</p>"
assert result =~ "<p>Para two</p>"
end
end
describe "fenced code blocks" do
test "renders code block" do
md = "```\nfoo\nbar\n```"
result = Markdown.to_html!(md)
assert result =~ "<pre><code>foo\nbar</code></pre>"
end
test "renders code block with language" do
md = "```elixir\nIO.puts(\"hi\")\n```"
result = Markdown.to_html!(md)
assert result =~ ~s(<code class="language-elixir">)
end
test "escapes HTML in code blocks" do
md = "```\n<script>alert('xss')</script>\n```"
result = Markdown.to_html!(md)
assert result =~ "&lt;script&gt;"
refute result =~ "<script>"
end
end
describe "tables" do
test "renders table with header" do
md = "| A | B |\n|---|---|\n| 1 | 2 |"
result = Markdown.to_html!(md)
assert result =~ "<thead>"
assert result =~ "<th>A</th>"
assert result =~ "<td>1</td>"
end
end
describe "lists" do
test "renders unordered list" do
md = "- one\n- two\n- three"
result = Markdown.to_html!(md)
assert result =~ "<ul>"
assert result =~ "<li>one</li>"
assert result =~ "<li>two</li>"
assert result =~ "<li>three</li>"
end
test "renders ordered list" do
md = "1. first\n2. second"
result = Markdown.to_html!(md)
assert result =~ "<ol>"
assert result =~ "<li>first</li>"
assert result =~ "<li>second</li>"
end
test "renders unordered list with * bullets" do
result = Markdown.to_html!("* one\n* two")
assert result =~ "<ul>"
assert result =~ "<li>one</li>"
assert result =~ "<li>two</li>"
end
test "renders unordered list with + bullets" do
result = Markdown.to_html!("+ alpha\n+ beta")
assert result =~ "<ul>"
assert result =~ "<li>alpha</li>"
assert result =~ "<li>beta</li>"
end
test "single-line bullet (binary < 2 bytes prefix safety)" do
assert Markdown.to_html!("*") =~ "<p>"
end
end
describe "inline formatting" do
test "renders bold with **" do
assert Markdown.to_html!("**bold**") =~ "<strong>bold</strong>"
end
test "renders bold with __" do
assert Markdown.to_html!("__bold__") =~ "<strong>bold</strong>"
end
test "renders italic with *" do
assert Markdown.to_html!("*italic*") =~ "<em>italic</em>"
end
test "renders inline code" do
assert Markdown.to_html!("`code`") =~ "<code>code</code>"
end
test "renders links" do
assert Markdown.to_html!("[text](http://example.com)") =~ ~s(<a href="http://example.com">text</a>)
end
end
describe "list continuation" do
test "continues unordered list items with indentation" do
md = "- item one\n continued\n- item two"
result = Markdown.to_html!(md)
assert result =~ "<li>item one continued</li>"
assert result =~ "<li>item two</li>"
end
end
describe "table without separator" do
test "renders table body only when no separator row" do
md = "| A | B |"
result = Markdown.to_html!(md)
assert result =~ "<tbody>"
refute result =~ "<thead>"
end
end
describe "CRLF handling" do
test "normalizes CRLF to LF" do
result = Markdown.to_html!("Hello\r\nworld")
assert result =~ "<p>Hello world</p>"
end
end
describe "empty input" do
test "handles empty string" do
assert Markdown.to_html!("") == ""
end
end
describe "horizontal rules" do
test "renders --- as hr" do
assert Markdown.to_html!("---") =~ "<hr />"
end
test "renders *** as hr" do
assert Markdown.to_html!("***") =~ "<hr />"
end
test "renders ___ as hr" do
assert Markdown.to_html!("___") =~ "<hr />"
end
end
describe "HTML escaping" do
test "escapes angle brackets in paragraphs" do
result = Markdown.to_html!("x < y > z")
assert result =~ "&lt;"
assert result =~ "&gt;"
end
test "escapes ampersands" do
result = Markdown.to_html!("a & b")
assert result =~ "&amp;"
end
end
end