From 5e7279aac107fe2c6223405576ba47980bac992c Mon Sep 17 00:00:00 2001 From: Jamil Bou Kheir Date: Wed, 3 Jun 2020 10:36:05 -0700 Subject: [PATCH] User controller tested --- apps/fg_http/lib/fg_http/users/user.ex | 19 ++-- .../controllers/user_controller.ex | 39 ++++++--- .../fg_http_web/templates/user/edit.html.eex | 2 +- .../fg_http_web/templates/user/show.html.eex | 9 ++ apps/fg_http/mix.exs | 1 + .../controllers/user_controller_test.exs | 86 +++++++++++++++++++ apps/fg_vpn/mix.exs | 3 +- apps/fg_wall/mix.exs | 3 +- 8 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 apps/fg_http/test/fg_http_web/controllers/user_controller_test.exs diff --git a/apps/fg_http/lib/fg_http/users/user.ex b/apps/fg_http/lib/fg_http/users/user.ex index b8b3dcf25..1578f9c54 100644 --- a/apps/fg_http/lib/fg_http/users/user.ex +++ b/apps/fg_http/lib/fg_http/users/user.ex @@ -30,6 +30,7 @@ defmodule FgHttp.Users.User do user |> cast(attrs, [:email, :password_hash, :password, :password_confirmation]) |> validate_required([:email, :password, :password_confirmation]) + |> validate_password_equality() |> unique_constraint(:email) |> put_password_hash() |> validate_required([:password_hash]) @@ -39,17 +40,15 @@ defmodule FgHttp.Users.User do def update_changeset( user, %{ - user: %{ - password: _password, - password_confirmation: _password_confirmation, - current_password: _current_password - } + "password" => _password, + "password_confirmation" => _password_confirmation, + "current_password" => _current_password } = attrs ) do user |> cast(attrs, [:email, :password, :password_confirmation, :current_password]) - |> verify_current_password(attrs[:current_password]) |> validate_required([:password, :password_confirmation, :current_password]) + |> verify_current_password(attrs[:current_password]) |> validate_password_equality() |> put_password_hash() |> validate_required([:password_hash]) @@ -59,10 +58,8 @@ defmodule FgHttp.Users.User do def update_changeset( user, %{ - user: %{ - password: _password, - password_confirmation: _password_confirmation - } + "password" => _password, + "password_confirmation" => _password_confirmation } = attrs ) do user @@ -74,7 +71,7 @@ defmodule FgHttp.Users.User do end # Only email being updated - def update_changeset(user, %{user: %{email: _email}} = attrs) do + def update_changeset(user, %{"email" => _email} = attrs) do user |> cast(attrs, [:email]) |> validate_required([:email]) diff --git a/apps/fg_http/lib/fg_http_web/controllers/user_controller.ex b/apps/fg_http/lib/fg_http_web/controllers/user_controller.ex index 1892dea81..8f42ebeeb 100644 --- a/apps/fg_http/lib/fg_http_web/controllers/user_controller.ex +++ b/apps/fg_http/lib/fg_http_web/controllers/user_controller.ex @@ -4,7 +4,7 @@ defmodule FgHttpWeb.UserController do """ use FgHttpWeb, :controller - alias FgHttp.{Users, Users.Session, Users.User} + alias FgHttp.{Sessions, Users, Users.User} plug FgHttpWeb.Plugs.SessionLoader when action in [:show, :edit, :update, :delete] @@ -18,9 +18,12 @@ defmodule FgHttpWeb.UserController do def create(conn, %{"user" => user_params}) do case Users.create_user(user_params) do {:ok, user} -> + # XXX: Cast the user to a session struct to prevent this db call + session = Sessions.get_session!(user.id) + conn |> put_session(:user_id, user.id) - |> assign(:session, %Session{id: user.id, email: user.email}) + |> assign(:session, session) |> put_flash(:info, "User created successfully.") |> redirect(to: Routes.device_path(conn, :index)) @@ -33,7 +36,8 @@ defmodule FgHttpWeb.UserController do # GET /user/edit def edit(conn, _params) do - user = conn.current_user + # XXX: Cast the session to a user struct to prevent this db call + user = Users.get_user!(conn.assigns.session.id) changeset = Users.change_user(user) render(conn, "edit.html", changeset: changeset) @@ -41,18 +45,26 @@ defmodule FgHttpWeb.UserController do # GET /user def show(conn, _params) do + # XXX: Cast the session to a user struct to prevent this db call + user = Users.get_user!(conn.assigns.session.id) + conn - |> render("show.html", user: conn.current_user) + |> render("show.html", user: user, session: conn.assigns.session) end # PATCH /user - def update(conn, params) do - case Users.update_user(conn.current_user, params) do + def update(conn, %{"user" => user_params}) do + user = Users.get_user!(conn.assigns.session.id) + + case Users.update_user(user, user_params) do {:ok, user} -> + # XXX: Cast the user to a session struct to prevent this db call + session = Sessions.get_session!(user.id) + conn - |> assign(:current_user, user) + |> assign(:session, session) |> put_flash(:info, "User updated successfully.") - |> redirect(to: Routes.user_path(conn, :show, conn.current_user)) + |> redirect(to: Routes.user_path(conn, :show)) {:error, changeset} -> conn @@ -63,17 +75,20 @@ defmodule FgHttpWeb.UserController do # DELETE /user def delete(conn, _params) do - case Users.delete_user(conn.current_user) do + user = Users.get_user!(conn.assigns.session.id) + + case Users.delete_user(user) do {:ok, _user} -> conn - |> assign(:current_user, nil) + |> clear_session() + |> assign(:session, nil) |> put_flash(:info, "User deleted successfully.") |> redirect(to: "/") - {:error, _changeset} -> + {:error, changeset} -> conn |> put_flash(:error, "Error deleting User.") - |> redirect(to: Routes.user_path(:show, conn.current_user)) + |> render("edit.html", changeset: changeset) end end end diff --git a/apps/fg_http/lib/fg_http_web/templates/user/edit.html.eex b/apps/fg_http/lib/fg_http_web/templates/user/edit.html.eex index aa341db86..a9c9110ad 100644 --- a/apps/fg_http/lib/fg_http_web/templates/user/edit.html.eex +++ b/apps/fg_http/lib/fg_http_web/templates/user/edit.html.eex @@ -1 +1 @@ -

