From e3defe76860e3ad4bcd96a3b9648c5f04f3ae50b Mon Sep 17 00:00:00 2001
From: Kerdo Kurs <kerdokurs@gmail.com>
Date: Mon, 18 Nov 2024 16:33:25 +0200
Subject: [PATCH] implement TDD for profile page #46

---
 features/config.exs                           |  4 +
 features/contexts/user_profile_context.exs    | 75 +++++++++++++++++++
 features/user_profile.feature                 | 16 ++++
 .../controllers/profile_controller.ex         |  2 +-
 .../controllers/profile_controller_test.exs   | 49 ++++++++++++
 5 files changed, 145 insertions(+), 1 deletion(-)
 create mode 100644 features/contexts/user_profile_context.exs
 create mode 100644 features/user_profile.feature
 create mode 100644 test/proptrackr_web/controllers/profile_controller_test.exs

diff --git a/features/config.exs b/features/config.exs
index 4ef5992..16c41d3 100644
--- a/features/config.exs
+++ b/features/config.exs
@@ -17,4 +17,8 @@ defmodule WhiteBreadConfig do
         context:       PasswordChangeContext,
         feature_paths: ["features/password_change.feature"]
 
+  suite name:          "User Profile Features",
+        context:       UserProfileContext,
+        feature_paths: ["features/user_profile.feature"]
+
 end
diff --git a/features/contexts/user_profile_context.exs b/features/contexts/user_profile_context.exs
new file mode 100644
index 0000000..7dcffa6
--- /dev/null
+++ b/features/contexts/user_profile_context.exs
@@ -0,0 +1,75 @@
+defmodule UserProfileContext do
+  use WhiteBread.Context
+  use Hound.Helpers
+  alias PropTrackr.Accounts
+  alias PropTrackr.Repo
+  alias PropTrackr.Accounts.User
+
+  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(:user, existing_user)
+    }
+  end
+
+  and_ ~r/^I am logged in$/, fn state ->
+    setup_session(state[:user][:email], state[:user][:password])
+    {:ok, state}
+  end
+
+  when_ ~r/^I go to the profile page$/, fn state ->
+    navigate_to("/me")
+    {:ok, state}
+  end
+
+  then_ ~r/^I should see my profile details$/, fn state ->
+    assert visible_in_page? ~r/#{state[:user][:name]} #{state[:user][:surname]}'s profile/
+    assert visible_in_page? ~r/#{state[:user][:email]}/
+    assert visible_in_page? ~r/#{state[:user][:phone_number]}/
+    assert visible_in_page? ~r/#{state[:user][:bio]}/
+    assert visible_in_page? ~r/#{state[:user][:birth_date]}/
+    {:ok, state}
+  end
+
+  given_ ~r/^I am not logged in$/, fn state ->
+    navigate_to("/logout")
+    {: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
+
+  defp setup_session(email, password) do
+    navigate_to("/login")
+    fill_field({:id, "email"}, email)
+    fill_field({:id, "password"}, password)
+    click({:id, "login_button"})
+  end
+
+end
diff --git a/features/user_profile.feature b/features/user_profile.feature
new file mode 100644
index 0000000..9fa4557
--- /dev/null
+++ b/features/user_profile.feature
@@ -0,0 +1,16 @@
+Feature: FR-30 User profile
+
+    Scenario: Authenticated user should be able to view their profile
+        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
+        When I go to the profile page
+        Then I should see my profile details
+
+    Scenario: Unauthenticated user should be shown an error message and redirected to the homepage
+        Given I am not logged in
+        When I go to the profile page
+        Then I should see an error message
+        And I should be redirected to the login page
+
diff --git a/lib/proptrackr_web/controllers/profile_controller.ex b/lib/proptrackr_web/controllers/profile_controller.ex
index 73d1c19..4465b54 100644
--- a/lib/proptrackr_web/controllers/profile_controller.ex
+++ b/lib/proptrackr_web/controllers/profile_controller.ex
@@ -9,7 +9,7 @@ defmodule PropTrackrWeb.ProfileController do
     user_id = get_session(conn, :user_id)
     if user_id == nil do
       conn
-      |> put_flash(:error, "You are not logged!")
+      |> put_flash(:error, "You are not logged in!")
       |> redirect(to: ~p"/login")
     else
       user = Repo.get(User, user_id)
diff --git a/test/proptrackr_web/controllers/profile_controller_test.exs b/test/proptrackr_web/controllers/profile_controller_test.exs
new file mode 100644
index 0000000..62e406e
--- /dev/null
+++ b/test/proptrackr_web/controllers/profile_controller_test.exs
@@ -0,0 +1,49 @@
+defmodule PropTrackrWeb.ProfileControllerTest do
+  use PropTrackrWeb.ConnCase
+  alias PropTrackr.Accounts.User
+  alias PropTrackr.Repo
+
+  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 see their data on the profile page", %{conn: conn, user: user} do
+    conn = conn |> setup_session(user)
+    conn = get conn, "/me"
+    assert html_response(conn, 200) =~ ~r/#{user.name} #{user.surname}'s profile/
+    assert html_response(conn, 200) =~ ~r/#{user.email}/
+    assert html_response(conn, 200) =~ ~r/#{user.phone_number}/
+    assert html_response(conn, 200) =~ ~r/#{user.bio}/
+    assert html_response(conn, 200) =~ ~r/#{user.birth_date}/
+  end
+
+  test "Unauthenticated user should see an error message", %{conn: conn} do
+    conn = get conn, "/me"
+    assert redirected_to(conn) == "/login"
+    conn = get conn, redirected_to(conn)
+    assert html_response(conn, 200) =~ ~r/You are not logged in!/
+  end
+
+  test "Unauthenticated user should be redirected to the login page", %{conn: conn} do
+    conn = get conn, "/me"
+    assert redirected_to(conn) == "/login"
+  end
+
+  defp setup_session(conn, user) do
+    conn = conn |> post("/login", email: user.email, password: user.password)
+    conn = get conn, redirected_to(conn)
+    conn
+  end
+end
-- 
GitLab