Finished basic onboarding flow; added tests

This commit is contained in:
Kieran Eglin 2024-02-20 09:26:38 -08:00
parent 2de585aae6
commit 329c2e5530
No known key found for this signature in database
GPG key ID: 193984967FCF432D
17 changed files with 183 additions and 46 deletions

View file

@ -100,7 +100,6 @@ defmodule Pinchflat.Media do
field -> List.wrap(mapped_struct[field])
end)
|> List.flatten()
# TODO: test
|> Enum.filter(&is_binary/1)
end

View file

@ -11,11 +11,6 @@ defmodule Pinchflat.MediaSource do
alias Pinchflat.MediaSource.Source
alias Pinchflat.MediaClient.SourceDetails
# TODO: test
def sources_exist? do
Repo.exists?(Source)
end
@doc """
Returns the list of sources. Returns [%Source{}, ...]
"""

View file

@ -8,11 +8,6 @@ defmodule Pinchflat.Profiles do
alias Pinchflat.Profiles.MediaProfile
# TODO: test
def media_profiles_exist? do
Repo.exists?(MediaProfile)
end
@doc """
Returns the list of media_profiles. Returns [%MediaProfile{}, ...]
"""

View file

@ -7,7 +7,7 @@
>
<.icon name="hero-bars-3" />
</button>
<a class="hidden sm:block flex-shrink-0 lg:hidden" href="#">
<a class="hidden sm:block flex-shrink-0 lg:hidden" href="/">
<h2 class="text-title-md2 font-bold text-white">Pinchflat</h2>
</a>
</div>
@ -22,7 +22,7 @@
name="q"
value={@params["q"]}
placeholder="Type to search..."
class="w-full bg-transparent pl-9 pr-4 border-0 focus:ring-0 focus:outline-none xl:w-125"
class="w-full bg-transparent pl-9 pr-4 border-0 focus:ring-0 focus:outline-none lg:w-125"
/>
</form>
</div>

View file

@ -4,7 +4,9 @@
@click.outside="sidebarToggle = false"
>
<div class="flex items-center justify-between gap-2 px-6 py-5.5 lg:py-6.5">
<h2 class="text-title-md2 font-bold text-white">Pinchflat</h2>
<a href="/">
<h2 class="text-title-md2 font-bold text-white">Pinchflat</h2>
</a>
<button class="block lg:hidden" @click.stop="sidebarToggle = !sidebarToggle">
<.icon name="hero-arrow-left" class="fill-current" />
@ -15,6 +17,8 @@
<div>
<h3 class="mb-4 ml-4 text-sm font-medium text-bodydark2">MENU</h3>
<ul class="mb-6 flex flex-col gap-1.5">
<.sidebar_item icon="hero-home" text="Home" navigate={~p"/"} />
<.sidebar_item icon="hero-tv" text="Sources" navigate={~p"/sources"} />
<.sidebar_item icon="hero-adjustments-vertical" text="Media Profiles" navigate={~p"/media_profiles"} />

View file

@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title suffix=" · Phoenix Framework">
<.live_title>
<%= assigns[:page_title] || "Pinchflat" %>
</.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />

View file

@ -13,9 +13,9 @@ defmodule PinchflatWeb.MediaProfiles.MediaProfileController do
changeset = Profiles.change_media_profile(%MediaProfile{})
if get_session(conn, :onboarding) do
render(conn, :new, changeset: changeset, onboarding: true, layout: {Layouts, :onboarding})
render(conn, :new, changeset: changeset, layout: {Layouts, :onboarding})
else
render(conn, :new, changeset: changeset, onboarding: false)
render(conn, :new, changeset: changeset)
end
end
@ -23,14 +23,18 @@ defmodule PinchflatWeb.MediaProfiles.MediaProfileController do
case Profiles.create_media_profile(media_profile_params) do
{:ok, media_profile} ->
redirect_location =
if get_session(conn, :onboarding), do: ~p"/", else: ~p"/media_profiles/#{media_profile}"
if get_session(conn, :onboarding), do: ~p"/?onboarding=1", else: ~p"/media_profiles/#{media_profile}"
conn
|> put_flash(:info, "Media profile created successfully.")
|> redirect(to: redirect_location)
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, :new, changeset: changeset)
if get_session(conn, :onboarding) do
render(conn, :new, changeset: changeset, layout: {Layouts, :onboarding})
else
render(conn, :new, changeset: changeset)
end
end
end

View file

