defmodule BerrypodWeb.Admin.MediaTest do use BerrypodWeb.ConnCase, async: false import Phoenix.LiveViewTest import Berrypod.AccountsFixtures alias Berrypod.Media @svg_attrs %{ image_type: "logo", filename: "logo.svg", content_type: "image/svg+xml", file_size: 512, data: "" } @raster_attrs %{ image_type: "media", filename: "banner.png", content_type: "image/png", file_size: 1024, data: <<137, 80, 78, 71>>, alt: "A banner image" } setup do user = user_fixture() %{user: user} end describe "media library page" do setup %{conn: conn, user: user} do %{conn: log_in_user(conn, user)} end test "renders media library for admin", %{conn: conn} do {:ok, _view, html} = live(conn, ~p"/admin/media") assert html =~ "Media" assert html =~ "Upload image" end test "shows images in grid", %{conn: conn} do {:ok, _} = Media.upload_image(@svg_attrs) {:ok, _} = Media.upload_image(@raster_attrs) {:ok, _view, html} = live(conn, ~p"/admin/media") assert html =~ "logo.svg" assert html =~ "banner.png" end test "filters by type", %{conn: conn} do {:ok, _} = Media.upload_image(@svg_attrs) {:ok, _} = Media.upload_image(@raster_attrs) {:ok, view, _html} = live(conn, ~p"/admin/media") html = render_change(view, "filter_type", %{"type" => "media"}) assert html =~ "banner.png" refute html =~ "logo.svg" end test "filters by search", %{conn: conn} do {:ok, _} = Media.upload_image(@svg_attrs) {:ok, _} = Media.upload_image(@raster_attrs) {:ok, view, _html} = live(conn, ~p"/admin/media") html = render_keyup(view, "filter_search", %{"value" => "banner"}) assert html =~ "banner.png" refute html =~ "logo.svg" end test "selects image and shows detail panel", %{conn: conn} do {:ok, image} = Media.upload_image(@raster_attrs) {:ok, view, _html} = live(conn, ~p"/admin/media") html = render_click(view, "select_image", %{"id" => image.id}) assert html =~ "Image details" assert html =~ "banner.png" assert html =~ "Alt text" end test "updates metadata", %{conn: conn} do {:ok, image} = Media.upload_image(@raster_attrs) {:ok, view, _html} = live(conn, ~p"/admin/media") render_click(view, "select_image", %{"id" => image.id}) render_submit(view, "update_metadata", %{ "metadata" => %{"alt" => "Updated alt", "caption" => "New caption", "tags" => "hero"} }) updated = Media.get_image(image.id) assert updated.alt == "Updated alt" assert updated.caption == "New caption" assert updated.tags == "hero" end test "deletes orphaned image", %{conn: conn} do {:ok, image} = Media.upload_image(@raster_attrs) {:ok, view, _html} = live(conn, ~p"/admin/media") render_click(view, "select_image", %{"id" => image.id}) render_click(view, "confirm_delete") html = render_click(view, "delete_image") assert html =~ "Image deleted" assert Media.get_image(image.id) == nil end test "refuses to delete in-use image", %{conn: conn} do {:ok, image} = Media.upload_image(@svg_attrs) Berrypod.Settings.update_theme_settings(%{logo_image_id: image.id}) {:ok, view, _html} = live(conn, ~p"/admin/media") render_click(view, "select_image", %{"id" => image.id}) render_click(view, "confirm_delete") html = render_click(view, "delete_image") assert html =~ "Cannot delete" assert Media.get_image(image.id) != nil end test "orphan filter shows only unreferenced images", %{conn: conn} do {:ok, logo} = Media.upload_image(@svg_attrs) {:ok, _orphan} = Media.upload_image(@raster_attrs) Berrypod.Settings.update_theme_settings(%{logo_image_id: logo.id}) {:ok, view, _html} = live(conn, ~p"/admin/media") html = render_click(view, "toggle_orphans") assert html =~ "banner.png" refute html =~ "logo.svg" end test "shows usage info for referenced image", %{conn: conn} do {:ok, image} = Media.upload_image(@svg_attrs) Berrypod.Settings.update_theme_settings(%{logo_image_id: image.id}) {:ok, view, _html} = live(conn, ~p"/admin/media") html = render_click(view, "select_image", %{"id" => image.id}) assert html =~ "Used in" assert html =~ "Logo" end test "shows no-alt-text warning for images without alt", %{conn: conn} do {:ok, _} = Media.upload_image(Map.delete(@raster_attrs, :alt)) {:ok, _view, html} = live(conn, ~p"/admin/media") assert html =~ "No alt text" end end end