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) # Poll for processing with early exit (max 50ms) Enum.reduce_while(1..5, nil, fn _, _ -> try do {:halt, render(view)} rescue _ -> Process.sleep(5) {:cont, nil} end end) # View should still be alive 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}) # Poll for processing with early exit (max 50ms) Enum.reduce_while(1..5, nil, fn _, _ -> try do {:halt, render(view)} rescue _ -> Process.sleep(5) {:cont, nil} end end) # View should still be alive and render 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}) # Poll for processing with early exit (max 50ms) html = Enum.reduce_while(1..5, nil, fn _, _ -> try do {:halt, render(view)} rescue _ -> Process.sleep(5) {:cont, nil} end end) || render(view) 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