firehose/blogex/test/blogex/blog_test.exs
2026-04-01 20:39:19 +00:00

193 lines
4.9 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 "excludes future-dated posts", %{blog: blog} do
ids = blog.all_posts() |> Enum.map(& &1.id)
refute "future-post" in ids
end
test "includes today-dated published posts" do
{:ok, _} = FakeBlog.start([
build(id: "today", date: Date.utc_today(), published: true),
build(id: "tomorrow", date: Date.add(Date.utc_today(), 1), published: true)
])
ids = FakeBlog.all_posts() |> Enum.map(& &1.id)
assert "today" in ids
refute "tomorrow" 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 "excludes future-dated posts", %{blog: blog} do
posts = blog.recent_posts(100)
ids = Enum.map(posts, & &1.id)
refute "future-post" in ids
end
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 "excludes future-dated posts", %{blog: blog} do
posts = blog.posts_by_tag("future-only")
assert posts == []
end
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 "excludes tags only on future-dated posts", %{blog: blog} do
refute "future-only" in blog.all_tags()
end
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 "returns a future-dated published post by slug", %{blog: blog} do
post = blog.get_post!("future-post")
assert post.id == "future-post"
end
test "returns a draft post by slug", %{blog: blog} do
post = blog.get_post!("draft-post")
assert post.id == "draft-post"
end
end
describe "get_post/1" do
test "returns nil for unknown id", %{blog: blog} do
assert blog.get_post("nope") == nil
end
test "returns a future-dated post", %{blog: blog} do
assert %{id: "future-post"} = blog.get_post("future-post")
end
test "returns a draft post", %{blog: blog} do
assert %{id: "draft-post"} = blog.get_post("draft-post")
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