@@ -26,6 +26,16 @@ defmodule ReencodarrWeb.FailuresLiveTest do
2626 end
2727 end
2828
29+ defp total_pages_from_html ( html ) do
30+ case Regex . run (
31+ ~r/ of\s *<span class="font-medium text-white">(\d +)<\/ span>/ ,
32+ html
33+ ) do
34+ [ _ , total ] -> String . to_integer ( total )
35+ _ -> nil
36+ end
37+ end
38+
2939 # ---------------------------------------------------------------------------
3040 # Mount / basic render
3141 # ---------------------------------------------------------------------------
@@ -407,5 +417,116 @@ defmodule ReencodarrWeb.FailuresLiveTest do
407417
408418 assert current_page_from_html ( html ) == 1
409419 end
420+
421+ test "shows Page 1 of 2 with 21 failures at per_page 20" , % { conn: conn } do
422+ Enum . each ( 1 .. 21 , fn n ->
423+ { :ok , video } = Fixtures . video_fixture ( % { path: "/media/paginate_#{ n } .mkv" } )
424+ Media . record_video_failure ( video , :encoding , :timeout , message: "p #{ n } " )
425+ end )
426+
427+ { :ok , view , _ } = live ( conn , ~p" /failures" )
428+ html = loaded_html ( view )
429+
430+ assert current_page_from_html ( html ) == 1
431+ assert total_pages_from_html ( html ) == 2
432+ end
433+
434+ test "navigating to page 2 shows the 21st failure" , % { conn: conn } do
435+ { :ok , first_video } = Fixtures . video_fixture ( % { path: "/media/first_on_page_one.mkv" } )
436+ Media . record_video_failure ( first_video , :encoding , :timeout , message: "first" )
437+
438+ Enum . each ( 2 .. 20 , fn n ->
439+ { :ok , v } = Fixtures . video_fixture ( % { path: "/media/filler_#{ n } .mkv" } )
440+ Media . record_video_failure ( v , :encoding , :timeout , message: "filler #{ n } " )
441+ end )
442+
443+ { :ok , last_video } = Fixtures . video_fixture ( % { path: "/media/last_on_page_two.mkv" } )
444+ Media . record_video_failure ( last_video , :encoding , :timeout , message: "last" )
445+
446+ { :ok , view , _ } = live ( conn , ~p" /failures" )
447+ loaded_html ( view )
448+
449+ view
450+ |> element ( "button[phx-click='change_page'][title='Next page']" )
451+ |> render_click ( )
452+
453+ html = render_async ( view )
454+
455+ assert current_page_from_html ( html ) == 2
456+ assert html =~ "last_on_page_two"
457+ refute html =~ "first_on_page_one"
458+ end
459+
460+ test "filter resets page to 1 when on page 2" , % { conn: conn } do
461+ Enum . each ( 1 .. 21 , fn n ->
462+ { :ok , video } = Fixtures . video_fixture ( % { path: "/media/filter_reset_#{ n } .mkv" } )
463+ Media . record_video_failure ( video , :encoding , :timeout , message: "filter #{ n } " )
464+ end )
465+
466+ { :ok , view , _ } = live ( conn , ~p" /failures" )
467+ loaded_html ( view )
468+
469+ view
470+ |> element ( "button[phx-click='change_page'][title='Next page']" )
471+ |> render_click ( )
472+
473+ render_async ( view )
474+
475+ view
476+ |> element ( "button[phx-click='filter_failures'][phx-value-filter='encoding']" )
477+ |> render_click ( )
478+
479+ html = render_async ( view )
480+
481+ assert current_page_from_html ( html ) == 1
482+ end
483+
484+ test "change_page clamps to total_pages when page exceeds total" , % { conn: conn } do
485+ Enum . each ( 1 .. 21 , fn n ->
486+ { :ok , video } = Fixtures . video_fixture ( % { path: "/media/clamp_#{ n } .mkv" } )
487+ Media . record_video_failure ( video , :encoding , :timeout , message: "clamp #{ n } " )
488+ end )
489+
490+ { :ok , view , _ } = live ( conn , ~p" /failures" )
491+ loaded_html ( view )
492+
493+ render_click ( view , "change_page" , % { "page" => "999" } )
494+ html = render_async ( view )
495+
496+ # page should be clamped to total_pages (2), not left at 999
497+ assert current_page_from_html ( html ) == 2
498+ end
499+
500+ test "reset_all_failures resets page to 1" , % { conn: conn } do
501+ Enum . each ( 1 .. 21 , fn n ->
502+ { :ok , video } = Fixtures . video_fixture ( % { path: "/media/reset_page_#{ n } .mkv" } )
503+ Media . record_video_failure ( video , :encoding , :timeout , message: "reset #{ n } " )
504+ end )
505+
506+ { :ok , view , _ } = live ( conn , ~p" /failures" )
507+ loaded_html ( view )
508+
509+ view
510+ |> element ( "button[phx-click='change_page'][title='Next page']" )
511+ |> render_click ( )
512+
513+ render_async ( view )
514+
515+ view
516+ |> element ( "button[phx-click='reset_all_failures']" )
517+ |> render_click ( )
518+
519+ render_async ( view )
520+
521+ # Add a new failure after the reset — it will land on page 1
522+ { :ok , new_video } = Fixtures . video_fixture ( % { path: "/media/new_after_reset.mkv" } )
523+ Media . record_video_failure ( new_video , :encoding , :timeout , message: "after reset" )
524+
525+ send ( view . pid , :update_failures_data )
526+ html = render_async ( view )
527+
528+ # If page was not reset to 1, we'd be on page 2 and the new failure would be invisible
529+ assert html =~ "new_after_reset"
530+ end
410531 end
411532end
0 commit comments