截止上一章,我們基本完成用戶注冊的所有邏輯,但界面上還有些問題需要解決。
-
錯誤信息不明顯
截圖中可以看到,“請?zhí)顚憽比齻€字不突出,很多時候用戶會視而不見。
-
密碼輸入框
在密碼框中輸入的內容,現(xiàn)在是明文顯示,通常常是用 * 號代替。
第 1 個問題。
Phoenix 生成的 form.html.eex
模板里使用了 Bootstrap 樣式:
<div class="form-group">
<%= label f, :username, class: "control-label" %>
<%= text_input f, :username, class: "form-control" %>
<%= error_tag f, :username %>
</div>
但模板中生成的樣式與 Bootstrap 的比,差了 has-error
這樣的 CSS 狀態(tài)類。我們可以給它補上:
diff --git a/lib/tv_recipe_web/templates/user/form.html.eex b/lib/tv_recipe_web/templates/user/form.html.eex
index 5857c33..b047466 100644
--- a/lib/tv_recipe_web/templates/user/form.html.eex
+++ b/lib/tv_recipe_web/templates/user/form.html.eex
@@ -5,19 +5,19 @@
</div>
<% end %>
- <div class="form-group">
+ <div class="form-group <%= if f.errors[:username], do: "has-error" %>">
<%= label f, :username, class: "control-label" %>
<%= text_input f, :username, class: "form-control" %>
<%= error_tag f, :username %>
</div>
- <div class="form-group">
+ <div class="form-group <%= if f.errors[:email], do: "has-error" %>">
<%= label f, :email, class: "control-label" %>
<%= text_input f, :email, class: "form-control" %>
<%= error_tag f, :email %>
</div>
- <div class="form-group">
+ <div class="form-group <%= if f.errors[:password], do: "has-error" %>">
<%= label f, :password, class: "control-label" %>
<%= text_input f, :password, class: "form-control" %>
<%= error_tag f, :password %>
這樣我們的錯誤提示界面就會變成:
非常醒目。至于 Phoenix 生成的模板里為什么不帶 has-error
,可以看 github 上的一個 issue。
第 2 個問題就容易解決了,我們來看現(xiàn)有代碼:
<div class="form-group <%= if f.errors[:password], do: "has-error" %>">
<%= label f, :password, class: "control-label" %>
<%= text_input f, :password, class: "form-control" %>
<%= error_tag f, :password %>
</div>
生成的模板里現(xiàn)在用了 text_input
,它本來就是明文顯示的,改為 password_input
后,界面上就會用 * 號代替我們的輸入。
這樣,我們結束了用戶注冊模塊。接下來,我們將開始開發(fā)用戶的登錄/退出功能。
但是,且慢,還有一個差點被我們遺忘的。
控制器的測試
你可能對 mix test test/tv_recipe/users_test.exs
命令已經爛熟于心。但 mix test test/tv_recipe_web/controllers/user_controller_test.exs
呢?
我們在生成用戶的樣板文件時,曾經生成過一個 user_controller_test.exs
文件,讓我們運行下 mix test test/tv_recipe_web/controllers/user_controller_test.exs
看看結果:
$ mix test test/tv_recipe_web/controllers/user_controller_test.exs
Compiling 1 file (.ex)
....
1) test updates chosen resource and redirects when data is valid (TvRecipe.UserControllerTest)
test/tv_recipe_web/controllers/user_controller_test.exs:47
** (RuntimeError) expected redirection with status 302, got: 200
stacktrace:
(phoenix) lib/phoenix/test/conn_test.ex:443: Phoenix.ConnTest.redirected_to/2
test/tv_recipe_web/controllers/user_controller_test.exs:50: (test)
....
2) test creates resource and redirects when data is valid (TvRecipe.UserControllerTest)
test/tv_recipe_web/controllers/user_controller_test.exs:18
** (RuntimeError) expected redirection with status 302, got: 200
stacktrace:
(phoenix) lib/phoenix/test/conn_test.ex:443: Phoenix.ConnTest.redirected_to/2
test/tv_recipe_web/controllers/user_controller_test.exs:20: (test)
Finished in 0.3 seconds
10 tests, 2 failures
好消息是,10 個測試,有 8 個通過;壞消息是有 2 個未通過。
顯然,從模板文件到現(xiàn)在,我們的代碼已經變化,現(xiàn)在測試文件一樣需要根據(jù)實際情況做調整:
diff --git a/test/tv_recipe_web/controllers/user_controller_test.exs b/test/tv_recipe_web/controllers/user_controller_test.exs
index 2e08483..95d3108 100644
--- a/test/tv_recipe_web/controllers/user_controller_test.exs
+++ b/test/tv_recipe_web/controllers/user_controller_test.exs
@@ -2,7 +2,7 @@ defmodule TvRecipe.UserControllerTest do
use TvRecipe.ConnCase
alias TvRecipe.User
- @valid_attrs %{email: "some content", password: "some content", username: "some content"}
+ @valid_attrs %{email: "chenxsan@gmail.com", password: "some content", username: "chenxsan"}
@invalid_attrs %{}
test "lists all entries on index", %{conn: conn} do
@@ -18,7 +18,7 @@ defmodule TvRecipe.UserControllerTest do
test "creates resource and redirects when data is valid", %{conn: conn} do
conn = post conn, Routes.user_path(conn, :create), user: @valid_attrs
assert redirected_to(conn) == Routes.user_path(conn, :index)
- assert Repo.get_by(User, @valid_attrs)
+ assert Repo.get_by(User, @valid_attrs |> Map.delete(:password))
end
test "does not create resource and renders errors when data is invalid", %{conn: conn} do
@@ -48,7 +48,7 @@ defmodule TvRecipe.UserControllerTest do
user = Repo.insert! %User{}
conn = put conn, Routes.user_path(conn, :update, user), user: @valid_attrs
assert redirected_to(conn) == Routes.user_path(conn, :show, user)
- assert Repo.get_by(User, @valid_attrs)
+ assert Repo.get_by(User, @valid_attrs |> Map.delete(:password))
end
我們在代碼中做了三處修改,一個是訂正 @valid_attrs
,另外兩個是修改 Repo.get
,因為我們的 User
不再有 password
字段,所以應該從 @valid_attrs
中移除它,否則就會報錯。
再運行測試,全部通過。
更多建議: