defmodule ToweropsWeb.ReportsLiveTest do use ToweropsWeb.ConnCase, async: true import Phoenix.LiveViewTest import Towerops.OrganizationsFixtures alias ToweropsWeb.ReportsLive setup :register_and_log_in_user setup %{conn: conn, user: user} do org = organization_fixture(user.id) conn = Plug.Conn.put_session(conn, :current_organization_id, org.id) %{conn: conn, org: org, user: user} end describe "mount and render" do test "renders the reports page with empty state", %{conn: conn} do {:ok, _view, html} = live(conn, ~p"/reports") assert html =~ "Reports" end test "show_form / hide_form toggle the form", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/reports") assert render_click(view, "show_form", %{}) assert render_click(view, "hide_form", %{}) end test "save with invalid params re-renders the form", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/reports") _ = render_click(view, "show_form", %{}) html = render_change(view, "save", %{ "report" => %{"name" => "", "type" => "uptime_summary"} }) assert html =~ "Reports" end test "save with valid params creates a report", %{conn: conn} do {:ok, view, _html} = live(conn, ~p"/reports") _ = render_click(view, "show_form", %{}) html = render_submit(form(view, "form, [phx-submit=save]", %{}), %{ "report" => %{ "name" => "Weekly Uptime", "type" => "uptime_summary", "format" => "html", "schedule_type" => "weekly", "scope_target" => "all", "scope_days" => "7", "recipients_text" => "ops@example.com, exec@example.com", "enabled" => "true" } }) # Either flash success or re-render — both reach `Reports.create_report` which # is the goal here for coverage. We only assert the live view didn't crash. assert html =~ "Reports" end end describe "humanize helpers" do test "humanize_type maps known types and falls back" do assert "Uptime Summary" == ReportsLive.humanize_type("uptime_summary") assert "Alert History" == ReportsLive.humanize_type("alert_history") assert "Capacity Trends" == ReportsLive.humanize_type("capacity_trends") assert "RF Link Health" == ReportsLive.humanize_type("rf_link_health") assert "anything" == ReportsLive.humanize_type("anything") end test "humanize_schedule capitalizes the schedule type" do assert "Weekly" == ReportsLive.humanize_schedule(%{"type" => "weekly"}) assert "-" == ReportsLive.humanize_schedule(%{}) end test "format_recipients joins lists" do assert "a@x, b@y" == ReportsLive.format_recipients(["a@x", "b@y"]) assert "-" == ReportsLive.format_recipients(nil) end test "status_badge maps known statuses and falls back" do assert {"Success", classes} = ReportsLive.status_badge("success") assert classes =~ "green" assert {"Failed", _} = ReportsLive.status_badge("failed") assert {"Partial", _} = ReportsLive.status_badge("partial_failure") assert {"Never Run", _} = ReportsLive.status_badge(nil) end end describe "toggle / delete / run_now" do setup %{org: org, user: user} do {:ok, report} = Towerops.Reports.create_report(%{ "organization_id" => org.id, "created_by_id" => user.id, "name" => "Test Report", "report_type" => "uptime_summary", "format" => "csv", "schedule" => %{"type" => "weekly"}, "scope" => %{"target" => "all", "days" => 7}, "recipients" => ["ops@example.com"], "enabled" => true }) %{report: report} end test "toggle flips the enabled flag", %{conn: conn, report: report} do {:ok, view, _html} = live(conn, ~p"/reports") _ = render_click(view, "toggle", %{"id" => report.id}) reloaded = Towerops.Reports.get_report!(report.id) assert reloaded.enabled == false end test "delete removes the report from the list", %{conn: conn, report: report} do {:ok, view, _html} = live(conn, ~p"/reports") html = render_click(view, "delete", %{"id" => report.id}) assert html =~ "Report deleted" assert_raise Ecto.NoResultsError, fn -> Towerops.Reports.get_report!(report.id) end end test "run_now enqueues a ReportWorker job", %{conn: conn, report: report} do {:ok, view, _html} = live(conn, ~p"/reports") html = render_click(view, "run_now", %{"id" => report.id}) assert html =~ "queued for delivery" end end end