Added addresses. Cleaning routes. Flow.

This commit is contained in:
Ryan Pandya 2022-11-05 18:12:02 -07:00
parent bb6d7e1e2d
commit fe0d748a53
21 changed files with 318 additions and 286 deletions

View File

@ -12,6 +12,7 @@ defmodule Friends.Friend do
field(:nickname, :string)
field(:born, :date)
field(:phone, :string)
field(:address, :string)
field(:email, :string)
field(:slug, :string)
field(:memories, {:array, :string})
@ -89,15 +90,15 @@ defmodule Friends.Friend do
def create(params) do
%Friend{}
|> Friend.changeset(%{params | id: nil})
|> Map.put(:action, :insert)
|> Friend.changeset(%{params | id: nil})
|> Map.put(:action, :insert)
end
def update(params) do
{:ok, Friend.get_by_id(params.id |> String.to_integer())
|> Friend.changeset(params)
|> Map.put(:action, :update)
}
{:ok,
Friend.get_by_id(params.id |> String.to_integer())
|> Friend.changeset(params)
|> Map.put(:action, :update)}
end
def commit(changeset) do
@ -107,18 +108,19 @@ defmodule Friends.Friend do
|> load_preloads
end
def generate_slug(%Ecto.Changeset{} = changeset) do
slug = changeset.changes.name |> to_slug
changeset |> changeset(%{
changeset
|> changeset(%{
slug: slug
})
end
def generate_slug(%Friend{} = friend) do
%{
friend | slug: friend.name |> to_slug
friend
| slug: friend.name |> to_slug
}
end
@ -128,11 +130,12 @@ defmodule Friends.Friend do
params
|> create()
|> commit()
_number ->
params
|> update()
|> commit()
end
end
end
def get_relationships(friend) do
@ -154,15 +157,16 @@ defmodule Friends.Friend do
end
def can_be_edited_by(friend, user) do
friend.id == user.profile.id
if user |> is_nil(), do: false, else: friend.id == user.profile.id
end
def assign_user(%Friend{} = friend) do
case friend.email |> Friends.Accounts.get_user_by_email do
case friend.email |> Friends.Accounts.get_user_by_email() do
nil ->
nil
user ->
user |> Friends.Accounts.assign_profile
user |> Friends.Accounts.assign_profile()
end
end
@ -170,24 +174,31 @@ defmodule Friends.Friend do
model
|> @repo.preload(:user)
end
def load_user(%Friends.Friend{} = friend), do: friend
def load_relationships(%Friends.Friend{
relationships: %Ecto.Association.NotLoaded{},
reverse_relationships: %Ecto.Association.NotLoaded{}
} = model) do
def load_relationships(
%Friends.Friend{
relationships: %Ecto.Association.NotLoaded{},
reverse_relationships: %Ecto.Association.NotLoaded{}
} = model
) do
model
|> @repo.preload([:relationships, :reverse_relationships])
end
def load_relationships(%Friends.Friend{} = friend), do: friend
def load_preloads(%Friends.Friend{
relationships: %Ecto.Association.NotLoaded{},
reverse_relationships: %Ecto.Association.NotLoaded{},
user: %Ecto.Association.NotLoaded{}} = model) do
def load_preloads(
%Friends.Friend{
relationships: %Ecto.Association.NotLoaded{},
reverse_relationships: %Ecto.Association.NotLoaded{},
user: %Ecto.Association.NotLoaded{}
} = model
) do
model
|> @repo.preload([:user,:relationships, :reverse_relationships])
|> @repo.preload([:user, :relationships, :reverse_relationships])
end
def load_preloads(%Friends.Friend{} = friend), do: friend
def load_preloads(%Friends.Friend{} = friend), do: friend
end

View File

@ -1,13 +1,12 @@
defmodule FriendsWeb.FriendController do
defmodule FriendsWeb.FriendsController do
use FriendsWeb, :controller
alias Friends.{Friend, Relationship}
alias Friends.Accounts.User
import Helpers
def index(conn, _params) do
conn
|> assign(:all_friends, Friend.all)
|> assign(:all_friends, Friend.all())
|> render("index.html")
end
end

View File

@ -7,15 +7,14 @@ defmodule FriendsWeb.PageController do
def index(conn, _params) do
new_friend = Friend.new() |> Friend.changeset()
if(conn|> get_session(:linked)) do
if(conn |> get_session(:linked)) do
# If logged in and linked, redirect to friend_path :index
conn |> redirect(to: FriendsWeb.Router.Helpers.friend_path(conn, :index))
conn |> redirect(to: FriendsWeb.Router.Helpers.friends_path(conn, :index))
else
# Otherwise, show the landing page
conn
|> assign(:new_friend, new_friend)
|> assign(:all_friends, Friend.all())
|> assign(:users, User |> Repo.all())
|> assign(:friends, Friend.all())
|> render("index.html")
end
end

View File

@ -128,18 +128,21 @@ defmodule FriendsWeb.UserAuth do
end
@doc """
Used when a user is signed in and should therefore have a profile linked.
Used to detect or link a profile to a user.
"""
def capture_profile(conn, _opts) do
current_user = conn.assigns[:current_user]
if current_user do
# There's a user, but is there a profile?
profile = current_user |> Map.get(:profile)
case profile do
nil ->
# No profile linked
conn
|> create_or_link_profile(current_user)
_profile ->
# Profile already linked
conn |> put_session(:linked, true)
@ -151,31 +154,31 @@ defmodule FriendsWeb.UserAuth do
end
defp create_or_link_profile(conn, user) do
case user.email |> Friends.Friend.get_by_email do
case user.email |> Friends.Friend.get_by_email() do
# Find a profile and link it
nil ->
conn
|> redirect(to: Routes.profile_form_path(conn, :new))
|> put_flash(:info, "You're logged in but we still need to make you a profile!")
|> redirect(to: Routes.friends_edit_path(conn, :overview, :new))
|> halt()
# Or make a new one
profile ->
_profile ->
user
|> Friends.Accounts.assign_profile
|> Friends.Accounts.assign_profile()
conn
|> put_session(:linked, true)
end
end
@doc """
Used for routes that require the user to be authenticated.
If you want to enforce the user email is confirmed before
they use the application at all, here would be a good place.
"""
def require_authenticated_user(conn, _opts) do
def require_authenticated_user(conn, _opts \\ nil) do
if conn.assigns[:current_user] do
conn
else

View File

@ -4,7 +4,30 @@ defmodule FriendsWeb.FriendsLive.Components do
import Helpers
alias Friends.Friend
def show_page("overview", assigns) do
def header(assigns) do
~H"""
<div class="border-b-4 flex flex-row justify-between">
<h1 class="mb-0 pl-2" style="height:48px; text-indent:5px"><%= @friend.name %></h1>
</div>
"""
end
def menu(assigns) do
~H"""
<div class="hidden sm:tabs sm:mb-8">
<%= for page <- [:overview, :timeline, :relationships] do %>
<% is_active = if(page == @live_action) do "tab-active" end %>
<.link patch={Routes.friends_show_path(FriendsWeb.Endpoint, page, @friend.slug)} class={"font-bold sm:tab-lg flex-grow no-underline tab tab-lifted #{is_active}"}>
<%= page |> to_string |> :string.titlecase() %>
</.link>
<% end %>
</div>
"""
end
def show_page(:main, assigns), do: show_page(:overview, %{assigns | live_action: :overview})
def show_page(:overview, assigns) do
~H"""
<ul class="py-4 pl-0 md:text-xl h-1/2">
<li class="flex flex-row mb-8 gap-6">
@ -32,18 +55,17 @@ defmodule FriendsWeb.FriendsLive.Components do
<strong class="w-28 text-right">Phone:</strong>
<div class=""><%= @friend.phone %></div>
</li>
<li class="flex flex-row mb-8 gap-6">
<strong class="w-28 text-right">Address:</strong>
<div class=""><%= @friend.address %></div>
</li>
</ul>
<%= if @friend |> Friend.can_be_edited_by(@current_user) do %>
<div class="form-control flex flex-row mb-4">
<.link patch={"/friend/#{@friend.slug}/#{@page_view}/edit"} class="btn btn-block md:btn-wide text-white">edit</.link>
</div>
<% end %>
"""
end
def show_page("calendar", assigns) do
def show_page(:timeline, assigns) do
~H"""
<div id="calendar" class="flex md:flex-row flex-col gap-8 p-8">
<div id="timeline" class="flex md:flex-row flex-col gap-8 p-8">
<%= for event <- @friend |> Friends.Friend.get_events do %>
<ul>
<li>
@ -58,7 +80,7 @@ defmodule FriendsWeb.FriendsLive.Components do
"""
end
def show_page("relationships", assigns) do
def show_page(:relationships, assigns) do
~H"""
<div id="relationships" class="flex md:flex-row flex-col gap-8">
<%= for relation <- @friend |> relations do %>
@ -80,15 +102,12 @@ defmodule FriendsWeb.FriendsLive.Components do
<div class="italic p-4">No relationships on record yet.</div>
<% end %>
</div>
<div class="form-control flex flex-row my-8">
<.link patch={"/friend/#{@friend.slug}/update?page=relationships"} class="btn btn-block md:btn-wide text-white">edit</.link>
</div>
"""
end
###
def form_page("overview", assigns) do
def edit_page(:overview, assigns) do
~H"""
<.form
for={@changeset}
@ -140,7 +159,7 @@ defmodule FriendsWeb.FriendsLive.Components do
<div class="form-control flex flex-row gap-x-4 md:justify-end mb-4 md:w-1/2">
<div class="flex-1">
<.link patch={"/friend/#{@friend.slug}"} class="btn btn-block btn-outline">back</.link>
<.link patch={Routes.friends_show_path(FriendsWeb.Endpoint, :overview, @friend.slug)} class="btn btn-block btn-outline">back</.link>
</div>
<div class="flex-1">
<%= if @changeset.valid? do %>
@ -159,9 +178,9 @@ defmodule FriendsWeb.FriendsLive.Components do
"""
end
def form_page("relationships", assigns) do
def edit_page(:relationships, assigns) do
~H"""
<%= FriendsWeb.FriendLive.Friend.header(assigns) %>
<%= Components.header(assigns) %>
"""
end
end

View File

@ -1,7 +1,7 @@
defmodule FriendsWeb.FriendsLive.Friend do
use FriendsWeb, :live_view
alias FriendsWeb.FriendLive.Components
alias FriendsWeb.FriendsLive.Components
alias FriendsWeb.Router.Helpers, as: Routes
alias Friends.Friend
@ -18,32 +18,6 @@ defmodule FriendsWeb.FriendsLive.Friend do
|> assign(:changeset, %Friend{} |> Friend.changeset())}
end
# Show Friend
def handle_params(%{"slug" => slug} = attrs, _url, socket) do
friend = Friend.get_by_slug(slug)
page =
if (attrs |> Map.get("page")) in ["overview", "calendar", "relationships"] do
attrs["page"]
else
"redir"
end
if page == "redir" do
{:noreply,
socket
|> push_patch(to: "/friend/#{slug}/overview")}
else
{:noreply,
socket
|> title(friend.name <> " - " <> (page |> :string.titlecase()))
|> assign_friend(friend)
|> page_view(page)
|> assign(:current_user, nil)
|> assign(:action, Routes.friend_path(socket, :update, friend.id))}
end
end
# New Friend
def handle_params(_attrs, _token, socket) do
friend = Friend.new()
@ -52,8 +26,7 @@ defmodule FriendsWeb.FriendsLive.Friend do
socket
|> title("New Friend")
|> assign_friend(friend)
|> page_view("overview")
|> assign(:action, Routes.friend_path(socket, :create))}
|> assign(:action, Routes.friends_path(socket, :create))}
end
# Handle form validation
@ -134,57 +107,5 @@ defmodule FriendsWeb.FriendsLive.Friend do
|> push_navigate(to: "/")}
end
# Set variables on page: friend, changeset, relationships
def assign_friend(socket, friend) do
socket
|> assign(:friend, friend)
|> assign(:changeset, friend |> Friend.changeset())
|> assign(:relationships, friend.relationships)
end
# Same thing, but this time we have a changeset we want to keep
def assign_friend(socket, friend, changeset) do
socket
|> assign(:friend, friend)
|> assign(:changeset, changeset)
|> assign(:relationships, friend.relationships)
end
# Route to the right sub-template in Components/Components.ex
def content(assigns) do
~H"""
<%= if @live_action != :new do %>
<%= FriendsWeb.FriendsLive.Friend.menu(assigns) %>
<% end %>
<%= cond do %>
<% @live_action == :show -> %>
<%= header(assigns) %>
<%= @page_view |> Components.show_page(assigns) %>
<% @live_action in [:edit, :new] -> %>
<%= @page_view |> Components.form_page(assigns) %>
<% end %>
"""
end
def header(assigns) do
~H"""
<div class="border-b-4 flex flex-row justify-between">
<h1 class="mb-0 pl-2" style="height:48px; text-indent:5px"><%= @friend.name %></h1>
</div>
"""
end
def menu(assigns) do
~H"""
<div class="hidden sm:tabs sm:mb-8">
<%= for page <- ["overview", "calendar", "relationships"] do %>
<% is_active = if(page == @page_view) do "tab-active" end %>
<.link patch={"/friend/#{@friend.slug}/#{page}"} class={"font-bold sm:tab-lg flex-grow no-underline tab tab-lifted #{is_active}"}>
<%= page |> :string.titlecase() %>
</.link>
<% end %>
</div>
"""
end
end

