defmodule BlogexTest do @moduledoc """ Behaviour tests for the `Blogex` facade. The facade is a thin delegating layer over `Blogex.Registry`, but callers (Phoenix controllers, LiveViews) only ever see the answers, so these tests assert the answers: the exact module lists, post orderings and tag sets the fixtures imply. Asserting `Blogex.x() == Blogex.Registry.x()` would pin the delegation instead of the behaviour and would keep passing if both sides drifted together. Non-async: the registry is configured through the process-global `:blogex` application env. """ use ExUnit.Case alias Blogex.Test.{AlphaBlog, BetaBlog} setup do Application.put_env(:blogex, :blogs, [AlphaBlog, BetaBlog]) on_exit(fn -> Application.delete_env(:blogex, :blogs) end) end describe "blogs/0" do test "returns the configured blog modules" do assert Blogex.blogs() == [AlphaBlog, BetaBlog] end end describe "get_blog!/1 and get_blog/1" do test "return the module registered for a blog_id" do assert Blogex.get_blog!(:alpha) == AlphaBlog assert Blogex.get_blog(:beta) == BetaBlog end test "an unknown blog_id returns nil and raises" do assert Blogex.get_blog(:nope) == nil assert_raise Blogex.NotFoundError, fn -> Blogex.get_blog!(:nope) end end end describe "all_posts/0" do # Newest first across both blogs: beta's 2026-03-15 post, then alpha's # 2026-03-01. Drafts (a-draft) and future-dated posts (b-future) are not # visible to readers, so neither appears. test "merges published posts from every blog, newest first" do assert ids(Blogex.all_posts()) == ["b1", "a1"] end end describe "all_posts_unfiltered/0" do # Everything, newest first: the 2099 scheduled post, then b1, the alpha # draft, and alpha's oldest. test "includes drafts and future-dated posts, newest first" do assert ids(Blogex.all_posts_unfiltered()) == ["b-future", "b1", "a-draft", "a1"] end end describe "all_tags/0" do test "returns the unique tags across blogs, sorted" do assert Blogex.all_tags() == ["devops", "elixir"] end end defp ids(posts), do: Enum.map(posts, & &1.id) end