controllers tests are passing
Some checks failed
ci / build (push) Failing after 4m19s
ci / Tests & Checks (push) Failing after 9m47s

This commit is contained in:
CJ_Clippy 2025-02-12 06:09:01 -08:00
parent aa75c224fc
commit 4225bbdf61
28 changed files with 744 additions and 328 deletions

View File

@ -1,4 +1,4 @@
defmodule Bright.PatreonEntitlements do
defmodule Bright.Patrons.PatreonEntitlements do
@spec extract_tiers(map()) :: list(String.t())
def extract_tiers(response_body) do
response_body

View File

@ -1,4 +1,4 @@
defmodule Bright.TierMapper do
defmodule Bright.Patrons.TierMapper do
@patreon_tiers %{
"everyone" => 0,
"free" => 0,
@ -34,10 +34,16 @@ defmodule Bright.TierMapper do
def get_tier_number(_, _), do: 0
def largest_tier_for_platform(_platform, []), do: 0
@spec largest_tier_for_platform(any(), nil | maybe_improper_list()) :: any()
def largest_tier_for_platform(platform, tier_ids)
when is_list(tier_ids) and is_binary(platform) do
when is_binary(platform) and is_list(tier_ids) do
tier_ids
|> Enum.map(&get_tier_number(platform, &1))
|> Enum.max()
end
@spec largest_tier_for_platform(any(), list()) :: integer()
def largest_tier_for_platform(_, _), do: 0
def largest_tier_for_platform(_), do: 0
end

View File

@ -35,7 +35,7 @@ defmodule Bright.Users.User do
"""
def registration_changeset(user, attrs, _opts \\ []) do
user
|> cast(attrs, [:patreon_id, :github_id, :role])
|> cast(attrs, [:patreon_id, :github_id, :role, :patron_tier])
|> validate_provider_id()
end

View File

@ -19,6 +19,27 @@ defmodule BrightWeb.CoreComponents do
alias Phoenix.LiveView.JS
@doc """
Renders an external link.
## Example:
```heex
<.external_link href="https://example.com">Visit Example</.external_link>
```
"""
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
attr :href, :string, required: true
slot :inner_block, required: true
def(external_link(assigns)) do
~H"""
<.link href={@href} target="_blank" rel="noopener noreferrer" {@rest}>
{render_slot(@inner_block)}
<.icon name="arrow-up-right-from-square" class="ml-0" />
</.link>
"""
end
@doc """
Renders a modal.

View File

@ -1,4 +1,81 @@
<main class="section">
<.flash_group flash={@flash} />
{@inner_content}
</main>
<div>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<.link href={~p"/"} class="navbar-item">
<h1 class="title">🔞💦 Futureporn.net</h1>
</.link>
<.link
role="button"
class="navbar-burger"
aria-label="menu"
aria-expanded="false"
phx-click={JS.toggle(to: ".navbar-menu")}
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</.link>
</div>
<div class="navbar-menu">
<div class="navbar-start">
<.link href={~p"/streams"} class="navbar-item">
Streams Archive
</.link>
<.link href={~p"/vods"} class="navbar-item">
Vods
</.link>
<.link href={~p"/vtubers"} class="navbar-item">
Vtubers
</.link>
<.link href={~p"/about"} class="navbar-item">
About
</.link>
<!--<.link
href={~p"/patrons"}
class="navbar-item">
Patrons
</.link>
<.link
href={~p"/api"}
class="navbar-item">
API
</.link>-->
</div>
<div class="navbar-end">
<div class="navbar-item">
<.icon name="person-digging" class="is-unclickable" />
<.icon name="hammer" class="is-unclickable" />
</div>
<%= if @current_user do %>
<.link href={~p"/profile"} class="navbar-item">
Profile
</.link>
<.link href={~p"/auth/logout"} method="get" class="navbar-item">
Log out
</.link>
<% else %>
<.link href={~p"/auth/patreon"} method="get" class="navbar-item">
Sign in via Patreon
</.link>
<p>hello</p>
<.link href={~p"/auth/patreon"} class="navbar-item">
Log in
</.link>
<% end %>
</div>
</div>
</nav>
<main class="container">
<.flash_group flash={@flash} />
{@inner_content}
</main>
</div>

View File

@ -28,81 +28,6 @@
</script>
</head>
<body class="">
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<.link href={~p"/"} class="navbar-item">
<h1 class="title">🔞💦 Futureporn.net</h1>
</.link>
<a
role="button"
class="navbar-burger"
aria-label="menu"
aria-expanded="false"
phx-click={JS.toggle(to: ".navbar-menu")}
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div class="navbar-menu">
<div class="navbar-start">
<.link href={~p"/streams"} class="navbar-item">
Streams Archive
</.link>
<.link href={~p"/vods"} class="navbar-item">
Vods
</.link>
<.link href={~p"/vtubers"} class="navbar-item">
Vtubers
</.link>
<.link href={~p"/about"} class="navbar-item">
About
</.link>
<!--<.link
href={~p"/patrons"}
class="navbar-item">
Patrons
</.link>
<.link
href={~p"/api"}
class="navbar-item">
API
</.link>-->
</div>
<div class="navbar-end">
<div class="navbar-item">
<.icon name="person-digging" class="is-unclickable" />
<.icon name="hammer" class="is-unclickable" />
</div>
<%= if @current_user do %>
<.link href={~p"/profile"} class="navbar-item">
Profile
</.link>
<.link href={~p"/auth/logout"} method="get" class="navbar-item">
Log out
</.link>
<% else %>
<.link href={~p"/auth/patreon"} method="get" class="navbar-item">
Sign in via Patreon
</.link>
<p>hello</p>
<.link href={~p"/auth/patreon"} class="navbar-item">
Log in
</.link>
<% end %>
</div>
</div>
</nav>
{@inner_content}
</body>
</html>

View File

@ -4,6 +4,7 @@ defmodule BrightWeb.AuthController do
alias Bright.Users
alias Bright.Users.User
alias Bright.Patrons.TierMapper
alias Bright.Repo
require Logger
@ -66,12 +67,19 @@ defmodule BrightWeb.AuthController do
end
end
def callback(conn = %{assigns: %{ueberauth_failure: fails}}, _params) do
Logger.error(inspect(fails))
def callback(
conn = %{assigns: %{ueberauth_failure: %Ueberauth.Failure{errors: errors}}},
_params
) do
error_messages =
errors
|> Enum.map(fn %Ueberauth.Failure.Error{message: message} -> message end)
# Join multiple errors into a single string if needed
|> Enum.join(", ")
conn
|> put_flash(:error, "Something went wrong; please try again.")
|> render("new.html", user: nil)
|> put_flash(:error, "Authentication failed: #{error_messages}")
|> redirect(to: ~p"/")
end
defp params_from_ueberauth(%{provider: :github, info: info, uid: uid}) do
@ -88,14 +96,15 @@ defmodule BrightWeb.AuthController do
"getting params_from_ueberauth provider: :patreon. info=#{inspect(info)}, uid=#{inspect(uid)}, user=#{inspect(user)}"
)
currently_entitled_tiers = Bright.PatreonEntitlements.extract_tiers(user)
Logger.debug("currently_entitled_tiers=#{currently_entitled_tiers}")
patron_tier = Bright.TierMapper.largest_tier_for_platform("patreon", currently_entitled_tiers)
currently_entitled_tiers = Bright.Patrons.PatreonEntitlements.extract_tiers(user)
Logger.debug("currently_entitled_tiers=#{inspect(currently_entitled_tiers)}")
patron_tier =
TierMapper.largest_tier_for_platform("patreon", currently_entitled_tiers)
Logger.debug(">>>> computed patron_tier=#{inspect(patron_tier)}")
%{
name: info.name,
handle: info.nickname,
patreon_handle: info.nickname,
patreon_id: uid,
patron_tier: patron_tier
}
@ -129,7 +138,7 @@ defmodule BrightWeb.AuthController do
user = user_id && Users.get_user!(user_id)
Logger.debug(
"fetch_current_user attempting to get user. user_id=#{user_id} user=#{inspect(user)}"
"fetch_current_user attempting to get user. user_id=#{inspect(user_id)} user=#{inspect(user)}"
)
assign(conn, :current_user, user)
@ -211,6 +220,40 @@ defmodule BrightWeb.AuthController do
end
end
def require_patron_tier_1(conn, _), do: require_patron_tier(conn, 1)
def require_patron_tier_2(conn, _), do: require_patron_tier(conn, 2)
def require_patron_tier_3(conn, _), do: require_patron_tier(conn, 3)
@doc """
Ensures the user has a patron tier of `tier_level` or higher,
or has the role of "admin".
Redirects users who don't meet the requirement.
"""
def require_patron_tier(conn, tier_level) when is_integer(tier_level) do
user = conn.assigns[:current_user] || %{}
Logger.debug(
"require_patron_tier with conn=#{inspect(conn)} and tier_level=#{inspect(tier_level)} and user=#{inspect(user)}"
)
case user do
%{role: "admin"} ->
conn
%{patron_tier: patron_tier} when is_integer(patron_tier) and patron_tier >= tier_level ->
conn
_ ->
user_return_to = conn.assigns[:user_return_to] || "/"
conn
|> put_flash(:error, "This route is for tier #{tier_level} or higher.")
|> redirect(to: user_return_to)
|> halt()
end
end
@doc """
Used for routes that require the user to have admin privs.
"""
@ -219,7 +262,11 @@ defmodule BrightWeb.AuthController do
%{role: "admin"} ->
conn
_ ->
user ->
Logger.debug(
"A USER IS DOING A THING THAT REQUIRES ADMIN USER. BUT WE THINK THEY ARE NOT AN ADMIN. user=#{inspect(user)}"
)
conn
|> put_flash(:error, "Only admins can do that.")
|> maybe_store_return_to()

View File

@ -3,33 +3,34 @@ defmodule BrightWeb.PageController do
require Logger
@spec home(Plug.Conn.t(), any()) :: Plug.Conn.t()
def home(conn, _params) do
# The home page is often custom made,
# so skip the default app layout.
# render(conn, :home, layout: false)
# render(conn, :home)
# render(conn, "index.html", current_user: get_session(conn, :current_user))
# send_resp(conn, 201, "")
conn
|> put_status(202)
|> render(:home, layout: false, current_user: get_session(conn, :current_user))
|> render(:home)
# redirect(conn, to: ~p"/redirect_test")
# redirect(conn, external: "https://elixir-lang.org/")
end
def about(conn, _params) do
render(conn, :about, layout: false)
render(conn, :about)
end
def api(conn, _params) do
render(conn, :api, layout: false)
render(conn, :api)
end
def profile(conn, _params) do
sesh = get_session(conn, :current_user)
Logger.debug("/profile with sesh=#{inspect(sesh)} conn=#{inspect(conn)}")
render(conn, :profile, layout: false)
render(conn, :profile)
end
def health(conn, _params) do
@ -38,6 +39,6 @@ defmodule BrightWeb.PageController do
end
def redirect_test(conn, _params) do
render(conn, :home, layout: false)
render(conn, :home)
end
end

View File

@ -20,7 +20,7 @@
</p>
</i>
<a class="mt-5 button is-primary" href={~p"/streams"}>Streams Archive</a>
<.link class="mt-5 button is-primary" href={~p"/streams"}>Streams Archive</.link>
</div>
</div>
</div>

View File

@ -30,8 +30,8 @@
<p class="subtitle is-6">Futureporn User {@current_user.id}</p>
<p class="subtitle is-6"><i>n</i> uploads</p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec
iaculis mauris. <a>@bulmaio</a>. <a href="#">#css</a>
<a href="#">#responsive</a>
iaculis mauris. <.link>@bulmaio</.link>. <.link href="#">#css</.link>
<.link href="#">#responsive</.link>
<br />
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
</div>

View File

@ -2,19 +2,19 @@
<div class="level-left">
<div class="level-item">
<%= if @torrent && @torrent.magnet do %>
<a target="_blank" href={@torrent.magnet}><.icon name="magnet" class="icon" /></a>
<.link target="_blank" href={@torrent.magnet}><.icon name="magnet" class="icon" /></.link>
<% end %>
</div>
<div class="level-item">
<%= if @torrent && @torrent.cdn_url do %>
<a target="_blank" href={@torrent.cdn_url} class="button">
<.link target="_blank" href={@torrent.cdn_url} class="button">
<span class="icon-text">
<span class="icon">
<.icon name="download" />
</span>
<span>Download</span>
</span>
</a>
</.link>
<% end %>
</div>
<div class="level-item">

View File

@ -25,7 +25,9 @@
>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
<.link href="http://videojs.com/html5-video-support/" target="_blank">
supports HTML5 video
</.link>
</p>
</video>
<% else %>
@ -60,7 +62,7 @@
<:item title="Torrent"><TorrentHTML.summary torrent={@vod.torrent} /></:item>
<:item title="Source VOD File">
<%= if @vod.s3_cdn_url do %>
<a
<.link
class="button is-secondary"
href={@vod.s3_cdn_url}
download={Path.basename(@vod.s3_cdn_url)}
@ -73,7 +75,7 @@
Download
</span>
</span>
</a>
</.link>
<% end %>
</:item>
<:item title="HLS Playlist URL">{@vod.playlist_url}</:item>

View File

@ -14,6 +14,7 @@ defmodule BrightWeb.VtuberController do
render(conn, :new, changeset: changeset)
end
@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t()
def create(conn, %{"vtuber" => vtuber_params}) do
case Vtubers.create_vtuber(vtuber_params) do
{:ok, vtuber} ->

View File

@ -4,28 +4,22 @@ defmodule BrightWeb.IdenticonLive do
def render(assigns) do
~H"""
<div class="level">
<div class="level-left">
<div class="level-item">
<figure id="identicon" class="image is-48x48">
{raw(
IdenticonSvg.generate(assigns.identicon_seed, 5, :basic, 0.8, 2,
squircle_curvature: 0.8
)
)}
</figure>
</div>
<div class="level-item">
<button
class="button"
phx-click={JS.push("randomize", loading: "#identicon")}
phx-target={@myself}
>
<.icon name="dice" class="icon" />
<span>Randomize Identicon</span>
</button>
</div>
</div>
<div>
<button
class="button"
phx-click={JS.push("randomize", loading: "#identicon")}
phx-target={@myself}
>
<span class="icon is-small">
<.icon name="dice" />
</span>
<figure id="identicon" class="icon image is-24x24 mr-2">
{raw(
IdenticonSvg.generate(assigns.identicon_seed, 5, :basic, 0.8, 2, squircle_curvature: 0.8)
)}
</figure>
<span>Randomize Identicon</span>
</button>
</div>
"""
end

View File

@ -5,32 +5,134 @@ defmodule BrightWeb.ProfileLive do
def render(assigns) do
~H"""
<.header>
Profile
</.header>
<section class="section">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<.live_component
module={BrightWeb.IdenticonLive}
id={"user-#{@current_user.id}-identicon"}
identicon_seed={@current_user.identicon_seed}
/>
<div class="columns">
<div class="column is-half">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<figure class="image is-48x48">
{raw(
IdenticonSvg.generate(@current_user.identicon_seed, 5, :basic, 0.8, 2,
squircle_curvature: 0.8
)
)}
</figure>
</div>
<div class="media-content">
<p class="title is-4">User {@current_user.id}</p>
<p class="subtitle is-6">@{@current_user.id}</p>
</div>
</div>
<div class="content">
<p class="title is-5 mt-5">Patron Tier</p>
<p class="tag subtitle is-6 mt-2">{@current_user.patron_tier}</p>
<p class="title is-5 mt-5">Role</p>
<p class="tag subtitle is-6 mt-2">{@current_user.role}</p>
</div>
</div>
</div>
<div class="content">
<p class="title is-4">User {@current_user.id}</p>
<p class="title is-5 mt-5">Patron Tier</p>
<p class="tag subtitle is-6 mt-2">{@current_user.patron_tier}</p>
<p>
Change your patron tier at
<a target="_blank" href="https://patreon.com/CJ_Clippy">patreon.com/CJ_Clippy</a>
</p>
</div>
<div class="column is-half">
<div class="card">
<header class="card-header">
<p class="card-header-title">Settings</p>
</header>
<div class="content">
<div class="card-content">
<.live_component
module={BrightWeb.IdenticonLive}
id={"user-#{@current_user.id}-identicon"}
identicon_seed={@current_user.identicon_seed}
/>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="hero">
<div class="hero-body">
<p class="title">Care to upgrade your Patron Tier?</p>
</div>
</section>
<section class="section">
<table class="table is-striped is-hoverable is-fullwidth">
<thead>
<tr>
<th>Feature</th>
<th>Tier 0</th>
<th>Tier 1</th>
<th>Tier 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Viewing</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>RSS</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>API</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Patron List</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Uploads</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Content Adding</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Sponsored Link</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</section>
<section class="hero mb-5">
<div class="hero-body">
<p class="title">Thank you for your support!</p>
<p class="subtitle is-6">
Change your patron tier at
<.external_link target="_blank" href="https://patreon.com/CJ_Clippy">
patreon.com/CJ_Clippy
</.external_link>
</p>
</div>
</section>
"""
end

View File

@ -6,7 +6,9 @@ defmodule BrightWeb.Router do
import BrightWeb.AuthController,
only: [
fetch_current_user: 2,
require_admin_user: 2
require_admin_user: 2,
require_authenticated_user: 2,
require_patron_tier_1: 2
]
pipeline :browser do
@ -36,7 +38,14 @@ defmodule BrightWeb.Router do
post("/:provider/callback", AuthController, :callback)
end
## protected routes
## tier 1 protected routes
scope "/", BrightWeb do
pipe_through [:browser, :require_authenticated_user, :require_patron_tier_1]
resources("/vtubers", VtuberController, only: [:new, :create, :edit, :update])
end
## admin protected routes
## this section needs to be above the unprotected routes,
## so routes like "/streams/new" take precedence.
scope "/", BrightWeb do
@ -67,31 +76,24 @@ defmodule BrightWeb.Router do
# end
resources("/vods", VodController, only: [:create, :new, :edit, :update, :delete])
resources("/vtubers", VtuberController, only: [:create, :new, :edit, :update, :delete])
resources("/vtubers", VtuberController, only: [:delete])
get("/tags/new", TagController, :new)
post("/tags", TagController, :create)
get("/tags/:id/edit", TagController, :edit)
resources("/tags", TagController, only: [:new, :create, :edit, :update, :delete])
resources("/torrents", TorrentController, only: [:create, :new, :edit, :update, :delete])
resources("/torrents", TorrentController, only: [:new, :create, :edit, :update, :delete])
## !!! DANGER, platforms must only be writable by admins, (unless we implement SVG sanitizing)
## @todo remove SVGs from the database and instead put them in assets
resources("/platforms", PlatformController, only: [:new, :create, :edit, :update, :delete])
oban_dashboard("/oban")
live_session :authenticated,
on_mount: [{BrightWeb.AuthController, :ensure_authenticated}] do
live("/profile", ProfileLive)
end
end
## tier 0 users can access these routes
scope "/", BrightWeb do
pipe_through(:browser)
get("/", PageController, :home)
get("/patrons", PatronController, :index)
get("/about", PageController, :about)
get("/goals", PageController, :about)
@ -105,8 +107,7 @@ defmodule BrightWeb.Router do
get("/vods/:id", VodController, :show)
get("/vods", VodController, :index)
get("/tags", TagController, :index)
get("/tags/:id", TagController, :show)
resources("/tags", TagController, only: [:index, :show])
get("/platforms", PlatformController, :index)
get("/platforms/:id", PlatformController, :show)
@ -117,6 +118,11 @@ defmodule BrightWeb.Router do
get("/vods", VodController, :index)
get("/vods/:id", VodController, :show)
end
live_session :authenticated,
on_mount: [{BrightWeb.AuthController, :ensure_authenticated}] do
live("/profile", ProfileLive)
end
end
scope "/feeds", BrightWeb do

View File

@ -1,8 +1,16 @@
defmodule Bright.PatreonEntitlementsTest do
use ExUnit.Case
alias Bright.PatreonEntitlements
alias Bright.Patrons.PatreonEntitlements
describe "extract_tiers/1" do
test "handles empty included list" do
assert PatreonEntitlements.extract_tiers(%{"included" => []}) == []
end
test "handles no included list" do
assert PatreonEntitlements.extract_tiers(%{"data" => []}) == []
end
test "returns a list of tier IDs when included contains tier items" do
response_body = %{
"included" => [

View File

@ -1,64 +1,80 @@
defmodule Bright.TierMapperTest do
use ExUnit.Case
alias Bright.TierMapper
alias Bright.Patrons.TierMapper
describe "largest_tier_for_platform/2" do
test "gets the big big" do
assert TierMapper.largest_tier_for_platform("patreon", ["10620388", "8154170"]) == 1
assert TierMapper.largest_tier_for_platform("patreon", ["10620388", "8154170"]) === 1
end
test "handles nil list" do
assert TierMapper.largest_tier_for_platform("patreon", nil) === 0
end
test "handles platform with empty list" do
assert TierMapper.largest_tier_for_platform("patreon", []) === 0
end
test "handles nil platform" do
assert TierMapper.largest_tier_for_platform(nil) === 0
end
test "handles empty list" do
assert TierMapper.largest_tier_for_platform([]) === 0
end
end
describe "get_tier_number/2" do
test "maps Patreon 'everyone' tier to 0" do
assert TierMapper.get_tier_number("patreon", "-1") == 0
assert TierMapper.get_tier_number("patreon", "-1") === 0
end
test "maps Patreon 'free' tier to 0" do
assert TierMapper.get_tier_number("patreon", "10620388") == 0
assert TierMapper.get_tier_number("patreon", "10620388") === 0
end
test "maps Patreon 'archiveSupporter' tier to 1" do
assert TierMapper.get_tier_number("patreon", "8154170") == 1
assert TierMapper.get_tier_number("patreon", "8154170") === 1
end
test "maps Patreon 'stealthSupporter' tier to 1" do
assert TierMapper.get_tier_number("patreon", "9561793") == 1
assert TierMapper.get_tier_number("patreon", "9561793") === 1
end
test "maps Patreon 'tuneItUp' tier to 2" do
assert TierMapper.get_tier_number("patreon", "9184994") == 2
assert TierMapper.get_tier_number("patreon", "9184994") === 2
end
test "maps Patreon 'maxQ' tier to 2" do
assert TierMapper.get_tier_number("patreon", "22529959") == 2
assert TierMapper.get_tier_number("patreon", "22529959") === 2
end
test "maps Patreon 'archiveCollector' tier to 3" do
assert TierMapper.get_tier_number("patreon", "8154171") == 3
assert TierMapper.get_tier_number("patreon", "8154171") === 3
end
test "maps Patreon 'advancedArchiveSupporter' tier to 3" do
assert TierMapper.get_tier_number("patreon", "8686045") == 3
assert TierMapper.get_tier_number("patreon", "8686045") === 3
end
test "maps Patreon 'quantumSupporter' tier to 4" do
assert TierMapper.get_tier_number("patreon", "8694826") == 4
assert TierMapper.get_tier_number("patreon", "8694826") === 4
end
test "maps Patreon 'sneakyQuantumSupporter' tier to 4" do
assert TierMapper.get_tier_number("patreon", "9560538") == 4
assert TierMapper.get_tier_number("patreon", "9560538") === 4
end
test "maps Patreon 'luberPlusPlus' tier to 5" do
assert TierMapper.get_tier_number("patreon", "8686022") == 5
assert TierMapper.get_tier_number("patreon", "8686022") === 5
end
test "returns 0 for unknown Patreon tier" do
assert TierMapper.get_tier_number("patreon", "99999999") == 0
assert TierMapper.get_tier_number("patreon", "99999999") === 0
end
test "returns 0 for non-Patreon platforms" do
assert TierMapper.get_tier_number("someotherplatform", "10620388") == 0
assert TierMapper.get_tier_number("someotherplatform", "10620388") === 0
end
end
end

View File

@ -1,46 +1,193 @@
defmodule BrightWeb.AuthControllerTest do
use BrightWeb.ConnCase
alias Bright.Users
alias BrightWeb.AuthController
require Logger
@patron_tier_1_required_error "This route is for tier 1 or higher."
@patron_tier_2_required_error "This route is for tier 2 or higher."
@patron_tier_3_required_error "This route is for tier 3 or higher."
describe "patreon auth" do
test "successful auth on existing user signs you in", %{conn: conn} do
test "successful auth on existing user sets the session", %{conn: conn} do
Logger.debug("successful auth on existing user sets the session")
user = Bright.Repo.insert!(%Bright.Users.User{patreon_id: 1234})
conn =
conn
|> assign(:ueberauth_auth, %{provider: :patreon, info: %{nickname: "joeblow"}})
|> assign(:ueberauth_auth, %{
provider: :patreon,
info: %{nickname: "joeblow"},
uid: 1234,
extra: %{raw_info: %{user: %{}}}
})
|> get("/auth/patreon/callback")
assert redirected_to(conn) == Routes.home_path(conn, :show)
assert get_session(conn, "id") == user.id
end
test "successful auth on new user sends you to profile", %{conn: conn} do
Logger.debug("successful auth on new user sends you to profile")
conn =
conn
|> assign(:ueberauth_auth, %{
provider: :patreon,
info: %{name: "Joe Blow", handle: "joeblow"},
uid: 1234
uid: 4321,
extra: %{raw_info: %{user: %{}}}
})
|> get("/auth/patreon/callback")
assert redirected_to(conn) ==
Routes.user_path(conn, :profile, %{
name: "Joe Blow",
handle: "joeblow",
patreon_handle: "joeblow"
})
assert redirected_to(conn) == ~p"/profile"
end
test "failed auth doesn't sign you in", %{conn: conn} do
test "failed auth doesn't set the session", %{conn: conn} do
Logger.debug("failed auth doesn't put a user id in the session")
auth = %Ueberauth.Failure{
errors: [%Ueberauth.Failure.Error{message: "simulated failure"}],
provider: :patreon,
strategy: Ueberauth.Strategy.Patreon
}
conn =
conn
|> assign(:ueberauth_failure, %{})
|> bypass_through(BrightWeb.Router, :browser)
|> assign(:ueberauth_failure, auth)
|> get("/auth/patreon/callback")
|> BrightWeb.AuthController.callback(%{})
assert conn.status == 302
assert Phoenix.Flash.get(conn.assigns.flash, :error) =~ "simulated failure"
assert get_session(conn, :id) == nil
end
test "user stays logged in even if they reload the page", %{conn: conn} do
Logger.debug("user stays logged in even if they reload the page")
user = Bright.Repo.insert!(%Bright.Users.User{patreon_id: 1234})
# Simulate login
conn =
conn
|> assign(:ueberauth_auth, %{
provider: :patreon,
info: %{nickname: "joeblow"},
uid: 1234,
extra: %{raw_info: %{user: %{}}}
})
|> get("/auth/patreon/callback")
assert conn.status == 200
assert get_session(conn, "id") == nil
# Verify user is logged in
assert get_session(conn, "id") == user.id
# Simulate a page reload (new GET request)
conn = get(conn, "/profile")
# Verify the session is still active
assert get_session(conn, "id") == user.id
end
end
describe "require_patron_tier/2" do
test "allows access to admins", %{conn: conn} do
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> get("/")
|> assign(:current_user, %{patron_tier: 0, role: "admin"})
|> AuthController.require_patron_tier(3)
refute conn.halted
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
end
test "allows access when patron tier is higher than required", %{conn: conn} do
# Setup conn with a user that has higher patron tier
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> get("/")
|> assign(:current_user, %{patron_tier: 3})
# Call the plug with a lower tier requirement
|> AuthController.require_patron_tier(2)
# Assert the connection wasn't halted or redirected
refute conn.halted
end
test "allows access when patron tier equals required tier", %{conn: conn} do
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> assign(:current_user, %{patron_tier: 2})
|> AuthController.require_patron_tier(2)
refute conn.halted
end
test "redirects when patron tier is lower than required", %{conn: conn} do
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> assign(:current_user, %{patron_tier: 1})
|> get("/")
|> AuthController.require_patron_tier(2)
assert conn.halted
assert redirected_to(conn) == "/"
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"This route is for tier 2 or higher."
end
test "redirects when user has no patron tier", %{conn: conn} do
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> assign(:current_user, %{})
|> get("/")
|> AuthController.require_patron_tier(2)
assert conn.halted
assert redirected_to(conn) == "/"
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"This route is for tier 2 or higher."
end
@tag :unit
test "redirects when no current user exists", %{conn: conn} do
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> assign(:current_user, %{})
|> get("/")
|> AuthController.require_patron_tier(2)
assert conn.halted
assert redirected_to(conn) == "/"
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"This route is for tier 2 or higher."
end
@tag :unit
test "respects custom return path", %{conn: conn} do
conn =
conn
|> bypass_through(BrightWeb.Router, :browser)
|> assign(:current_user, %{patron_tier: 1})
|> assign(:user_return_to, "/custom/path")
|> get("/")
|> AuthController.require_patron_tier(2)
assert conn.halted
assert redirected_to(conn) == "/custom/path"
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
"This route is for tier 2 or higher."
end
end
end

View File

@ -3,6 +3,6 @@ defmodule BrightWeb.PageControllerTest do
test "GET /", %{conn: conn} do
conn = get(conn, ~p"/")
assert html_response(conn, 200) =~ "Futureporn.net"
assert html_response(conn, 202) =~ "Futureporn.net"
end
end

View File

@ -15,6 +15,8 @@ defmodule BrightWeb.PlatformControllerTest do
end
describe "new platform" do
setup [:create_admin]
test "renders form", %{conn: conn} do
conn = get(conn, ~p"/platforms/new")
assert html_response(conn, 200) =~ "New Platform"
@ -22,6 +24,8 @@ defmodule BrightWeb.PlatformControllerTest do
end
describe "create platform" do
setup [:create_admin]
test "redirects to show when data is valid", %{conn: conn} do
conn = post(conn, ~p"/platforms", platform: @create_attrs)
@ -39,7 +43,7 @@ defmodule BrightWeb.PlatformControllerTest do
end
describe "edit platform" do
setup [:create_platform]
setup [:create_platform, :create_admin]
test "renders form for editing chosen platform", %{conn: conn, platform: platform} do
conn = get(conn, ~p"/platforms/#{platform}/edit")
@ -48,7 +52,7 @@ defmodule BrightWeb.PlatformControllerTest do
end
describe "update platform" do
setup [:create_platform]
setup [:create_platform, :create_admin]
test "redirects when data is valid", %{conn: conn, platform: platform} do
conn = put(conn, ~p"/platforms/#{platform}", platform: @update_attrs)
@ -65,7 +69,7 @@ defmodule BrightWeb.PlatformControllerTest do
end
describe "delete platform" do
setup [:create_platform]
setup [:create_platform, :create_admin]
test "deletes chosen platform", %{conn: conn, platform: platform} do
conn = delete(conn, ~p"/platforms/#{platform}")

View File

@ -2,6 +2,7 @@ defmodule BrightWeb.StreamControllerTest do
use BrightWeb.ConnCase
import Bright.StreamsFixtures
require Logger
@create_attrs %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
@update_attrs %{
@ -19,13 +20,17 @@ defmodule BrightWeb.StreamControllerTest do
end
describe "new stream" do
setup [:create_admin]
test "renders form", %{conn: conn} do
conn = get(conn, ~p"/streams/new")
assert html_response(conn, 200) =~ "New Stream"
end
end
describe "create stream" do
describe "admin create stream" do
setup [:create_admin]
test "redirects to show when data is valid", %{conn: conn} do
conn = post(conn, ~p"/streams", stream: @create_attrs)
@ -38,12 +43,13 @@ defmodule BrightWeb.StreamControllerTest do
test "renders errors when data is invalid", %{conn: conn} do
conn = post(conn, ~p"/streams", stream: @invalid_attrs)
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
assert html_response(conn, 200) =~ "New Stream"
end
end
describe "edit stream" do
setup [:create_stream]
setup [:create_stream, :create_admin]
test "renders form for editing chosen stream", %{conn: conn, stream: stream} do
conn = get(conn, ~p"/streams/#{stream}/edit")
@ -51,8 +57,8 @@ defmodule BrightWeb.StreamControllerTest do
end
end
describe "update stream" do
setup [:create_stream]
describe "admin update stream" do
setup [:create_stream, :create_admin]
test "redirects when data is valid", %{conn: conn, stream: stream} do
conn = put(conn, ~p"/streams/#{stream}", stream: @update_attrs)
@ -64,12 +70,13 @@ defmodule BrightWeb.StreamControllerTest do
test "renders errors when data is invalid", %{conn: conn, stream: stream} do
conn = put(conn, ~p"/streams/#{stream}", stream: @invalid_attrs)
Logger.debug("renders errors when data is invalid. conn=#{inspect(conn)}")
assert html_response(conn, 200) =~ "Edit Stream"
end
end
describe "delete stream" do
setup [:create_stream]
describe "admin delete stream" do
setup [:create_stream, :create_admin]
test "deletes chosen stream", %{conn: conn, stream: stream} do
conn = delete(conn, ~p"/streams/#{stream}")

View File

@ -2,10 +2,11 @@ defmodule BrightWeb.TagControllerTest do
use BrightWeb.ConnCase
import Bright.TagsFixtures
require Logger
@create_attrs %{name: "some name"}
@update_attrs %{name: "some updated name"}
@invalid_attrs %{name: nil}
@invalid_attrs %{name: 3}
describe "index" do
test "lists all tags", %{conn: conn} do
@ -15,6 +16,8 @@ defmodule BrightWeb.TagControllerTest do
end
describe "new tag" do
setup :create_admin
test "renders form", %{conn: conn} do
conn = get(conn, ~p"/tags/new")
assert html_response(conn, 200) =~ "New Tag"
@ -22,6 +25,8 @@ defmodule BrightWeb.TagControllerTest do
end
describe "create tag" do
setup :create_admin
test "redirects to show when data is valid", %{conn: conn} do
conn = post(conn, ~p"/tags", tag: @create_attrs)
@ -39,7 +44,7 @@ defmodule BrightWeb.TagControllerTest do
end
describe "edit tag" do
setup [:create_tag]
setup [:create_tag, :create_admin]
test "renders form for editing chosen tag", %{conn: conn, tag: tag} do
conn = get(conn, ~p"/tags/#{tag}/edit")
@ -48,10 +53,11 @@ defmodule BrightWeb.TagControllerTest do
end
describe "update tag" do
setup [:create_tag]
setup [:create_tag, :create_admin]
test "redirects when data is valid", %{conn: conn, tag: tag} do
conn = put(conn, ~p"/tags/#{tag}", tag: @update_attrs)
Logger.debug("tag update redirect conn=#{inspect(conn)}")
assert redirected_to(conn) == ~p"/tags/#{tag}"
conn = get(conn, ~p"/tags/#{tag}")
@ -65,7 +71,7 @@ defmodule BrightWeb.TagControllerTest do
end
describe "delete tag" do
setup [:create_tag]
setup [:create_tag, :create_admin]
test "deletes chosen tag", %{conn: conn, tag: tag} do
conn = delete(conn, ~p"/tags/#{tag}")

View File

@ -19,12 +19,14 @@ defmodule BrightWeb.TorrentControllerTest do
describe "index" do
test "lists all torrent", %{conn: conn} do
conn = get(conn, ~p"/torrent")
conn = get(conn, ~p"/torrents")
assert html_response(conn, 200) =~ "Listing Torrent"
end
end
describe "new torrent" do
setup [:create_admin]
test "renders form", %{conn: conn} do
conn = get(conn, ~p"/torrents/new")
assert html_response(conn, 200) =~ "New Torrent"
@ -32,8 +34,10 @@ defmodule BrightWeb.TorrentControllerTest do
end
describe "create torrent" do
setup [:create_admin]
test "redirects to show when data is valid", %{conn: conn} do
conn = post(conn, ~p"/torrent", torrent: @create_attrs)
conn = post(conn, ~p"/torrents", torrent: @create_attrs)
assert %{id: id} = redirected_params(conn)
assert redirected_to(conn) == ~p"/torrents/#{id}"
@ -49,7 +53,7 @@ defmodule BrightWeb.TorrentControllerTest do
end
describe "edit torrent" do
setup [:create_torrent]
setup [:create_torrent, :create_admin]
test "renders form for editing chosen torrent", %{conn: conn, torrent: torrent} do
conn = get(conn, ~p"/torrents/#{torrent}/edit")
@ -58,7 +62,7 @@ defmodule BrightWeb.TorrentControllerTest do
end
describe "update torrent" do
setup [:create_torrent]
setup [:create_torrent, :create_admin]
test "redirects when data is valid", %{conn: conn, torrent: torrent} do
conn = put(conn, ~p"/torrents/#{torrent}", torrent: @update_attrs)
@ -75,11 +79,11 @@ defmodule BrightWeb.TorrentControllerTest do
end
describe "delete torrent" do
setup [:create_torrent]
setup [:create_torrent, :create_admin]
test "deletes chosen torrent", %{conn: conn, torrent: torrent} do
conn = delete(conn, ~p"/torrents/#{torrent}")
assert redirected_to(conn) == ~p"/torrent"
assert redirected_to(conn) == ~p"/torrents"
assert_error_sent 404, fn ->
get(conn, ~p"/torrents/#{torrent}")

View File

@ -1,88 +0,0 @@
defmodule BrightWeb.UrlControllerTest do
use BrightWeb.ConnCase
import Bright.UrlsFixtures
alias Bright.Urls.Url
@create_attrs %{
link: "some link",
title: "some title"
}
@update_attrs %{
link: "some updated link",
title: "some updated title"
}
@invalid_attrs %{link: nil, title: nil}
setup %{conn: conn} do
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end
describe "index" do
test "lists all urls", %{conn: conn} do
conn = get(conn, ~p"/api/urls")
assert json_response(conn, 200)["data"] == []
end
end
describe "create url" do
test "renders url when data is valid", %{conn: conn} do
conn = post(conn, ~p"/api/urls", url: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get(conn, ~p"/api/urls/#{id}")
assert %{
"id" => ^id,
"link" => "some link",
"title" => "some title"
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn} do
conn = post(conn, ~p"/api/urls", url: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end
describe "update url" do
setup [:create_url]
test "renders url when data is valid", %{conn: conn, url: %Url{id: id} = url} do
conn = put(conn, ~p"/api/urls/#{url}", url: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get(conn, ~p"/api/urls/#{id}")
assert %{
"id" => ^id,
"link" => "some updated link",
"title" => "some updated title"
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn, url: url} do
conn = put(conn, ~p"/api/urls/#{url}", url: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end
describe "delete url" do
setup [:create_url]
test "deletes chosen url", %{conn: conn, url: url} do
conn = delete(conn, ~p"/api/urls/#{url}")
assert response(conn, 204)
assert_error_sent 404, fn ->
get(conn, ~p"/api/urls/#{url}")
end
end
end
defp create_url(_) do
url = url_fixture()
%{url: url}
end
end

View File

@ -2,14 +2,13 @@ defmodule BrightWeb.VodControllerTest do
use BrightWeb.ConnCase
import Bright.StreamsFixtures
require Logger
@create_attrs %{
s3_cdn_url: "some s3_cdn_url",
s3_upload_id: "some s3_upload_id",
s3_key: "some s3_key",
s3_bucket: "some s3_bucket",
mux_asset_id: "some mux_asset_id",
mux_playback_id: "some mux_playback_id",
torrent: "some torrent"
}
@update_attrs %{
@ -22,6 +21,7 @@ defmodule BrightWeb.VodControllerTest do
torrent: "some updated torrent"
}
@invalid_attrs %{
stream_id: "this is obviously invalid",
s3_cdn_url: nil,
s3_upload_id: nil,
s3_key: nil,
@ -39,6 +39,8 @@ defmodule BrightWeb.VodControllerTest do
end
describe "new vod" do
setup [:create_admin]
test "renders form", %{conn: conn} do
conn = get(conn, ~p"/vods/new")
assert html_response(conn, 200) =~ "New Vod"
@ -46,8 +48,12 @@ defmodule BrightWeb.VodControllerTest do
end
describe "create vod" do
setup [:create_admin]
test "redirects to show when data is valid", %{conn: conn} do
conn = post(conn, ~p"/vods", vod: @create_attrs)
stream = stream_fixture()
conn = post(conn, ~p"/vods", vod: Map.put(@create_attrs, :stream_id, stream.id))
Logger.debug(">>> redirect conn=#{inspect(conn)}")
assert %{id: id} = redirected_params(conn)
assert redirected_to(conn) == ~p"/vods/#{id}"
@ -63,7 +69,7 @@ defmodule BrightWeb.VodControllerTest do
end
describe "edit vod" do
setup [:create_vod]
setup [:create_vod, :create_admin]
test "renders form for editing chosen vod", %{conn: conn, vod: vod} do
conn = get(conn, ~p"/vods/#{vod}/edit")
@ -72,7 +78,7 @@ defmodule BrightWeb.VodControllerTest do
end
describe "update vod" do
setup [:create_vod]
setup [:create_vod, :create_admin]
test "redirects when data is valid", %{conn: conn, vod: vod} do
conn = put(conn, ~p"/vods/#{vod}", vod: @update_attrs)
@ -84,12 +90,21 @@ defmodule BrightWeb.VodControllerTest do
test "renders errors when data is invalid", %{conn: conn, vod: vod} do
conn = put(conn, ~p"/vods/#{vod}", vod: @invalid_attrs)
Logger.debug("renders errors... conn=#{inspect(conn)}")
assert html_response(conn, 200) =~ "Edit Vod"
assert conn.assigns.changeset.valid? == false
# kinda weird that there's no flash error for this
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
# kinda weird that Phoenix gives this a 200 rather than 401
assert html_response(conn, 200) =~ "is invalid"
end
end
describe "delete vod" do
setup [:create_vod]
setup [:create_vod, :create_admin]
test "deletes chosen vod", %{conn: conn, vod: vod} do
conn = delete(conn, ~p"/vods/#{vod}")
@ -102,7 +117,8 @@ defmodule BrightWeb.VodControllerTest do
end
defp create_vod(_) do
vod = vod_fixture()
stream = stream_fixture()
vod = vod_fixture(%{stream_id: stream.id})
%{vod: vod}
end
end

View File

@ -7,10 +7,18 @@ defmodule BrightWeb.VtuberControllerTest do
import Bright.VtubersFixtures
require Logger
@create_attrs %{}
@create_attrs %{
slug: "testvtuber",
display_name: "test",
theme_color: "#813d9c",
image: "https://example.com/image.jpg"
}
@update_attrs %{}
@invalid_attrs %{}
@invalid_attrs %{theme_color: 3}
@only_admins_error "Only admins can do that."
@patron_tier_1_required_error "This route is for tier 1 or higher."
@patron_tier_2_required_error "This route is for tier 2 or higher."
@patron_tier_3_required_error "This route is for tier 3 or higher."
describe "index" do
test "lists all vtubers", %{conn: conn} do
@ -34,12 +42,12 @@ defmodule BrightWeb.VtuberControllerTest do
test "redirects to /vtubers", %{conn: conn} do
conn = get(conn, ~p"/vtubers/new")
assert html_response(conn, 302) =~ "<html>"
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @only_admins_error
assert redirected_to(conn) == ~p"/vtubers"
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
assert redirected_to(conn) == ~p"/"
end
end
describe "create vtuber" do
describe "create vtuber as admin" do
setup [:create_admin]
test "redirects to :show when data is valid", %{conn: conn} do
@ -47,11 +55,12 @@ defmodule BrightWeb.VtuberControllerTest do
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
assert %{id: id} = redirected_params(conn)
assert redirected_to(conn) == ~p"/vtubers/#{id}"
Logger.debug("CREATED conn=#{inspect(conn)}")
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "created successfully."
conn = get(conn, ~p"/vtubers/#{id}")
assert html_response(conn, 200) =~ "Vtuber #{id}"
assert %{id: id} = redirected_params(conn, 302)
assert redirected_to(conn) == ~p"/vtubers/#{id}"
end
test "renders errors when data is invalid", %{conn: conn, user: user} do
@ -60,6 +69,73 @@ defmodule BrightWeb.VtuberControllerTest do
end
end
@tag :onlyme
describe "create vtuber as tier 0" do
setup [:create_patron_tier_0_user]
test "user with patron_tier 0 cannot :new", %{conn: conn} do
conn = get(conn, ~p"/vtubers/new")
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
assert conn.status == 302
assert redirected_to(conn) == ~p"/"
end
test "user with patron_tier 0 cannot :create", %{conn: conn} do
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
assert conn.status == 302
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
assert redirected_to(conn) == ~p"/"
end
end
describe "create vtuber as tier 1" do
setup [:create_patron_tier_1_user]
test "authorized to :new", %{conn: conn} do
conn = get(conn, ~p"/vtubers/new")
assert conn.status == 200
end
test "authorized to :create", %{conn: conn} do
Logger.debug("conn=#{inspect(conn)}")
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "success"
assert conn.status == 302
assert redirected_to(conn) =~ "/vtubers/"
end
end
describe "create vtuber as tier 2" do
setup [:create_patron_tier_2_user]
test "user with patron_tier 2 can :new", %{conn: conn} do
conn = get(conn, ~p"/vtubers/new")
assert conn.status == 200
end
test "user with patron_tier 2 can :create", %{conn: conn} do
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
assert conn.status == 302
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "success"
end
end
describe "create vtuber as tier 3" do
setup [:create_patron_tier_3_user]
test "user with patron_tier 3 can :new", %{conn: conn} do
conn = get(conn, ~p"/vtubers/new")
assert conn.status == 200
end
test "user with patron_tier 3 can :create", %{conn: conn} do
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
assert conn.status == 302
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "created"
end
end
@tag :onlyme
describe "edit vtuber as admin" do
setup [:create_vtuber, :create_admin]
@ -95,22 +171,35 @@ defmodule BrightWeb.VtuberControllerTest do
test "renders errors when data is invalid", %{conn: conn, vtuber: vtuber} do
conn = put(conn, ~p"/vtubers/#{vtuber}", vtuber: @invalid_attrs)
assert html_response(conn, 200) =~ "Edit Vtuber"
Logger.debug(">>> conn=#{inspect(conn)}")
assert conn.assigns.changeset.valid? == false
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
# kinda weird that Phoenix gives this a 200 rather than 401
assert html_response(conn, 200) =~ "is invalid"
end
end
describe "update vtuber as user" do
describe "update vtuber as user (patron_tier 0)" do
setup [:create_vtuber, :create_user]
test "redirects when user is not an admin", %{conn: conn, user: user, vtuber: vtuber} do
# test "redirects when data is valid", %{conn: conn, user: user, vtuber: vtuber} do
# Logger.debug(">>. redirect conn=#{inspect(conn)}, user=#{inspect(user)}")
# conn = put(conn, ~p"/vtubers/#{vtuber}", vtuber: @update_attrs)
# assert redirected_to(conn) == ~p"/vtubers/#{vtuber}"
# conn = get(conn, ~p"/vtubers/#{vtuber}")
# assert html_response(conn, 200)
# end
test "redirects", %{conn: conn, user: user, vtuber: vtuber} do
Logger.debug("hello here is user=#{inspect(user)}")
conn = get(conn, ~p"/vtubers/#{vtuber}")
conn = put(conn, ~p"/vtubers/#{vtuber}", vtuber: @update_attrs)
assert conn.halted
assert redirected_to(conn) == ~p"/vtubers/#{vtuber}"
assert redirected_to(conn) =~ "/"
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @only_admins_error
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
end
end

View File

@ -16,6 +16,7 @@ defmodule BrightWeb.ConnCase do
"""
import Bright.UsersFixtures
require Logger
use ExUnit.CaseTemplate
@ -50,8 +51,32 @@ defmodule BrightWeb.ConnCase do
{:ok, user: user, conn: conn}
end
def create_user(%{conn: conn}) do
user = user_fixture(%{role: "user", patreon_id: 4321})
def create_user(opts) do
create_patron_tier_0_user(opts)
end
def create_patron_tier_0_user(%{conn: conn}) do
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 0})
conn = login_user(conn, user)
{:ok, user: user, conn: conn}
end
def create_patron_tier_1_user(%{conn: conn}) do
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 1})
Logger.debug("user just created. user=#{inspect(user)}")
conn = login_user(conn, user)
Logger.debug("create_patron_tier_1_user just finished with conn=#{inspect(conn)}")
{:ok, user: user, conn: conn}
end
def create_patron_tier_2_user(%{conn: conn}) do
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 2})
conn = login_user(conn, user)
{:ok, user: user, conn: conn}
end
def create_patron_tier_3_user(%{conn: conn}) do
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 3})
conn = login_user(conn, user)
{:ok, user: user, conn: conn}
end