View File

@ -1,3 +0,0 @@
defmodule FriendsWeb.FriendLive do
use FriendsWeb, :live_view
end

View File

@ -0,0 +1,3 @@
defmodule FriendsWeb.FriendsLive do
use FriendsWeb, :live_view
end

View File

@ -1,31 +1,40 @@
"""
defmodule FriendsWeb.FriendLive.Show do
defmodule FriendsWeb.FriendsLive.Show do
use FriendsWeb, :live_view
import FriendsWeb.LiveHelpers
alias Friends.Friend
alias FriendsWeb.FriendsLive.Components
def handle_params(attrs, token, socket) do
FriendsWeb.FriendLive.Friend.handle_params(attrs, token, socket)
def mount(%{"slug" => slug} = _attrs, token, socket) do
live_action = socket.assigns.live_action || false
friend = Friend.get_by_slug(slug)
editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
if(live_action) do
{:ok,
socket
|> assign(:live_action, live_action)
|> assign_current_user(token |> Map.get("user_token"))
|> assign(:friend, friend)
|> title(friend.name <> " - " <> (live_action |> titlecase))
|> assign(:changeset, %Friend{} |> Friend.changeset())
|> assign(:action, editable)}
else
{:ok, socket |> redirect(to: Routes.friends_show_path(socket, :overview, friend.slug))}
end
end
def mount(%{"slug" => slug} = attrs, token, socket) do
friend = slug |> Friends.Friend.get_by_slug()
def handle_params(%{"slug" => slug} = attrs, _url, socket) do
live_action = socket.assigns.live_action || false
page =
if (attrs |> Map.get("page")) in ["overview", "calendar", "relationships"] do
attrs["page"]
else
"overview"
end
friend = Friend.get_by_slug(slug)
editable = friend |> Friend.can_be_edited_by(socket.assigns[:current_user])
{:ok,
{:noreply,
socket
|> title(friend.name <> " - " <> (page |> :string.titlecase()))
|> page_view(page)
|> assign_current_user(token |> Map.get("user_token"))
|> assign(:friend, friend)
|> assign(:changeset, %Friend{} |> Friend.changeset())
|> assign(:action, Routes.friend_path(socket, :update, friend.id))}
|> assign_friend(friend)
|> assign(:live_action, live_action)
|> title(friend.name <> " - " <> (live_action |> titlecase))
|> assign(:editable, editable)}
end
end
"""

