diff --git a/config/dev.exs b/config/dev.exs index 2d702a5..3b8a5d8 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -2,8 +2,9 @@ import Config # Configure your database config :lokal, Lokal.Repo, - url: System.get_env("DATABASE_URL") || - "ecto://postgres:postgres@localhost/lokal_dev", + url: + System.get_env("DATABASE_URL") || + "ecto://postgres:postgres@localhost/lokal_dev", show_sensitive_data_on_connection_error: true, pool_size: 10 diff --git a/lib/lokal_web/component/topbar.ex b/lib/lokal_web/component/topbar.ex index 78118d6..46ccd25 100644 --- a/lib/lokal_web/component/topbar.ex +++ b/lib/lokal_web/component/topbar.ex @@ -18,70 +18,83 @@ defmodule LokalWeb.Component.Topbar do
<%= link to: Routes.live_path(LokalWeb.Endpoint, PageLive) do %> -

Lokal

+

+ Lokal +

<% end %> - <%= if @title_content do %> | <%= render_slot(@title_content) %> <% end %>
-
- <%= if @flash && @flash |> Map.has_key?(:info) do %> - <% end %> - <%= if @flash && @flash |> Map.has_key?(:error) do %> - <% end %> diff --git a/lib/lokal_web/templates/layout/app.html.heex b/lib/lokal_web/templates/layout/app.html.heex index 533a4d5..57a48d3 100644 --- a/lib/lokal_web/templates/layout/app.html.heex +++ b/lib/lokal_web/templates/layout/app.html.heex @@ -1,19 +1,16 @@
- <%= render "topbar.html", assigns %> - + <%= render("topbar.html", assigns) %> <%= if get_flash(@conn, :info) do %> <% end %> - <%= if get_flash(@conn, :error) do %> <% end %>
- <%= @inner_content %>
diff --git a/lib/lokal_web/templates/layout/live.html.heex b/lib/lokal_web/templates/layout/live.html.heex index b29413d..e107881 100644 --- a/lib/lokal_web/templates/layout/live.html.heex +++ b/lib/lokal_web/templates/layout/live.html.heex @@ -1,19 +1,15 @@
- + - <%= if @flash && @flash |> Map.has_key?(:info) do %> - - <% end %> - - <%= if @flash && @flash |> Map.has_key?(:error) do %> - + + <% end %> + <%= if @flash && @flash |> Map.has_key?(:error) do %> + <% end %> - <%= @inner_content %>
diff --git a/lib/lokal_web/templates/layout/root.html.heex b/lib/lokal_web/templates/layout/root.html.heex index a2397e5..d97d6fd 100644 --- a/lib/lokal_web/templates/layout/root.html.heex +++ b/lib/lokal_web/templates/layout/root.html.heex @@ -1,13 +1,19 @@ - - - + + + <%= csrf_meta_tag() %> - <%= live_title_tag assigns[:page_title] || "Lokal", suffix: "" %> - - + <%= live_title_tag(assigns[:page_title] || "Lokal", suffix: "") %> + + <%= @inner_content %> diff --git a/test/lokal/accounts_test.exs b/test/lokal/accounts_test.exs index c67753e..8e026b5 100644 --- a/test/lokal/accounts_test.exs +++ b/test/lokal/accounts_test.exs @@ -496,1010 +496,6 @@ defmodule Lokal.AccountsTest do end end - describe "inspect/2" do - test "does not include password" do - refute inspect(%User{password: "123456"}) =~ "password: \"123456\"" - end - end - import Lokal.AccountsFixtures - alias Lokal.Accounts.{User, UserToken} - - describe "get_user_by_email/1" do - test "does not return the user if the email does not exist" do - refute Accounts.get_user_by_email("unknown@example.com") - end - - test "returns the user if the email exists" do - %{id: id} = user = user_fixture() - assert %User{id: ^id} = Accounts.get_user_by_email(user.email) - end - end - - describe "get_user_by_email_and_password/2" do - test "does not return the user if the email does not exist" do - refute Accounts.get_user_by_email_and_password("unknown@example.com", "hello world!") - end - - test "does not return the user if the password is not valid" do - user = user_fixture() - refute Accounts.get_user_by_email_and_password(user.email, "invalid") - end - - test "returns the user if the email and password are valid" do - %{id: id} = user = user_fixture() - - assert %User{id: ^id} = - Accounts.get_user_by_email_and_password(user.email, valid_user_password()) - end - end - - describe "get_user!/1" do - test "raises if id is invalid" do - assert_raise Ecto.NoResultsError, fn -> - Accounts.get_user!(-1) - end - end - - test "returns the user with the given id" do - %{id: id} = user = user_fixture() - assert %User{id: ^id} = Accounts.get_user!(user.id) - end - end - - describe "register_user/1" do - test "requires email and password to be set" do - {:error, changeset} = Accounts.register_user(%{}) - - assert %{ - password: ["can't be blank"], - email: ["can't be blank"] - } = errors_on(changeset) - end - - test "validates email and password when given" do - {:error, changeset} = Accounts.register_user(%{email: "not valid", password: "not valid"}) - - assert %{ - email: ["must have the @ sign and no spaces"], - password: ["should be at least 12 character(s)"] - } = errors_on(changeset) - end - - test "validates maximum values for email and password for security" do - too_long = String.duplicate("db", 100) - {:error, changeset} = Accounts.register_user(%{email: too_long, password: too_long}) - assert "should be at most 160 character(s)" in errors_on(changeset).email - assert "should be at most 80 character(s)" in errors_on(changeset).password - end - - test "validates email uniqueness" do - %{email: email} = user_fixture() - {:error, changeset} = Accounts.register_user(%{email: email}) - assert "has already been taken" in errors_on(changeset).email - - # Now try with the upper cased email too, to check that email case is ignored. - {:error, changeset} = Accounts.register_user(%{email: String.upcase(email)}) - assert "has already been taken" in errors_on(changeset).email - end - - test "registers users with a hashed password" do - email = unique_user_email() - {:ok, user} = Accounts.register_user(valid_user_attributes(email: email)) - assert user.email == email - assert is_binary(user.hashed_password) - assert is_nil(user.confirmed_at) - assert is_nil(user.password) - end - end - - describe "change_user_registration/2" do - test "returns a changeset" do - assert %Ecto.Changeset{} = changeset = Accounts.change_user_registration(%User{}) - assert changeset.required == [:password, :email] - end - - test "allows fields to be set" do - email = unique_user_email() - password = valid_user_password() - - changeset = - Accounts.change_user_registration( - %User{}, - valid_user_attributes(email: email, password: password) - ) - - assert changeset.valid? - assert get_change(changeset, :email) == email - assert get_change(changeset, :password) == password - assert is_nil(get_change(changeset, :hashed_password)) - end - end - - describe "change_user_email/2" do - test "returns a user changeset" do - assert %Ecto.Changeset{} = changeset = Accounts.change_user_email(%User{}) - assert changeset.required == [:email] - end - end - - describe "apply_user_email/3" do - setup do - %{user: user_fixture()} - end - - test "requires email to change", %{user: user} do - {:error, changeset} = Accounts.apply_user_email(user, valid_user_password(), %{}) - assert %{email: ["did not change"]} = errors_on(changeset) - end - - test "validates email", %{user: user} do - {:error, changeset} = - Accounts.apply_user_email(user, valid_user_password(), %{email: "not valid"}) - - assert %{email: ["must have the @ sign and no spaces"]} = errors_on(changeset) - end - - test "validates maximum value for email for security", %{user: user} do - too_long = String.duplicate("db", 100) - - {:error, changeset} = - Accounts.apply_user_email(user, valid_user_password(), %{email: too_long}) - - assert "should be at most 160 character(s)" in errors_on(changeset).email - end - - test "validates email uniqueness", %{user: user} do - %{email: email} = user_fixture() - - {:error, changeset} = - Accounts.apply_user_email(user, valid_user_password(), %{email: email}) - - assert "has already been taken" in errors_on(changeset).email - end - - test "validates current password", %{user: user} do - {:error, changeset} = - Accounts.apply_user_email(user, "invalid", %{email: unique_user_email()}) - - assert %{current_password: ["is not valid"]} = errors_on(changeset) - end - - test "applies the email without persisting it", %{user: user} do - email = unique_user_email() - {:ok, user} = Accounts.apply_user_email(user, valid_user_password(), %{email: email}) - assert user.email == email - assert Accounts.get_user!(user.id).email != email - end - end - - describe "deliver_update_email_instructions/3" do - setup do - %{user: user_fixture()} - end - - test "sends token through notification", %{user: user} do - token = - extract_user_token(fn url -> - Accounts.deliver_update_email_instructions(user, "current@example.com", url) - end) - - {:ok, token} = Base.url_decode64(token, padding: false) - assert user_token = Repo.get_by(UserToken, token: :crypto.hash(:sha256, token)) - assert user_token.user_id == user.id - assert user_token.sent_to == user.email - assert user_token.context == "change:current@example.com" - end - end - - describe "update_user_email/2" do - setup do - user = user_fixture() - email = unique_user_email() - - token = - extract_user_token(fn url -> - Accounts.deliver_update_email_instructions(%{user | email: email}, user.email, url) - end) - - %{user: user, token: token, email: email} - end - - test "updates the email with a valid token", %{user: user, token: token, email: email} do - assert Accounts.update_user_email(user, token) == :ok - changed_user = Repo.get!(User, user.id) - assert changed_user.email != user.email - assert changed_user.email == email - assert changed_user.confirmed_at - assert changed_user.confirmed_at != user.confirmed_at - refute Repo.get_by(UserToken, user_id: user.id) - end - - test "does not update email with invalid token", %{user: user} do - assert Accounts.update_user_email(user, "oops") == :error - assert Repo.get!(User, user.id).email == user.email - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not update email if user email changed", %{user: user, token: token} do - assert Accounts.update_user_email(%{user | email: "current@example.com"}, token) == :error - assert Repo.get!(User, user.id).email == user.email - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not update email if token expired", %{user: user, token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - assert Accounts.update_user_email(user, token) == :error - assert Repo.get!(User, user.id).email == user.email - assert Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "change_user_password/2" do - test "returns a user changeset" do - assert %Ecto.Changeset{} = changeset = Accounts.change_user_password(%User{}) - assert changeset.required == [:password] - end - - test "allows fields to be set" do - changeset = - Accounts.change_user_password(%User{}, %{ - "password" => "new valid password" - }) - - assert changeset.valid? - assert get_change(changeset, :password) == "new valid password" - assert is_nil(get_change(changeset, :hashed_password)) - end - end - - describe "update_user_password/3" do - setup do - %{user: user_fixture()} - end - - test "validates password", %{user: user} do - {:error, changeset} = - Accounts.update_user_password(user, valid_user_password(), %{ - password: "not valid", - password_confirmation: "another" - }) - - assert %{ - password: ["should be at least 12 character(s)"], - password_confirmation: ["does not match password"] - } = errors_on(changeset) - end - - test "validates maximum values for password for security", %{user: user} do - too_long = String.duplicate("db", 100) - - {:error, changeset} = - Accounts.update_user_password(user, valid_user_password(), %{password: too_long}) - - assert "should be at most 80 character(s)" in errors_on(changeset).password - end - - test "validates current password", %{user: user} do - {:error, changeset} = - Accounts.update_user_password(user, "invalid", %{password: valid_user_password()}) - - assert %{current_password: ["is not valid"]} = errors_on(changeset) - end - - test "updates the password", %{user: user} do - {:ok, user} = - Accounts.update_user_password(user, valid_user_password(), %{ - password: "new valid password" - }) - - assert is_nil(user.password) - assert Accounts.get_user_by_email_and_password(user.email, "new valid password") - end - - test "deletes all tokens for the given user", %{user: user} do - _ = Accounts.generate_user_session_token(user) - - {:ok, _} = - Accounts.update_user_password(user, valid_user_password(), %{ - password: "new valid password" - }) - - refute Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "generate_user_session_token/1" do - setup do - %{user: user_fixture()} - end - - test "generates a token", %{user: user} do - token = Accounts.generate_user_session_token(user) - assert user_token = Repo.get_by(UserToken, token: token) - assert user_token.context == "session" - - # Creating the same token for another user should fail - assert_raise Ecto.ConstraintError, fn -> - Repo.insert!(%UserToken{ - token: user_token.token, - user_id: user_fixture().id, - context: "session" - }) - end - end - end - - describe "get_user_by_session_token/1" do - setup do - user = user_fixture() - token = Accounts.generate_user_session_token(user) - %{user: user, token: token} - end - - test "returns user by token", %{user: user, token: token} do - assert session_user = Accounts.get_user_by_session_token(token) - assert session_user.id == user.id - end - - test "does not return user for invalid token" do - refute Accounts.get_user_by_session_token("oops") - end - - test "does not return user for expired token", %{token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - refute Accounts.get_user_by_session_token(token) - end - end - - describe "delete_session_token/1" do - test "deletes the token" do - user = user_fixture() - token = Accounts.generate_user_session_token(user) - assert Accounts.delete_session_token(token) == :ok - refute Accounts.get_user_by_session_token(token) - end - end - - describe "deliver_user_confirmation_instructions/2" do - setup do - %{user: user_fixture()} - end - - test "sends token through notification", %{user: user} do - token = - extract_user_token(fn url -> - Accounts.deliver_user_confirmation_instructions(user, url) - end) - - {:ok, token} = Base.url_decode64(token, padding: false) - assert user_token = Repo.get_by(UserToken, token: :crypto.hash(:sha256, token)) - assert user_token.user_id == user.id - assert user_token.sent_to == user.email - assert user_token.context == "confirm" - end - end - - describe "confirm_user/1" do - setup do - user = user_fixture() - - token = - extract_user_token(fn url -> - Accounts.deliver_user_confirmation_instructions(user, url) - end) - - %{user: user, token: token} - end - - test "confirms the email with a valid token", %{user: user, token: token} do - assert {:ok, confirmed_user} = Accounts.confirm_user(token) - assert confirmed_user.confirmed_at - assert confirmed_user.confirmed_at != user.confirmed_at - assert Repo.get!(User, user.id).confirmed_at - refute Repo.get_by(UserToken, user_id: user.id) - end - - test "does not confirm with invalid token", %{user: user} do - assert Accounts.confirm_user("oops") == :error - refute Repo.get!(User, user.id).confirmed_at - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not confirm email if token expired", %{user: user, token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - assert Accounts.confirm_user(token) == :error - refute Repo.get!(User, user.id).confirmed_at - assert Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "deliver_user_reset_password_instructions/2" do - setup do - %{user: user_fixture()} - end - - test "sends token through notification", %{user: user} do - token = - extract_user_token(fn url -> - Accounts.deliver_user_reset_password_instructions(user, url) - end) - - {:ok, token} = Base.url_decode64(token, padding: false) - assert user_token = Repo.get_by(UserToken, token: :crypto.hash(:sha256, token)) - assert user_token.user_id == user.id - assert user_token.sent_to == user.email - assert user_token.context == "reset_password" - end - end - - describe "get_user_by_reset_password_token/1" do - setup do - user = user_fixture() - - token = - extract_user_token(fn url -> - Accounts.deliver_user_reset_password_instructions(user, url) - end) - - %{user: user, token: token} - end - - test "returns the user with valid token", %{user: %{id: id}, token: token} do - assert %User{id: ^id} = Accounts.get_user_by_reset_password_token(token) - assert Repo.get_by(UserToken, user_id: id) - end - - test "does not return the user with invalid token", %{user: user} do - refute Accounts.get_user_by_reset_password_token("oops") - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not return the user if token expired", %{user: user, token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - refute Accounts.get_user_by_reset_password_token(token) - assert Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "reset_user_password/2" do - setup do - %{user: user_fixture()} - end - - test "validates password", %{user: user} do - {:error, changeset} = - Accounts.reset_user_password(user, %{ - password: "not valid", - password_confirmation: "another" - }) - - assert %{ - password: ["should be at least 12 character(s)"], - password_confirmation: ["does not match password"] - } = errors_on(changeset) - end - - test "validates maximum values for password for security", %{user: user} do - too_long = String.duplicate("db", 100) - {:error, changeset} = Accounts.reset_user_password(user, %{password: too_long}) - assert "should be at most 80 character(s)" in errors_on(changeset).password - end - - test "updates the password", %{user: user} do - {:ok, updated_user} = Accounts.reset_user_password(user, %{password: "new valid password"}) - assert is_nil(updated_user.password) - assert Accounts.get_user_by_email_and_password(user.email, "new valid password") - end - - test "deletes all tokens for the given user", %{user: user} do - _ = Accounts.generate_user_session_token(user) - {:ok, _} = Accounts.reset_user_password(user, %{password: "new valid password"}) - refute Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "inspect/2" do - test "does not include password" do - refute inspect(%User{password: "123456"}) =~ "password: \"123456\"" - end - end - import Lokal.AccountsFixtures - alias Lokal.Accounts.{User, UserToken} - - describe "get_user_by_email/1" do - test "does not return the user if the email does not exist" do - refute Accounts.get_user_by_email("unknown@example.com") - end - - test "returns the user if the email exists" do - %{id: id} = user = user_fixture() - assert %User{id: ^id} = Accounts.get_user_by_email(user.email) - end - end - - describe "get_user_by_email_and_password/2" do - test "does not return the user if the email does not exist" do - refute Accounts.get_user_by_email_and_password("unknown@example.com", "hello world!") - end - - test "does not return the user if the password is not valid" do - user = user_fixture() - refute Accounts.get_user_by_email_and_password(user.email, "invalid") - end - - test "returns the user if the email and password are valid" do - %{id: id} = user = user_fixture() - - assert %User{id: ^id} = - Accounts.get_user_by_email_and_password(user.email, valid_user_password()) - end - end - - describe "get_user!/1" do - test "raises if id is invalid" do - assert_raise Ecto.NoResultsError, fn -> - Accounts.get_user!("11111111-1111-1111-1111-111111111111") - end - end - - test "returns the user with the given id" do - %{id: id} = user = user_fixture() - assert %User{id: ^id} = Accounts.get_user!(user.id) - end - end - - describe "register_user/1" do - test "requires email and password to be set" do - {:error, changeset} = Accounts.register_user(%{}) - - assert %{ - password: ["can't be blank"], - email: ["can't be blank"] - } = errors_on(changeset) - end - - test "validates email and password when given" do - {:error, changeset} = Accounts.register_user(%{email: "not valid", password: "not valid"}) - - assert %{ - email: ["must have the @ sign and no spaces"], - password: ["should be at least 12 character(s)"] - } = errors_on(changeset) - end - - test "validates maximum values for email and password for security" do - too_long = String.duplicate("db", 100) - {:error, changeset} = Accounts.register_user(%{email: too_long, password: too_long}) - assert "should be at most 160 character(s)" in errors_on(changeset).email - assert "should be at most 80 character(s)" in errors_on(changeset).password - end - - test "validates email uniqueness" do - %{email: email} = user_fixture() - {:error, changeset} = Accounts.register_user(%{email: email}) - assert "has already been taken" in errors_on(changeset).email - - # Now try with the upper cased email too, to check that email case is ignored. - {:error, changeset} = Accounts.register_user(%{email: String.upcase(email)}) - assert "has already been taken" in errors_on(changeset).email - end - - test "registers users with a hashed password" do - email = unique_user_email() - {:ok, user} = Accounts.register_user(valid_user_attributes(email: email)) - assert user.email == email - assert is_binary(user.hashed_password) - assert is_nil(user.confirmed_at) - assert is_nil(user.password) - end - end - - describe "change_user_registration/2" do - test "returns a changeset" do - assert %Ecto.Changeset{} = changeset = Accounts.change_user_registration(%User{}) - assert changeset.required == [:password, :email] - end - - test "allows fields to be set" do - email = unique_user_email() - password = valid_user_password() - - changeset = - Accounts.change_user_registration( - %User{}, - valid_user_attributes(email: email, password: password) - ) - - assert changeset.valid? - assert get_change(changeset, :email) == email - assert get_change(changeset, :password) == password - assert is_nil(get_change(changeset, :hashed_password)) - end - end - - describe "change_user_email/2" do - test "returns a user changeset" do - assert %Ecto.Changeset{} = changeset = Accounts.change_user_email(%User{}) - assert changeset.required == [:email] - end - end - - describe "apply_user_email/3" do - setup do - %{user: user_fixture()} - end - - test "requires email to change", %{user: user} do - {:error, changeset} = Accounts.apply_user_email(user, valid_user_password(), %{}) - assert %{email: ["did not change"]} = errors_on(changeset) - end - - test "validates email", %{user: user} do - {:error, changeset} = - Accounts.apply_user_email(user, valid_user_password(), %{email: "not valid"}) - - assert %{email: ["must have the @ sign and no spaces"]} = errors_on(changeset) - end - - test "validates maximum value for email for security", %{user: user} do - too_long = String.duplicate("db", 100) - - {:error, changeset} = - Accounts.apply_user_email(user, valid_user_password(), %{email: too_long}) - - assert "should be at most 160 character(s)" in errors_on(changeset).email - end - - test "validates email uniqueness", %{user: user} do - %{email: email} = user_fixture() - - {:error, changeset} = - Accounts.apply_user_email(user, valid_user_password(), %{email: email}) - - assert "has already been taken" in errors_on(changeset).email - end - - test "validates current password", %{user: user} do - {:error, changeset} = - Accounts.apply_user_email(user, "invalid", %{email: unique_user_email()}) - - assert %{current_password: ["is not valid"]} = errors_on(changeset) - end - - test "applies the email without persisting it", %{user: user} do - email = unique_user_email() - {:ok, user} = Accounts.apply_user_email(user, valid_user_password(), %{email: email}) - assert user.email == email - assert Accounts.get_user!(user.id).email != email - end - end - - describe "deliver_update_email_instructions/3" do - setup do - %{user: user_fixture()} - end - - test "sends token through notification", %{user: user} do - token = - extract_user_token(fn url -> - Accounts.deliver_update_email_instructions(user, "current@example.com", url) - end) - - {:ok, token} = Base.url_decode64(token, padding: false) - assert user_token = Repo.get_by(UserToken, token: :crypto.hash(:sha256, token)) - assert user_token.user_id == user.id - assert user_token.sent_to == user.email - assert user_token.context == "change:current@example.com" - end - end - - describe "update_user_email/2" do - setup do - user = user_fixture() - email = unique_user_email() - - token = - extract_user_token(fn url -> - Accounts.deliver_update_email_instructions(%{user | email: email}, user.email, url) - end) - - %{user: user, token: token, email: email} - end - - test "updates the email with a valid token", %{user: user, token: token, email: email} do - assert Accounts.update_user_email(user, token) == :ok - changed_user = Repo.get!(User, user.id) - assert changed_user.email != user.email - assert changed_user.email == email - assert changed_user.confirmed_at - assert changed_user.confirmed_at != user.confirmed_at - refute Repo.get_by(UserToken, user_id: user.id) - end - - test "does not update email with invalid token", %{user: user} do - assert Accounts.update_user_email(user, "oops") == :error - assert Repo.get!(User, user.id).email == user.email - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not update email if user email changed", %{user: user, token: token} do - assert Accounts.update_user_email(%{user | email: "current@example.com"}, token) == :error - assert Repo.get!(User, user.id).email == user.email - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not update email if token expired", %{user: user, token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - assert Accounts.update_user_email(user, token) == :error - assert Repo.get!(User, user.id).email == user.email - assert Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "change_user_password/2" do - test "returns a user changeset" do - assert %Ecto.Changeset{} = changeset = Accounts.change_user_password(%User{}) - assert changeset.required == [:password] - end - - test "allows fields to be set" do - changeset = - Accounts.change_user_password(%User{}, %{ - "password" => "new valid password" - }) - - assert changeset.valid? - assert get_change(changeset, :password) == "new valid password" - assert is_nil(get_change(changeset, :hashed_password)) - end - end - - describe "update_user_password/3" do - setup do - %{user: user_fixture()} - end - - test "validates password", %{user: user} do - {:error, changeset} = - Accounts.update_user_password(user, valid_user_password(), %{ - password: "not valid", - password_confirmation: "another" - }) - - assert %{ - password: ["should be at least 12 character(s)"], - password_confirmation: ["does not match password"] - } = errors_on(changeset) - end - - test "validates maximum values for password for security", %{user: user} do - too_long = String.duplicate("db", 100) - - {:error, changeset} = - Accounts.update_user_password(user, valid_user_password(), %{password: too_long}) - - assert "should be at most 80 character(s)" in errors_on(changeset).password - end - - test "validates current password", %{user: user} do - {:error, changeset} = - Accounts.update_user_password(user, "invalid", %{password: valid_user_password()}) - - assert %{current_password: ["is not valid"]} = errors_on(changeset) - end - - test "updates the password", %{user: user} do - {:ok, user} = - Accounts.update_user_password(user, valid_user_password(), %{ - password: "new valid password" - }) - - assert is_nil(user.password) - assert Accounts.get_user_by_email_and_password(user.email, "new valid password") - end - - test "deletes all tokens for the given user", %{user: user} do - _ = Accounts.generate_user_session_token(user) - - {:ok, _} = - Accounts.update_user_password(user, valid_user_password(), %{ - password: "new valid password" - }) - - refute Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "generate_user_session_token/1" do - setup do - %{user: user_fixture()} - end - - test "generates a token", %{user: user} do - token = Accounts.generate_user_session_token(user) - assert user_token = Repo.get_by(UserToken, token: token) - assert user_token.context == "session" - - # Creating the same token for another user should fail - assert_raise Ecto.ConstraintError, fn -> - Repo.insert!(%UserToken{ - token: user_token.token, - user_id: user_fixture().id, - context: "session" - }) - end - end - end - - describe "get_user_by_session_token/1" do - setup do - user = user_fixture() - token = Accounts.generate_user_session_token(user) - %{user: user, token: token} - end - - test "returns user by token", %{user: user, token: token} do - assert session_user = Accounts.get_user_by_session_token(token) - assert session_user.id == user.id - end - - test "does not return user for invalid token" do - refute Accounts.get_user_by_session_token("oops") - end - - test "does not return user for expired token", %{token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - refute Accounts.get_user_by_session_token(token) - end - end - - describe "delete_session_token/1" do - test "deletes the token" do - user = user_fixture() - token = Accounts.generate_user_session_token(user) - assert Accounts.delete_session_token(token) == :ok - refute Accounts.get_user_by_session_token(token) - end - end - - describe "deliver_user_confirmation_instructions/2" do - setup do - %{user: user_fixture()} - end - - test "sends token through notification", %{user: user} do - token = - extract_user_token(fn url -> - Accounts.deliver_user_confirmation_instructions(user, url) - end) - - {:ok, token} = Base.url_decode64(token, padding: false) - assert user_token = Repo.get_by(UserToken, token: :crypto.hash(:sha256, token)) - assert user_token.user_id == user.id - assert user_token.sent_to == user.email - assert user_token.context == "confirm" - end - end - - describe "confirm_user/1" do - setup do - user = user_fixture() - - token = - extract_user_token(fn url -> - Accounts.deliver_user_confirmation_instructions(user, url) - end) - - %{user: user, token: token} - end - - test "confirms the email with a valid token", %{user: user, token: token} do - assert {:ok, confirmed_user} = Accounts.confirm_user(token) - assert confirmed_user.confirmed_at - assert confirmed_user.confirmed_at != user.confirmed_at - assert Repo.get!(User, user.id).confirmed_at - refute Repo.get_by(UserToken, user_id: user.id) - end - - test "does not confirm with invalid token", %{user: user} do - assert Accounts.confirm_user("oops") == :error - refute Repo.get!(User, user.id).confirmed_at - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not confirm email if token expired", %{user: user, token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - assert Accounts.confirm_user(token) == :error - refute Repo.get!(User, user.id).confirmed_at - assert Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "deliver_user_reset_password_instructions/2" do - setup do - %{user: user_fixture()} - end - - test "sends token through notification", %{user: user} do - token = - extract_user_token(fn url -> - Accounts.deliver_user_reset_password_instructions(user, url) - end) - - {:ok, token} = Base.url_decode64(token, padding: false) - assert user_token = Repo.get_by(UserToken, token: :crypto.hash(:sha256, token)) - assert user_token.user_id == user.id - assert user_token.sent_to == user.email - assert user_token.context == "reset_password" - end - end - - describe "get_user_by_reset_password_token/1" do - setup do - user = user_fixture() - - token = - extract_user_token(fn url -> - Accounts.deliver_user_reset_password_instructions(user, url) - end) - - %{user: user, token: token} - end - - test "returns the user with valid token", %{user: %{id: id}, token: token} do - assert %User{id: ^id} = Accounts.get_user_by_reset_password_token(token) - assert Repo.get_by(UserToken, user_id: id) - end - - test "does not return the user with invalid token", %{user: user} do - refute Accounts.get_user_by_reset_password_token("oops") - assert Repo.get_by(UserToken, user_id: user.id) - end - - test "does not return the user if token expired", %{user: user, token: token} do - {1, nil} = Repo.update_all(UserToken, set: [inserted_at: ~N[2020-01-01 00:00:00]]) - refute Accounts.get_user_by_reset_password_token(token) - assert Repo.get_by(UserToken, user_id: user.id) - end - end - - describe "reset_user_password/2" do - setup do - %{user: user_fixture()} - end - - test "validates password", %{user: user} do - {:error, changeset} = - Accounts.reset_user_password(user, %{ - password: "not valid", - password_confirmation: "another" - }) - - assert %{ - password: ["should be at least 12 character(s)"], - password_confirmation: ["does not match password"] - } = errors_on(changeset) - end - - test "validates maximum values for password for security", %{user: user} do - too_long = String.duplicate("db", 100) - {:error, changeset} = Accounts.reset_user_password(user, %{password: too_long}) - assert "should be at most 80 character(s)" in errors_on(changeset).password - end - - test "updates the password", %{user: user} do - {:ok, updated_user} = Accounts.reset_user_password(user, %{password: "new valid password"}) - assert is_nil(updated_user.password) - assert Accounts.get_user_by_email_and_password(user.email, "new valid password") - end - - test "deletes all tokens for the given user", %{user: user} do - _ = Accounts.generate_user_session_token(user) - {:ok, _} = Accounts.reset_user_password(user, %{password: "new valid password"}) - refute Repo.get_by(UserToken, user_id: user.id) - end - end - describe "inspect/2" do test "does not include password" do refute inspect(%User{password: "123456"}) =~ "password: \"123456\"" diff --git a/test/lokal_web/controllers/page_controller_test.exs b/test/lokal_web/controllers/page_controller_test.exs index 0e87eb8..d1e4ceb 100644 --- a/test/lokal_web/controllers/page_controller_test.exs +++ b/test/lokal_web/controllers/page_controller_test.exs @@ -3,6 +3,6 @@ defmodule LokalWeb.PageControllerTest do test "GET /", %{conn: conn} do conn = get(conn, "/") - assert html_response(conn, 200) =~ "Welcome to Phoenix!" + assert html_response(conn, 200) =~ "Welcome to Lokal" end end diff --git a/test/lokal_web/controllers/user_auth_test.exs b/test/lokal_web/controllers/user_auth_test.exs index 7108dc9..7b0ef5f 100644 --- a/test/lokal_web/controllers/user_auth_test.exs +++ b/test/lokal_web/controllers/user_auth_test.exs @@ -140,7 +140,7 @@ defmodule LokalWeb.UserAuthTest do test "stores the path to redirect to on GET", %{conn: conn} do halted_conn = - %{conn | request_path: "/foo", query_string: ""} + %{conn | path_info: ["foo"], query_string: ""} |> fetch_flash() |> UserAuth.require_authenticated_user([]) @@ -148,7 +148,7 @@ defmodule LokalWeb.UserAuthTest do assert get_session(halted_conn, :user_return_to) == "/foo" halted_conn = - %{conn | request_path: "/foo", query_string: "bar=baz"} + %{conn | path_info: ["foo"], query_string: "bar=baz"} |> fetch_flash() |> UserAuth.require_authenticated_user([]) @@ -156,7 +156,7 @@ defmodule LokalWeb.UserAuthTest do assert get_session(halted_conn, :user_return_to) == "/foo?bar=baz" halted_conn = - %{conn | request_path: "/foo?bar", method: "POST"} + %{conn | path_info: ["foo"], query_string: "bar", method: "POST"} |> fetch_flash() |> UserAuth.require_authenticated_user([]) diff --git a/test/lokal_web/controllers/user_confirmation_controller_test.exs b/test/lokal_web/controllers/user_confirmation_controller_test.exs index c45c43d..5b5d164 100644 --- a/test/lokal_web/controllers/user_confirmation_controller_test.exs +++ b/test/lokal_web/controllers/user_confirmation_controller_test.exs @@ -13,7 +13,7 @@ defmodule LokalWeb.UserConfirmationControllerTest do test "renders the confirmation page", %{conn: conn} do conn = get(conn, Routes.user_confirmation_path(conn, :new)) response = html_response(conn, 200) - assert response =~ "

