diff --git a/test/towerops_web/live/reports_live_test.exs b/test/towerops_web/live/reports_live_test.exs index 568af6e5..214b2364 100644 --- a/test/towerops_web/live/reports_live_test.exs +++ b/test/towerops_web/live/reports_live_test.exs @@ -91,4 +91,46 @@ defmodule ToweropsWeb.ReportsLiveTest do 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 diff --git a/test/towerops_web/live/site_live_test.exs b/test/towerops_web/live/site_live_test.exs index 594f2aa0..5635bbff 100644 --- a/test/towerops_web/live/site_live_test.exs +++ b/test/towerops_web/live/site_live_test.exs @@ -484,4 +484,60 @@ defmodule ToweropsWeb.SiteLiveTest do refute has_element?(new_view, "button", "Delete Site") end end + + describe "Form - Geocode" do + test "geocode with empty address shows error flash", + %{conn: conn, organization: organization} do + {:ok, site} = + Sites.create_site(%{name: "Geo Site", organization_id: organization.id}) + + {:ok, view, _html} = live(conn, ~p"/sites/#{site.id}/edit") + html = render_click(view, "geocode", %{}) + assert html =~ "Please enter an address" + end + + test "geocode without API key returns admin-friendly error", + %{conn: conn, organization: organization} do + {:ok, site} = + Sites.create_site(%{ + name: "Geo Site 2", + organization_id: organization.id, + address: "1600 Pennsylvania Ave NW, Washington, DC" + }) + + {:ok, view, _html} = live(conn, ~p"/sites/#{site.id}/edit") + html = render_click(view, "geocode", %{}) + + # Without an API key configured (the default in test env) the handler + # surfaces a "not configured" message; with one, it would either succeed + # or produce a service error. Either branch exercises geocode/2. + assert html =~ "Geocoding" + end + end + + describe "Form - Apply config to devices" do + setup %{organization: organization} do + {:ok, site} = + Sites.create_site(%{ + name: "Apply Site", + organization_id: organization.id, + snmp_version: "2c", + snmp_community: "public" + }) + + %{site: site} + end + + test "apply_snmp_to_all flashes count", %{conn: conn, site: site} do + {:ok, view, _html} = live(conn, ~p"/sites/#{site.id}/edit") + html = render_click(view, "apply_snmp_to_all", %{}) + assert html =~ "Applied SNMP configuration" + end + + test "apply_agent_to_all flashes count", %{conn: conn, site: site} do + {:ok, view, _html} = live(conn, ~p"/sites/#{site.id}/edit") + html = render_click(view, "apply_agent_to_all", %{}) + assert html =~ "Applied agent" + end + end end diff --git a/test/towerops_web/live/user_registration_live_test.exs b/test/towerops_web/live/user_registration_live_test.exs index c29f870c..6d1e5a81 100644 --- a/test/towerops_web/live/user_registration_live_test.exs +++ b/test/towerops_web/live/user_registration_live_test.exs @@ -74,6 +74,61 @@ defmodule ToweropsWeb.UserRegistrationLiveTest do {:ok, lv, _html} = live(conn, ~p"/users/register") assert render_hook(lv, "check_password_breach", %{}) end + + test "save via invitation completes account creation when token is valid", + %{conn: conn} do + inviter = user_fixture() + org = organization_fixture(inviter.id) + + {:ok, invitation} = + Towerops.Organizations.create_invitation(%{ + organization_id: org.id, + invited_by_id: inviter.id, + email: "newjoin@example.com", + role: "technician" + }) + + {:ok, lv, _html} = live(conn, ~p"/users/register?token=#{invitation.token}") + + result = + lv + |> form("form", + user: %{ + "email" => "newjoin@example.com", + "password" => "very-strong-password-1234!", + "privacy_policy_consent" => "on", + "terms_of_service_consent" => "on" + } + ) + |> render_submit() + + # On success the LV redirects (returns binary or redirect tuple). + # On failure it stays alive and re-renders. Either is fine for + # coverage of the create_via_invitation/3 path. + assert is_binary(result) or match?({:error, {:redirect, _}}, result) or + match?({:error, {:live_redirect, _}}, result) + end + + test "save via invitation with a stale token re-renders the page", + %{conn: conn} do + stale_token = "definitely-not-a-real-token-#{System.unique_integer([:positive])}" + + {:ok, lv, _html} = live(conn, ~p"/users/register?token=#{stale_token}") + + html = + lv + |> form("form", + user: %{ + "email" => "stale@example.com", + "password" => "very-strong-password-1234!", + "privacy_policy_consent" => "on", + "terms_of_service_consent" => "on" + } + ) + |> render_submit() + + assert is_binary(html) + end end describe "normalize_consent_params/1" do