View File

@ -1,5 +1,13 @@
<section class="row">
<article class="column prose">
<FriendsWeb.FriendLive.Friend.content friend={@friend} page_view={@page_view} changeset={@changeset} action={@action} live_action={@live_action}/>
<%= Components.menu(assigns) %>
<%= Components.header(assigns) %>
<%= Components.show_page(@live_action, assigns) %>
<%= if @editable do %>
<div class="form-control flex flex-row mb-4">
<.link patch={Routes.friends_edit_path(FriendsWeb.Endpoint, :overview, @friend.slug)} class="btn btn-block md:btn-wide text-white">edit</.link>
</div>
<% end %>
</article>
</section>

View File

@ -52,54 +52,63 @@ defmodule FriendsWeb.Router do
end
## Authentication routes
scope "/", FriendsWeb do
# Routes that only work if user not authenticated
scope "/users", FriendsWeb do
pipe_through [:browser, :redirect_if_user_is_authenticated]
# Requires the user NOT be authenticated:
get "/users/register", UserRegistrationController, :new
post "/users/register", UserRegistrationController, :create
get "/users/log_in", UserSessionController, :new
post "/users/log_in", UserSessionController, :create
get "/users/reset_password", UserResetPasswordController, :new
post "/users/reset_password", UserResetPasswordController, :create
get "/users/reset_password/:token", UserResetPasswordController, :edit
put "/users/reset_password/:token", UserResetPasswordController, :update
get "/register", UserRegistrationController, :new
post "/register", UserRegistrationController, :create
get "/log_in", UserSessionController, :new
post "/log_in", UserSessionController, :create
get "/reset_password", UserResetPasswordController, :new
post "/reset_password", UserResetPasswordController, :create
get "/reset_password/:token", UserResetPasswordController, :edit
put "/reset_password/:token", UserResetPasswordController, :update
end
scope "/", FriendsWeb do
pipe_through [:browser, :require_authenticated_user]
# Requires the user DO be authenticated:
live "/profile/new", ProfileLive.Form, :new
get "/users/settings", UserSettingsController, :edit
put "/users/settings", UserSettingsController, :update
get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email
end
scope "/", FriendsWeb do
# Confirmation and logout
scope "/users", FriendsWeb do
pipe_through [:browser]
delete "/users/log_out", UserSessionController, :delete
get "/users/confirm", UserConfirmationController, :new
post "/users/confirm", UserConfirmationController, :create
get "/users/confirm/:token", UserConfirmationController, :edit
post "/users/confirm/:token", UserConfirmationController, :update
delete "/log_out", UserSessionController, :delete
get "/confirm", UserConfirmationController, :new
post "/confirm", UserConfirmationController, :create
get "/confirm/:token", UserConfirmationController, :edit
post "/confirm/:token", UserConfirmationController, :update
end
# Routes that require the user be authenticated:
scope "/users/settings", FriendsWeb do
pipe_through [:browser, :require_authenticated_user]
get "/", UserSettingsController, :edit
put "/", UserSettingsController, :update
get "/confirm_email/:token", UserSettingsController, :confirm_email
end
# THE ACTUAL GUTS OF THE APP
scope "/", FriendsWeb do
pipe_through [:browser, :capture_profile]
get "/", PageController, :index
get "/friends", FriendController, :index
live "/friend/:slug", FriendLive.Show
live "/friend/:slug/edit", FriendLive.Edit
end
# View-only modes (don't require being logged in and having a profile)
scope "/friends", FriendsWeb do
pipe_through [:browser]
get "/", FriendsController, :index
live "/:slug", FriendsLive.Show
live "/:slug/overview", FriendsLive.Show, :overview
live "/:slug/timeline", FriendsLive.Show, :timeline
live "/:slug/relationships", FriendsLive.Show, :relationships
end
# Edit modes (require being logged in and having a profile)
scope "/update/", FriendsWeb do
pipe_through [:browser, :require_authenticated_user, :capture_profile]
live "/:slug/overview", FriendsLive.Edit, :overview
live "/:slug/timeline", FriendsLive.Edit, :timeline
live "/:slug/relationships", FriendsLive.Edit, :relationships
post "/:slug/update", FriendsController, :update
end
end