Resend confirmation instructions

" + assert response =~ "Resend confirmation instructions" end end diff --git a/test/lokal_web/controllers/user_registration_controller_test.exs b/test/lokal_web/controllers/user_registration_controller_test.exs index 4ee0886..2cfeec4 100644 --- a/test/lokal_web/controllers/user_registration_controller_test.exs +++ b/test/lokal_web/controllers/user_registration_controller_test.exs @@ -7,7 +7,7 @@ defmodule LokalWeb.UserRegistrationControllerTest do test "renders registration page", %{conn: conn} do conn = get(conn, Routes.user_registration_path(conn, :new)) response = html_response(conn, 200) - assert response =~ "

Register

" + assert response =~ "Register" assert response =~ "Log in" assert response =~ "Register" end @@ -46,7 +46,7 @@ defmodule LokalWeb.UserRegistrationControllerTest do }) response = html_response(conn, 200) - assert response =~ "

Register

" + assert response =~ "Register" assert response =~ "must have the @ sign and no spaces" assert response =~ "should be at least 12 character" end diff --git a/test/lokal_web/controllers/user_reset_password_controller_test.exs b/test/lokal_web/controllers/user_reset_password_controller_test.exs index f44cc56..3f2733b 100644 --- a/test/lokal_web/controllers/user_reset_password_controller_test.exs +++ b/test/lokal_web/controllers/user_reset_password_controller_test.exs @@ -13,7 +13,7 @@ defmodule LokalWeb.UserResetPasswordControllerTest do test "renders the reset password page", %{conn: conn} do conn = get(conn, Routes.user_reset_password_path(conn, :new)) response = html_response(conn, 200) - assert response =~ "

