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
80 lines
2.4 KiB
Elixir
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
|