Skip to content

Commit a3361f2

Browse files
committed
Fix tests and format
1 parent 96b9626 commit a3361f2

File tree

9 files changed

+118
-7
lines changed

9 files changed

+118
-7
lines changed

lib/elixir_boilerplate_web/controllers/error_html.ex renamed to lib/elixir_boilerplate_web/errors/error_html.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule ElixirBoilerplateWeb.Controllers.ErrorHTML do
1+
defmodule ElixirBoilerplateWeb.Errors.ErrorHTML do
22
use ElixirBoilerplateWeb, :html
33

44
# If you want to customize your error pages,

lib/elixir_boilerplate_web/controllers/error_json.ex renamed to lib/elixir_boilerplate_web/errors/error_json.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule ElixirBoilerplateWeb.Controllers.ErrorJSON do
1+
defmodule ElixirBoilerplateWeb.Errors.ErrorJSON do
22
# If you want to customize a particular status code,
33
# you may add your own clauses, such as:
44
#
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
defmodule ElixirBoilerplateWeb.Errors do
2+
alias Ecto.Changeset
3+
4+
import Phoenix.Template, only: [embed_templates: 1]
5+
6+
embed_templates("templates/*")
7+
8+
@doc """
9+
Generates a human-readable block containing all errors in a changeset. Errors
10+
are then localized using translations in the `ecto` domain.
11+
12+
For example, you could have an `errors.po` file in the french locale:
13+
14+
```
15+
msgid ""
16+
msgstr ""
17+
"Language: fr"
18+
19+
msgid "can't be blank"
20+
msgstr "ne peut être vide"
21+
```
22+
"""
23+
def changeset_to_error_messages(changeset) do
24+
changeset
25+
|> Changeset.traverse_errors(&translate_error/1)
26+
|> convert_errors_to_html(changeset.data.__struct__)
27+
end
28+
29+
defp translate_error({message, options}) do
30+
if options[:count] do
31+
Gettext.dngettext(ElixirBoilerplate.Gettext, "errors", message, message, options[:count], options)
32+
else
33+
Gettext.dgettext(ElixirBoilerplate.Gettext, "errors", message, options)
34+
end
35+
end
36+
37+
defp convert_errors_to_html(errors, schema) do
38+
errors = Enum.reduce(errors, [], &convert_error_field(&1, &2, schema))
39+
40+
error_messages(%{errors: errors})
41+
end
42+
43+
defp convert_error_field({field, errors}, memo, schema) when is_list(errors) do
44+
memo ++ Enum.flat_map(errors, &convert_error_subfield(&1, field, [], schema))
45+
end
46+
47+
defp convert_error_field({field, errors}, memo, schema) when is_map(errors) do
48+
memo ++ Enum.flat_map(Map.keys(errors), &convert_error_subfield(&1, field, errors[&1], schema))
49+
end
50+
51+
defp convert_error_subfield(message, field, _, _schema) when is_binary(message) do
52+
# NOTE `schema` is available here if we want to use something like
53+
# `schema.humanize_field(field)` to be able to display `"Email address is
54+
# invalid"` instead of `email is invalid"`.
55+
["#{field} #{message}"]
56+
end
57+
58+
defp convert_error_subfield(message, field, memo, schema) when is_map(message) do
59+
Enum.reduce(message, memo, fn {subfield, errors}, memo ->
60+
memo ++ convert_error_field({"#{field}.#{subfield}", errors}, memo, schema)
61+
end)
62+
end
63+
64+
defp convert_error_subfield(subfield, field, errors, schema) do
65+
field = "#{field}.#{subfield}"
66+
convert_error_field({field, errors}, [], schema)
67+
end
68+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>Not found</title>
7+
</head>
8+
<body>
9+
<p>Sorry, the page you are looking for does not exist.</p>
10+
</body>
11+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<%= if @errors != [] do %>
2+
<ul>
3+
<%= for error <- @errors do %>
4+
<li><%= error %></li>
5+
<% end %>
6+
</ul>
7+
<% end %>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule ElixirBoilerplateWeb.ErrorHtmlTest do
2+
use ElixirBoilerplate.DataCase, async: true
3+
4+
# Bring render_to_string/3 for testing custom views
5+
import Phoenix.Template
6+
7+
alias ElixirBoilerplateWeb.Errors.ErrorHTML
8+
9+
test "renders 404.html" do
10+
assert render_to_string(ErrorHTML, "404", "html", []) == "Not Found"
11+
end
12+
13+
test "renders 500.html" do
14+
assert render_to_string(ErrorHTML, "500", "html", []) == "Internal Server Error"
15+
end
16+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
defmodule ElixirBoilerplateWeb.ErrorJsonTest do
2+
use ElixirBoilerplate.DataCase, async: true
3+
4+
alias ElixirBoilerplateWeb.Errors.ErrorJSON
5+
6+
test "renders 404" do
7+
assert ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}}
8+
end
9+
10+
test "renders 500" do
11+
assert ErrorJSON.render("500.json", %{}) == %{errors: %{detail: "Internal Server Error"}}
12+
end
13+
end

test/elixir_boilerplate_web/errors_test.exs renamed to test/elixir_boilerplate_web/errors/errors_test.exs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
defmodule ElixirBoilerplateWeb.ErrorsTest do
22
use ElixirBoilerplate.DataCase, async: true
33

4-
alias ElixirBoilerplateWeb.Errors
5-
64
defmodule UserRole do
75
use Ecto.Schema
86

@@ -74,7 +72,7 @@ defmodule ElixirBoilerplateWeb.ErrorsTest do
7472

7573
defp changeset_to_error_messages(changeset) do
7674
changeset
77-
|> Errors.changeset_to_error_messages()
75+
|> ElixirBoilerplateWeb.Errors.changeset_to_error_messages()
7876
|> Phoenix.HTML.Safe.to_iodata()
7977
|> IO.iodata_to_binary()
8078
end

test/support/conn_case.ex

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ defmodule ElixirBoilerplateWeb.ConnCase do
2626
import Plug.Conn
2727
import Phoenix.ConnTest
2828

29-
import ElixirBoilerplateWeb.Router.Helpers
30-
3129
# The default endpoint for testing
3230
@endpoint Endpoint
3331
end

0 commit comments

Comments
 (0)