defmodule ToweropsWeb.AgentLive.EditTest do use ToweropsWeb.ConnCase import Phoenix.LiveViewTest alias Towerops.AgentsFixtures setup %{conn: conn} do user = Towerops.AccountsFixtures.user_fixture(enable_totp: true) {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id) conn = conn |> log_in_user(user) |> put_session(:current_organization_id, organization.id) %{conn: conn, user: user, organization: organization} end defp create_agent(organization_id, name \\ nil) do {:ok, agent_token, _raw_token} = AgentsFixtures.agent_token_fixture(organization_id, name) agent_token end describe "mount and display" do test "renders edit form with agent name", %{conn: conn, organization: org} do agent = create_agent(org.id, "Original Agent Name") {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit") assert html =~ "Edit Agent" assert html =~ "Original Agent Name" assert html =~ "Agent Name" assert html =~ "Save Changes" assert html =~ "Cancel" end test "displays allow remote debug checkbox", %{conn: conn, organization: org} do agent = create_agent(org.id) {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit") assert html =~ "Allow Remote Debugging" end test "displays back to agent link", %{conn: conn, organization: org} do agent = create_agent(org.id) {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit") assert html =~ "Back to agent" assert html =~ ~p"/agents/#{agent.id}" end test "sets page title to Edit plus agent name", %{conn: conn, organization: org} do agent = create_agent(org.id, "My Agent") {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit") assert html =~ "Edit My Agent" end end describe "form validation" do test "validates name changes in real time", %{conn: conn, organization: org} do agent = create_agent(org.id, "Original Name") {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit") # Submit empty name to trigger validation error html = view |> form("#edit-agent-form", agent_token: %{name: ""}) |> render_change() assert html =~ "can't be blank" || html =~ "can't be blank" end test "validates with valid name", %{conn: conn, organization: org} do agent = create_agent(org.id, "Original Name") {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit") html = view |> form("#edit-agent-form", agent_token: %{name: "Updated Agent Name"}) |> render_change() refute html =~ "can't be blank" refute html =~ "can't be blank" end end describe "form submission" do test "saves changes and redirects to show page", %{conn: conn, organization: org} do agent = create_agent(org.id, "Original Name") {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit") view |> form("#edit-agent-form", agent_token: %{name: "Updated Agent Name"}) |> render_submit() flash = assert_redirect(view, ~p"/agents/#{agent.id}") assert flash["info"] =~ "Agent updated successfully" end test "shows error when saving with blank name", %{conn: conn, organization: org} do agent = create_agent(org.id, "Original Name") {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit") html = view |> form("#edit-agent-form", agent_token: %{name: ""}) |> render_submit() assert html =~ "can't be blank" || html =~ "can't be blank" end end describe "authentication" do test "redirects to login when not authenticated" do conn = build_conn() assert {:error, {:redirect, %{to: to}}} = live(conn, ~p"/agents/#{Ecto.UUID.generate()}/edit") assert to =~ "/users/log-in" end end describe "authorization" do test "raises when editing agent from another organization", %{conn: conn} do other_user = Towerops.AccountsFixtures.user_fixture(enable_totp: true) {:ok, other_org} = Towerops.Organizations.create_organization(%{name: "Other Org"}, other_user.id) other_agent = create_agent(other_org.id, "Other Org Agent") assert_raise Ecto.NoResultsError, fn -> live(conn, ~p"/agents/#{other_agent.id}/edit") end end test "superuser can edit agent from any organization" do superuser = Towerops.AccountsFixtures.user_fixture(enable_totp: true) superuser |> Ecto.Changeset.change(%{is_superuser: true}) |> Towerops.Repo.update!() {:ok, super_org} = Towerops.Organizations.create_organization(%{name: "Super Org"}, superuser.id) other_user = Towerops.AccountsFixtures.user_fixture(enable_totp: true) {:ok, other_org} = Towerops.Organizations.create_organization(%{name: "Other Org"}, other_user.id) other_agent = create_agent(other_org.id, "Cross-Org Agent") super_conn = build_conn() |> log_in_user(superuser) |> put_session(:current_organization_id, super_org.id) {:ok, _view, html} = live(super_conn, ~p"/agents/#{other_agent.id}/edit") assert html =~ "Cross-Org Agent" end end end