towerops/test/towerops_web/live/device_live_nested/show_test.exs
Graham McIntire cd19e6626c fix(tests): replace Process.sleep with event-driven sync patterns
Replaced unbounded Process.sleep calls across the test suite with
event-driven alternatives: :sys.get_state sync barriers, assert_receive
with bounded timeouts, and Process.send_after + assert_receive.

Largest improvements:
- storm_detector_test: 120-150ms sleeps removed, uses assert_receive
- deferred_discovery_test: 500ms -> 50ms (timeout test simulation)
- event_logger_test: polling loop replaced with :sys.get_state barrier
- tcp_executor_test: 2000ms sleep replaced with bounded recv timeout
- rate_limit_test: sleeps replaced with send_after + assert_receive
- Various 5-50ms sleeps removed from live_view tests
- Unused require Logger removed from 2 test files
2026-06-02 15:16:53 -05:00

168 lines
4.3 KiB
Elixir

defmodule ToweropsWeb.DeviceLive.NestedShowTest do
use ToweropsWeb.ConnCase
import Phoenix.LiveViewTest
alias Towerops.Monitoring
alias Towerops.Organizations
alias Towerops.Sites
setup :register_and_log_in_user
setup %{user: user} do
{:ok, organization} = Organizations.create_organization(%{name: "Test Org"}, user.id)
{:ok, site} =
Sites.create_site(%{
name: "Test Site",
organization_id: organization.id
})
{:ok, device} =
Towerops.Devices.create_device(%{
name: "Test Router",
ip_address: "192.168.1.1",
site_id: site.id,
organization_id: organization.id
})
%{organization: organization, site: site, device: device}
end
describe "Show" do
test "displays device information", %{conn: conn, device: device, organization: _org} do
{:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
assert html =~ device.name
assert html =~ device.ip_address
end
test "displays overview tab by default", %{conn: conn, device: device, organization: _org} do
{:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
assert html =~ "Overview"
end
test "displays metrics when device has checks", %{
conn: conn,
device: device,
organization: _org
} do
# Create some checks
Monitoring.create_check(%{
device_id: device.id,
status: :success,
response_time_ms: 10,
checked_at: DateTime.utc_now()
})
Monitoring.create_check(%{
device_id: device.id,
status: :success,
response_time_ms: 15,
checked_at: DateTime.utc_now()
})
Monitoring.create_check(%{
device_id: device.id,
status: :failure,
response_time_ms: nil,
checked_at: DateTime.utc_now()
})
{:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
assert html =~ "Device Information"
end
test "displays empty state when no checks exist", %{
conn: conn,
device: device,
organization: _org
} do
{:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
assert html =~ device.name
end
test "refreshes data periodically", %{conn: conn, device: device, organization: _org} do
{:ok, view, _html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
# Trigger a status change
Monitoring.create_check(%{
device_id: device.id,
status: :failure,
response_time_ms: nil,
checked_at: DateTime.utc_now()
})
# Send refresh message
send(view.pid, :refresh_data)
# render processes the async message — it may raise on the first call
# if the LiveView hasn't finished processing the send, so retry once.
try do
render(view)
rescue
_ -> render(view)
end
assert render(view)
end
test "requires authentication", %{device: device, organization: _org} do
conn = build_conn()
{:error, redirect} = live(conn, ~p"/devices/#{device.id}")
assert {:redirect, %{to: path}} = redirect
assert path == ~p"/users/log-in"
end
test "handles equipment_status_changed event", %{
conn: conn,
device: device,
organization: _org
} do
{:ok, view, _html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
# Simulate status change event
send(view.pid, {:device_status_changed, device.id, :up, 25})
# render processes the async message
try do
render(view)
rescue
_ -> render(view)
end
assert render(view)
end
test "handles discovery_completed event", %{
conn: conn,
device: device,
organization: _org
} do
{:ok, view, _html} = live(conn, ~p"/devices/#{device.id}?tab=overview")
# Simulate discovery completed event
send(view.pid, {:discovery_completed, device.id})
# render processes the async message
html =
try do
render(view)
rescue
_ -> render(view)
end
assert html =~ "Discovery completed"
end
test "switches to different tabs", %{conn: conn, device: device, organization: _org} do
{:ok, _view, html} = live(conn, ~p"/devices/#{device.id}?tab=events")
assert html =~ device.name
end
end
end