85 lines
2.7 KiB
Elixir
85 lines
2.7 KiB
Elixir
defmodule MvWeb.Helpers.JoinDescriptionRendererTest do
|
|
@moduledoc """
|
|
Tests for the join-description renderer that auto-links raw URLs and Markdown
|
|
links while escaping all other content.
|
|
"""
|
|
use ExUnit.Case, async: true
|
|
use ExUnitProperties
|
|
|
|
alias MvWeb.Helpers.JoinDescriptionRenderer
|
|
|
|
defp html(value) do
|
|
value
|
|
|> JoinDescriptionRenderer.render()
|
|
|> Phoenix.HTML.safe_to_string()
|
|
end
|
|
|
|
describe "render/1" do
|
|
test "converts a raw URL to an anchor tag" do
|
|
result = html("Akzeptiere https://example.com/dsgvo")
|
|
|
|
assert result =~ ~s(<a href="https://example.com/dsgvo")
|
|
assert result =~ "https://example.com/dsgvo</a>"
|
|
assert result =~ "Akzeptiere "
|
|
end
|
|
|
|
test "converts Markdown [text](url) to an anchor tag with the link text" do
|
|
result = html("[Datenschutzerklärung](https://example.com/dsgvo)")
|
|
|
|
assert result =~ ~s(<a href="https://example.com/dsgvo")
|
|
assert result =~ ">Datenschutzerklärung</a>"
|
|
end
|
|
|
|
test "returns an empty safe string for nil input" do
|
|
assert JoinDescriptionRenderer.render(nil) == {:safe, ""}
|
|
end
|
|
|
|
test "escapes arbitrary HTML in non-link text" do
|
|
result = html("<script>alert(1)</script>")
|
|
|
|
refute result =~ "<script>"
|
|
assert result =~ "<script>"
|
|
end
|
|
|
|
test "does not double-link a Markdown link whose URL also looks like a raw URL" do
|
|
result = html("[Datenschutz](https://example.com/x)")
|
|
|
|
# exactly one anchor, no nested anchor for the inner raw URL
|
|
assert result |> :binary.matches("<a ") |> length() == 1
|
|
end
|
|
end
|
|
|
|
describe "property: link-free text" do
|
|
property "preserves non-link text content as HTML-escaped output" do
|
|
check all(text <- link_free_string()) do
|
|
result = html(text)
|
|
|
|
# No links emitted, and text content equals the HTML-escaped input.
|
|
refute result =~ "<a "
|
|
assert result == Phoenix.HTML.html_escape(text) |> Phoenix.HTML.safe_to_string()
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "property: well-formed Markdown links" do
|
|
property "renders every [text](https://...) as a single anchor with verbatim text and url" do
|
|
check all(
|
|
label <- string(:alphanumeric, min_length: 1),
|
|
path <- string(:alphanumeric)
|
|
) do
|
|
url = "https://example.com/#{path}"
|
|
result = html("[#{label}](#{url})")
|
|
|
|
assert result =~ ~s(<a href="#{url}">#{label}</a>)
|
|
assert result |> :binary.matches("<a ") |> length() == 1
|
|
end
|
|
end
|
|
end
|
|
|
|
# Printable strings that contain no bare URLs and no Markdown-link opening bracket.
|
|
defp link_free_string do
|
|
:printable
|
|
|> string()
|
|
|> filter(fn s -> not String.contains?(s, "http") and not String.contains?(s, "[") end)
|
|
end
|
|
end
|