View File

@ -3,7 +3,7 @@
<ul class="text-xl">
<%= for f <- @all_friends do %>
<li>
<.link href={"/friend/#{f.slug}"}><%= f.name %></.link>
<.link href={Routes.friends_show_path(@conn, :overview, f.slug)}><%= f.name %></.link>
<%= if @current_user do %>
<%= if f.id == @current_user.profile.id do %>
(you)
@ -14,6 +14,6 @@
<%= if @current_user do %>
<div class="m-4 mt-16">
<.link href="/friends/new" class="btn btn-primary">Add Friend</.link>
<.link href={Routes.friends_edit_path(@conn, :overview, :new)}>Add Friend</.link>
</div>
<% end %>

View File

@ -9,7 +9,7 @@
and basically go back to the 2011 Facebook we all miss.
</p>
<div class="hidden md:block">
<.db_stats all_friends={@all_friends} users={@users} />
<.friends_list friends={@friends} />
</div>
</div>
<div id="sign-up" class="prose card md:w-fit bg-neutral-content text-neutral shadow-xl items-center">
@ -20,7 +20,7 @@
<.sign_up new_friend={@new_friend} />
</div>
</div>
<div id="stats" class="prose w-full mb-8 md:hidden">
<.db_stats all_friends={@all_friends} users={@users} />
<div id="friends" class="prose w-full mb-8 md:hidden">
<.friends_list friends={@friends} />
</div>
</div>

