Files
firehose/blogex/test/blogex/router_test.exs
T
Firehose Bot c5db0cbda8 Fix compile-time link validation and add tag page links
- Restore HTML link extraction in LinkValidator (removed in a83634d
  under the false premise that post bodies are raw markdown; they
  are HTML rendered by NimblePublisher at compile time). The missing
  regex made extract_links/1 find zero links, silently disabling
  compile-time validation.
- Support /blog/{blog_id}/tag/{tag} links: validate blog ID,
  require non-empty tag (tags are user-defined, e.g. pi.dev).
- Fix invalid links in two posts: tag/Pi.dev -> tag/pi.dev,
  2026-07-13-synthetic-tdd.md -> synthetic-tdd.
- Fix test warnings: use Plug.Test deprecation, unused import,
  runtime-defined TestBlogValid module.
- Add regression tests for HTML extraction and tag page links.
2026-10-08 08:43:51 +01:00

162 lines
3.9 KiB
Elixir

defmodule Blogex.RouterTest do
use ExUnit.Case
import Plug.Test
import Blogex.Test.PostBuilder
alias Blogex.Test.FakeBlog
setup do
posts = [
build(id: "first-post", title: "First", tags: ["elixir"], date: ~D[2026-03-10]),
build(id: "second-post", title: "Second", tags: ["otp"], date: ~D[2026-02-01]),
build(id: "draft", published: false, date: ~D[2026-03-12]),
build(
id: "future-post",
title: "Future",
tags: ["elixir"],
date: ~D[2099-01-01],
published: true
)
]
{:ok, _} =
FakeBlog.start(posts,
blog_id: :test,
title: "Test Blog",
description: "Test",
base_path: "/blog/test"
)
:ok
end
defp call(method, path) do
conn(method, path)
|> Blogex.Router.call(Blogex.Router.init(blog: FakeBlog))
end
describe "GET /feed.xml" do
test "returns RSS XML" do
conn = call(:get, "/feed.xml")
assert conn.status == 200
assert get_content_type(conn) =~ "application/rss+xml"
assert conn.resp_body =~ "<rss version=\"2.0\""
end
test "includes published posts" do
conn = call(:get, "/feed.xml")
assert conn.resp_body =~ "first-post"
refute conn.resp_body =~ "draft"
end
test "excludes future-dated posts from feed" do
conn = call(:get, "/feed.xml")
refute conn.resp_body =~ "future-post"
end
end
describe "GET /atom.xml" do
test "returns Atom XML" do
conn = call(:get, "/atom.xml")
assert conn.status == 200
assert get_content_type(conn) =~ "application/atom+xml"
assert conn.resp_body =~ "<feed xmlns="
end
end
describe "GET /:slug" do
test "returns post as JSON" do
conn = call(:get, "/first-post")
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert body["id"] == "first-post"
assert body["title"] == "First"
end
test "returns 404 for unknown slug" do
conn = call(:get, "/nonexistent")
assert conn.status == 404
end
test "returns 200 for draft post accessed by slug" do
conn = call(:get, "/draft")
assert conn.status == 200
end
test "returns 200 for future-dated post accessed by slug" do
conn = call(:get, "/future-post")
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert body["id"] == "future-post"
end
end
describe "GET /tag/:tag" do
test "returns posts matching tag" do
conn = call(:get, "/tag/elixir")
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert body["tag"] == "elixir"
assert length(body["posts"]) == 1
assert hd(body["posts"])["id"] == "first-post"
end
test "excludes future-dated posts from tag results" do
conn = call(:get, "/tag/elixir")
body = Jason.decode!(conn.resp_body)
ids = Enum.map(body["posts"], & &1["id"])
refute "future-post" in ids
end
test "returns empty list for unknown tag" do
conn = call(:get, "/tag/unknown")
body = Jason.decode!(conn.resp_body)
assert body["posts"] == []
end
end
describe "GET /" do
test "returns paginated post list" do
conn = call(:get, "/")
assert conn.status == 200
body = Jason.decode!(conn.resp_body)
assert is_list(body["posts"])
assert body["total_entries"] == 2
end
test "excludes draft posts from listing" do
conn = call(:get, "/")
body = Jason.decode!(conn.resp_body)
ids = Enum.map(body["posts"], & &1["id"])
refute "draft" in ids
end
test "excludes future-dated posts from listing" do
conn = call(:get, "/")
body = Jason.decode!(conn.resp_body)
ids = Enum.map(body["posts"], & &1["id"])
refute "future-post" in ids
end
end
defp get_content_type(conn) do
conn
|> Plug.Conn.get_resp_header("content-type")
|> List.first("")
end
end