Merge branch 'chore-test-coverage' into 'master'
chore: Increase test coverage throughout the framework See merge request mythic-insight/legendary!119
This commit is contained in:
commit
6893fc8d23
35 changed files with 573 additions and 126 deletions
|
@ -9,10 +9,11 @@ defmodule AppWeb.LiveHelpers do
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_auth(socket) do
|
def require_auth(socket) do
|
||||||
if socket.assigns.current_user do
|
case socket.assigns do
|
||||||
socket
|
%{current_user: user} when not is_nil(user) ->
|
||||||
else
|
socket
|
||||||
redirect(socket, to: "/")
|
_ ->
|
||||||
|
redirect(socket, to: "/")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ defmodule AppWeb.Router do
|
||||||
forward "/sent_emails", Bamboo.SentEmailViewerPlug
|
forward "/sent_emails", Bamboo.SentEmailViewerPlug
|
||||||
end
|
end
|
||||||
|
|
||||||
if Mix.env() == :e2e do
|
if Mix.env() in [:e2e, :test] do
|
||||||
forward("/end-to-end", Legendary.CoreWeb.Plug.TestEndToEnd, otp_app: :app)
|
forward("/end-to-end", Legendary.CoreWeb.Plug.TestEndToEnd, otp_app: :app)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,12 @@ defmodule AppWeb.ErrorHelpers do
|
||||||
@doc """
|
@doc """
|
||||||
Generates tag for inlined form input errors.
|
Generates tag for inlined form input errors.
|
||||||
"""
|
"""
|
||||||
def error_tag(form, field) do
|
def error_tag(form, field, opts \\ []) do
|
||||||
|
{extra_classes, _rest_opts} = Keyword.pop(opts, :class, "")
|
||||||
|
|
||||||
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
||||||
content_tag(:span, translate_error(error),
|
content_tag(:span, translate_error(error),
|
||||||
class: "invalid-feedback",
|
class: "invalid-feedback #{extra_classes}",
|
||||||
phx_feedback_for: input_id(form, field)
|
phx_feedback_for: input_id(form, field)
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
29
apps/app/test/app_web/error_helpers_test.exs
Normal file
29
apps/app/test/app_web/error_helpers_test.exs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
defmodule AppWeb.ErrorHelpersTest do
|
||||||
|
use AppWeb.ConnCase
|
||||||
|
|
||||||
|
import Phoenix.HTML, only: [safe_to_string: 1]
|
||||||
|
import Phoenix.HTML.Form, only: [form_for: 3]
|
||||||
|
|
||||||
|
import AppWeb.ErrorHelpers
|
||||||
|
|
||||||
|
def form do
|
||||||
|
:example
|
||||||
|
|> form_for(
|
||||||
|
"/example",
|
||||||
|
as: :test_params,
|
||||||
|
errors: [error_field: {"is an error", []}]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "error_tag/2" do
|
||||||
|
test "generates a span with an invalid-feedback class" do
|
||||||
|
[safe] = error_tag(form(), :error_field)
|
||||||
|
assert safe_to_string(safe) =~ "invalid-feedback"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "error_tag/3" do
|
||||||
|
[safe] = error_tag(form(), :error_field, class: "test-class")
|
||||||
|
assert safe_to_string(safe) =~ "test-class"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
46
apps/app/test/app_web/live_helpers_test.exs
Normal file
46
apps/app/test/app_web/live_helpers_test.exs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
defmodule AppWeb.LiveHelpersText do
|
||||||
|
use AppWeb.ConnCase
|
||||||
|
|
||||||
|
import Mock
|
||||||
|
|
||||||
|
import AppWeb.LiveHelpers
|
||||||
|
|
||||||
|
describe "assign_defaults/2" do
|
||||||
|
test "sets current_user" do
|
||||||
|
{store, _store_config} = Pow.Plug.Base.store(Application.get_env(:core, :pow))
|
||||||
|
socket = %Phoenix.LiveView.Socket{endpoint: AppWeb.Endpoint}
|
||||||
|
|
||||||
|
with_mock Pow.Plug, [verify_token: fn (_, _, _, _) -> {:ok, "h3110"} end] do
|
||||||
|
with_mock store, [get: fn (_config, _token) -> {%{id: 1234}, nil} end] do
|
||||||
|
new_socket = assign_defaults(socket, %{"core_auth" => "h3ll0"})
|
||||||
|
assert %{assigns: %{current_user: %{id: 1234}}} = new_socket
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "require_auth/1" do
|
||||||
|
test "with user" do
|
||||||
|
user = %{id: 4567}
|
||||||
|
socket =
|
||||||
|
%Phoenix.LiveView.Socket{assigns: %{current_user: user}}
|
||||||
|
|> require_auth()
|
||||||
|
|
||||||
|
assert !socket.redirected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "without user" do
|
||||||
|
socket = %Phoenix.LiveView.Socket{} |> require_auth()
|
||||||
|
|
||||||
|
assert socket.redirected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "without nil user" do
|
||||||
|
socket =
|
||||||
|
%Phoenix.LiveView.Socket{assigns: %{current_user: nil}}
|
||||||
|
|> require_auth()
|
||||||
|
|
||||||
|
assert socket.redirected
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -116,15 +116,17 @@ defmodule Legendary.Content.Post do
|
||||||
|
|
||||||
def maybe_put_guid(changeset) do
|
def maybe_put_guid(changeset) do
|
||||||
import Legendary.Content.Router.Helpers, only: [url: 1, posts_url: 3]
|
import Legendary.Content.Router.Helpers, only: [url: 1, posts_url: 3]
|
||||||
slug = changeset |> get_field(:name)
|
guid = changeset |> get_field(:guid)
|
||||||
|
|
||||||
case slug do
|
case guid do
|
||||||
nil -> changeset
|
nil ->
|
||||||
_ ->
|
|
||||||
base = url(Legendary.CoreWeb.Endpoint)
|
base = url(Legendary.CoreWeb.Endpoint)
|
||||||
|
slug = changeset |> get_field(:name)
|
||||||
|
|
||||||
changeset
|
changeset
|
||||||
|> put_default(:guid, posts_url(URI.merge(base, "/pages"), :show, slug))
|
|> put_default(:guid, posts_url(URI.merge(base, "/pages"), :show, slug))
|
||||||
|
_ ->
|
||||||
|
changeset
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,7 @@ defmodule Legendary.Content.Sitemaps do
|
||||||
generate()
|
generate()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec generate :: :ok
|
||||||
def generate do
|
def generate do
|
||||||
create do
|
create do
|
||||||
add "", priority: 0.5, changefreq: "hourly", expires: nil
|
add "", priority: 0.5, changefreq: "hourly", expires: nil
|
|
@ -67,9 +67,7 @@ defmodule Legendary.Content.PostsController do
|
||||||
conn |> show_one(post, page_string)
|
conn |> show_one(post, page_string)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def show(conn, %{"id" => id, "page" => page_string}) when is_list(id) do
|
def show(conn, %{"id" => id} = params) when is_list(id), do: show(conn, Map.merge(params, %{"id" => Enum.join(id, "/")}))
|
||||||
show(conn, %{"id" => Enum.join(id, "/"), "page" => page_string})
|
|
||||||
end
|
|
||||||
def show(conn, %{"id" => id}), do: show(conn, %{"id" => id, "page" => "1"})
|
def show(conn, %{"id" => id}), do: show(conn, %{"id" => id, "page" => "1"})
|
||||||
|
|
||||||
defp try_static_post(conn, id) do
|
defp try_static_post(conn, id) do
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<atom:link href="<%= Legendary.Content.Router.Helpers.url(Legendary.CoreWeb.Endpoint) %><%= @feed_url %>" rel="self" type="application/rss+xml" />
|
<atom:link href="<%= Legendary.Content.Router.Helpers.url(Legendary.CoreWeb.Endpoint) %><%= @feed_url %>" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
<%= for post <- @posts do %>
|
<%= for post <- @posts do %>
|
||||||
|
<%= if unauthenticated_post?(post) do %>
|
||||||
<item>
|
<item>
|
||||||
<title><%= post.title |> HtmlSanitizeEx.strip_tags() %></title>
|
<title><%= post.title |> HtmlSanitizeEx.strip_tags() %></title>
|
||||||
<description>
|
<description>
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
%></pubDate>
|
%></pubDate>
|
||||||
<guid isPermaLink="true"><%= post.guid %></guid>
|
<guid isPermaLink="true"><%= post.guid %></guid>
|
||||||
</item>
|
</item>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
|
|
|
@ -8,10 +8,12 @@ defmodule Legendary.Content.ErrorHelpers do
|
||||||
@doc """
|
@doc """
|
||||||
Generates tag for inlined form input errors.
|
Generates tag for inlined form input errors.
|
||||||
"""
|
"""
|
||||||
def error_tag(form, field) do
|
def error_tag(form, field, opts \\ []) do
|
||||||
|
{extra_classes, _rest_opts} = Keyword.pop(opts, :class, "")
|
||||||
|
|
||||||
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
||||||
content_tag(:span, translate_error(error),
|
content_tag(:span, translate_error(error),
|
||||||
class: "invalid-feedback",
|
class: "invalid-feedback #{extra_classes}",
|
||||||
phx_feedback_for: input_id(form, field)
|
phx_feedback_for: input_id(form, field)
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,71 +1,10 @@
|
||||||
defmodule Legendary.Content.FeedsView do
|
defmodule Legendary.Content.FeedsView do
|
||||||
use Legendary.Content, :view
|
use Legendary.Content, :view
|
||||||
use Phoenix.HTML
|
use Phoenix.HTML
|
||||||
alias Phoenix.HTML
|
|
||||||
alias Phoenix.HTML.Tag
|
|
||||||
|
|
||||||
import Legendary.Content.LayoutView, only: [title: 3, excerpt: 3]
|
import Legendary.Content.LayoutView, only: [title: 3, excerpt: 3]
|
||||||
|
|
||||||
def gravatar_url_for_email(email) do
|
def unauthenticated_post?(post) do
|
||||||
email
|
|
||||||
|> Kernel.||("noreply@example.com")
|
|
||||||
|> String.trim()
|
|
||||||
|> String.downcase()
|
|
||||||
|> (&(:crypto.hash(:md5, &1))).()
|
|
||||||
|> Base.encode16()
|
|
||||||
|> String.downcase()
|
|
||||||
|> (&("https://www.gravatar.com/avatar/#{&1}")).()
|
|
||||||
end
|
|
||||||
|
|
||||||
def auto_paragraph_tags(string) do
|
|
||||||
string
|
|
||||||
|> Kernel.||("")
|
|
||||||
|> String.split(["\n\n", "\r\n\r\n"], trim: true)
|
|
||||||
|> Enum.map(fn text ->
|
|
||||||
[Tag.content_tag(:p, text |> HTML.raw(), []), ?\n]
|
|
||||||
end)
|
|
||||||
|> HTML.html_escape()
|
|
||||||
end
|
|
||||||
|
|
||||||
def post_class(post) do
|
|
||||||
sticky =
|
|
||||||
if post.sticky do
|
|
||||||
"sticky"
|
|
||||||
end
|
|
||||||
"post post-#{post.id} #{sticky}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def post_topmatter(conn, post) do
|
|
||||||
author =
|
|
||||||
post.author ||
|
|
||||||
%Legendary.Auth.User{
|
|
||||||
email: "example@example.org",
|
|
||||||
display_name: "Anonymous",
|
|
||||||
homepage_url: "#"
|
|
||||||
}
|
|
||||||
assigns = %{post: post, author: author, conn: conn}
|
|
||||||
~E"""
|
|
||||||
<% _ = assigns # suppress unused assigns warning %>
|
|
||||||
<div class="Comment-topmatter">
|
|
||||||
|
|
||||||
<h4>
|
|
||||||
<%= link to: author.homepage_url || "#", rel: "author", class: "p-author h-card" do %>
|
|
||||||
<%= author.display_name %>
|
|
||||||
<%= img_tag gravatar_url_for_email(author.email), alt: "Photo of #{author.display_name}", class: "Gravatar u-photo" %>
|
|
||||||
<% end %>
|
|
||||||
</h4>
|
|
||||||
<h5>
|
|
||||||
<%= link to: Routes.posts_path(conn, :show, post) do %>
|
|
||||||
<time class="dt-published" datetime="<%= post.post %>">
|
|
||||||
<%= post.post |> Timex.format!("%F", :strftime) %>
|
|
||||||
</time>
|
|
||||||
<% end %>
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
def unauthenticated_post?(_conn, post) do
|
|
||||||
post.password == nil || String.length(post.password) == 0
|
post.password == nil || String.length(post.password) == 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,8 +45,32 @@ defmodule Legendary.Content.PostsTest do
|
||||||
assert %Post{} = Posts.get_post_with_drafts!(Integer.to_string(id))
|
assert %Post{} = Posts.get_post_with_drafts!(Integer.to_string(id))
|
||||||
end
|
end
|
||||||
|
|
||||||
test "update_posts/2", %{public_post: post} do
|
describe "update_posts/2" do
|
||||||
assert {:ok, %Post{content: "boop"}} = Posts.update_posts(post, %{content: "boop"})
|
setup do
|
||||||
|
post_with_guid =
|
||||||
|
%Post{
|
||||||
|
title: "Post with guid",
|
||||||
|
name: "post-with-guid",
|
||||||
|
status: "publish",
|
||||||
|
type: "post",
|
||||||
|
guid: "/beep",
|
||||||
|
date: ~N[2020-01-01T00:00:00],
|
||||||
|
}
|
||||||
|
|> Repo.insert!()
|
||||||
|
|
||||||
|
%{
|
||||||
|
post_with_guid: post_with_guid
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with no guid", %{public_post: post} do
|
||||||
|
assert {:ok, %Post{content: "boop"}} = Posts.update_posts(post, %{content: "boop"})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with an existing guid", %{post_with_guid: post} do
|
||||||
|
revised_post = Posts.update_posts(post, %{content: "boop"})
|
||||||
|
assert {:ok, %Post{content: "boop", guid: "/beep"}} = revised_post
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "delete_posts/1", %{public_post: post} do
|
test "delete_posts/1", %{public_post: post} do
|
||||||
|
|
38
apps/content/test/content/sitemap_storage_test.exs
Normal file
38
apps/content/test/content/sitemap_storage_test.exs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
defmodule Legendary.Content.SitemapStorageTest do
|
||||||
|
use Legendary.Content.DataCase
|
||||||
|
|
||||||
|
import Legendary.Content.SitemapStorage
|
||||||
|
alias Sitemap.Location
|
||||||
|
alias Legendary.Content.{Post, Repo}
|
||||||
|
|
||||||
|
test "creates a post with the content" do
|
||||||
|
data = "<hello />"
|
||||||
|
content = data |> :zlib.gzip() |> Base.encode64
|
||||||
|
write(:file, data)
|
||||||
|
path = Location.filename(:file)
|
||||||
|
|
||||||
|
post = from(p in Post, where: p.name == ^path) |> Repo.one()
|
||||||
|
|
||||||
|
assert post.content == content
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updates an existing sitemap" do
|
||||||
|
path = Location.filename(:file)
|
||||||
|
|
||||||
|
%Post{
|
||||||
|
content: "<hello />" |> :zlib.gzip() |> Base.encode64,
|
||||||
|
name: path
|
||||||
|
}
|
||||||
|
|> Repo.insert!()
|
||||||
|
|
||||||
|
new_data = "<world />"
|
||||||
|
new_content = new_data |> :zlib.gzip() |> Base.encode64
|
||||||
|
|
||||||
|
write(:file, new_data)
|
||||||
|
|
||||||
|
|
||||||
|
post = from(p in Post, where: p.name == ^path) |> Repo.one()
|
||||||
|
|
||||||
|
assert post.content == new_content
|
||||||
|
end
|
||||||
|
end
|
78
apps/content/test/content/sitemaps_test.exs
Normal file
78
apps/content/test/content/sitemaps_test.exs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
defmodule Legendary.Content.SitemapsTest do
|
||||||
|
use Legendary.Content.DataCase
|
||||||
|
|
||||||
|
alias Legendary.Content.{Post, Repo}
|
||||||
|
|
||||||
|
import Mock
|
||||||
|
|
||||||
|
import Legendary.Content.Sitemaps
|
||||||
|
|
||||||
|
@xml ~s(
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset
|
||||||
|
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||||
|
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
|
||||||
|
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
|
||||||
|
xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'
|
||||||
|
xmlns:geo='http://www.google.com/geo/schemas/sitemap/1.0'
|
||||||
|
xmlns:news='http://www.google.com/schemas/sitemap-news/0.9'
|
||||||
|
xmlns:image='http://www.google.com/schemas/sitemap-image/1.1'
|
||||||
|
xmlns:video='http://www.google.com/schemas/sitemap-video/1.1'
|
||||||
|
xmlns:mobile='http://www.google.com/schemas/sitemap-mobile/1.0'
|
||||||
|
xmlns:pagemap='http://www.google.com/schemas/sitemap-pagemap/1.0'
|
||||||
|
xmlns:xhtml='http://www.w3.org/1999/xhtml'
|
||||||
|
>
|
||||||
|
<url>
|
||||||
|
<loc>https://localhost</loc>
|
||||||
|
<lastmod>2021-08-19T21:44:37Z</lastmod>
|
||||||
|
<changefreq>hourly</changefreq>
|
||||||
|
<priority>0.5</priority>
|
||||||
|
</url><url>
|
||||||
|
<loc>https://localhost/public-post</loc>
|
||||||
|
<lastmod>2021-08-19T21:44:37Z</lastmod>
|
||||||
|
<changefreq>hourly</changefreq>
|
||||||
|
<priority>0.5</priority>
|
||||||
|
</url><url>
|
||||||
|
<loc>https://localhost/public-post?page=2</loc>
|
||||||
|
<lastmod>2021-08-19T21:44:37Z</lastmod>
|
||||||
|
<changefreq>hourly</changefreq>
|
||||||
|
<priority>0.5</priority>
|
||||||
|
</url></urlset>
|
||||||
|
)
|
||||||
|
|
||||||
|
describe "generate/0" do
|
||||||
|
setup do
|
||||||
|
public_post =
|
||||||
|
%Post{
|
||||||
|
title: "Public post",
|
||||||
|
name: "public-post",
|
||||||
|
status: "publish",
|
||||||
|
type: "post",
|
||||||
|
date: ~N[2020-01-01T00:00:00],
|
||||||
|
content: """
|
||||||
|
Page 1
|
||||||
|
<!--nextpage-->
|
||||||
|
Page 2
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|> Repo.insert!()
|
||||||
|
|
||||||
|
%{
|
||||||
|
public_post: public_post,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "generates results" do
|
||||||
|
with_mock Sitemap.Funcs, [
|
||||||
|
iso8601: fn -> "2021-08-19T21:44:37Z" end,
|
||||||
|
iso8601: & &1,
|
||||||
|
eraser: fn (elm) -> passthrough([elm]) end
|
||||||
|
] do
|
||||||
|
with_mock Legendary.Content.SitemapStorage, [write: fn (_name, _data) -> :ok end] do
|
||||||
|
assert :ok = perform(%{})
|
||||||
|
assert_called Legendary.Content.SitemapStorage.write(:file, String.trim(@xml))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Legendary.Content.PostsControllerTest do
|
defmodule Legendary.Content.PostsControllerTest do
|
||||||
use Legendary.Content.ConnCase
|
use Legendary.Content.ConnCase
|
||||||
|
|
||||||
alias Legendary.Content.{Comment, Options, Posts, Repo, Term, TermRelationship, TermTaxonomy}
|
alias Legendary.Content.{Comment, Options, Post, Posts, Repo, Term, TermRelationship, TermTaxonomy}
|
||||||
|
|
||||||
@create_attrs %{
|
@create_attrs %{
|
||||||
id: 123,
|
id: 123,
|
||||||
|
@ -165,6 +165,21 @@ defmodule Legendary.Content.PostsControllerTest do
|
||||||
assert html_response(conn, 200)
|
assert html_response(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "shows the post if the id has slashes", %{conn: conn} do
|
||||||
|
%Post{
|
||||||
|
name: "a/b/c",
|
||||||
|
content: "slashed id",
|
||||||
|
status: "publish",
|
||||||
|
type: "post",
|
||||||
|
date: ~N[2020-01-01T00:00:00]
|
||||||
|
}
|
||||||
|
|> Repo.insert!()
|
||||||
|
|
||||||
|
conn = get conn, Routes.nested_posts_path(conn, :show, ["a", "b", "c"])
|
||||||
|
|
||||||
|
assert html_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
test "show a 404 if there's no match", %{conn: conn} do
|
test "show a 404 if there's no match", %{conn: conn} do
|
||||||
assert_raise Phoenix.Router.NoRouteError, fn ->
|
assert_raise Phoenix.Router.NoRouteError, fn ->
|
||||||
get conn, Routes.posts_path(conn, :show, "blooper")
|
get conn, Routes.posts_path(conn, :show, "blooper")
|
||||||
|
|
29
apps/content/test/content_web/views/error_helpers_test.exs
Normal file
29
apps/content/test/content_web/views/error_helpers_test.exs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
defmodule Legendary.Content.ErrorHelpersTest do
|
||||||
|
use Legendary.Content.DataCase
|
||||||
|
|
||||||
|
import Phoenix.HTML, only: [safe_to_string: 1]
|
||||||
|
import Phoenix.HTML.Form, only: [form_for: 3]
|
||||||
|
|
||||||
|
import Legendary.Content.ErrorHelpers
|
||||||
|
|
||||||
|
def form do
|
||||||
|
:example
|
||||||
|
|> form_for(
|
||||||
|
"/example",
|
||||||
|
as: :test_params,
|
||||||
|
errors: [error_field: {"is an error", []}]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "error_tag/2" do
|
||||||
|
test "generates a span with an invalid-feedback class" do
|
||||||
|
[safe] = error_tag(form(), :error_field)
|
||||||
|
assert safe_to_string(safe) =~ "invalid-feedback"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "error_tag/3" do
|
||||||
|
[safe] = error_tag(form(), :error_field, class: "test-class")
|
||||||
|
assert safe_to_string(safe) =~ "test-class"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
apps/content/test/content_web/views/feeds_view_test.exs
Normal file
17
apps/content/test/content_web/views/feeds_view_test.exs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
defmodule Legendary.Content.FeedsViewTest do
|
||||||
|
use Legendary.Content.DataCase
|
||||||
|
|
||||||
|
import Legendary.Content.FeedsView
|
||||||
|
|
||||||
|
alias Legendary.Content.Post
|
||||||
|
|
||||||
|
describe "unauthenticated_post?/1" do
|
||||||
|
test "with post password" do
|
||||||
|
refute unauthenticated_post?(%Post{password: "password"})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "without post password" do
|
||||||
|
assert unauthenticated_post?(%Post{})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,6 +4,8 @@ defmodule Legendary.Content.PostsViewTest do
|
||||||
import Legendary.Content.PostsView
|
import Legendary.Content.PostsView
|
||||||
import Phoenix.HTML, only: [safe_to_string: 1]
|
import Phoenix.HTML, only: [safe_to_string: 1]
|
||||||
|
|
||||||
|
alias Legendary.Content.Post
|
||||||
|
|
||||||
test "auto_paragraph_tags/1 with nil" do
|
test "auto_paragraph_tags/1 with nil" do
|
||||||
assert safe_to_string(auto_paragraph_tags(nil)) =~ ""
|
assert safe_to_string(auto_paragraph_tags(nil)) =~ ""
|
||||||
end
|
end
|
||||||
|
@ -11,4 +13,22 @@ defmodule Legendary.Content.PostsViewTest do
|
||||||
test "auto_paragraph_tags/1 with text" do
|
test "auto_paragraph_tags/1 with text" do
|
||||||
assert safe_to_string(auto_paragraph_tags("Bloop\n\nBloop")) =~ "<p>Bloop</p>\n<p>Bloop</p>"
|
assert safe_to_string(auto_paragraph_tags("Bloop\n\nBloop")) =~ "<p>Bloop</p>\n<p>Bloop</p>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "authenticated_for_post?/2" do
|
||||||
|
test "without password" do
|
||||||
|
assert authenticated_for_post?(nil, %Post{})
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with post password that matches", %{conn: conn} do
|
||||||
|
with_mock Plug.Conn, [get_session: fn (_conn, :post_password) -> "password" end] do
|
||||||
|
assert authenticated_for_post?(conn, %Post{password: "password"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with post password that does not match", %{conn: conn} do
|
||||||
|
with_mock Plug.Conn, [get_session: fn (_conn, :post_password) -> "password" end] do
|
||||||
|
refute authenticated_for_post?(conn, %Post{password: "password2"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule AuthWeb.Pow.ControllerCallbacks do
|
defmodule Legendary.AuthWeb.Pow.ControllerCallbacks do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Hook into Pow Controllers to provide additional framework feature. In particular,
|
Hook into Pow Controllers to provide additional framework feature. In particular,
|
||||||
we disconnect any active live views when a user logs out. This will cause the
|
we disconnect any active live views when a user logs out. This will cause the
|
||||||
|
@ -36,6 +36,7 @@ defmodule AuthWeb.Pow.ControllerCallbacks do
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> Conn.delete_session(:live_socket_id)
|
|> Conn.delete_session(:live_socket_id)
|
||||||
|
|> Conn.delete_session(:current_user_id)
|
||||||
|
|
||||||
ControllerCallbacks.before_respond(
|
ControllerCallbacks.before_respond(
|
||||||
Pow.Phoenix.SessionController,
|
Pow.Phoenix.SessionController,
|
||||||
|
|
|
@ -16,8 +16,12 @@ defmodule Legendary.CoreWeb.Plug.TestEndToEnd do
|
||||||
send_resp(conn, 200, "connection has already been checked out")
|
send_resp(conn, 200, "connection has already been checked out")
|
||||||
else
|
else
|
||||||
{:ok, _pid} = Agent.start_link(&checkout_shared_db_conn/0, name: :db_owner_agent)
|
{:ok, _pid} = Agent.start_link(&checkout_shared_db_conn/0, name: :db_owner_agent)
|
||||||
{:ok, _} = load_test_seeds(conn)
|
case load_test_seeds(conn) do
|
||||||
send_resp(conn, 200, "connection checked out")
|
{:ok, _} ->
|
||||||
|
send_resp(conn, 200, "connection checked out")
|
||||||
|
{:error, msg} ->
|
||||||
|
send_resp(conn, 500, msg)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,7 +44,10 @@ defmodule Legendary.CoreWeb.Plug.TestEndToEnd do
|
||||||
Ecto.Repo.all_running()
|
Ecto.Repo.all_running()
|
||||||
|> Enum.map(fn repo ->
|
|> Enum.map(fn repo ->
|
||||||
:ok = Ecto.Adapters.SQL.Sandbox.checkout(repo, ownership_timeout: :infinity)
|
:ok = Ecto.Adapters.SQL.Sandbox.checkout(repo, ownership_timeout: :infinity)
|
||||||
:ok = Ecto.Adapters.SQL.Sandbox.mode(repo, {:shared, self()})
|
case Ecto.Adapters.SQL.Sandbox.mode(repo, {:shared, self()}) do
|
||||||
|
:ok -> :ok
|
||||||
|
:already_shared -> :ok
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,14 +66,16 @@ defmodule Legendary.CoreWeb.Plug.TestEndToEnd do
|
||||||
{:app, {:ok, app}} <- {:app, Map.fetch(conn.body_params, "app")},
|
{:app, {:ok, app}} <- {:app, Map.fetch(conn.body_params, "app")},
|
||||||
true <- String.match?(seed_set, @valid_seed_set_characters),
|
true <- String.match?(seed_set, @valid_seed_set_characters),
|
||||||
true <- String.match?(app, @valid_app_characters) do
|
true <- String.match?(app, @valid_app_characters) do
|
||||||
seed_path = "apps/#{app}/test/seed_sets/#{seed_set}.exs"
|
|
||||||
|
project_base = Path.expand(Path.join(__DIR__, "../../../../.."))
|
||||||
|
seed_path = Path.join(project_base, "apps/#{app}/test/seed_sets/#{seed_set}.exs")
|
||||||
|
|
||||||
try do
|
try do
|
||||||
{result, _} = Code.eval_file(seed_path)
|
{result, _} = Code.eval_file(seed_path)
|
||||||
{:ok, result}
|
{:ok, result}
|
||||||
rescue
|
rescue
|
||||||
e in Code.LoadError ->
|
e in Code.LoadError ->
|
||||||
{:error, "could not load a seed set at #{seed_path}: #{e}"}
|
{:error, e.message}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{:app, :error} -> {:error, "app parameter is required if seed set is set"}
|
{:app, :error} -> {:error, "app parameter is required if seed set is set"}
|
||||||
|
|
|
@ -31,4 +31,8 @@ defmodule Legendary.CoreWeb.Router do
|
||||||
live_dashboard "/dashboard", metrics: Legendary.CoreWeb.Telemetry
|
live_dashboard "/dashboard", metrics: Legendary.CoreWeb.Telemetry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Mix.env() in [:e2e, :test] do
|
||||||
|
forward("/end-to-end", Legendary.CoreWeb.Plug.TestEndToEnd, otp_app: :app)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,7 +48,7 @@ defmodule Legendary.CoreWeb.Helpers do
|
||||||
{type, rest_opts} = Keyword.pop(opts, :type, input_type(f, field))
|
{type, rest_opts} = Keyword.pop(opts, :type, input_type(f, field))
|
||||||
{classes, rest_opts} = Keyword.pop(rest_opts, :class, default_classes_for_type(type))
|
{classes, rest_opts} = Keyword.pop(rest_opts, :class, default_classes_for_type(type))
|
||||||
{label_text, rest_opts} = Keyword.pop(rest_opts, :label)
|
{label_text, rest_opts} = Keyword.pop(rest_opts, :label)
|
||||||
{input_helper, _rest_opts} = Keyword.pop(rest_opts, :input_helper, input_type(f, field))
|
{input_helper, _rest_opts} = Keyword.pop(rest_opts, :input_helper, type)
|
||||||
|
|
||||||
error_classes =
|
error_classes =
|
||||||
if Keyword.get_values(f.errors, field) |> Enum.any?() do
|
if Keyword.get_values(f.errors, field) |> Enum.any?() do
|
||||||
|
|
|
@ -9,11 +9,13 @@ defmodule Mix.Tasks.Legendary.CreateAdmin do
|
||||||
alias Ecto.Changeset
|
alias Ecto.Changeset
|
||||||
|
|
||||||
@shortdoc "Create an admin user."
|
@shortdoc "Create an admin user."
|
||||||
def run(_) do
|
def run(args) do
|
||||||
Application.ensure_all_started(:core)
|
Application.ensure_all_started(:core)
|
||||||
|
|
||||||
email = ExPrompt.string_required("Email: ")
|
{switches, _, _} = OptionParser.parse(args, strict: [email: :string, password: :string])
|
||||||
password = ExPrompt.password("Password: ")
|
|
||||||
|
email = Keyword.get_lazy(switches, :email, fn -> ExPrompt.string_required("Email: ") end)
|
||||||
|
password = Keyword.get_lazy(switches, :password, fn -> ExPrompt.password("Password: ") end)
|
||||||
|
|
||||||
params = %{
|
params = %{
|
||||||
email: email,
|
email: email,
|
||||||
|
@ -27,7 +29,7 @@ defmodule Mix.Tasks.Legendary.CreateAdmin do
|
||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_confirm_email(changeset) do
|
defp maybe_confirm_email(changeset) do
|
||||||
field_list = User.__schema__(:fields)
|
field_list = User.__schema__(:fields)
|
||||||
|
|
||||||
case Enum.any?(field_list, &(&1 == :email_confirmed_at)) do
|
case Enum.any?(field_list, &(&1 == :email_confirmed_at)) do
|
||||||
|
|
33
apps/core/test/auth_web/controller_callback_test.exs
Normal file
33
apps/core/test/auth_web/controller_callback_test.exs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule Legendary.AuthWeb.Pow.ControllerCallbacksTest do
|
||||||
|
use Legendary.CoreWeb.ConnCase, async: true
|
||||||
|
|
||||||
|
import Legendary.AuthWeb.Pow.ControllerCallbacks
|
||||||
|
import Plug.Conn, only: [assign: 3, get_session: 2]
|
||||||
|
|
||||||
|
alias Legendary.Auth.User
|
||||||
|
|
||||||
|
describe "before_respond/4" do
|
||||||
|
setup %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> init_test_session([])
|
||||||
|
|> assign(:current_user, %User{id: 123})
|
||||||
|
|
||||||
|
%{conn: conn}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "sets the live_socket_id in session upon sign in", %{conn: conn} do
|
||||||
|
{:ok, conn} = before_respond(Pow.Phoenix.SessionController, :create, {:ok, conn}, [])
|
||||||
|
|
||||||
|
assert get_session(conn, "live_socket_id") == "users_sockets:123"
|
||||||
|
assert get_session(conn, "current_user_id") == 123
|
||||||
|
end
|
||||||
|
|
||||||
|
test "removes the live_socket_id and broadcasts a disconnect signal upon sign out", %{conn: conn, } do
|
||||||
|
{:ok, conn} = before_respond(Pow.Phoenix.SessionController, :delete, {:ok, conn}, [])
|
||||||
|
|
||||||
|
assert get_session(conn, "live_socket_id") == nil
|
||||||
|
assert get_session(conn, "current_user_id") == nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,8 +1,15 @@
|
||||||
defmodule Legendary.AuthWeb.HelpersTest do
|
defmodule Legendary.AuthWeb.HelpersTest do
|
||||||
use Legendary.CoreWeb.ConnCase
|
use Legendary.CoreWeb.ConnCase, async: true
|
||||||
|
|
||||||
import Legendary.AuthWeb.Helpers
|
import Legendary.AuthWeb.Helpers
|
||||||
|
|
||||||
|
alias Phoenix.LiveView.Socket
|
||||||
|
|
||||||
|
describe "current_user/1" do
|
||||||
|
test "can get a user from the assigns in a socket", do: assert current_user(%Socket{assigns: %{current_user: %{id: 867}}}).id == 867
|
||||||
|
test "can get a user from the __assigns__ in a socket", do: assert current_user(%Socket{assigns: %{__assigns__: %{current_user: %{id: 867}}}}).id == 867
|
||||||
|
end
|
||||||
|
|
||||||
describe "has_role?/2" do
|
describe "has_role?/2" do
|
||||||
test "with a user", %{conn: conn} do
|
test "with a user", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule Legendary.AuthWeb.Plugs.RequireAdminTest do
|
defmodule Legendary.AuthWeb.Plugs.RequireAdminTest do
|
||||||
use Legendary.CoreWeb.ConnCase
|
use Legendary.CoreWeb.ConnCase, async: true
|
||||||
|
|
||||||
alias Legendary.AuthWeb.Plugs.RequireAdmin
|
alias Legendary.AuthWeb.Plugs.RequireAdmin
|
||||||
alias Legendary.Auth.User
|
alias Legendary.Auth.User
|
||||||
|
|
38
apps/core/test/core_web/plugs/test_end_to_end_test.exs
Normal file
38
apps/core/test/core_web/plugs/test_end_to_end_test.exs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
defmodule Legendary.CoreWeb.Plug.TestEndToEndTest do
|
||||||
|
use Legendary.CoreWeb.ConnCase
|
||||||
|
|
||||||
|
test "/db/setup can check out a connection", %{conn: conn} do
|
||||||
|
conn = post conn, "/end-to-end/db/setup", %{seed_set: "test_end_to_end_test", app: "core"}
|
||||||
|
|
||||||
|
assert response(conn, 200) =~ "connection checked out"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/db/setup twice is a no-op", %{conn: conn} do
|
||||||
|
conn = post conn, "/end-to-end/db/setup", %{seed_set: "test_end_to_end_test", app: "core"}
|
||||||
|
conn = post conn, "/end-to-end/db/setup", %{seed_set: "test_end_to_end_test", app: "core"}
|
||||||
|
|
||||||
|
assert response(conn, 200) =~ "connection has already been checked out"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/db/setup with no-existent seed set is an error", %{conn: conn} do
|
||||||
|
conn = post conn, "/end-to-end/db/setup", %{seed_set: "oops", app: "core"}
|
||||||
|
|
||||||
|
assert response(conn, 500) =~ "could not load"
|
||||||
|
assert response(conn, 500) =~ "oops.exs"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/db/teardown can check in a connection", %{conn: conn} do
|
||||||
|
conn = post conn, "/end-to-end/db/setup", %{seed_set: "test_end_to_end_test", app: "core"}
|
||||||
|
conn = post conn, "/end-to-end/db/teardown"
|
||||||
|
|
||||||
|
assert response(conn, 200) =~ "checked in database connection"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "/db/teardown checking in twice is a no-op", %{conn: conn} do
|
||||||
|
conn = post conn, "/end-to-end/db/setup", %{seed_set: "test_end_to_end_test", app: "core"}
|
||||||
|
conn = post conn, "/end-to-end/db/teardown"
|
||||||
|
conn = post conn, "/end-to-end/db/teardown"
|
||||||
|
|
||||||
|
assert response(conn, 200) =~ "connection has already been checked back in"
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule Legendary.CoreWeb.HelpersTest do
|
defmodule Legendary.CoreWeb.HelpersTest do
|
||||||
use Legendary.CoreWeb.ConnCase
|
use Legendary.CoreWeb.ConnCase, async: true
|
||||||
|
|
||||||
import Legendary.CoreWeb.Helpers
|
import Legendary.CoreWeb.Helpers
|
||||||
import Ecto.Changeset,
|
import Ecto.Changeset,
|
||||||
|
@ -35,6 +35,17 @@ defmodule Legendary.CoreWeb.HelpersTest do
|
||||||
changeset
|
changeset
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "current_user?/1" do
|
||||||
|
test "returns nil for a conn with no user", %{conn: conn}, do: refute conn |> setup_pow() |> current_user()
|
||||||
|
test "returns a user for a conn with a user", %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> setup_user(id: 456)
|
||||||
|
|
||||||
|
assert current_user(conn).id == 456
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "has_role?/2" do
|
describe "has_role?/2" do
|
||||||
test "with a user", %{conn: conn} do
|
test "with a user", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
|
@ -105,6 +116,87 @@ defmodule Legendary.CoreWeb.HelpersTest do
|
||||||
assert markup =~ "<label"
|
assert markup =~ "<label"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "styled_input for date_select" do
|
||||||
|
markup =
|
||||||
|
form()
|
||||||
|
|> styled_input(:no_error_field, type: :date_select)
|
||||||
|
|> safe_to_string()
|
||||||
|
|
||||||
|
assert markup =~ "<select"
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "styled_button/1" do
|
||||||
|
test "makes a button with content" do
|
||||||
|
markup =
|
||||||
|
styled_button("Push Me")
|
||||||
|
|> safe_to_string()
|
||||||
|
|
||||||
|
assert markup =~ ">Push Me"
|
||||||
|
assert markup =~ "<button"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "styled_button_link/2" do
|
||||||
|
test "makes a link with content and attributes" do
|
||||||
|
markup =
|
||||||
|
styled_button_link("Push Me", to: "#anchor")
|
||||||
|
|> safe_to_string()
|
||||||
|
|
||||||
|
assert markup =~ ">Push Me"
|
||||||
|
assert markup =~ "<a"
|
||||||
|
assert markup =~ ~s(href="#anchor")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "paginator/3" do
|
||||||
|
def reflector(range, current), do: {range, current}
|
||||||
|
|
||||||
|
test "works with only one page" do
|
||||||
|
assert paginator(1..1, 1, &reflector/2) == [{1..1, 1}]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works with two pages" do
|
||||||
|
assert paginator(1..2, 1, &reflector/2) == [{1..2, 1}, {1..2, 2}]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works with three pages" do
|
||||||
|
assert paginator(1..3, 3, &reflector/2) == [{1..3, 1}, {1..3, 2}, {1..3, 3}]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works with many pages" do
|
||||||
|
assert paginator(1..10, 7, &reflector/2) == [{1..10, 1}, {1..10, 6}, {1..10, 7}, {1..10, 8}, {1..10, 10}]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "group_rounding_class/3" do
|
||||||
|
test "handles the only element", do: assert group_rounding_class(1..1, 1) == "rounded-l rounded-r"
|
||||||
|
test "handles the first element", do: assert group_rounding_class(1..2, 1) == "rounded-l"
|
||||||
|
test "handles the last element", do: assert group_rounding_class(1..2, 2) == "rounded-r"
|
||||||
|
test "handles middle elements", do: assert group_rounding_class(1..3, 2) == ""
|
||||||
|
test "handles custom classes", do: assert group_rounding_class(1..3, 1, ["custom", "", ""]) == "custom"
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "floating_form/3" do
|
||||||
|
test "includes title and content" do
|
||||||
|
markup =
|
||||||
|
floating_form("Test Title", %{action: "test"}, do: "Test Content")
|
||||||
|
|> safe_to_string()
|
||||||
|
|
||||||
|
assert markup =~ "Test Title"
|
||||||
|
assert markup =~ "Test Content"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "floating_page_wrapper/1" do
|
||||||
|
test "includes content" do
|
||||||
|
markup =
|
||||||
|
floating_page_wrapper(do: "Test Content")
|
||||||
|
|> safe_to_string()
|
||||||
|
|
||||||
|
assert markup =~ "Test Content"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
test "pow_extension_enabled?/1" do
|
test "pow_extension_enabled?/1" do
|
||||||
assert pow_extension_enabled?(PowEmailConfirmation) == true
|
assert pow_extension_enabled?(PowEmailConfirmation) == true
|
||||||
assert pow_extension_enabled?(:donkdonk) == false
|
assert pow_extension_enabled?(:donkdonk) == false
|
||||||
|
|
17
apps/core/test/mix/tasks/create_admin_test.exs
Normal file
17
apps/core/test/mix/tasks/create_admin_test.exs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
defmodule Mix.Tasks.Legendary.CreateAdminTest do
|
||||||
|
use Legendary.Core.DataCase
|
||||||
|
|
||||||
|
import Mix.Tasks.Legendary.CreateAdmin
|
||||||
|
|
||||||
|
alias Legendary.Auth.User
|
||||||
|
|
||||||
|
describe "run/1" do
|
||||||
|
test "creates an admin user" do
|
||||||
|
run(["--email=test@example.com", "--password=openseasame"])
|
||||||
|
|
||||||
|
user = from(u in User, where: u.email == "test@example.com") |> Repo.one()
|
||||||
|
|
||||||
|
assert %User{email: "test@example.com"} = user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
0
apps/core/test/seed_sets/test_end_to_end_test.exs
Normal file
0
apps/core/test/seed_sets/test_end_to_end_test.exs
Normal file
14
apps/core/test/shared_db_connection_pool_test.exs
Normal file
14
apps/core/test/shared_db_connection_pool_test.exs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
defmodule Legendary.Core.SharedDBConnectionPoolTest do
|
||||||
|
use Legendary.Core.DataCase
|
||||||
|
|
||||||
|
import Legendary.Core.SharedDBConnectionPool
|
||||||
|
|
||||||
|
test "child_spec/2" do
|
||||||
|
spec = child_spec({Postgrex.Protocol, []})
|
||||||
|
|
||||||
|
assert %{id: Legendary.Core.SharedDBConnectionPool, start: start} = spec
|
||||||
|
assert {Legendary.Core.SharedDBConnectionPool, :start_link, [{Postgrex.Protocol, opts}]} = start
|
||||||
|
assert [{:name, hashed_name}] = opts
|
||||||
|
assert Atom.to_string(hashed_name) =~ "Legendary.Core.SharedDBConnectionPool."
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,6 +28,22 @@ defmodule Legendary.CoreWeb.ConnCase do
|
||||||
|
|
||||||
# The default endpoint for testing
|
# The default endpoint for testing
|
||||||
@endpoint Legendary.CoreWeb.Endpoint
|
@endpoint Legendary.CoreWeb.Endpoint
|
||||||
|
|
||||||
|
def setup_pow(conn) do
|
||||||
|
conn
|
||||||
|
|> Pow.Plug.put_config(current_user_assigns_key: :current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_user(conn, attrs \\ []) do
|
||||||
|
user =
|
||||||
|
attrs
|
||||||
|
|> Enum.into(%{})
|
||||||
|
|> (& struct(Legendary.Auth.User, &1)).()
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> setup_pow()
|
||||||
|
|> Pow.Plug.assign_current_user(user, [])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
defmodule Legendary.Core.Cluster.EmptyClusterStrategy do
|
|
||||||
@moduledoc """
|
|
||||||
A libcluster nil strategy that always returns no nodes.
|
|
||||||
"""
|
|
||||||
use GenServer
|
|
||||||
use Cluster.Strategy
|
|
||||||
|
|
||||||
alias Cluster.Strategy.State
|
|
||||||
|
|
||||||
def start_link([%State{} = state]) do
|
|
||||||
new_state = %State{state | :meta => []}
|
|
||||||
GenServer.start_link(__MODULE__, [new_state])
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def init([state]) do
|
|
||||||
{:ok, state, :infinity}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_info(_, state) do
|
|
||||||
{:noreply, state, :infinity}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -40,7 +40,7 @@ config :core, :pow,
|
||||||
user: Legendary.Auth.User,
|
user: Legendary.Auth.User,
|
||||||
repo: Legendary.Core.Repo,
|
repo: Legendary.Core.Repo,
|
||||||
extensions: [PowEmailConfirmation, PowPersistentSession, PowResetPassword],
|
extensions: [PowEmailConfirmation, PowPersistentSession, PowResetPassword],
|
||||||
controller_callbacks: AuthWeb.Pow.ControllerCallbacks,
|
controller_callbacks: Legendary.AuthWeb.Pow.ControllerCallbacks,
|
||||||
mailer_backend: Legendary.AuthWeb.Pow.Mailer,
|
mailer_backend: Legendary.AuthWeb.Pow.Mailer,
|
||||||
web_mailer_module: Legendary.AuthWeb,
|
web_mailer_module: Legendary.AuthWeb,
|
||||||
web_module: Legendary.AuthWeb,
|
web_module: Legendary.AuthWeb,
|
||||||
|
|
|
@ -42,9 +42,4 @@ config :content, Oban, crontab: false, queues: false, plugins: false
|
||||||
|
|
||||||
config :logger, level: :warn
|
config :logger, level: :warn
|
||||||
|
|
||||||
config :libcluster,
|
config :libcluster, topologies: []
|
||||||
topologies: [
|
|
||||||
# erlang_hosts: [
|
|
||||||
# strategy: Legendary.Core.Cluster.EmptyClusterStrategy
|
|
||||||
# ]
|
|
||||||
]
|
|
||||||
|
|
Loading…
Reference in a new issue