Forgot your password?

" + assert response =~ "Forgot your password?" end end @@ -54,7 +54,7 @@ defmodule LokalWeb.UserResetPasswordControllerTest do test "renders reset password", %{conn: conn, token: token} do conn = get(conn, Routes.user_reset_password_path(conn, :edit, token)) - assert html_response(conn, 200) =~ "

Reset password

" + assert html_response(conn, 200) =~ "Reset password" end test "does not render reset password with invalid token", %{conn: conn} do @@ -99,7 +99,7 @@ defmodule LokalWeb.UserResetPasswordControllerTest do }) response = html_response(conn, 200) - assert response =~ "

Reset password

" + assert response =~ "Reset password" assert response =~ "should be at least 12 character(s)" assert response =~ "does not match password" end diff --git a/test/lokal_web/controllers/user_session_controller_test.exs b/test/lokal_web/controllers/user_session_controller_test.exs index d692e09..9851f8a 100644 --- a/test/lokal_web/controllers/user_session_controller_test.exs +++ b/test/lokal_web/controllers/user_session_controller_test.exs @@ -11,9 +11,8 @@ defmodule LokalWeb.UserSessionControllerTest do test "renders log in page", %{conn: conn} do conn = get(conn, Routes.user_session_path(conn, :new)) response = html_response(conn, 200) - assert response =~ "

