towerops/test/towerops_web/live/mobile_qr_live_test.exs
Graham McIntire 3a408a8dc1 Security hardening + performance fixes across codebase
CRITICAL:
- Membership: remove :role/:org_id/:user_id from mass-assignment cast; use explicit create_changeset/4 and role_update_changeset/2
- GraphQL member resolver: add authorize_invite/3 checking admin/owner role and role hierarchy
- REST invitations controller: add auth check for invite creation

HIGH:
- ApiToken: remove :organization_id/:user_id from cast; use explicit create_changeset/4

MEDIUM:
- Move 8 LiveView Ecto queries into context modules (Admin, Alerts, Coverages, OnCall, Snmp)
- Replace Process.put/Process.get with socket assigns for unresolved_alert_count (user_auth + layouts + 50 templates)
- Add batch get_utilization_for_interfaces/1 to eliminate N+1 capacity queries in device show
- Replace Process.sleep with Process.monitor/assert_receive or Process.send_after in 5 test files

LOW:
- Add handle_params/3 to UserResetPasswordLive, UserRegistrationLive, StatusPageLive
- Remove redundant Repo.preload calls; add preloads to list_site_devices/1
- Fix @impl annotations and credo nesting warnings
2026-06-21 17:40:50 -05:00

80 lines
2.4 KiB
Elixir

defmodule ToweropsWeb.MobileQRLiveTest do
use ToweropsWeb.ConnCase, async: true
import Ecto.Query
import Phoenix.LiveViewTest
alias Towerops.MobileSessions.QRLoginToken
setup :register_and_log_in_user
describe "mount" do
test "renders QR code display", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/mobile/qr-login")
assert html =~ "Link Mobile App"
end
test "shows QR code image", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/mobile/qr-login")
assert has_element?(view, "img")
end
test "shows waiting message", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/mobile/qr-login")
assert html =~ "Waiting for mobile app to scan"
end
test "shows how-to instructions", %{conn: conn} do
{:ok, _view, html} = live(conn, ~p"/mobile/qr-login")
assert html =~ "How to link your phone"
end
end
describe "handle_info" do
test "catch-all handles unexpected messages without crashing", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/mobile/qr-login")
send(view.pid, :unexpected_message)
assert render(view) =~ "Link Mobile App"
end
test ":check_completion still pending — does not crash and re-arms timer", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/mobile/qr-login")
send(view.pid, :check_completion)
# Trigger a render to verify view is still alive after the handler runs
assert render(view) =~ "Link Mobile App"
end
test ":check_completion completes login when matching mobile session exists", %{
conn: conn,
user: user
} do
{:ok, view, _html} = live(conn, ~p"/mobile/qr-login")
qr_token =
Towerops.Repo.one!(
from q in QRLoginToken,
where: q.user_id == ^user.id,
order_by: [desc: q.inserted_at],
limit: 1
)
{:ok, _mobile_session} =
Towerops.MobileSessions.complete_qr_login(qr_token.token, %{
device_name: "iPhone Test",
os: "iOS",
os_version: "17.0",
ip_address: "127.0.0.1",
user_agent: "Test Agent"
})
# The completed session is found via check_qr_login_completed
assert Towerops.MobileSessions.check_qr_login_completed(qr_token.token)
send(view.pid, :check_completion)
html = render(view)
# The template shows the QR page until @completed switches
assert html =~ "Link Mobile App"
end
end
end