Add three-level agent assignment hierarchy (Equipment > Site > Organization) allowing flexible agent deployment strategies. Agents now receive only equipment assigned to them through direct assignment or inheritance from site/organization defaults. Key changes: - Add agent_token_id to Sites table with migration - Implement get_effective_agent_token/1 for hierarchical resolution - Add list_agent_polling_targets/1 to return polling targets per agent - Update API config endpoint to use hierarchical polling targets - Add agent assignment UI to equipment, site, and organization forms - Show agent source (direct/site/org/none) in equipment form - Add equipment count column to agent list - Update terminology from "poll from server" to "cloud polling" Tests: - Add 8 comprehensive tests for list_agent_polling_targets/1 - Add end-to-end test for hierarchical config endpoint - All 775 tests passing
140 lines
4.1 KiB
Elixir
140 lines
4.1 KiB
Elixir
defmodule ToweropsWeb.Org.SettingsLiveTest do
|
|
use ToweropsWeb.ConnCase
|
|
|
|
import Phoenix.LiveViewTest
|
|
import Towerops.AccountsFixtures
|
|
import Towerops.AgentsFixtures
|
|
import Towerops.OrganizationsFixtures
|
|
|
|
setup do
|
|
user = user_fixture()
|
|
organization = organization_fixture(user.id)
|
|
|
|
%{user: user, organization: organization}
|
|
end
|
|
|
|
describe "Settings page" do
|
|
test "displays organization settings form", %{conn: conn, user: user, organization: org} do
|
|
{:ok, _view, html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
assert html =~ "Organization Settings"
|
|
assert html =~ "Organization Name"
|
|
assert html =~ org.name
|
|
end
|
|
|
|
test "shows no agents message when no agents exist", %{
|
|
conn: conn,
|
|
user: user,
|
|
organization: org
|
|
} do
|
|
{:ok, _view, html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
assert html =~ "No agents configured yet"
|
|
assert html =~ "Create an agent"
|
|
end
|
|
|
|
test "shows default agent dropdown when agents exist", %{
|
|
conn: conn,
|
|
user: user,
|
|
organization: org
|
|
} do
|
|
{:ok, agent_token, _token} = agent_token_fixture(org.id, "Test Agent")
|
|
|
|
{:ok, _view, html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
assert html =~ "Default Remote Agent"
|
|
assert html =~ agent_token.name
|
|
assert html =~ "No default agent - cloud polling"
|
|
end
|
|
|
|
test "updates organization name successfully", %{conn: conn, user: user, organization: org} do
|
|
{:ok, view, _html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
assert view
|
|
|> form("#organization-form", organization: %{name: "Updated Name"})
|
|
|> render_submit()
|
|
|
|
assert_redirected(view, ~p"/orgs/#{org.slug}")
|
|
|
|
# Verify the organization was actually updated
|
|
updated_org = Towerops.Organizations.get_organization!(org.id)
|
|
assert updated_org.name == "Updated Name"
|
|
end
|
|
|
|
test "sets default agent for organization", %{conn: conn, user: user, organization: org} do
|
|
{:ok, agent_token, _token} = agent_token_fixture(org.id, "Test Agent")
|
|
|
|
{:ok, view, _html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
assert view
|
|
|> form("#organization-form", organization: %{default_agent_token_id: agent_token.id})
|
|
|> render_submit()
|
|
|
|
assert_redirected(view, ~p"/orgs/#{org.slug}")
|
|
|
|
# Verify the default agent was set
|
|
updated_org = Towerops.Organizations.get_organization!(org.id)
|
|
assert updated_org.default_agent_token_id == agent_token.id
|
|
end
|
|
|
|
test "clears default agent for organization", %{conn: conn, user: user, organization: org} do
|
|
{:ok, agent_token, _token} = agent_token_fixture(org.id, "Test Agent")
|
|
|
|
# First set a default agent
|
|
{:ok, org} =
|
|
Towerops.Organizations.update_organization(org, %{
|
|
default_agent_token_id: agent_token.id
|
|
})
|
|
|
|
{:ok, view, _html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
# Now clear it
|
|
assert view
|
|
|> form("#organization-form", organization: %{default_agent_token_id: ""})
|
|
|> render_submit()
|
|
|
|
assert_redirected(view, ~p"/orgs/#{org.slug}")
|
|
|
|
# Verify the default agent was cleared
|
|
updated_org = Towerops.Organizations.get_organization!(org.id)
|
|
assert updated_org.default_agent_token_id == nil
|
|
end
|
|
|
|
test "validates organization name", %{conn: conn, user: user, organization: org} do
|
|
{:ok, view, _html} =
|
|
conn
|
|
|> log_in_user(user)
|
|
|> live(~p"/orgs/#{org.slug}/settings")
|
|
|
|
html =
|
|
view
|
|
|> form("#organization-form", organization: %{name: ""})
|
|
|> render_change()
|
|
|
|
assert html =~ "can't be blank"
|
|
end
|
|
|
|
test "requires authentication", %{conn: conn, organization: org} do
|
|
assert {:error, {:redirect, %{to: "/users/log-in"}}} =
|
|
live(conn, ~p"/orgs/#{org.slug}/settings")
|
|
end
|
|
end
|
|
end
|