@ -1,5 +1,5 @@
<div class="mb-6 flex gap-3 flex-row items-center">
<.link :if={not @onboarding} navigate={~p"/media_profiles"}>
<.link :if={!Plug.Conn.get_session(@conn, :onboarding)} navigate={~p"/media_profiles"}>
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
</.link>
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Media Profile</h2>

View file

@ -20,11 +20,10 @@ defmodule PinchflatWeb.MediaSources.SourceController do
render(conn, :new,
changeset: changeset,
media_profiles: media_profiles(),
onboarding: true,
layout: {Layouts, :onboarding}
)
else
render(conn, :new, changeset: changeset, media_profiles: media_profiles(), onboarding: false)
render(conn, :new, changeset: changeset, media_profiles: media_profiles())
end
end
@ -32,14 +31,22 @@ defmodule PinchflatWeb.MediaSources.SourceController do
case MediaSource.create_source(source_params) do
{:ok, source} ->
redirect_location =
if get_session(conn, :onboarding), do: ~p"/", else: ~p"/sources/#{source}"
if get_session(conn, :onboarding), do: ~p"/?onboarding=1", else: ~p"/sources/#{source}"
conn
|> put_flash(:info, "Source created successfully.")
|> redirect(to: redirect_location)
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, :new, changeset: changeset, media_profiles: media_profiles())
if get_session(conn, :onboarding) do
render(conn, :new,
changeset: changeset,
media_profiles: media_profiles(),
layout: {Layouts, :onboarding}
)
else
render(conn, :new, changeset: changeset, media_profiles: media_profiles())
end
end
end

View file

@ -1,5 +1,5 @@
<div class="mb-6 flex gap-3 flex-row items-center">
<.link :if={not @onboarding} navigate={~p"/sources"}>
<.link :if={!Plug.Conn.get_session(@conn, :onboarding)} navigate={~p"/sources"}>
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
</.link>
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Source</h2>

View file

@ -1,25 +1,35 @@
defmodule PinchflatWeb.Pages.PageController do
use PinchflatWeb, :controller
alias Pinchflat.Profiles
alias Pinchflat.MediaSource
alias Pinchflat.Repo
alias Pinchflat.MediaSource.Source
alias Pinchflat.Profiles.MediaProfile
def home(conn, _params) do
media_profiles_exist = Profiles.media_profiles_exist?()
sources_exist = MediaSource.sources_exist?()
def home(conn, params) do
force_onboarding = params["onboarding"]
media_profiles_exist = Repo.exists?(MediaProfile)
sources_exist = Repo.exists?(Source)
if media_profiles_exist && sources_exist do
conn
|> put_session(:onboarding, false)
|> render(:home)
if !force_onboarding && media_profiles_exist && sources_exist do
render_home_page(conn)
else
conn
|> put_session(:onboarding, true)
|> render(:onboarding_checklist,
media_profiles_exist: media_profiles_exist,
sources_exist: sources_exist,
layout: {Layouts, :onboarding}
)
render_onboarding_page(conn, media_profiles_exist, sources_exist)
end
end
defp render_home_page(conn) do
conn
|> put_session(:onboarding, false)
|> render(:home)
end
defp render_onboarding_page(conn, media_profiles_exist, sources_exist) do
conn
|> put_session(:onboarding, true)
|> render(:onboarding_checklist,
media_profiles_exist: media_profiles_exist,
sources_exist: sources_exist,
layout: {Layouts, :onboarding}
)
end
end

View file

@ -1 +1,8 @@
<h1>hey</h1>
<div class="rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark">
<div class="max-w-full overflow-x-auto">
<div class="flex flex-col gap-10 text-center my-10">
<h2 class="text-2xl">TODO: Put some useful info or analytics here</h2>
<p>For now, the options in the sidebar have what you need</p>
</div>
</div>
</div>

View file

@ -245,6 +245,18 @@ defmodule Pinchflat.MediaTest do
"video/test.srt"
]
end
test "strips out nil values" do
filepaths = %{
media_filepath: "/video/test.mp4",
thumbnail_filepath: nil,
subtitle_filepaths: [["en", nil]]
}
media_item = media_item_fixture(filepaths)
assert Media.media_filepaths(media_item) == ["/video/test.mp4"]
end
end
describe "create_media_item/1" do

View file

