Phoenix 優(yōu)化用戶注冊(cè)界面

2023-12-18 14:34 更新

截止上一章,我們基本完成用戶注冊(cè)的所有邏輯,但界面上還有些問(wèn)題需要解決。

  1. 錯(cuò)誤信息不明顯

    Phoenix 用戶名不為空的錯(cuò)誤信息

    截圖中可以看到,“請(qǐng)?zhí)顚?xiě)”三個(gè)字不突出,很多時(shí)候用戶會(huì)視而不見(jiàn)。

  2. 密碼輸入框

    密碼輸入框

    在密碼框中輸入的內(nèi)容,現(xiàn)在是明文顯示,通常常是用 * 號(hào)代替。

第 1 個(gè)問(wèn)題。

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)類(lèi)。我們可以給它補(bǔ)上:

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 %>

這樣我們的錯(cuò)誤提示界面就會(huì)變成:

用戶名不為空

非常醒目。至于 Phoenix 生成的模板里為什么不帶 has-error,可以看 github 上的一個(gè) issue

第 2 個(gè)問(wèn)題就容易解決了,我們來(lái)看現(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,它本來(lái)就是明文顯示的,改為 password_input 后,界面上就會(huì)用 * 號(hào)代替我們的輸入。

這樣,我們結(jié)束了用戶注冊(cè)模塊。接下來(lái),我們將開(kāi)始開(kāi)發(fā)用戶的登錄/退出功能。

但是,且慢,還有一個(gè)差點(diǎn)被我們遺忘的。

控制器的測(cè)試

你可能對(duì) mix test test/tv_recipe/users_test.exs 命令已經(jīng)爛熟于心。但 mix test test/tv_recipe_web/controllers/user_controller_test.exs 呢?

我們?cè)谏捎脩舻臉影逦募r(shí),曾經(jīng)生成過(guò)一個(gè) user_controller_test.exs 文件,讓我們運(yùn)行下 mix test test/tv_recipe_web/controllers/user_controller_test.exs 看看結(jié)果:

$ 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 個(gè)測(cè)試,有 8 個(gè)通過(guò);壞消息是有 2 個(gè)未通過(guò)。

顯然,從模板文件到現(xiàn)在,我們的代碼已經(jīng)變化,現(xiàn)在測(cè)試文件一樣需要根據(jù)實(shí)際情況做調(diào)整:

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

我們?cè)诖a中做了三處修改,一個(gè)是訂正 @valid_attrs,另外兩個(gè)是修改 Repo.get,因?yàn)槲覀兊?User 不再有 password 字段,所以應(yīng)該從 @valid_attrs 中移除它,否則就會(huì)報(bào)錯(cuò)。

再運(yùn)行測(cè)試,全部通過(guò)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)