defmodule ToweropsWeb.EquipmentLiveTest do use ToweropsWeb.ConnCase import Phoenix.LiveViewTest setup :register_and_log_in_user setup %{user: user} do {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id) {:ok, site} = Towerops.Sites.create_site(%{ name: "Test Site", organization_id: organization.id }) %{organization: organization, site: site} end describe "Index" do test "lists all equipment", %{conn: conn, organization: organization, site: site} do {:ok, equipment} = Towerops.Equipment.create_equipment(%{ name: "Router 1", ip_address: "192.168.1.1", description: "Main router", site_id: site.id }) {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment") assert html =~ "Equipment" assert html =~ equipment.name assert html =~ "192.168.1.1" end test "displays empty state when no equipment", %{conn: conn, organization: organization} do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment") assert html =~ "No equipment" end test "has link to add new equipment", %{conn: conn, organization: organization} do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment") assert html =~ "New Equipment" end test "requires authentication", %{organization: organization} do conn = build_conn() {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/equipment") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" end end describe "Show" do setup %{site: site} do {:ok, equipment} = Towerops.Equipment.create_equipment(%{ name: "Router 1", ip_address: "192.168.1.1", description: "Main router", site_id: site.id, monitoring_enabled: true, check_interval_seconds: 300 }) %{equipment: equipment} end test "displays equipment details", %{ conn: conn, organization: organization, equipment: equipment } do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert html =~ equipment.name assert html =~ "192.168.1.1" assert html =~ "Status" assert html =~ "Uptime" end test "displays monitoring metrics", %{ conn: conn, organization: organization, equipment: equipment } do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert html =~ "Status" assert html =~ "Uptime" assert html =~ "Avg Response" end test "displays dashboard widgets", %{conn: conn, organization: organization, equipment: equipment} do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert html =~ "Response Time" assert html =~ "Availability" end test "displays recent checks", %{ conn: conn, organization: organization, equipment: equipment } do # Create a check {:ok, _check} = Towerops.Monitoring.create_check(%{ equipment_id: equipment.id, status: :success, response_time_ms: 10, checked_at: DateTime.utc_now() }) {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert html =~ "Recent Checks" assert html =~ "10ms" end test "displays empty state when no checks", %{ conn: conn, organization: organization, equipment: equipment } do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert html =~ "No monitoring checks yet" end test "triggers manual check", %{ conn: conn, organization: organization, equipment: equipment } do {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") html = view |> element("button", "Check Now") |> render_click() assert html =~ "Check triggered" end test "deletes equipment", %{conn: conn, organization: organization, equipment: equipment} do {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") {:ok, _, html} = view |> element("button", "Delete") |> render_click() |> follow_redirect(conn, ~p"/orgs/#{organization.slug}/equipment") assert html =~ "Equipment deleted successfully" end test "requires authentication", %{organization: organization, equipment: equipment} do conn = build_conn() {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" end end describe "New" do test "renders new equipment form", %{conn: conn, organization: organization} do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new") assert html =~ "New Equipment" assert html =~ "Add new equipment to monitor" end test "creates new equipment", %{conn: conn, organization: organization, site: site} do {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new") view |> form("#equipment-form", equipment: %{ name: "New Router", ip_address: "192.168.1.100", site_id: site.id, description: "Test router", monitoring_enabled: true, check_interval_seconds: 300, snmp_enabled: true, snmp_version: "2c", snmp_community: "public", snmp_port: 161 } ) |> render_submit() # Verify equipment was created equipment_list = Towerops.Equipment.list_organization_equipment(organization.id) assert length(equipment_list) > 0 new_equipment = Enum.find(equipment_list, &(&1.name == "New Router")) assert new_equipment assert new_equipment.ip_address == "192.168.1.100" end test "validates required fields", %{conn: conn, organization: organization} do {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new") html = view |> form("#equipment-form", equipment: %{name: "", ip_address: ""}) |> render_submit() assert html =~ "can't be blank" end test "validates IP address format", %{conn: conn, organization: organization, site: site} do {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new") html = view |> form("#equipment-form", equipment: %{ name: "Router", ip_address: "invalid-ip", site_id: site.id } ) |> render_submit() assert html =~ "must be a valid IPv4 or IPv6 address" end test "pre-selects site from query param", %{ conn: conn, organization: organization, site: site } do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new?site_id=#{site.id}") assert html =~ "New Equipment" end test "requires authentication", %{organization: organization} do conn = build_conn() {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" end end describe "Edit" do setup %{site: site} do {:ok, equipment} = Towerops.Equipment.create_equipment(%{ name: "Router 1", ip_address: "192.168.1.1", site_id: site.id }) %{equipment: equipment} end test "renders edit form", %{conn: conn, organization: organization, equipment: equipment} do {:ok, _view, html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}/edit") assert html =~ "Edit Equipment" assert html =~ "Update equipment details" end test "updates equipment", %{conn: conn, organization: organization, equipment: equipment} do {:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}/edit") {:ok, _, html} = view |> form("#equipment-form", equipment: %{ name: "Updated Router", ip_address: "192.168.1.2" } ) |> render_submit() |> follow_redirect(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}") assert html =~ "Equipment updated successfully" assert html =~ "Updated Router" end test "requires authentication", %{organization: organization, equipment: equipment} do conn = build_conn() {:error, redirect} = live(conn, ~p"/orgs/#{organization.slug}/equipment/#{equipment.id}/edit") assert {:redirect, %{to: path}} = redirect assert path == ~p"/users/log-in" end end end