@ -22,6 +22,15 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
conn = get(conn, ~p"/media_profiles/new")
assert html_response(conn, 200) =~ "New Media Profile"
end
test "renders correct layout when onboarding", %{session_conn: session_conn} do
session_conn =
session_conn
|> put_session(:onboarding, true)
|> get(~p"/media_profiles/new")
refute html_response(session_conn, 200) =~ "MENU"
end
end
describe "create media_profile" do
@ -39,6 +48,24 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
conn = post(conn, ~p"/media_profiles", media_profile: @invalid_attrs)
assert html_response(conn, 200) =~ "New Media Profile"
end
test "redirects to onboarding when onboarding", %{session_conn: session_conn} do
session_conn =
session_conn
|> put_session(:onboarding, true)
|> post(~p"/media_profiles", media_profile: @create_attrs)
assert redirected_to(session_conn) == ~p"/?onboarding=1"
end
test "renders correct layout on error when onboarding", %{session_conn: session_conn} do
session_conn =
session_conn
|> put_session(:onboarding, true)
|> post(~p"/media_profiles", media_profile: @invalid_attrs)
refute html_response(session_conn, 200) =~ "MENU"
end
end
describe "edit media_profile" do

View file

@ -1,8 +1,52 @@
defmodule PinchflatWeb.PageControllerTest do
use PinchflatWeb.ConnCase
test "GET /", %{conn: conn} do
conn = get(conn, ~p"/")
assert html_response(conn, 200) =~ "Peace of mind from prototype to production"
import Pinchflat.ProfilesFixtures
import Pinchflat.MediaSourceFixtures
describe "GET / when testing onboarding" do
test "sets the onboarding session to true when onboarding", %{conn: conn} do
conn = get(conn, ~p"/")
assert get_session(conn, :onboarding)
end
test "displays the onboarding page when no media profiles exist", %{conn: conn} do
conn = get(conn, ~p"/")
assert html_response(conn, 200) =~ "Welcome to Pinchflat"
end
test "displays the onboarding page when no sources exist", %{conn: conn} do
_ = media_profile_fixture()
conn = get(conn, ~p"/")
assert html_response(conn, 200) =~ "Welcome to Pinchflat"
end
test "displays the onboarding page when onboarding is forced", %{conn: conn} do
_ = media_profile_fixture()
_ = source_fixture()
conn = get(conn, ~p"/?onboarding=1")
assert html_response(conn, 200) =~ "Welcome to Pinchflat"
end
test "sets the onboarding session to false when not onboarding", %{conn: conn} do
conn = get(conn, ~p"/")
assert get_session(conn, :onboarding)
_ = media_profile_fixture()
_ = source_fixture()
conn = get(conn, ~p"/")
refute get_session(conn, :onboarding)
end
test "displays the home page when not onboarding", %{conn: conn} do
_ = media_profile_fixture()
_ = source_fixture()
conn = get(conn, ~p"/")
assert html_response(conn, 200) =~ "MENU"
end
end
end

View file

@ -38,6 +38,15 @@ defmodule PinchflatWeb.SourceControllerTest do
conn = get(conn, ~p"/sources/new")
assert html_response(conn, 200) =~ "New Source"
end
test "renders correct layout when onboarding", %{session_conn: session_conn} do
session_conn =
session_conn
|> put_session(:onboarding, true)
|> get(~p"/sources/new")
refute html_response(session_conn, 200) =~ "MENU"
end
end
describe "create source" do
@ -56,6 +65,26 @@ defmodule PinchflatWeb.SourceControllerTest do
conn = post(conn, ~p"/sources", source: invalid_attrs)
assert html_response(conn, 200) =~ "New Source"
end
test "redirects to onboarding when onboarding", %{session_conn: session_conn, create_attrs: create_attrs} do
expect(YtDlpRunnerMock, :run, 1, &runner_function_mock/3)
session_conn =
session_conn
|> put_session(:onboarding, true)
|> post(~p"/sources", source: create_attrs)
assert redirected_to(session_conn) == ~p"/?onboarding=1"
end
test "renders correct layout on error when onboarding", %{session_conn: session_conn, invalid_attrs: invalid_attrs} do
session_conn =
session_conn
|> put_session(:onboarding, true)
|> post(~p"/sources", source: invalid_attrs)
refute html_response(session_conn, 200) =~ "MENU"
end
end
describe "edit source" do

View file

@ -34,6 +34,10 @@ defmodule PinchflatWeb.ConnCase do
setup tags do
Pinchflat.DataCase.setup_sandbox(tags)
{:ok, conn: Phoenix.ConnTest.build_conn()}
conn = Phoenix.ConnTest.build_conn()
session_conn = Plug.Test.init_test_session(conn, %{})
{:ok, conn: conn, session_conn: session_conn}
end
end