User controller tested

This commit is contained in:
Jamil Bou Kheir
2020-06-03 10:36:05 -07:00
parent cb5fb28783
commit 5e7279aac1
8 changed files with 136 additions and 26 deletions

View File

@@ -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])

View File

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

View File

@@ -1 +1 @@
<h3>Account</h3>
<h3>Edit Account</h3>

View File

@@ -0,0 +1,9 @@
<h3>Your Account</h3>
<dl>
<dt>Email</dt>
<dd><%= @user.email %></dd>
<dt>Last signed in at</dt>
<dd><%= @session.last_signed_in_at %></dd>
</dl>

View File

@@ -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"},

View File

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

View File

@@ -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}

View File

@@ -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}