Log in

" - assert response =~ "Log in" - assert response =~ "Register" + assert response =~ "Log in" + assert response =~ "Register" end test "redirects if already logged in", %{conn: conn, user: user} do @@ -75,7 +74,7 @@ defmodule LokalWeb.UserSessionControllerTest do }) response = html_response(conn, 200) - assert response =~ "

Log in

" + assert response =~ "Log in" assert response =~ "Invalid email or password" end end diff --git a/test/lokal_web/controllers/user_settings_controller_test.exs b/test/lokal_web/controllers/user_settings_controller_test.exs index b7bd633..14ca4c8 100644 --- a/test/lokal_web/controllers/user_settings_controller_test.exs +++ b/test/lokal_web/controllers/user_settings_controller_test.exs @@ -10,7 +10,7 @@ defmodule LokalWeb.UserSettingsControllerTest do test "renders settings page", %{conn: conn} do conn = get(conn, Routes.user_settings_path(conn, :edit)) response = html_response(conn, 200) - assert response =~ "

Settings

" + assert response =~ "Settings" end test "redirects if user is not logged in" do @@ -50,7 +50,7 @@ defmodule LokalWeb.UserSettingsControllerTest do }) response = html_response(old_password_conn, 200) - assert response =~ "

Settings

" + assert response =~ "Settings" assert response =~ "should be at least 12 character(s)" assert response =~ "does not match password" assert response =~ "is not valid" @@ -83,7 +83,7 @@ defmodule LokalWeb.UserSettingsControllerTest do }) response = html_response(conn, 200) - assert response =~ "

