Skip to content

Commit

Permalink
Added more unit tests (#5)
Browse files Browse the repository at this point in the history
* First steps of the unit tests

* Added changeset validation in tests

* Updated test names and small stuff

* Got some good stuff working

* Actually have login tests working

* Formatting
  • Loading branch information
nvsneddon authored Sep 30, 2024
1 parent c5efe6e commit 2788964
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 12 deletions.
13 changes: 9 additions & 4 deletions lib/perseus/auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ defmodule Perseus.Auth do
@signup_token_ttl 60 * 15
@session_token_ttl 60 * 60

def send_login_email(email, url_fun) do
def send_login_email(email, url_fun \\ nil) do
with {:ok, _} <- Accounts.get_user_by_email(email),
{:ok, token} <- generate_login_token(email),
encoded_token <- BinaryUtils.encode(token),
{:ok, _} <- UserNotifier.deliver_login_link(email, url_fun.(encoded_token)) do
:ok
encoded_token <- BinaryUtils.encode(token) do
# If `url_fun` is provided, deliver the login link via email
if url_fun do
UserNotifier.deliver_login_link(email, url_fun.(encoded_token))
else
# Otherwise, just return the encoded token
{:ok, encoded_token}
end
else
_ -> :error
end
Expand Down
5 changes: 3 additions & 2 deletions test/perseus/auth/token_store_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ defmodule Perseus.Auth.TokenStoreTest do
setup do
# Create an ETS table for testing purposes
init_table(@magic_link_table)
init_table(@signup_table)
init_table(@session_table)
:ok
end
Expand Down Expand Up @@ -56,9 +57,9 @@ defmodule Perseus.Auth.TokenStoreTest do
end

test "stores session token correctly", %{token: token, user: user, ttl: ttl} do
TokenStore.store_signup_token(token, user, ttl)
TokenStore.store_session_token(token, user, ttl)

assert [{^token, ^user, _}] = :ets.lookup(@signup_table, token)
assert [{^token, ^user, _}] = :ets.lookup(@session_table, token)
end
end

Expand Down
55 changes: 55 additions & 0 deletions test/perseus_web/resolvers/auth_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
defmodule PerseusWeb.Resolvers.AuthTest do
use Perseus.DataCase

alias Perseus.Auth
alias PerseusWeb.Resolvers

import Perseus.AccountsFixtures

describe "login_user/3" do
setup do
%{user: user_fixture()}
end

test "with valid context should login user", %{user: user} do
result = Resolvers.Auth.login_user(nil, nil, %{context: %{email: user.email}})

# Assert that the resolver returns :ok and a session_token
assert {:ok, %{session_token: session_token}} = result
assert {:ok, ^user} = Auth.find_user(session_token)
end

test "with invalid email address should return error" do
result = Resolvers.Auth.login_user(nil, nil, %{context: %{email: "invalid@example.com"}})

# Assert that the resolver returns :ok and a session_token
assert {:error, "User not found"} = result
end
end

describe "signup_user/3" do
setup do
%{user: valid_user_attributes()}
end

test "with valid data should signup user", %{user: user} do
result = Resolvers.Auth.signup_user(nil, %{user: user}, %{context: %{email: user.email}})

assert {:ok, %{session: _, new_user: created_user}} = result
assert created_user.email == user.email
assert created_user.first_name == user.first_name
assert created_user.last_name == user.last_name
assert created_user.verified == false
end

test "with invalid data should return a changeset" do
result =
Resolvers.Auth.signup_user(nil, %{user: %{first_name: "test"}}, %{
context: %{email: "invalid"}
})

assert {:error, %Ecto.Changeset{} = changeset} = result
assert "can't be blank" in errors_on(changeset).last_name
end
end
end
44 changes: 44 additions & 0 deletions test/perseus_web/schema/mutations/auth_mutations_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
defmodule PerseusWeb.Schema.Mutations.AuthMutationsTest do
alias Perseus.Utils.BinaryUtils
alias Perseus.Auth
use PerseusWeb.ConnCase, async: true

import Perseus.AccountsFixtures

# Define the query that you will be testing
@login_query """
mutation startSession {
logIn {
sessionToken
}
}
"""

describe "login mutation" do
setup do
user = user_fixture()
{:ok, token} = Auth.send_login_email(user.email)
%{user: user, token: token}
end

test "should login when email is found", %{conn: conn, user: user, token: token} do
conn =
conn
|> put_req_header("authorization", "MagicLink " <> token)
|> put_req_header("x-custom-header", "custom-value")
|> post("/api/graphql", %{query: @login_query})

assert json_response(conn, 200)
response_data = json_response(conn, 200)["data"]

assert %{
"logIn" => %{
"sessionToken" => session_token
}
} = response_data

{:ok, decoded_session_token} = BinaryUtils.decode(session_token)
assert {:ok, ^user} = Auth.find_user(decoded_session_token)
end
end
end
16 changes: 10 additions & 6 deletions test/support/fixtures/accounts_fixtures.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ defmodule Perseus.AccountsFixtures do
def user_fixture(attrs \\ %{}) do
{:ok, user} =
attrs
|> Enum.into(%{
email: "someemail@example.com",
first_name: "some first_name",
last_name: "some last_name",
verified: true
})
|> valid_user_attributes()
|> Perseus.Accounts.create_user()

user
end

def valid_user_attributes(attr \\ %{}) do
Enum.into(attr, %{
email: "someemail@example.com",
first_name: "some first_name",
last_name: "some last_name",
verified: true
})
end
end

0 comments on commit 2788964

Please sign in to comment.