firehose/blogex/test/blogex/blog_test.exs
Your Name bc14696f57 Static blog with front page summary
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.
2026-03-17 11:17:21 +00:00

146 lines
3.6 KiB
Elixir

defmodule Blogex.BlogTest do
use ExUnit.Case
import Blogex.Test.PostBuilder
alias Blogex.Test.FakeBlog
setup do
Blogex.Test.Setup.with_blog()
end
describe "all_posts/0" do
test "excludes drafts", %{blog: blog} do
ids = blog.all_posts() |> Enum.map(& &1.id)
assert "draft-post" not in ids
end
test "returns posts newest first", %{blog: blog} do
dates = blog.all_posts() |> Enum.map(& &1.date)
assert dates == Enum.sort(dates, {:desc, Date})
end
end
describe "recent_posts/1" do
test "returns at most n posts", %{blog: blog} do
assert length(blog.recent_posts(2)) == 2
end
test "returns newest posts", %{blog: blog} do
[first | _] = blog.recent_posts(1)
assert first.id == "newest-post"
end
end
describe "posts_by_tag/1" do
test "returns only posts with the given tag", %{blog: blog} do
posts = blog.posts_by_tag("testing")
assert [%{id: "middle-post"}] = posts
end
test "returns empty list for unknown tag", %{blog: blog} do
assert blog.posts_by_tag("nonexistent") == []
end
test "excludes drafts even if tag matches" do
{:ok, _} = FakeBlog.start([
build(id: "pub", tags: ["elixir"], published: true),
build(id: "draft", tags: ["elixir"], published: false)
])
ids = FakeBlog.posts_by_tag("elixir") |> Enum.map(& &1.id)
assert "pub" in ids
refute "draft" in ids
end
end
describe "all_tags/0" do
test "returns unique sorted tags from published posts", %{blog: blog} do
tags = blog.all_tags()
assert tags == Enum.sort(tags)
assert "elixir" in tags
assert "devops" in tags
end
test "excludes tags only appearing on drafts" do
{:ok, _} = FakeBlog.start([
build(tags: ["visible"], published: true),
build(id: "d", tags: ["hidden"], published: false)
])
refute "hidden" in FakeBlog.all_tags()
end
end
describe "get_post!/1" do
test "returns post by id", %{blog: blog} do
post = blog.get_post!("oldest-post")
assert post.id == "oldest-post"
end
test "raises for unknown id", %{blog: blog} do
assert_raise Blogex.NotFoundError, fn ->
blog.get_post!("nope")
end
end
test "raises for draft post id", %{blog: blog} do
assert_raise Blogex.NotFoundError, fn ->
blog.get_post!("draft-post")
end
end
end
describe "get_post/1" do
test "returns nil for unknown id", %{blog: blog} do
assert blog.get_post("nope") == nil
end
end
describe "paginate/2" do
setup do
posts = build_many(25)
{:ok, _} = FakeBlog.start(posts)
%{blog: FakeBlog}
end
test "returns the correct page size", %{blog: blog} do
result = blog.paginate(1, 10)
assert length(result.entries) == 10
end
test "calculates total pages", %{blog: blog} do
result = blog.paginate(1, 10)
assert result.total_pages == 3
assert result.total_entries == 25
end
test "returns fewer entries on last page", %{blog: blog} do
result = blog.paginate(3, 10)
assert length(result.entries) == 5
end
test "page 2 does not overlap with page 1", %{blog: blog} do
page1_ids = blog.paginate(1, 10).entries |> MapSet.new(& &1.id)
page2_ids = blog.paginate(2, 10).entries |> MapSet.new(& &1.id)
assert MapSet.disjoint?(page1_ids, page2_ids)
end
test "returns empty entries beyond last page", %{blog: blog} do
result = blog.paginate(99, 10)
assert result.entries == []
end
end
end