Settings

" + assert response =~ "Settings" assert response =~ "must have the @ sign and no spaces" assert response =~ "is not valid" end diff --git a/test/lokal_web/live/page_live_test.exs b/test/lokal_web/live/page_live_test.exs index 7be5c48..52b33d9 100644 --- a/test/lokal_web/live/page_live_test.exs +++ b/test/lokal_web/live/page_live_test.exs @@ -5,7 +5,7 @@ defmodule LokalWeb.PageLiveTest do test "disconnected and connected render", %{conn: conn} do {:ok, page_live, disconnected_html} = live(conn, "/") - assert disconnected_html =~ "Welcome to Phoenix!" - assert render(page_live) =~ "Welcome to Phoenix!" + assert disconnected_html =~ "Welcome to Lokal" + assert render(page_live) =~ "Welcome to Lokal" end end diff --git a/test/support/fixtures/accounts_fixtures.ex b/test/support/fixtures/accounts_fixtures.ex index 71b1f23..9378e74 100644 --- a/test/support/fixtures/accounts_fixtures.ex +++ b/test/support/fixtures/accounts_fixtures.ex @@ -7,27 +7,6 @@ defmodule Lokal.AccountsFixtures do def unique_user_email, do: "user#{System.unique_integer()}@example.com" def valid_user_password, do: "hello world!" - def user_fixture(attrs \\ %{}) do - {:ok, user} = - attrs - |> Enum.into(%{ - email: unique_user_email(), - password: valid_user_password() - }) - |> Lokal.Accounts.register_user() - - user - end - - def extract_user_token(fun) do - {:ok, captured} = fun.(&"[TOKEN]#{&1}[TOKEN]") - [_, token, _] = String.split(captured.body, "[TOKEN]") - token - end - - def unique_user_email, do: "user#{System.unique_integer()}@example.com" - def valid_user_password, do: "hello world!" - def valid_user_attributes(attrs \\ %{}) do Enum.into(attrs, %{ email: unique_user_email(),