Goal: have a personal blog, and try out another point in the 'modular app design with elixir' space. Designing OTP systems with elixir had some interesting ideas.
124 lines
2.9 KiB
Elixir
124 lines
2.9 KiB
Elixir
defmodule Blogex.RouterTest do
|
|
use ExUnit.Case
|
|
use 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])
|
|
]
|
|
|
|
{: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
|
|
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 404 for draft post" do
|
|
conn = call(:get, "/draft")
|
|
|
|
assert conn.status == 404
|
|
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 "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
|
|
end
|
|
|
|
defp get_content_type(conn) do
|
|
conn
|
|
|> Plug.Conn.get_resp_header("content-type")
|
|
|> List.first("")
|
|
end
|
|
end
|