108 lines
2.5 KiB
Elixir
108 lines
2.5 KiB
Elixir
defmodule Blogex.Test.FakeBlog do
|
|
@moduledoc """
|
|
A test double that implements the same interface as a `use Blogex.Blog`
|
|
module, but backed by an Agent so tests can control the post data.
|
|
|
|
## Usage in tests
|
|
|
|
setup do
|
|
posts = [PostBuilder.build(id: "hello"), PostBuilder.build(id: "world")]
|
|
Blogex.Test.FakeBlog.start(posts, blog_id: :engineering, title: "Eng Blog")
|
|
:ok
|
|
end
|
|
|
|
Then pass `Blogex.Test.FakeBlog` anywhere a blog module is expected.
|
|
"""
|
|
|
|
use Agent
|
|
|
|
@defaults [
|
|
blog_id: :test_blog,
|
|
title: "Test Blog",
|
|
description: "A blog for tests",
|
|
base_path: "/blog/test"
|
|
]
|
|
|
|
def start(posts \\ [], opts \\ []) do
|
|
opts = Keyword.merge(@defaults, opts)
|
|
|
|
state = %{
|
|
posts: posts,
|
|
blog_id: opts[:blog_id],
|
|
title: opts[:title],
|
|
description: opts[:description],
|
|
base_path: opts[:base_path]
|
|
}
|
|
|
|
case Agent.start(fn -> state end, name: __MODULE__) do
|
|
{:ok, pid} -> {:ok, pid}
|
|
{:error, {:already_started, pid}} ->
|
|
Agent.update(__MODULE__, fn _ -> state end)
|
|
{:ok, pid}
|
|
end
|
|
end
|
|
|
|
def stop, do: Agent.stop(__MODULE__)
|
|
|
|
defp get(key), do: Agent.get(__MODULE__, &Map.fetch!(&1, key))
|
|
|
|
def blog_id, do: get(:blog_id)
|
|
def title, do: get(:title)
|
|
def description, do: get(:description)
|
|
def base_path, do: get(:base_path)
|
|
|
|
def unfiltered_posts do
|
|
get(:posts)
|
|
|> Enum.sort_by(& &1.date, {:desc, Date})
|
|
end
|
|
|
|
def all_posts do
|
|
today = Date.utc_today()
|
|
|
|
get(:posts)
|
|
|> Enum.filter(&(&1.published and not Date.after?(&1.date, today)))
|
|
|> Enum.sort_by(& &1.date, {:desc, Date})
|
|
end
|
|
|
|
def recent_posts(n \\ 5), do: Enum.take(all_posts(), n)
|
|
|
|
def all_tags do
|
|
all_posts()
|
|
|> Enum.flat_map(& &1.tags)
|
|
|> Enum.uniq()
|
|
|> Enum.sort()
|
|
end
|
|
|
|
def posts_by_tag(tag) do
|
|
Enum.filter(all_posts(), fn post -> tag in post.tags end)
|
|
end
|
|
|
|
def get_post!(id) do
|
|
Enum.find(unfiltered_posts(), &(&1.id == id)) ||
|
|
raise Blogex.NotFoundError, "post #{inspect(id)} not found"
|
|
end
|
|
|
|
def get_post(id) do
|
|
Enum.find(unfiltered_posts(), &(&1.id == id))
|
|
end
|
|
|
|
def paginate(page \\ 1, per_page \\ 10) do
|
|
posts = all_posts()
|
|
total = length(posts)
|
|
total_pages = max(ceil(total / per_page), 1)
|
|
|
|
entries =
|
|
posts
|
|
|> Enum.drop((page - 1) * per_page)
|
|
|> Enum.take(per_page)
|
|
|
|
%{
|
|
entries: entries,
|
|
page: page,
|
|
per_page: per_page,
|
|
total_entries: total,
|
|
total_pages: total_pages
|
|
}
|
|
end
|
|
end
|