Account

+

Edit Account

diff --git a/apps/fg_http/lib/fg_http_web/templates/user/show.html.eex b/apps/fg_http/lib/fg_http_web/templates/user/show.html.eex index e69de29bb..a14f55068 100644 --- a/apps/fg_http/lib/fg_http_web/templates/user/show.html.eex +++ b/apps/fg_http/lib/fg_http_web/templates/user/show.html.eex @@ -0,0 +1,9 @@ +

Your Account

+ +
+
Email
+
<%= @user.email %>
+ +
Last signed in at
+
<%= @session.last_signed_in_at %>
+
diff --git a/apps/fg_http/mix.exs b/apps/fg_http/mix.exs index e59c47477..5752d766e 100644 --- a/apps/fg_http/mix.exs +++ b/apps/fg_http/mix.exs @@ -45,6 +45,7 @@ defmodule FgHttp.MixProject do defp deps do [ {:phoenix, "~> 1.5.1"}, + {:excoveralls, "~> 0.13", only: :test}, {:argon2_elixir, "~> 2.0"}, {:phoenix_pubsub, "~> 2.0"}, {:phoenix_ecto, "~> 4.0"}, diff --git a/apps/fg_http/test/fg_http_web/controllers/user_controller_test.exs b/apps/fg_http/test/fg_http_web/controllers/user_controller_test.exs new file mode 100644 index 000000000..3232d352e --- /dev/null +++ b/apps/fg_http/test/fg_http_web/controllers/user_controller_test.exs @@ -0,0 +1,86 @@ +defmodule FgHttpWeb.UserControllerTest do + use FgHttpWeb.ConnCase, async: true + + alias FgHttp.Users.Session + + @valid_create_attrs %{ + email: "fixure", + password: "password", + password_confirmation: "password" + } + @invalid_create_attrs %{ + email: "fixture", + password: "password", + password_confirmation: "wrong_password" + } + @valid_update_attrs %{ + "email" => "new-email", + "password" => "new_password", + "password_confirmation" => "new_password" + } + @invalid_update_attrs %{ + email: "new-email", + password: "new_password", + password_confirmation: "wrong_password" + } + + describe "new" do + test "renders sign up form", %{unauthed_conn: conn} do + test_conn = get(conn, Routes.user_path(conn, :new)) + + assert html_response(test_conn, 200) =~ "Sign Up" + end + end + + describe "create" do + test "creates user when params are valid", %{unauthed_conn: conn} do + test_conn = post(conn, Routes.user_path(conn, :create), user: @valid_create_attrs) + + assert redirected_to(test_conn) == "/devices" + assert %Session{} = test_conn.assigns.session + end + + test "renders errors when params are invalid", %{unauthed_conn: conn} do + test_conn = post(conn, Routes.user_path(conn, :create), user: @invalid_create_attrs) + + assert html_response(test_conn, 200) =~ "Sign Up" + end + end + + describe "edit" do + test "renders edit user form", %{authed_conn: conn} do + test_conn = get(conn, Routes.user_path(conn, :edit)) + + assert html_response(test_conn, 200) =~ "Edit Account" + end + end + + describe "show" do + test "renders user details", %{authed_conn: conn} do + test_conn = get(conn, Routes.user_path(conn, :show)) + + assert html_response(test_conn, 200) =~ "Your Account" + end + end + + describe "update" do + test "updates user when params are valid", %{authed_conn: conn} do + test_conn = put(conn, Routes.user_path(conn, :update), user: @valid_update_attrs) + + assert redirected_to(test_conn) == Routes.user_path(test_conn, :show) + end + + test "renders errors when params are invalid", %{authed_conn: conn} do + test_conn = put(conn, Routes.user_path(conn, :update), user: @invalid_update_attrs) + + assert html_response(test_conn, 200) =~ "Edit Account" + end + end + + describe "delete" do + test "deletes user", %{authed_conn: conn} do + test_conn = delete(conn, Routes.user_path(conn, :delete)) + assert redirected_to(test_conn) == "/" + end + end +end diff --git a/apps/fg_vpn/mix.exs b/apps/fg_vpn/mix.exs index e7f9f9963..0ed3b762c 100644 --- a/apps/fg_vpn/mix.exs +++ b/apps/fg_vpn/mix.exs @@ -33,7 +33,8 @@ defmodule FgVpn.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:credo, "~> 1.4", only: [:dev, :test], runtime: false} + {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, + {:excoveralls, "~> 0.13", only: :test} # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, # {:sibling_app_in_umbrella, in_umbrella: true} diff --git a/apps/fg_wall/mix.exs b/apps/fg_wall/mix.exs index 2faab890f..e55def960 100644 --- a/apps/fg_wall/mix.exs +++ b/apps/fg_wall/mix.exs @@ -33,7 +33,8 @@ defmodule FgWall.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:credo, "~> 1.4", only: [:dev, :test], runtime: false} + {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, + {:excoveralls, "~> 0.13", only: :test} # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, # {:sibling_app_in_umbrella, in_umbrella: true}