yak(link-validator-never-sees-compiled-html-internal-link-validation-is-vacuous-ddd1): Link validator never sees compiled HTML — internal-link validation is vacuous

This commit is contained in:
Willem van den Ende
2026-10-28 22:08:45 +00:00
parent 4e7798c906
commit c04d8c856c
8 changed files with 175 additions and 19 deletions
+1
View File
@@ -19,6 +19,7 @@
"file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"},
"finch": {:hex, :finch, "0.24.0", "4022b6194e907b6d9b597c168001cac38e488a35fe36cef9d8297e3159782510", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.8", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "33ba40069c3587c2f99f9125b766e19dad87d6d54be3c6961db2304df04cef00"},
"fine": {:hex, :fine, "0.1.6", "4bf7151493443c454aac9f2fa2f34f5fefd0346a83fb5586a016c4a135c63247", [:mix], [], "hexpm", "5638eb4495488e885ebec167fa57973e5c35e1a50c344eb7666c90ec1c4e3b12"},
"floki": {:hex, :floki, "0.38.4", "10f98971e892aed2c2f1b3a0f928e488e3797e1c6dd3dfd98db40b14e9a78bcf", [:mix], [], "hexpm", "bdb34645eee8e79845c7edaca2d4099a52804ee4d4a3ecc683a69451f0244973"},
"gen_smtp": {:hex, :gen_smtp, "1.3.0", "62c3d91f0dcf6ce9db71bcb6881d7ad0d1d834c7f38c13fa8e952f4104a8442e", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "0b73fbf069864ecbce02fe653b16d3f35fd889d0fdd4e14527675565c39d84e6"},
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "0435d4ca364a608cc75e2f8683d374e55abbae26", [tag: "v2.2.0", sparse: "optimized", depth: 1]},
@@ -88,6 +88,49 @@ defmodule FirehoseWeb.BlogTest do
end
end
describe "internal links in compiled posts" do
# `Blogex.Blog._validate_links/2` validates `post.body` after
# NimblePublisher rendered it to HTML. If extraction cannot read that HTML,
# every post looks link-free and compile-time validation is vacuous - which
# is the failure the real posts below pin against.
defp posts_with_internal_links do
Enum.filter(Firehose.EngineeringBlog.all_posts(), fn post ->
Blogex.LinkValidator.extract_links(post.body) != []
end)
end
test "the validator sees internal links in real compiled posts" do
refute posts_with_internal_links() == []
end
test "the post that links to swim-the-test exposes that link" do
post =
Enum.find(posts_with_internal_links(), &(&1.id == "delayed-gratification-in-ai-summer"))
assert post, "expected the compiled post to be visible with internal links extracted"
assert "/blog/engineering/swim-the-test" in Blogex.LinkValidator.extract_links(post.body)
end
test "no internal link in a real compiled post is invisible to extraction" do
# Deliberately permissive scan (any <a> whose href appears in any
# position, quoted or not): every /blog/ link it finds must also come out
# of extract_links/1, or a bad one could never be reported.
links_in_body = fn body ->
~r/<a\s[^>]*?href=["']?(\/blog\/[^"'\s>]+)/
|> Regex.scan(body)
|> Enum.map(fn [_, link] -> link end)
|> Enum.uniq()
end
for post <- Firehose.EngineeringBlog.all_posts(),
link <- links_in_body.(post.body) do
assert link in Blogex.LinkValidator.extract_links(post.body),
"#{post.id}: #{link} is in the compiled body but not extracted"
end
end
end
describe "input validation" do
test "GET /blog/nonexistent returns 404", %{conn: conn} do
assert conn |> get("/blog/nonexistent") |> html_response(404)