View File

@ -1,6 +1,5 @@
defmodule FriendsWeb.FriendView do
defmodule FriendsWeb.FriendsView do
use FriendsWeb, :view
import Phoenix.Component
import Helpers
end

View File

@ -1,5 +1,10 @@
defmodule FriendsWeb.LiveHelpers do
use FriendsWeb, :live_component
alias Friends.Friend
def titlecase(atom) do
atom |> to_string |> :string.titlecase()
end
def assign_current_user(socket, user_token) do
user =
@ -26,8 +31,19 @@ defmodule FriendsWeb.LiveHelpers do
|> assign(:page_title, title)
end
# Set page_view variable
def page_view(socket, page) do
socket |> assign(:page_view, page)
# Set variables on page: friend, changeset, relationships
def assign_friend(socket, friend) do
socket
|> assign(:friend, friend)
|> assign(:changeset, friend |> Friend.changeset())
|> assign(:relationships, friend.relationships)
end
# Same thing, but this time we have a changeset we want to keep
def assign_friend(socket, friend, changeset) do
socket
|> assign(:friend, friend)
|> assign(:changeset, changeset)
|> assign(:relationships, friend.relationships)
end
end

View File

@ -6,24 +6,25 @@ defmodule FriendsWeb.PageView do
alias FriendsWeb.Components.SignUp, as: SignUp
def sign_up(assigns), do: SignUp.sign_up_form(assigns)
def db_stats(assigns) do
def friends_list(assigns) do
~H"""
<h3 class="mt-12 border-b-2">
Database stats
</h3>
<ul>
<li>
<.link patch="/friends" class="">
<%= pluralize(@all_friends |> length, "friend") %>
</.link>
</li>
<li>
<.link patch="/users" class="">
<%= pluralize(@users |> length, "user") %>
</.link>
</li>
</ul>
"""
All Friends
</h3>
<ul>
<%= for friend <- @friends do %>
<li>
<div id={"friend-#{friend.id}"} class="">
<div class="">
<h3 class="">
<.link href={Routes.live_path(FriendsWeb.Endpoint, FriendsWeb.FriendsLive.Show, friend.slug)}><%= friend.name %></.link>
</h3>
</div>
</div>
</li>
<% end %>
</ul>
"""
end
end

View File

@ -0,0 +1,9 @@
defmodule Friends.Repo.Migrations.AddAddressesToFriends do
use Ecto.Migration
def change do
alter table(:friends) do
add :address, :string
end
end
end

View File

@ -3,20 +3,22 @@ defmodule Friends.FriendsTest do
alias Friends.Friend
import Friends.{AccountsFixtures,FriendsFixtures}
# alias Friends.Accounts.{User, UserToken}
import Friends.{AccountsFixtures, FriendsFixtures}
# alias Friends.Accounts.{User, UserToken}
describe "new/1" do
test "no params" do
f = Friend.new()
assert f.id == :new
end
test "with params" do
attrs = valid_friend_attributes()
f = attrs |> Friend.new()
assert f.id == :new
assert f.name == attrs |> Map.get(:name)
end
test "has no loaded preloads" do
f = Friend.new()
assert %Ecto.Association.NotLoaded{} = f.user
@ -27,19 +29,22 @@ defmodule Friends.FriendsTest do
describe "commit/1" do
test "changes id" do
f = valid_friend_attributes()
|> Friend.create()
|> Friend.commit()
f =
valid_friend_attributes()
|> Friend.create()
|> Friend.commit()
assert f.id != :new
end
test "generates slug" do
f = valid_friend_attributes()
|> Friend.create()
|> Friend.commit()
assert f.slug != :nil
assert f.slug == f.name |> Helpers.to_slug
test "generates slug" do
f =
valid_friend_attributes()
|> Friend.create()
|> Friend.commit()
assert f.slug != nil
assert f.slug == f.name |> Helpers.to_slug()
end
end
@ -48,38 +53,41 @@ defmodule Friends.FriendsTest do
f = valid_friend_attributes() |> Friend.new()
assert f.slug == nil
end
test "generate_slug generates a slug, returns a friend" do
f = valid_friend_attributes() |> Friend.new() |> Friend.generate_slug
assert f.slug == f.name |> Helpers.to_slug
f = valid_friend_attributes() |> Friend.new() |> Friend.generate_slug()
assert f.slug == f.name |> Helpers.to_slug()
end
test "generate_slug generates a slug, returns a changeset" do
c = valid_friend_attributes() |> Friend.create() |> Friend.generate_slug
c = valid_friend_attributes() |> Friend.create() |> Friend.generate_slug()
f = c.data
assert f.slug == f.name |> Helpers.to_slug
assert f.slug == f.name |> Helpers.to_slug()
end
end
describe "assign_user/1" do
setup do
friend = friend_fixture()
%{
friend: friend,
user: user_fixture(%{email: friend.email})
}
end
test "links a user to a friend", %{user: user, friend: friend} do
assert user.profile == nil
assert friend.user == nil
describe "assign_user/1" do
setup do
friend = friend_fixture()
%{
friend: new_friend,
user: new_user
} = friend |> Friends.Friend.assign_user
%{
friend: friend,
user: user_fixture(%{email: friend.email})
}
end
assert new_user.profile.id == friend.id
assert new_friend.user.id == user.id
test "links a user to a friend", %{user: user, friend: friend} do
assert user.profile == nil
assert friend.user == nil
end
%{
friend: new_friend,
user: new_user
} = friend |> Friends.Friend.assign_user()
assert new_user.profile.id == friend.id
assert new_friend.user.id == user.id
end
end
describe "preloads" do
@ -89,32 +97,30 @@ defmodule Friends.FriendsTest do
test "default nothing loaded", %{friend: friend} do
f = friend
refute f.user |> Ecto.assoc_loaded?
refute f.relationships |> Ecto.assoc_loaded?
refute f.reverse_relationships |> Ecto.assoc_loaded?
refute f.user |> Ecto.assoc_loaded?()
refute f.relationships |> Ecto.assoc_loaded?()
refute f.reverse_relationships |> Ecto.assoc_loaded?()
end
test "load user", %{friend: friend} do
f = friend |> Friend.load_user
assert f.user |> Ecto.assoc_loaded?
refute f.relationships |> Ecto.assoc_loaded?
refute f.reverse_relationships |> Ecto.assoc_loaded?
f = friend |> Friend.load_user()
assert f.user |> Ecto.assoc_loaded?()
refute f.relationships |> Ecto.assoc_loaded?()
refute f.reverse_relationships |> Ecto.assoc_loaded?()
end
test "load relationships", %{friend: friend} do
f = friend |> Friend.load_relationships
refute f.user |> Ecto.assoc_loaded?
assert f.relationships |> Ecto.assoc_loaded?
assert f.reverse_relationships |> Ecto.assoc_loaded?
f = friend |> Friend.load_relationships()
refute f.user |> Ecto.assoc_loaded?()
assert f.relationships |> Ecto.assoc_loaded?()
assert f.reverse_relationships |> Ecto.assoc_loaded?()
end
test "load all", %{friend: friend} do
f = friend |> Friend.load_preloads
assert f.user |> Ecto.assoc_loaded?
assert f.relationships |> Ecto.assoc_loaded?
assert f.reverse_relationships |> Ecto.assoc_loaded?
f = friend |> Friend.load_preloads()
assert f.user |> Ecto.assoc_loaded?()
assert f.relationships |> Ecto.assoc_loaded?()
assert f.reverse_relationships |> Ecto.assoc_loaded?()
end
end
end

View File

@ -1,19 +1,15 @@
defmodule FriendsWeb.FriendControllerTest do
defmodule FriendsWeb.FriendsControllerTest do
use FriendsWeb.ConnCase, async: true
import Friends.{AccountsFixtures,FriendsFixtures}
import Friends.{AccountsFixtures, FriendsFixtures}
setup do
%{
user: _user,
friend: _friend
} =
friend_fixture(
%{email: user_fixture().email}
) |> Friends.Friend.assign_user
} = friend_fixture(%{email: user_fixture().email}) |> Friends.Friend.assign_user()
end
describe "GET '/friends'" do
test "shows the friends dashboard", %{conn: conn, friend: friend} do
conn = get(conn, "/friends")
assert html_response(conn, 200) =~ friend.name
@ -27,6 +23,9 @@ defmodule FriendsWeb.FriendControllerTest do
assert html_response(conn, 200) =~ "Log out"
end
test "shows option to add friend if logged in", %{conn: conn, friend: friend, user: user} do
conn = conn |> log_in_user(user) |> get("/friends")
assert html_response(conn, 200) =~ Routes.friends_edit_path(conn, :overview, :new)
end
end
end

View File

@ -0,0 +1,18 @@
defmodule FriendsWeb.FriendsLiveTest do
use FriendsWeb.ConnCase, async: true
import Friends.{AccountsFixtures, FriendsFixtures}
setup do
%{
user: _user,
friend: _friend
} = friend_fixture(%{email: user_fixture().email}) |> Friends.Friend.assign_user()
end
describe "GET '/friends/:slug'" do
test "shows the friend overview", %{conn: conn, friend: friend} do
conn = conn |> get("/friends/#{friend.slug}")
assert html_response(conn, 200) =~ friend.name
end
end
end

View File

@ -1,6 +1,6 @@
defmodule FriendsWeb.PageControllerTest do
use FriendsWeb.ConnCase, async: true
import Friends.{AccountsFixtures,FriendsFixtures}
import Friends.{AccountsFixtures, FriendsFixtures}
alias FriendsWeb.Router.Helpers, as: Routes
@ -16,17 +16,23 @@ defmodule FriendsWeb.PageControllerTest do
assert html_response(conn, 200) =~ "Register"
end
test "redirects to the new profile flow if logged in but has no profile", %{conn: conn, user: user} do
test "redirects to the new profile flow if logged in but has no profile", %{
conn: conn,
user: user
} do
_friend = friend_fixture(%{email: "random_email@invalid.biz"})
conn = conn |> log_in_user(user) |> get("/")
assert redirected_to(conn) == Routes.profile_form_path(conn, :new)
assert redirected_to(conn) == Routes.friends_edit_path(conn, :overview, :new)
assert get_flash(conn, :info) =~ "profile!"
end
test "redirects to the friends dashboard if logged in & has a profile", %{conn: conn, user: user} do
test "redirects to the friends dashboard if logged in & has a profile", %{
conn: conn,
user: user
} do
_friend = friend_fixture(%{email: user.email})
conn = conn |> log_in_user(user) |> get("/")
assert redirected_to(conn) == Routes.friend_path(conn, :index)
assert redirected_to(conn) == Routes.friends_path(conn, :index)
end
end
end