- Added comprehensive tests for ToweropsWeb.AgentLive.Index - Tests mount, create_agent, revoke_agent, and close_token_modal events - Tests agent status display and last_seen formatting - Coverage improved from 57.50% to 80.00% - Enhanced ToweropsWeb.UserAuth tests - Added tests for impersonation functionality - Added tests for organization loading and membership verification - Added tests for superuser authorization - Coverage improved from 51.08% to 61.87% - Expanded Towerops.Snmp.Profiles.Cisco tests - Added tests for all sensor type parsing functions - Added tests for different sensor scales, statuses, and error conditions - Tests sensor discovery with various data formats - Coverage improved from 57.30% to 100.00% Overall test coverage improved from 64.25% to 65.86%
205 lines
6.2 KiB
Elixir
205 lines
6.2 KiB
Elixir
defmodule ToweropsWeb.AgentLive.IndexTest do
|
|
use ToweropsWeb.ConnCase, async: true
|
|
|
|
import Phoenix.LiveViewTest
|
|
import Towerops.AccountsFixtures
|
|
|
|
alias Towerops.Agents
|
|
|
|
setup do
|
|
user = user_fixture()
|
|
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
|
|
|
%{user: user, organization: organization}
|
|
end
|
|
|
|
describe "mount" do
|
|
test "loads agent tokens for organization", %{conn: conn, user: user, organization: organization} do
|
|
# Create some agent tokens
|
|
{:ok, agent_token1, _token1} = Agents.create_agent_token(organization.id, "Agent 1")
|
|
{:ok, agent_token2, _token2} = Agents.create_agent_token(organization.id, "Agent 2")
|
|
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, _view, html} = live(conn)
|
|
|
|
assert html =~ "Remote Agents"
|
|
assert html =~ agent_token1.name
|
|
assert html =~ agent_token2.name
|
|
end
|
|
|
|
test "shows empty state when no agents exist", %{conn: conn, user: user, organization: organization} do
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, _view, html} = live(conn)
|
|
|
|
assert html =~ "Remote Agents"
|
|
end
|
|
|
|
test "requires authentication", %{conn: conn, organization: organization} do
|
|
conn = get(conn, "/orgs/#{organization.slug}/agents")
|
|
assert redirected_to(conn) == ~p"/users/log-in"
|
|
end
|
|
end
|
|
|
|
describe "create_agent event" do
|
|
test "creates new agent token and shows modal", %{conn: conn, user: user, organization: organization} do
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, view, _html} = live(conn)
|
|
|
|
# Trigger create_agent event with nested params
|
|
html = render_submit(view, "create_agent", %{"agent_form" => %{"name" => "New Agent"}})
|
|
|
|
assert html =~ "Agent created successfully"
|
|
assert html =~ "New Agent"
|
|
|
|
# Verify agent was actually created
|
|
agent_tokens = Agents.list_organization_agent_tokens(organization.id)
|
|
assert length(agent_tokens) == 1
|
|
assert hd(agent_tokens).name == "New Agent"
|
|
end
|
|
|
|
test "creates agent with flat params format", %{conn: conn, user: user, organization: organization} do
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, view, _html} = live(conn)
|
|
|
|
# Trigger create_agent event with flat params
|
|
html = render_submit(view, "create_agent", %{"name" => "Flat Agent"})
|
|
|
|
assert html =~ "Agent created successfully"
|
|
assert html =~ "Flat Agent"
|
|
end
|
|
|
|
test "shows error on creation failure", %{conn: conn, user: user, organization: organization} do
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, view, _html} = live(conn)
|
|
|
|
# Trigger create_agent with invalid params (empty name)
|
|
html = render_submit(view, "create_agent", %{"agent_form" => %{"name" => ""}})
|
|
|
|
assert html =~ "Failed to create agent"
|
|
end
|
|
end
|
|
|
|
describe "close_token_modal event" do
|
|
test "closes the token modal", %{conn: conn, user: user, organization: organization} do
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, view, _html} = live(conn)
|
|
|
|
# First create an agent to show the modal
|
|
render_submit(view, "create_agent", %{"name" => "Test Agent"})
|
|
|
|
# Now close the modal
|
|
_html = render_click(view, "close_token_modal", %{})
|
|
|
|
# Modal should be closed - verify by checking that we can still interact with the view
|
|
assert render(view) =~ "Test Agent"
|
|
end
|
|
end
|
|
|
|
describe "revoke_agent event" do
|
|
test "revokes agent token successfully", %{conn: conn, user: user, organization: organization} do
|
|
{:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Agent to Revoke")
|
|
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, view, _html} = live(conn)
|
|
|
|
html = render_click(view, "revoke_agent", %{"id" => agent_token.id})
|
|
|
|
assert html =~ "Agent revoked successfully"
|
|
|
|
# Verify agent was revoked (still in list but with enabled: false)
|
|
agent_tokens = Agents.list_organization_agent_tokens(organization.id)
|
|
refute Enum.empty?(agent_tokens)
|
|
revoked_agent = hd(agent_tokens)
|
|
refute revoked_agent.enabled
|
|
end
|
|
end
|
|
|
|
describe "agent status display" do
|
|
test "shows Never connected for agents without last_seen_at", %{
|
|
conn: conn,
|
|
user: user,
|
|
organization: organization
|
|
} do
|
|
{:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Never Seen")
|
|
|
|
# Verify the agent has no last_seen_at
|
|
assert is_nil(agent_token.last_seen_at)
|
|
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, _view, html} = live(conn)
|
|
|
|
assert html =~ "Never Seen"
|
|
assert html =~ "Never connected" or html =~ "Never"
|
|
end
|
|
|
|
test "shows agent status information in the page", %{
|
|
conn: conn,
|
|
user: user,
|
|
organization: organization
|
|
} do
|
|
{:ok, agent_token, _token} = Agents.create_agent_token(organization.id, "Status Agent")
|
|
|
|
# Update the agent to have a recent last_seen_at
|
|
agent_token
|
|
|> Ecto.Changeset.change(%{last_seen_at: DateTime.truncate(DateTime.utc_now(), :second)})
|
|
|> Towerops.Repo.update!()
|
|
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, _view, html} = live(conn)
|
|
|
|
assert html =~ "Status Agent"
|
|
# The status should show something about timing (Online, seconds ago, etc.)
|
|
assert html =~ "ago" or html =~ "Online"
|
|
end
|
|
end
|
|
|
|
describe "handle_params" do
|
|
test "handles :index action", %{conn: conn, user: user, organization: organization} do
|
|
conn =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> get("/orgs/#{organization.slug}/agents")
|
|
|
|
{:ok, view, _html} = live(conn)
|
|
|
|
# Verify we can navigate to the index action
|
|
assert render(view) =~ "Remote Agents"
|
|
end
|
|
end
|
|
end
|