diff --git a/features/contexts/user_registration_context.exs b/features/contexts/user_registration_context.exs index 8690d42106cbeea6c095bdba66a1139cef96b25d..d725695b8c55e53a3e1f23bfc62abc0e6191b847 100644 --- a/features/contexts/user_registration_context.exs +++ b/features/contexts/user_registration_context.exs @@ -5,83 +5,158 @@ defmodule UserRegistrationContext do alias PropTrackr.Repo alias PropTrackr.Accounts.User - feature_starting_state fn -> - Application.ensure_all_started(:hound) - %{state: "initialized"} - end - scenario_starting_state fn _state -> Ecto.Adapters.SQL.Sandbox.checkout(PropTrackr.Repo) Ecto.Adapters.SQL.Sandbox.mode(PropTrackr.Repo, {:shared, self()}) Hound.start_session() - %{state: "session_started"} + %{registered_users: []} end - scenario_finalize fn _status, _state -> + scenario_finalize fn _status, state -> + # Enum.each(state[:registered_users], &Repo.delete/1) Ecto.Adapters.SQL.Sandbox.checkin(PropTrackr.Repo) Hound.end_session() end - given_ ~r/^I am on the registration page$/, fn state -> + given_ ~r/^I want to register a new user$/, fn state -> navigate_to("/register") {:ok, state} end - when_ ~r/^I fill in the registration form with valid details$/, fn state -> - fill_registration_form( - "valid1@example.com", - "Test", - "User", - "12.12.12", - "1234567890", - "test123", - "test123" - ) + and_ ~r/^I have such user data$/, fn state, %{table_data: table} -> + user_data = List.first(table) + {:ok, state |> Map.put(:user_data, user_data)} + end + + when_ ~r/^I fill a registration form with valid data$/, fn state -> + fill_field({:id, "name"}, state[:user_data][:name]) + fill_field({:id, "surname"}, state[:user_data][:surname]) + formatted_date = formatDate(state[:user_data][:birth_date]) + fill_field({:id, "birth_date"}, formatted_date) + fill_field({:id, "phone_number"}, state[:user_data][:phone_number]) + fill_field({:id, "email"}, state[:user_data][:email]) + fill_field({:id, "password"}, state[:user_data][:password]) + fill_field({:id, "confirm_password"}, state[:user_data][:confirm_password]) {:ok, state} end - and_ ~r/^I submit the form$/, fn state -> + when_ ~r/^I click submit$/, fn state -> click({:id, "register_button"}) {:ok, state} end - then_ ~r/^I should see User created successfully.$/, fn state -> + then_ ~r/^I should see a success message$/, fn state -> assert visible_in_page? ~r/User created successfully./ {:ok, state} end - and_ ~r/^I should be redirected to the homepage$/, fn state -> - assert current_url() == "http://localhost:4001/users" + and_ ~r/^the user should be saved in the database$/, fn state -> + assert Repo.get_by(User, email: state[:user_data][:email]) {:ok, state} end - when_ ~r/^I fill in the registration form with mismatched passwords$/, fn state -> - fill_registration_form( - "mismatch_user@example.com", - "Mismatch", - "User", - "12.12.12", - "1122334455", - "test123", - "different123" - ) + and_ ~r/^I should be redirected to the main page$/, fn state -> + assert current_path() == "/" {:ok, state} end - then_ ~r/^I should see an error message Passwords do not match$/, fn state -> - assert visible_in_page? ~r/Passwords do not match/ + when_ ~r/^I fill a registration form with invalid phone number$/, fn state -> + fill_field({:id, "name"}, state[:user_data][:name]) + fill_field({:id, "surname"}, state[:user_data][:surname]) + formatted_date = formatDate(state[:user_data][:birth_date]) + fill_field({:id, "birth_date"}, formatted_date) + fill_field({:id, "phone_number"}, state[:user_data][:phone_number]) + fill_field({:id, "email"}, state[:user_data][:email]) + fill_field({:id, "password"}, state[:user_data][:password]) + fill_field({:id, "confirm_password"}, state[:user_data][:confirm_password]) {:ok, state} end - # Helper function to fill out the registration form with 7 fields - defp fill_registration_form(email, name, surname, birth_date, phone_number, password, confirm_password) do - fill_field({:name, "user[email]"}, email) - fill_field({:name, "user[name]"}, name) - fill_field({:name, "user[surname]"}, surname) - fill_field({:name, "user[birth_date]"}, birth_date) - fill_field({:name, "user[phone_number]"}, phone_number) - fill_field({:name, "user[password]"}, password) - fill_field({:name, "user[confirm_password]"}, confirm_password) + then_ ~r/^I should see an error message about the phone number$/, fn state -> + assert visible_page_text() =~ "must be between 3 and 15 digits, without '+' sign" + {:ok, state} + end + + and_ ~r/^the user should not be saved in the database$/, fn state -> + refute Repo.get_by(User, email: state[:user_data][:email]) + {:ok, state} + end + + and_ ~r/^I should still see the registration form$/, fn state -> + assert current_path() == "/register" + {:ok, state} + end + + when_ ~r/^I fill a registration form with invalid date$/, fn state -> + fill_field({:id, "name"}, state[:user_data][:name]) + fill_field({:id, "surname"}, state[:user_data][:surname]) + formatted_date = formatDate(state[:user_data][:birth_date]) + fill_field({:id, "birth_date"}, formatted_date) + fill_field({:id, "phone_number"}, state[:user_data][:phone_number]) + fill_field({:id, "email"}, state[:user_data][:email]) + fill_field({:id, "password"}, state[:user_data][:password]) + fill_field({:id, "confirm_password"}, state[:user_data][:confirm_password]) + {:ok, state} + end + + then_ ~r/^I should see an error message about the birth date$/, fn state -> + assert visible_page_text() =~ "Birth date cannot be in the future" or + assert visible_page_text() =~ "Date is too past" or + assert visible_page_text() =~ "is invalid" + {:ok, state} end + given_ ~r/^there exists the following account$/, 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 + + when_ ~r/^I fill a registration form with existing email$/, fn state -> + fill_field({:id, "name"}, state[:user_data][:name]) + fill_field({:id, "surname"}, state[:user_data][:surname]) + formatted_date = formatDate(state[:user_data][:birth_date]) + fill_field({:id, "birth_date"}, formatted_date) + fill_field({:id, "phone_number"}, state[:user_data][:phone_number]) + fill_field({:id, "email"}, state[:user_data][:email]) + fill_field({:id, "password"}, state[:user_data][:password]) + fill_field({:id, "confirm_password"}, state[:user_data][:confirm_password]) + {:ok, state} + end + + then_ ~r/^I should see an error message about the email$/, fn state -> + assert visible_page_text() =~ "An account with this email already exists." + {:ok, state} + end + + when_ ~r/^I fill a registration form with mismatched passwords$/, fn state -> + fill_field({:id, "name"}, state[:user_data][:name]) + fill_field({:id, "surname"}, state[:user_data][:surname]) + formatted_date = formatDate(state[:user_data][:birth_date]) + fill_field({:id, "birth_date"}, formatted_date) + fill_field({:id, "phone_number"}, state[:user_data][:phone_number]) + fill_field({:id, "email"}, state[:user_data][:email]) + fill_field({:id, "password"}, state[:user_data][:password]) + fill_field({:id, "confirm_password"}, state[:user_data][:confirm_password]) + {:ok, state} + end + + then_ ~r/^I should see an error message about the passwords$/, fn state -> + assert visible_page_text() =~ "Passwords do not match." + {:ok, state} + end + + defp formatDate(date) do + [year, month, day] = String.split(date, "-") + formatted_date = "#{month}-#{day}-#{year}" + formatted_date + end end diff --git a/features/user_registration.feature b/features/user_registration.feature index 9c5f3fef8f150efb9b1f4db945aabc4217cac72a..6c75f5b45540fbfcbe330f42abb0e5ab3382d2cc 100644 --- a/features/user_registration.feature +++ b/features/user_registration.feature @@ -1,15 +1,59 @@ -Feature: FR-01 User Registration +Feature: User Registration - Scenario: Unauthenticated user registers successfully (AC1, AC5, AC6, AC7) - Given I am on the registration page - When I fill in the registration form with valid details - And I submit the form - Then I should see User created successfully. - And I should be redirected to the homepage + Scenario: Valid user registration + Given I want to register a new user + And I have such user data + | name | surname | birth_date | phone_number | email | password | confirm_password | + | John | Doe | 1990-01-02 | 123456789 | john.doe@example.com | password | password | + When I fill a registration form with valid data + When I click submit + Then I should see a success message + And the user should be saved in the database + And I should be redirected to the main page - Scenario: User confirms password to prevent typos (AC2, AC3) - Given I am on the registration page - When I fill in the registration form with mismatched passwords - And I submit the form - Then I should see an error message Passwords do not match + Scenario: Invalid phone number + Given I want to register a new user + And I have such user data + | name | surname | birth_date | phone_number | email | password | confirm_password | + | Jane | Doe | 1990-01-01 | 123abc | jane.doe@example.com | password | password | + When I fill a registration form with invalid phone number + When I click submit + Then I should see an error message about the phone number + And the user should not be saved in the database + And I should still see the registration form + Scenario: Invalid birth date + Given I want to register a new user + And I have such user data + | name | surname | birth_date | phone_number | email | password | confirm_password | + | Michael | Smith | 2500-01-01 | 987654321 | michael.smith@example.com | password | password | + When I fill a registration form with invalid date + When I click submit + Then I should see an error message about the birth date + And the user should not be saved in the database + And I should still see the registration form + + Scenario: Email already exists + Given there exists the following account + | name | surname | birth_date | phone_number | email | password | confirm_password | + | John | Doe | 2000-01-01 | 123456789 | johnson.doe@example.com | password | password | + And I want to register a new user + And I have such user data + | name | surname | birth_date | phone_number | email | password | confirm_password | + | Jane | Smith | 2000-01-01 | 987654321 | johnson.doe@example.com | password | password | + When I fill a registration form with existing email + When I click submit + Then I should see an error message about the email + And the user should be saved in the database + And I should still see the registration form + + Scenario: Password and confirm password do not match + Given I want to register a new user + And I have such user data + | name | surname | birth_date | phone_number | email | password | confirm_password | + | Jane | Doe | 1990-01-01 | 123456789 | jane.doe@example.com | password | different | + When I fill a registration form with mismatched passwords + When I click submit + Then I should see an error message about the passwords + And the user should not be saved in the database + And I should still see the registration form \ No newline at end of file diff --git a/lib/proptrackr/accounts/user.ex b/lib/proptrackr/accounts/user.ex index 6d3b0df45e84cb51183cdb1e35d13d87a1d3a4f1..ba92799bd1f8eefb7ff7e579da04e9195bb34fdd 100644 --- a/lib/proptrackr/accounts/user.ex +++ b/lib/proptrackr/accounts/user.ex @@ -8,7 +8,7 @@ defmodule PropTrackr.Accounts.User do schema "users" do field :name, :string field :surname, :string - field :birth_date, :string + field :birth_date, :date field :phone_number, :string field :bio, :string field :email, :string @@ -25,27 +25,62 @@ defmodule PropTrackr.Accounts.User do struct |> cast(params, [:name, :surname, :birth_date, :phone_number, :bio, :email, :password, :confirm_password]) |> validate_required([:name, :surname, :birth_date, :phone_number, :email, :password, :confirm_password]) + |> validate_format(:name, ~r/^[a-zA-Z]+$/, message: "must contain only English letters") + |> validate_format(:surname, ~r/^[a-zA-Z]+$/, message: "must contain only English letters") + |> validate_format(:phone_number, ~r/^\d{3,15}$/, message: "must be between 3 and 15 digits, without '+' sign") + |> validate_format(:email, ~r/^[^@]+@[^@]+\.[^@]+$/, message: "must contain exactly one '@' sign and be in a valid format") + |> validate_length(:name, min: 2, max: 50) + |> validate_length(:surname, min: 2, max: 50) + |> validate_date(:birth_date) + |> validate_email_format() |> validate_password_confirmation(:password, :confirm_password) - # |> validate_unique_email() + |> validate_unique_email() + end + + defp validate_date(changeset, date) do + case get_field(changeset, date) do + nil -> changeset + birth_date -> + cond do + Date.diff(Date.utc_today(), birth_date) < 0 -> + add_error(changeset, date, "Birth date cannot be in the future") + + Date.diff(birth_date, ~D[1900-01-01]) < 0 -> + add_error(changeset, date, "Date is too past") + + true -> + changeset + end + end end defp validate_password_confirmation(changeset, field_1, field_2) do - if get_field(changeset, field_1) != get_field(changeset, field_2) do - changeset - |> add_error(field_2, "Passwords do not match.", [other: field_1]) - else - changeset + case get_field(changeset, field_1) do + nil -> changeset + password -> + confirm = get_field(changeset, field_2) + if password == confirm do + changeset + else + add_error(changeset, field_2, "Passwords do not match.") + end end end - defp validate_unique_email(changeset) do - email = get_field(changeset, :email) + defp validate_email_format(changeset) do + changeset + |> validate_format(:email, ~r/^[^@\s]+@[^@\s]+\.[^@\s]+$/, message: "must be a valid email address") + |> validate_length(:email, min: 6, max: 255) + end - # Only check for uniqueness if email is not nil - if email && Repo.get_by(User, email: email) do - add_error(changeset, :email, "An account with this email already exists.") - else - changeset + defp validate_unique_email(changeset) do + case get_field(changeset, :email) do + nil -> changeset + email -> + case Repo.get_by(User, email: email) do + nil -> changeset + _ -> add_error(changeset, :email, "An account with this email already exists.") + end end end diff --git a/lib/proptrackr_web/controllers/register_controller.ex b/lib/proptrackr_web/controllers/register_controller.ex index 4566c838a12e131b2384eef975093d3d31182241..132aca5f079046e8e80a13a25f6a5dec36f626e9 100644 --- a/lib/proptrackr_web/controllers/register_controller.ex +++ b/lib/proptrackr_web/controllers/register_controller.ex @@ -17,7 +17,7 @@ defmodule PropTrackrWeb.RegisterController do conn |> put_flash(:info, "User created successfully.") |> login(user.id, user) #Logins if succesfully created - |> redirect(to: ~p"/users") + |> redirect(to: ~p"/") {:error, %Ecto.Changeset{} = changeset} -> render(conn, "index.html", changeset: changeset) end diff --git a/lib/proptrackr_web/controllers/register_html/index.html.heex b/lib/proptrackr_web/controllers/register_html/index.html.heex index dacc5cea8eddb341ba94d9d5ea9971a2612395a2..a1de031157cdaf780e8a6bbdeac219626b2e832a 100644 --- a/lib/proptrackr_web/controllers/register_html/index.html.heex +++ b/lib/proptrackr_web/controllers/register_html/index.html.heex @@ -6,14 +6,14 @@ <.error :if={@changeset.action}> Oops, something went wrong! Please check the errors below. </.error> - <.input field={f[:name]} type="text" label="Name" /> - <.input field={f[:surname]} type="text" label="Surname" /> - <.input field={f[:birth_date]} type="text" label="Birth date" /> - <.input field={f[:phone_number]} type="text" label="Phone number" /> - <.input field={f[:bio]} type="text" label="Bio" /> - <.input field={f[:email]} type="text" label="Email" /> - <.input field={f[:password]} type="password" label="Password" /> - <.input field={f[:confirm_password]} type="password" label="Confirm password" /> + <.input field={f[:name]} id="name" type="text" label="Name" /> + <.input field={f[:surname]} id="surname" type="text" label="Surname" /> + <.input field={f[:birth_date]} id="birth_date" type="date" label="Birth date" /> + <.input field={f[:phone_number]} id="phone_number" type="tel" label="Phone number" /> + <.input field={f[:bio]} id="bio" type="textarea" label="Bio" /> + <.input field={f[:email]} id="email" type="email" label="Email" /> + <.input field={f[:password]} id="password" type="password" label="Password" /> + <.input field={f[:confirm_password]} id="confirm_password" type="password" label="Confirm password" /> <:actions> <.button id="register_button">Register</.button> </:actions> diff --git a/priv/repo/migrations/20241121112559_modify_birth_date.exs b/priv/repo/migrations/20241121112559_modify_birth_date.exs new file mode 100644 index 0000000000000000000000000000000000000000..57eab2d2f988d7cfa0a027460d04a6168f299390 --- /dev/null +++ b/priv/repo/migrations/20241121112559_modify_birth_date.exs @@ -0,0 +1,16 @@ +defmodule PropTrackr.Repo.Migrations.ModifyBirthDate do + use Ecto.Migration + + def change do + alter table(:users) do + add :birth_date, :date + end + end + + def up do + execute """ + alter table users alter column birth_date type date using (birth_date::date) + """ + end + +end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 04b23610c2f0ed2e615bcc69f557c7998de736f6..c7524071ebccd97b43d7a28d81be04b2915de02a 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -5,7 +5,7 @@ alias PropTrackr.{Repo, Accounts.User} name: "Shyngys", surname: "Satkan", birth_date: "2003-09-04", - phone_number: "+77011234567", + phone_number: "77011234567", bio: "Software engineer", email: "shyngys.satkan@example.com", password: "ssatkan", @@ -15,7 +15,7 @@ alias PropTrackr.{Repo, Accounts.User} name: "Jotaro", surname: "Kujo", birth_date: "1984-04-03", - phone_number: "+1234567890", + phone_number: "1234567890", bio: "Marine biologist and a stand user.", email: "jotaro.kujo@example.com", password: "oraoraora", diff --git a/test/proptrackr_web/controllers/favorite_controller_test.exs b/test/proptrackr_web/controllers/favorite_controller_test.exs index 6d23aa07238d752aa3f882440db76d9b8fd417c8..c97780748d94b880084a6a478a31cca277489075 100644 --- a/test/proptrackr_web/controllers/favorite_controller_test.exs +++ b/test/proptrackr_web/controllers/favorite_controller_test.exs @@ -10,7 +10,7 @@ defmodule PropTrackrWeb.FavoriteControllerTest do owner = %User{ name: "Property", surname: "Owner", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "111", bio: "Hey", email: "property.owner@gmail.com", @@ -22,7 +22,7 @@ defmodule PropTrackrWeb.FavoriteControllerTest do random_user = %User{ name: "Random", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Hi", email: "random.user@gmail.com", diff --git a/test/proptrackr_web/controllers/interest_controller_test.exs b/test/proptrackr_web/controllers/interest_controller_test.exs index 63d80c49d193ee4c60ace3ed5bcf9c9ab973354a..baf34ce4021955f8748791391b5d0010b7f427ca 100644 --- a/test/proptrackr_web/controllers/interest_controller_test.exs +++ b/test/proptrackr_web/controllers/interest_controller_test.exs @@ -9,14 +9,14 @@ defmodule PropTrackrWeb.InterestControllerTest do setup do owner = %User{ name: "Property", surname: "Owner", - birth_date: "2000-01-01", phone_number: "111", + birth_date: ~D[2000-01-01], phone_number: "111", email: "property.owner@gmail.com", password: "password", confirm_password: "password" } |> Repo.insert!() random_user = %User{ name: "Random", surname: "User", - birth_date: "2000-01-01", phone_number: "000", + birth_date: ~D[2000-01-01], phone_number: "000", email: "random.user@gmail.com", password: "password", confirm_password: "password" } |> Repo.insert!() diff --git a/test/proptrackr_web/controllers/login_controller_test.exs b/test/proptrackr_web/controllers/login_controller_test.exs index a3b380dcd8aad33d7a8bd980b3db8626e2280724..6642a675bb142fbac8a56c906fbd704a271e367c 100644 --- a/test/proptrackr_web/controllers/login_controller_test.exs +++ b/test/proptrackr_web/controllers/login_controller_test.exs @@ -11,7 +11,7 @@ defmodule PropTrackrWeb.LoginControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/logout_controller_test.exs b/test/proptrackr_web/controllers/logout_controller_test.exs index 223561f9135b7b7e693c7683be8593b59890e222..c74569f0531df70fd1a7894a1c80af7287a35142 100644 --- a/test/proptrackr_web/controllers/logout_controller_test.exs +++ b/test/proptrackr_web/controllers/logout_controller_test.exs @@ -7,7 +7,7 @@ defmodule PropTrackrWeb.LogoutControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/my_advertisements_controller_test.exs b/test/proptrackr_web/controllers/my_advertisements_controller_test.exs index a4f15d019efffdfd8b7ed9cab7996f61e8390ec2..9bc81bb93ca4fb4878eca556839196c168157c8d 100644 --- a/test/proptrackr_web/controllers/my_advertisements_controller_test.exs +++ b/test/proptrackr_web/controllers/my_advertisements_controller_test.exs @@ -22,7 +22,7 @@ defmodule PropTrackrWeb.MyPropertiesControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", @@ -35,7 +35,7 @@ defmodule PropTrackrWeb.MyPropertiesControllerTest do other_user = %User{ name: "Other", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "111", bio: "Hey", email: "other.user@gmail.com", diff --git a/test/proptrackr_web/controllers/my_favorites_controller_test.exs b/test/proptrackr_web/controllers/my_favorites_controller_test.exs index f43e47f0916a3ae2457ef399e1118a57bda8bd29..f27de8d4715306f44ee747498ad7091c91608e59 100644 --- a/test/proptrackr_web/controllers/my_favorites_controller_test.exs +++ b/test/proptrackr_web/controllers/my_favorites_controller_test.exs @@ -11,7 +11,7 @@ defmodule PropTrackrWeb.MyFavoritesControllerTest do owner = %User{ name: "Property", surname: "Owner", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "111", bio: "Hey", email: "property.owner@gmail.com", @@ -24,7 +24,7 @@ defmodule PropTrackrWeb.MyFavoritesControllerTest do random_user = %User{ name: "Random", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Hi", email: "random.user@gmail.com", diff --git a/test/proptrackr_web/controllers/password_controller_test.exs b/test/proptrackr_web/controllers/password_controller_test.exs index ae23a4cdf996f5c7aaba8e0983dcdba7ccf1ae2a..b1aa86dd9fa8f4b8fb48fa2562db0ac79dfaf833 100644 --- a/test/proptrackr_web/controllers/password_controller_test.exs +++ b/test/proptrackr_web/controllers/password_controller_test.exs @@ -9,7 +9,7 @@ defmodule PropTrackrWeb.PasswordControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/profile_controller_test.exs b/test/proptrackr_web/controllers/profile_controller_test.exs index 62e406e7cd15a1405c6374d736a43b790ad3344c..88f27431dc53b00aaf870f876e6a860338744bdd 100644 --- a/test/proptrackr_web/controllers/profile_controller_test.exs +++ b/test/proptrackr_web/controllers/profile_controller_test.exs @@ -7,7 +7,7 @@ defmodule PropTrackrWeb.ProfileControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/properties_controller_test.exs b/test/proptrackr_web/controllers/properties_controller_test.exs index 0bc3bf3e54c6221f1e9749af38702a7052697084..ced3628412d4e8768b0f8c6c3e87861562e277d9 100644 --- a/test/proptrackr_web/controllers/properties_controller_test.exs +++ b/test/proptrackr_web/controllers/properties_controller_test.exs @@ -86,7 +86,7 @@ defmodule PropTrackrWeb.PropertiesControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", @@ -98,7 +98,7 @@ defmodule PropTrackrWeb.PropertiesControllerTest do other_user = %User{ name: "Other", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "111", bio: "Hey", email: "other.user@gmail.com", diff --git a/test/proptrackr_web/controllers/search_controller_test.exs b/test/proptrackr_web/controllers/search_controller_test.exs index 3c7b79dd5c136a2671135595c4f2894966122ce3..7dbe3f4bda97c9d32b3bfdca8b8fb8c8b5871c5c 100644 --- a/test/proptrackr_web/controllers/search_controller_test.exs +++ b/test/proptrackr_web/controllers/search_controller_test.exs @@ -8,7 +8,7 @@ defmodule PropTrackrWeb.SearchControllerTest do user = %User{ name: "Owner", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/similar_properties_controller_test.exs b/test/proptrackr_web/controllers/similar_properties_controller_test.exs index ce396794f3cb4a09cacbf4d195687f9f57cedba6..2c7b8d0ba5db5eef8310ea1eba3847c87012236b 100644 --- a/test/proptrackr_web/controllers/similar_properties_controller_test.exs +++ b/test/proptrackr_web/controllers/similar_properties_controller_test.exs @@ -8,7 +8,7 @@ defmodule PropTrackrWeb.SimilarPropertiesControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/update_controller_test.exs b/test/proptrackr_web/controllers/update_controller_test.exs index 6b41cbe15bf87cdd33bbf059390e61eacd2938f1..f42709f4b2bd4760d92b48c4bd1bf82050b48524 100644 --- a/test/proptrackr_web/controllers/update_controller_test.exs +++ b/test/proptrackr_web/controllers/update_controller_test.exs @@ -9,7 +9,7 @@ defmodule PropTrackrWeb.UpdateControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com", diff --git a/test/proptrackr_web/controllers/user_controller_test.exs b/test/proptrackr_web/controllers/user_controller_test.exs index db835cf2453af0945eb0c71bfe54c9ad0e36ae80..da24871309811f3d965e7281e2191dd6ee83d62c 100644 --- a/test/proptrackr_web/controllers/user_controller_test.exs +++ b/test/proptrackr_web/controllers/user_controller_test.exs @@ -1,46 +1,123 @@ -defmodule PropTrackrWeb.UserControllerTest do +defmodule PropTrackrWeb.RegisterControllerTest do use PropTrackrWeb.ConnCase alias PropTrackr.Accounts.User alias PropTrackr.Repo - setup do - {:ok, user_params: %{ - name: "Test User", - surname: "Doe", - birth_date: "1990-01-01", - phone_number: "123-456-7890", - bio: "This is a test bio.", - email: "new_user@example.com", - password: "test123", - confirm_password: "test123" - }} - end + @valid_attrs %{ + name: "John", + surname: "Doe", + birth_date: ~D[1990-01-01], + phone_number: "123456789", + email: "john.doe@example.com", + password: "password", + confirm_password: "password" + } - test "AC1: unauthenticated user can register an account", %{conn: conn, user_params: user_params} do - conn = post(conn, "/register", user: user_params) - assert html_response(conn, 302) - assert get_flash(conn, :info) == "User created successfully." - assert redirected_to(conn) == "/users" - end + @invalid_phone_attrs %{ + name: "Jane", + surname: "Doe", + birth_date: ~D[1990-01-01], + phone_number: "123abc", + email: "jane.doe@example.com", + password: "password", + confirm_password: "password" + } - test "AC2 and AC3: user sees an error when passwords do not match", %{conn: conn, user_params: user_params} do - mismatched_params = Map.put(user_params, :confirm_password, "different_password") - conn = post(conn, "/register", user: mismatched_params) - assert html_response(conn, 200) =~ "Passwords do not match." - end + @future_date_attrs %{ + name: "Michael", + surname: "Smith", + birth_date: ~D[2500-01-01], + phone_number: "987654321", + email: "michael.smith@example.com", + password: "password", + confirm_password: "password" + } - # TODO(Kerdo): Reintroduce this test when re-enabling already existing email constraint - @tag :skip - test "AC4: user sees an error if an account with the same email exists", %{conn: conn, user_params: user_params} do - Repo.insert!(%User{email: user_params[:email], password: "test123"}) - conn = post(conn, "/register", user: user_params) - assert html_response(conn, 200) =~ "An account with this email already exists" + @mismatched_password_attrs %{ + name: "Jane", + surname: "Doe", + birth_date: ~D[1990-01-01], + phone_number: "123456789", + email: "jane.doe@example.com", + password: "password", + confirm_password: "different" + } + + setup %{conn: conn} do + {:ok, conn: conn} end - test "AC5, AC6, AC7: user is logged in, redirected, and shown notification upon successful registration", %{conn: conn, user_params: user_params} do - conn = post(conn, "/register", user: user_params) - assert get_flash(conn, :info) == "User created successfully." - assert redirected_to(conn) == "/users" - assert get_session(conn, :user_id) + describe "user registration" do + test "successful registration with valid attributes", %{conn: conn} do + conn = post(conn, ~p"/register", user: @valid_attrs) + + # Assert redirect to home page + assert redirected_to(conn) == ~p"/" + + # Assert flash message + assert get_flash(conn, :info) == "User created successfully." + + # Assert user was saved in database + user = Repo.get_by!(User, email: @valid_attrs.email) + assert user.name == @valid_attrs.name + assert user.surname == @valid_attrs.surname + assert user.phone_number == @valid_attrs.phone_number + end + + test "registration fails with invalid phone number", %{conn: conn} do + conn = post(conn, ~p"/register", user: @invalid_phone_attrs) + + # Assert rendering registration form again + assert html_response(conn, 200) =~ "Register" + + # Assert error message + assert html_response(conn, 200) =~ "must be between 3 and 15 digits, without '+' sign" + + # Assert user was not saved + assert Repo.get_by(User, email: @invalid_phone_attrs.email) == nil + end + + test "registration fails with future birth date", %{conn: conn} do + conn = post(conn, ~p"/register", user: @future_date_attrs) + + # Assert rendering registration form again + assert html_response(conn, 200) =~ "Register" + + # Assert user was not saved + assert Repo.get_by(User, email: @future_date_attrs.email) == nil + end + + test "registration fails with existing email", %{conn: conn} do + # First create a user + {:ok, _existing_user} = %User{} + |> User.changeset(@valid_attrs) + |> Repo.insert() + + # Try to register with same email + duplicate_email_attrs = %{@valid_attrs | name: "Jane", surname: "Smith"} + conn = post(conn, ~p"/register", user: duplicate_email_attrs) + + # Assert rendering registration form again + assert html_response(conn, 200) =~ "Register" + + # Assert error message + assert html_response(conn, 200) =~ "An account with this email already exists" + + # Assert only one user exists with this email + user = Repo.get_by!(User, email: @valid_attrs.email) + end + + test "registration fails with mismatched passwords", %{conn: conn} do + conn = post(conn, ~p"/register", user: @mismatched_password_attrs) + + # Assert rendering registration form again + assert html_response(conn, 200) =~ "Register" + + # Assert error message + assert html_response(conn, 200) =~ "Passwords do not match" + + # Assert user was not saved + assert Repo.get_by(User, email: @mismatched_password_attrs.email) == nil + end end end diff --git a/test/proptrackr_web/controllers/user_delete_controller_test.exs b/test/proptrackr_web/controllers/user_delete_controller_test.exs index d8ea6283abab58ff4ebc4e31a4b41f9379ea4f89..011e3b466e1abc3ff19a562f955237ccea32d64d 100644 --- a/test/proptrackr_web/controllers/user_delete_controller_test.exs +++ b/test/proptrackr_web/controllers/user_delete_controller_test.exs @@ -9,7 +9,7 @@ defmodule PropTrackrWeb.UserDeleteControllerTest do user = %User{ name: "Test", surname: "User", - birth_date: "2000-01-01", + birth_date: ~D[2000-01-01], phone_number: "000", bio: "Yo", email: "test.user@gmail.com",