Skip to content
Snippets Groups Projects
Commit d8f29a97 authored by kerdo's avatar kerdo
Browse files

Merge branch '15-fr-05-delete-account' into 'main'

Resolve "FR-05: Delete Account"

Closes #15

See merge request !16
parents 19addd55 b0d8d449
No related branches found
No related tags found
1 merge request!16Resolve "FR-05: Delete Account"
Pipeline #44724 passed
defmodule WhiteBreadConfig do
use WhiteBread.SuiteConfiguration
suite name: "FR-01 User Registration Features",
suite name: "User Registration Features",
context: UserRegistrationContext,
feature_paths: ["features/user_registration.feature"]
......@@ -16,6 +17,9 @@ defmodule WhiteBreadConfig do
suite name: "FR-04 Password Change Features",
context: PasswordChangeContext,
feature_paths: ["features/password_change.feature"]
suite name: "User Delete Features",
context: UserDeleteContext,
feature_paths: ["features/user_delete.feature"]
suite name: "FR-30 User Profile Features",
context: UserProfileContext,
......
defmodule UserDeleteContext do
use WhiteBread.Context
use Hound.Helpers
alias PropTrackr.Accounts
alias PropTrackr.Repo
alias PropTrackr.Accounts.User
import PropTrackr.Authentication
scenario_starting_state fn _state ->
Ecto.Adapters.SQL.Sandbox.checkout(PropTrackr.Repo)
Ecto.Adapters.SQL.Sandbox.mode(PropTrackr.Repo, {:shared, self()})
Hound.start_session()
%{}
end
scenario_finalize fn _status, _state ->
Ecto.Adapters.SQL.Sandbox.checkin(PropTrackr.Repo)
Hound.end_session()
end
given_ ~r/^there exists following accounts$/, fn state, %{table_data: table} ->
table
|> Enum.map(fn user_details -> User.changeset(%User{}, user_details) end)
|> Enum.each(fn changeset -> Repo.insert!(changeset) end)
existing_user = List.first(table)
{
:ok,
state
|> Map.put(:email, existing_user[:email])
|> Map.put(:password, existing_user[:password])
}
end
and_ ~r/^I am logged in$/, fn state ->
navigate_to("/login")
fill_field({:id, "email"}, state[:email])
fill_field({:id, "password"}, state[:password])
click({:id, "login_button"})
assert visible_in_page? ~r"Successfully logged in!"
assert current_path() == "/"
navigate_to("/users")
{:ok, state}
end
and_ ~r/^I navigate to the delete account page$/, fn state ->
navigate_to("/me/delete")
{:ok, state}
end
when_ ~r/^I click confirm delete$/, fn state ->
click({:id, "confirm_delete"})
{:ok, state}
end
then_ ~r/^I should receive a success notification$/, fn state ->
assert visible_in_page? ~r"Your account has been deleted successfully."
{:ok, state}
end
and_ ~r/^I should be redirected to the homepage$/, fn state ->
assert current_path() == "/"
{:ok, state}
end
and_ ~r/^my account should no longer exist in the system$/, fn state ->
user = Repo.get_by(User, email: state[:email])
assert user == nil
{:ok, state}
end
and_ ~r/^I am not logged in$/, fn state ->
navigate_to("/logout")
{:ok, state}
end
when_ ~r/^I try to access the delete functionality$/, fn state ->
navigate_to("/me/delete")
{:ok, state}
end
then_ ~r/^I should see an error message$/, fn state ->
assert visible_in_page? ~r/You are not logged in!/
{:ok, state}
end
and_ ~r/^I should be redirected to the login page$/, fn state ->
assert current_path() == "/login"
{:ok, state}
end
end
Scenario: Authenticated user can delete their account
Given there exists following accounts
| name | surname | birth_date | phone_number | email | password | confirm_password |
| Existing | Account | 2000-01-01 | 000 | existing.account@gmail.com | password | password |
And I am logged in
And I navigate to the delete account page
When I click confirm delete
Then I should receive a success notification
And I should be redirected to the homepage
And my account should no longer exist in the system
Scenario: Unauthenticated user attempts to delete account
Given there exists following accounts
| name | surname | birth_date | phone_number | email | password | confirm_password |
| Existing | Account | 2000-01-01 | 000 | existing.account@gmail.com | password | password |
And I am not logged in
When I try to access the delete functionality
Then I should see an error message
And I should be redirected to the login page
\ No newline at end of file
defmodule PropTrackrWeb.UserDeleteController do
use PropTrackrWeb, :controller
alias PropTrackr.Accounts.User
alias PropTrackr.Repo
alias Ecto.Multi
def index(conn, _params) do
user_id = get_session(conn, :user_id)
if user_id == nil do
conn
|> put_flash(:error, "You are not logged in!")
|> redirect(to: ~p"/login")
else
user = Repo.get(User, user_id)
render conn, "index.html"
end
end
def delete(conn, _params) do
user_id = get_session(conn, :user_id)
user = Repo.get(User, user_id)
if user do
result =
Multi.new()
|> Multi.delete_all(:properties, Ecto.assoc(user, :properties))
|> Multi.delete(:user, user)
|> Repo.transaction()
case result do
{:ok, _} ->
conn
|> delete_session(:user_id)
|> put_flash(:info, "Your account has been deleted successfully.")
|> redirect(to: "/")
{:error, _, _, _} ->
conn
|> put_flash(:error, "An error occurred while deleting your account.")
|> redirect(to: "/me/delete")
end
else
conn
|> put_flash(:error, "User not found.")
|> redirect(to: "/")
end
end
end
defmodule PropTrackrWeb.UserDeleteHTML do
use PropTrackrWeb, :html
embed_templates "user_delete_html/*"
end
<.header>
Delete Account
</.header>
<.simple_form :let={f} for={} action={~p"/me/delete/#{@current_user.id}"} method="delete">
<p>Are you sure you want to delete your account? This action cannot be undone.</p>
<:actions>
<.button id="confirm_delete" class="bg-red-700 hover:bg-red-500">
Confirm Delete
</.button>
</:actions>
</.simple_form>
<.back navigate={~p"/me"}>Changed your mind?</.back>
......@@ -29,6 +29,7 @@ defmodule PropTrackrWeb.Router do
resources "/me", ProfileController, only: [:index]
resources "/me/details", UpdateController, only: [:index, :create]
resources "/me/password", PasswordController, only: [:index, :create]
resources "/me/delete", UserDeleteController, only: [:index, :delete]
# Properties
get "/", PropertiesController, :index
......
defmodule PropTrackrWeb.UserDeleteControllerTest do
use PropTrackrWeb.ConnCase
alias PropTrackr.Accounts.User
alias PropTrackr.Repo
@valid_attrs %{email: "test.user@gmail.com", password: "testing"}
setup do
user = %User{
name: "Test",
surname: "User",
birth_date: "2000-01-01",
phone_number: "000",
bio: "Yo",
email: "test.user@gmail.com",
password: "testing",
confirm_password: "testing",
}
user = Repo.insert!(user)
{:ok, %{user: user}}
end
test "Authenticated user should be able to delete their account and be redirected to the homepage and logged out and data deleted", %{conn: conn, user: user} do
# Log in the user
conn = setup_session(conn, user)
# Ensure the user is logged in
assert get_session(conn, :user_id) == user.id
# Perform delete with the user ID in the route
conn = delete(conn, "/me/delete/#{user.id}")
# Verify redirection to homepage
assert redirected_to(conn) == "/"
# Follow the redirection
conn = get(conn, redirected_to(conn))
assert html_response(conn, 200)
# Ensure the response contains the correct flash message
assert get_flash(conn, :info) =~ "Your account has been deleted successfully."
# Verify the user is logged out
assert get_session(conn, :user_id) == nil
# Confirm the user's data is removed from the database
assert Repo.get(User, user.id) == nil
end
test "Unauthenticated user cannot access the delete page", %{conn: conn} do
# Attempt to access the delete account page
conn = get(conn, "/me/delete")
# Verify redirection to homepage
assert redirected_to(conn) == "/login"
# Follow the redirection
conn = get(conn, redirected_to(conn))
assert html_response(conn, 200)
end
defp setup_session(conn, user) do
conn = conn |> post("/login", @valid_attrs)
conn = get conn, redirected_to(conn)
conn
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment