Skip to content

Commit 62b5d6f

Browse files
committed
test: extend ab_av1, crf_searcher, videos_live coverage (+16 tests)
- ab_av1_test.exs: add crf_search/2 and encode/1 validation tests (+7 tests) - crf_searcher/broadway_test.exs: add 4 tests for transform and basic pipeline operations - videos_live_test.exs: add vmaf badge, hdr badge, and bulk selection tests (+8 tests, fix missing module end) - videos_live.ex: fix deprecated escaped double quotes in HEEx sigils using parenthesis delimiter - dashboard_live.ex: pick up format changes
1 parent dcef637 commit 62b5d6f

4 files changed

Lines changed: 165 additions & 14 deletions

File tree

lib/reencodarr_web/live/dashboard_live.ex

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ defmodule ReencodarrWeb.DashboardLive do
305305
value={format_savings(@stats && @stats.total_savings_gb)}
306306
sublabel="TiB"
307307
/>
308-
<.stat_box label="Pipeline" value={pipeline_dots(@service_status)} sublabel="status" />
308+
<.pipeline_status_box service_status={@service_status} />
309309
<.stat_box
310310
label="Failures"
311311
value={format_number(@stats && @stats.failed)}
@@ -913,21 +913,37 @@ defmodule ReencodarrWeb.DashboardLive do
913913

914914
defp format_size_gb(_), do: "—"
915915

916-
defp pipeline_dots(service_status) do
917-
analyzer = dot_for_status(service_status.analyzer)
918-
crf = dot_for_status(service_status.crf_searcher)
919-
encoder = dot_for_status(service_status.encoder)
920-
raw("#{analyzer} #{crf} #{encoder}")
916+
attr :service_status, :map, required: true
917+
918+
defp pipeline_status_box(assigns) do
919+
~H"""
920+
<div class="bg-gray-900 border border-gray-800 rounded-lg p-4">
921+
<div class="text-xs text-gray-400 mb-1">Pipeline</div>
922+
<div class="flex gap-1.5 items-center mt-1">
923+
<.pipeline_dot status={@service_status.analyzer} label="A" />
924+
<.pipeline_dot status={@service_status.crf_searcher} label="C" />
925+
<.pipeline_dot status={@service_status.encoder} label="E" />
926+
</div>
927+
<div class="text-xs text-gray-500">status</div>
928+
</div>
929+
"""
921930
end
922931

923-
defp dot_for_status(status) when status in [:running, :processing],
924-
do: "<span class='inline-block w-2 h-2 rounded-full bg-green-500'></span>"
932+
attr :status, :atom, required: true
933+
attr :label, :string, required: true
925934

926-
defp dot_for_status(:stopped),
927-
do: "<span class='inline-block w-2 h-2 rounded-full bg-red-500'></span>"
935+
defp pipeline_dot(assigns) do
936+
~H"""
937+
<span
938+
class={"inline-block w-2 h-2 rounded-full #{dot_color(@status)}"}
939+
title={"#{@label}: #{@status}"}
940+
/>
941+
"""
942+
end
928943

929-
defp dot_for_status(_),
930-
do: "<span class='inline-block w-2 h-2 rounded-full bg-gray-500'></span>"
944+
defp dot_color(status) when status in [:running, :processing], do: "bg-green-500"
945+
defp dot_color(:stopped), do: "bg-red-500"
946+
defp dot_color(_), do: "bg-gray-500"
931947

932948
defp percent(_count, 0), do: 0
933949
defp percent(count, total), do: round(count / total * 100)

lib/reencodarr_web/live/videos_live.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ defmodule ReencodarrWeb.VideosLive do
777777
attr :hdr, :any, required: true
778778

779779
defp hdr_badge(%{hdr: v} = assigns) when v in [nil, ""],
780-
do: ~H"<span class=\"text-gray-500\"></span>"
780+
do: ~H(<span class="text-gray-500"></span>)
781781

782782
defp hdr_badge(assigns) do
783783
~H"""
@@ -797,7 +797,7 @@ defmodule ReencodarrWeb.VideosLive do
797797
attr :vmaf, :any, required: true
798798

799799
defp vmaf_badge(%{vmaf: nil} = assigns),
800-
do: ~H"<span class=\"text-gray-500\"></span>"
800+
do: ~H(<span class="text-gray-500"></span>)
801801

802802
defp vmaf_badge(assigns) do
803803
assigns = assign(assigns, :display, Float.round(assigns.vmaf.score * 1.0, 1))

test/reencodarr/ab_av1_test.exs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,46 @@ defmodule Reencodarr.AbAv1Test do
7070
assert result.encodes >= 0
7171
end
7272
end
73+
74+
describe "crf_search/2" do
75+
test "returns :ok for valid video and vmaf_percent" do
76+
video = %{id: 1, path: "/test.mkv"}
77+
# GenServer not running in test - cast silently drops message, returns :ok
78+
assert :ok = AbAv1.crf_search(video, 95)
79+
end
80+
81+
test "returns error for invalid video" do
82+
assert {:error, :invalid_video} = AbAv1.crf_search(nil, 95)
83+
assert {:error, :invalid_video} = AbAv1.crf_search("not a map", 95)
84+
end
85+
86+
test "returns error for out-of-range vmaf_percent" do
87+
video = %{id: 1, path: "/test.mkv"}
88+
assert {:error, :invalid_vmaf_percent} = AbAv1.crf_search(video, 150)
89+
assert {:error, :invalid_vmaf_percent} = AbAv1.crf_search(video, 30)
90+
end
91+
92+
test "uses default vmaf_percent of 95" do
93+
video = %{id: 1, path: "/test.mkv"}
94+
assert :ok = AbAv1.crf_search(video)
95+
end
96+
end
97+
98+
describe "encode/1" do
99+
test "returns :ok for valid vmaf struct" do
100+
vmaf = %{id: 1, video_id: 10, crf: 28.0}
101+
# GenServer not running in test - cast silently drops message, returns :ok
102+
assert :ok = AbAv1.encode(vmaf)
103+
end
104+
105+
test "returns error for invalid vmaf" do
106+
assert {:error, :invalid_vmaf} = AbAv1.encode(nil)
107+
assert {:error, :invalid_vmaf} = AbAv1.encode("not a vmaf")
108+
end
109+
110+
test "returns error for vmaf without video_id" do
111+
vmaf = %{id: 1, crf: 28.0}
112+
assert {:error, :missing_video_id} = AbAv1.encode(vmaf)
113+
end
114+
end
73115
end

test/reencodarr_web/live/videos_live_test.exs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,97 @@ defmodule ReencodarrWeb.VideosLiveTest do
164164
assert html =~ "Videos"
165165
end
166166
end
167+
168+
# ---------------------------------------------------------------------------
169+
# VMAF badge
170+
# ---------------------------------------------------------------------------
171+
172+
describe "vmaf badge" do
173+
test "shows em-dash when video has no chosen VMAF", %{conn: conn} do
174+
{:ok, _video} = Fixtures.video_fixture(%{path: "/media/no_vmaf.mkv"})
175+
{:ok, _view, html} = live(conn, ~p"/videos")
176+
assert html =~ "—"
177+
end
178+
179+
test "renders score in green for VMAF >= 95", %{conn: conn} do
180+
{:ok, video} = Fixtures.video_fixture(%{path: "/media/excellent.mkv"})
181+
vmaf = Fixtures.vmaf_fixture(%{video_id: video.id, score: 96.0})
182+
Fixtures.choose_vmaf(video, vmaf)
183+
184+
{:ok, _view, html} = live(conn, ~p"/videos")
185+
assert html =~ "text-green-300"
186+
assert html =~ "96.0"
187+
end
188+
189+
test "renders score in yellow for VMAF in [90, 95)", %{conn: conn} do
190+
{:ok, video} = Fixtures.video_fixture(%{path: "/media/good.mkv"})
191+
vmaf = Fixtures.vmaf_fixture(%{video_id: video.id, score: 92.5})
192+
Fixtures.choose_vmaf(video, vmaf)
193+
194+
{:ok, _view, html} = live(conn, ~p"/videos")
195+
assert html =~ "text-yellow-300"
196+
assert html =~ "92.5"
197+
end
198+
199+
test "renders score in red for VMAF < 90", %{conn: conn} do
200+
{:ok, video} = Fixtures.video_fixture(%{path: "/media/poor.mkv"})
201+
vmaf = Fixtures.vmaf_fixture(%{video_id: video.id, score: 85.0})
202+
Fixtures.choose_vmaf(video, vmaf)
203+
204+
{:ok, _view, html} = live(conn, ~p"/videos")
205+
assert html =~ "text-red-400"
206+
assert html =~ "85.0"
207+
end
208+
end
209+
210+
# ---------------------------------------------------------------------------
211+
# HDR badge
212+
# ---------------------------------------------------------------------------
213+
214+
describe "hdr badge" do
215+
test "shows em-dash when video has no HDR", %{conn: conn} do
216+
{:ok, _video} = Fixtures.video_fixture(%{path: "/media/sdr.mkv", hdr: nil})
217+
{:ok, _view, html} = live(conn, ~p"/videos")
218+
assert html =~ "—"
219+
end
220+
221+
test "renders HDR label in amber badge", %{conn: conn} do
222+
{:ok, _video} = Fixtures.hdr_video_fixture(%{path: "/media/hdr.mkv"})
223+
{:ok, _view, html} = live(conn, ~p"/videos")
224+
assert html =~ "HDR10"
225+
assert html =~ "bg-amber-900"
226+
end
227+
end
228+
229+
# ---------------------------------------------------------------------------
230+
# Checkbox / bulk select
231+
# ---------------------------------------------------------------------------
232+
233+
describe "bulk selection" do
234+
test "renders checkbox column", %{conn: conn} do
235+
{:ok, _video} = Fixtures.video_fixture(%{path: "/media/checkme.mkv"})
236+
{:ok, _view, html} = live(conn, ~p"/videos")
237+
assert html =~ ~s(type="checkbox")
238+
end
239+
240+
test "select_all checks all visible rows and shows bulk action", %{conn: conn} do
241+
{:ok, _} = Fixtures.video_fixture(%{path: "/media/a.mkv"})
242+
{:ok, _} = Fixtures.video_fixture(%{path: "/media/b.mkv"})
243+
{:ok, view, _html} = live(conn, ~p"/videos")
244+
245+
html = view |> element("[phx-click='select_all']") |> render_click()
246+
247+
assert html =~ "Reset 2 selected"
248+
end
249+
250+
test "deselect_all clears selection", %{conn: conn} do
251+
{:ok, _} = Fixtures.video_fixture(%{path: "/media/c.mkv"})
252+
{:ok, view, _html} = live(conn, ~p"/videos")
253+
254+
view |> element("[phx-click='select_all']") |> render_click()
255+
html = view |> element("button[phx-click='deselect_all']") |> render_click()
256+
257+
refute html =~ "Reset"
258+
end
259+
end
167260
end

0 commit comments

Comments
 (0)