mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-09-06 21:14:26 +08:00
694 lines
24 KiB
Elixir
694 lines
24 KiB
Elixir
defmodule LivebookWeb.Integration.SessionLiveTest do
|
|
use Livebook.TeamsIntegrationCase, async: true
|
|
|
|
import Phoenix.LiveViewTest
|
|
import Livebook.SessionHelpers
|
|
|
|
@moduletag teams_for: :user
|
|
setup :teams
|
|
|
|
@moduletag subscribe_to_hubs_topics: [:connection, :crud, :secrets]
|
|
@moduletag subscribe_to_teams_topics: [:clients, :agents, :app_deployments, :app_server]
|
|
|
|
alias Livebook.FileSystem
|
|
alias Livebook.Sessions
|
|
alias Livebook.Session
|
|
|
|
setup do
|
|
{:ok, session} = Sessions.create_session(notebook: Livebook.Notebook.new())
|
|
Session.subscribe(session.id)
|
|
|
|
on_exit(fn ->
|
|
Session.close(session.pid)
|
|
end)
|
|
|
|
%{session: session}
|
|
end
|
|
|
|
describe "hubs" do
|
|
test "selects the notebook hub", %{team: %{id: id}, conn: conn, session: session} do
|
|
personal_id = Livebook.Hubs.Personal.id()
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
assert Session.get_notebook(session.pid).hub_id == personal_id
|
|
|
|
view
|
|
|> element(~s/#select-hub-#{id}/)
|
|
|> render_click()
|
|
|
|
assert_receive {:operation, {:set_notebook_hub, _, ^id}}
|
|
assert Session.get_notebook(session.pid).hub_id == id
|
|
end
|
|
|
|
test "closes all sessions from notebooks that belongs to the org when the org deletes the user",
|
|
%{team: team, conn: conn, user: user, node: node, session: session} do
|
|
id = team.id
|
|
Session.set_notebook_hub(session.pid, id)
|
|
|
|
assert_receive {:operation, {:set_notebook_hub, _, ^id}}
|
|
assert Session.get_notebook(session.pid).hub_id == id
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
assert has_element?(view, ~s/#select-hub-#{id}/)
|
|
|
|
# force user to be deleted from org
|
|
TeamsRPC.delete_user_org(node, user.id, team.org_id)
|
|
reason = "#{team.hub_name}: you were removed from the org"
|
|
|
|
# checks if the hub received the `user_deleted` event and deleted the hub
|
|
assert_receive {:hub_server_error, ^id, ^reason}
|
|
assert_receive {:hub_deleted, ^id}
|
|
refute team in Livebook.Hubs.get_hubs()
|
|
|
|
# all sessions that uses the deleted hub must be closed
|
|
assert_receive :session_closed
|
|
end
|
|
end
|
|
|
|
describe "secrets" do
|
|
test "creates a new secret", %{team: team, conn: conn, session: session} do
|
|
# loads the session page
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
# selects the notebook's hub with team hub id
|
|
view
|
|
|> element(~s/#select-hub-#{team.id}/)
|
|
|> render_click()
|
|
|
|
# clicks the button to add a new secret
|
|
view
|
|
|> element("#new-secret-button")
|
|
|> render_click(%{})
|
|
|
|
# redirects to secrets action to
|
|
# render the secret modal
|
|
assert_patch(view, ~p"/sessions/#{session.id}/secrets")
|
|
|
|
secret = build(:secret, hub_id: team.id)
|
|
|
|
attrs = %{
|
|
secret: %{
|
|
name: secret.name,
|
|
value: secret.value,
|
|
hub_id: team.id
|
|
}
|
|
}
|
|
|
|
# fills and submits the secrets modal form
|
|
# to create a new secret on team hub
|
|
form = element(view, ~s{#secrets-modal form[phx-submit="save"]})
|
|
|
|
render_change(form, attrs)
|
|
render_submit(form, attrs)
|
|
|
|
# receives the operation event
|
|
assert_receive {:operation, {:sync_hub_secrets, "__server__"}}
|
|
assert secret in Livebook.Hubs.get_secrets(team)
|
|
|
|
# checks the secret on the UI
|
|
assert_session_secret(view, session.pid, secret, :hub_secrets)
|
|
end
|
|
|
|
test "redirects the user to update or delete a secret",
|
|
%{team: team, conn: conn, session: session} do
|
|
# creates a secret
|
|
secret = insert_secret(hub_id: team.id)
|
|
assert_receive {:secret_created, ^secret}
|
|
|
|
# selects the notebook's hub with team hub id
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
# loads the session page
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
# clicks the button to edit a secret
|
|
view
|
|
|> element("#hub-#{team.id}-secret-#{secret.name}-edit-button")
|
|
|> render_click()
|
|
|
|
# redirects to hub page and loads the modal with
|
|
# the secret name and value filled
|
|
assert_redirect(view, ~p"/hub/#{team.id}/secrets/edit/#{secret.name}")
|
|
end
|
|
|
|
test "toggle a secret from team hub", %{team: team, conn: conn, session: session} do
|
|
# loads the session page
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
# selects the notebook's hub with team hub id
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
# creates a new secret
|
|
secret = build(:secret, hub_id: team.id)
|
|
|
|
assert Livebook.Hubs.create_secret(team, secret) == :ok
|
|
|
|
# receives the operation event
|
|
assert_receive {:operation, {:sync_hub_secrets, "__server__"}}
|
|
assert secret in Livebook.Hubs.get_secrets(team)
|
|
|
|
# checks the secret on the UI
|
|
Session.set_secret(session.pid, secret)
|
|
assert_session_secret(view, session.pid, secret)
|
|
end
|
|
|
|
test "adding a missing secret using 'Add secret' button",
|
|
%{team: team, conn: conn, session: session} do
|
|
secret = build(:secret, hub_id: team.id)
|
|
|
|
# selects the notebook's hub with team hub id
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
# executes the code to trigger the `System.EnvError` exception
|
|
# and outputs the 'Add secret' button
|
|
section_id = insert_section(session.pid)
|
|
code = ~s{System.fetch_env!("LB_#{secret.name}")}
|
|
cell_id = insert_text_cell(session.pid, section_id, :code, code)
|
|
|
|
Session.queue_cell_evaluation(session.pid, cell_id)
|
|
assert_receive {:operation, {:add_cell_evaluation_response, _, ^cell_id, _, _}}
|
|
|
|
# enters the session to check if the button exists
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
expected_url = ~p"/sessions/#{session.id}/secrets?secret_name=#{secret.name}"
|
|
add_secret_button = element(view, "a[href='#{expected_url}']")
|
|
assert has_element?(add_secret_button)
|
|
|
|
# clicks the button and fills the form to create a new secret
|
|
# that prefilled the name with the received from exception.
|
|
render_click(add_secret_button)
|
|
form_element = element(view, "#secrets-modal form[phx-submit='save']")
|
|
assert has_element?(form_element)
|
|
attrs = %{value: secret.value, hub_id: team.id}
|
|
render_submit(form_element, %{secret: attrs})
|
|
|
|
# receives the operation event
|
|
assert_receive {:operation, {:sync_hub_secrets, "__server__"}}
|
|
assert secret in Livebook.Hubs.get_secrets(team)
|
|
|
|
# checks if the secret exists and is inside the session,
|
|
# then executes the code cell again and checks if the
|
|
# secret value is what we expected.
|
|
assert_session_secret(view, session.pid, secret, :hub_secrets)
|
|
Session.queue_cell_evaluation(session.pid, cell_id)
|
|
|
|
assert_receive {:operation,
|
|
{:add_cell_evaluation_response, _, ^cell_id,
|
|
%{type: :terminal_text, text: output}, _}}
|
|
|
|
assert output == "\e[32m\"#{secret.value}\"\e[0m"
|
|
end
|
|
|
|
test "granting access for missing secret using 'Add secret' button",
|
|
%{team: team, conn: conn, session: session} do
|
|
secret = build(:secret, hub_id: team.id)
|
|
|
|
# selects the notebook's hub with team hub id
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
# executes the code to trigger the `System.EnvError` exception
|
|
# and outputs the 'Add secret' button
|
|
section_id = insert_section(session.pid)
|
|
code = ~s{System.fetch_env!("LB_#{secret.name}")}
|
|
cell_id = insert_text_cell(session.pid, section_id, :code, code)
|
|
|
|
Session.queue_cell_evaluation(session.pid, cell_id)
|
|
assert_receive {:operation, {:add_cell_evaluation_response, _, ^cell_id, _, _}}
|
|
|
|
# enters the session to check if the button exists
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
expected_url = ~p"/sessions/#{session.id}/secrets?secret_name=#{secret.name}"
|
|
add_secret_button = element(view, "a[href='#{expected_url}']")
|
|
assert has_element?(add_secret_button)
|
|
|
|
# creates the secret
|
|
assert Livebook.Hubs.create_secret(team, secret) == :ok
|
|
|
|
# receives the operation event
|
|
assert_receive {:operation, {:sync_hub_secrets, "__server__"}}
|
|
assert secret in Livebook.Hubs.get_secrets(team)
|
|
|
|
# remove the secret from session
|
|
Session.unset_secret(session.pid, secret.name)
|
|
|
|
# clicks the button and checks if the 'Grant access' banner
|
|
# is being shown, so clicks it's button to set the app secret
|
|
# to the session, allowing the user to fetches the secret.
|
|
render_click(add_secret_button)
|
|
|
|
assert render(view) =~
|
|
"in the #{hub_label(team)} workspace. Allow this notebook to access it?"
|
|
|
|
view
|
|
|> element("#secrets-modal button", "Grant access")
|
|
|> render_click()
|
|
|
|
# checks if the secret exists and is inside the session,
|
|
# then executes the code cell again and checks if the
|
|
# secret value is what we expected.
|
|
assert_session_secret(view, session.pid, secret, :hub_secrets)
|
|
Session.queue_cell_evaluation(session.pid, cell_id)
|
|
|
|
assert_receive {:operation,
|
|
{:add_cell_evaluation_response, _, ^cell_id,
|
|
%{type: :terminal_text, text: output}, _}}
|
|
|
|
assert output == "\e[32m\"#{secret.value}\"\e[0m"
|
|
end
|
|
end
|
|
|
|
describe "files" do
|
|
@describetag subscribe_to_hubs_topics: [:connection, :file_systems]
|
|
|
|
test "shows only hub's file systems", %{team: team, conn: conn, session: session} do
|
|
personal_id = Livebook.Hubs.Personal.id()
|
|
personal_file_system = build(:fs_s3)
|
|
Livebook.Hubs.Personal.save_file_system(personal_file_system)
|
|
|
|
team_id = team.id
|
|
|
|
bucket_url = "https://my-own-bucket.s3.amazonaws.com"
|
|
|
|
team_file_system =
|
|
build(:fs_s3,
|
|
id: FileSystem.S3.id(team_id, bucket_url),
|
|
bucket_url: bucket_url,
|
|
hub_id: team_id
|
|
)
|
|
|
|
Livebook.Hubs.create_file_system(team, team_file_system)
|
|
assert_receive {:file_system_created, %{hub_id: ^team_id} = team_file_system}
|
|
|
|
# loads the session page
|
|
{:ok, view, _html} = live(conn, ~p"/sessions/#{session.id}/add-file/storage")
|
|
|
|
# change the hub to Personal
|
|
# and checks the file systems from Personal
|
|
Session.set_notebook_hub(session.pid, personal_id)
|
|
assert_receive {:operation, {:set_notebook_hub, _client, ^personal_id}}
|
|
|
|
file_entry_select = element(view, "#add-file-entry-select")
|
|
|
|
# checks the file systems from Personal
|
|
assert render(file_entry_select) =~ "local"
|
|
assert render(file_entry_select) =~ personal_file_system.id
|
|
refute render(file_entry_select) =~ team_file_system.id
|
|
|
|
# change the hub to Team
|
|
# and checks the file systems from Team
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
assert_receive {:operation, {:set_notebook_hub, _client, ^team_id}}
|
|
|
|
assert render(file_entry_select) =~ "local"
|
|
refute render(file_entry_select) =~ personal_file_system.id
|
|
assert render(file_entry_select) =~ team_file_system.id
|
|
end
|
|
|
|
test "shows file system from offline hub", %{conn: conn, session: session} do
|
|
hub = offline_hub()
|
|
hub_id = hub.id
|
|
bucket_url = "https://#{hub.id}-file-system.s3.amazonaws.com"
|
|
|
|
file_system =
|
|
build(:fs_s3,
|
|
id: FileSystem.S3.id(hub_id, bucket_url),
|
|
bucket_url: bucket_url,
|
|
hub_id: hub_id,
|
|
external_id: "123"
|
|
)
|
|
|
|
put_offline_hub_file_system(file_system)
|
|
assert_receive {:file_system_created, ^file_system}
|
|
|
|
# loads the session page
|
|
{:ok, view, _html} = live(conn, ~p"/sessions/#{session.id}/add-file/storage")
|
|
|
|
# change the hub to Personal
|
|
# and checks the file systems from Offline hub
|
|
Session.set_notebook_hub(session.pid, hub_id)
|
|
assert_receive {:operation, {:set_notebook_hub, _client, ^hub_id}}
|
|
|
|
# checks the file systems from Offline hub
|
|
file_entry_select = element(view, "#add-file-entry-select")
|
|
assert render(file_entry_select) =~ "local"
|
|
assert render(file_entry_select) =~ file_system.id
|
|
|
|
remove_offline_hub_file_system(file_system)
|
|
end
|
|
end
|
|
|
|
describe "offline deployment with docker" do
|
|
@tag :tmp_dir
|
|
test "show deployment group on app deployment",
|
|
%{team: team, conn: conn, session: session, tmp_dir: tmp_dir} do
|
|
team_id = team.id
|
|
|
|
insert_deployment_group(
|
|
name: "DEPLOYMENT_GROUP_SUSIE",
|
|
mode: :online,
|
|
hub_id: team_id
|
|
)
|
|
|
|
Session.set_notebook_hub(session.pid, team_id)
|
|
assert_receive {:operation, {:set_notebook_hub, _client, ^team_id}}
|
|
|
|
notebook_path = Path.join(tmp_dir, "notebook.livemd")
|
|
file = FileSystem.File.local(notebook_path)
|
|
Session.set_file(session.pid, file)
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
app_settings = %{Livebook.Notebook.AppSettings.new() | slug: slug}
|
|
Session.set_app_settings(session.pid, app_settings)
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-docker")
|
|
|
|
assert render(view) =~ "Deployment Group"
|
|
assert has_element?(view, "#select_deployment_group_form")
|
|
end
|
|
|
|
@tag :tmp_dir
|
|
test "set deployment group on app deployment",
|
|
%{team: team, conn: conn, session: session, tmp_dir: tmp_dir} do
|
|
team_id = team.id
|
|
|
|
insert_deployment_group(
|
|
name: "DEPLOYMENT_GROUP_SUSIE",
|
|
mode: :online,
|
|
hub_id: team_id
|
|
)
|
|
|
|
deployment_group =
|
|
insert_deployment_group(
|
|
name: "DEPLOYMENT_GROUP_TOBIAS",
|
|
mode: :online,
|
|
hub_id: team_id
|
|
)
|
|
|
|
Session.set_notebook_hub(session.pid, team_id)
|
|
assert_receive {:operation, {:set_notebook_hub, _client, ^team_id}}
|
|
|
|
notebook_path = Path.join(tmp_dir, "notebook.livemd")
|
|
file = FileSystem.File.local(notebook_path)
|
|
Session.set_file(session.pid, file)
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
app_settings = %{Livebook.Notebook.AppSettings.new() | slug: slug}
|
|
Session.set_app_settings(session.pid, app_settings)
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-docker")
|
|
|
|
assert render(view) =~ "Deployment Group"
|
|
assert has_element?(view, "#select_deployment_group_form")
|
|
|
|
id = deployment_group.id
|
|
|
|
view
|
|
|> form("#select_deployment_group_form", %{deployment_group: %{id: id}})
|
|
|> render_change()
|
|
|
|
assert_receive {:operation, {:set_notebook_deployment_group, _client, ^id}}
|
|
end
|
|
|
|
@tag :tmp_dir
|
|
test "show no deployments groups available",
|
|
%{team: team, conn: conn, session: session, tmp_dir: tmp_dir} do
|
|
team_id = team.id
|
|
|
|
Session.set_notebook_hub(session.pid, team_id)
|
|
assert_receive {:operation, {:set_notebook_hub, _client, ^team_id}}
|
|
|
|
notebook_path = Path.join(tmp_dir, "notebook.livemd")
|
|
file = FileSystem.File.local(notebook_path)
|
|
Session.set_file(session.pid, file)
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
app_settings = %{Livebook.Notebook.AppSettings.new() | slug: slug}
|
|
Session.set_app_settings(session.pid, app_settings)
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-docker")
|
|
|
|
assert render(view) =~ "Deployment Group"
|
|
assert render(view) =~ "None configured"
|
|
refute has_element?(view, "#select_deployment_group_form")
|
|
end
|
|
end
|
|
|
|
describe "online deployment" do
|
|
@moduletag subscribe_to_teams_topics: [
|
|
:clients,
|
|
:agents,
|
|
:app_deployments,
|
|
:deployment_groups,
|
|
:app_server
|
|
]
|
|
|
|
test "shows a message when non-teams hub is selected", %{conn: conn, session: session} do
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
view
|
|
|> element("a", "Deploy with Livebook Teams")
|
|
|> render_click()
|
|
|
|
assert render(view) =~
|
|
"In order to deploy your app using Livebook Teams, you need to select"
|
|
end
|
|
|
|
test "deployment flow with no deployment groups in the hub",
|
|
%{team: team, conn: conn, session: session} do
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
view
|
|
|> element("a", "Deploy with Livebook Teams")
|
|
|> render_click()
|
|
|
|
# Step: configuring valid app settings
|
|
|
|
assert render(view) =~ "You must configure your app before deploying it."
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
|
|
view
|
|
|> element(~s/#app-settings-modal form/)
|
|
|> render_submit(%{"app_settings" => %{"slug" => slug}})
|
|
|
|
# From this point forward we are in a child LV
|
|
view = find_live_child(view, "app-teams")
|
|
assert render(view) =~ "App deployment with Livebook Teams"
|
|
|
|
# Step: deployment group creation
|
|
|
|
assert render(view) =~ "Step: add deployment group"
|
|
assert render(view) =~ "You must create a deployment group before deploying the app."
|
|
|
|
view
|
|
|> element(~s/#add-deployment-group-form/)
|
|
|> render_submit(%{"deployment_group" => %{"name" => "test"}})
|
|
|
|
# Step: agent instance setup
|
|
|
|
assert render(view) =~ "Step: add app server"
|
|
assert render(view) =~ "You must set up an app server for the app to run on."
|
|
|
|
assert render(view) =~ "Awaiting an app server to be set up."
|
|
|
|
[deployment_group] = Livebook.Hubs.TeamClient.get_deployment_groups(team.id)
|
|
simulate_agent_join(team, deployment_group)
|
|
|
|
assert render(view) =~ "An app server is running"
|
|
|
|
# Step: deploy
|
|
|
|
view
|
|
|> element("button", "Deploy")
|
|
|> render_click()
|
|
|
|
assert render(view) =~
|
|
"App deployment created successfully"
|
|
|
|
assert render(view) =~ "#{Livebook.Config.teams_url()}/orgs/#{team.org_id}"
|
|
end
|
|
|
|
test "deployment flow with existing deployment groups in the hub",
|
|
%{team: team, conn: conn, session: session} do
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
id = insert_deployment_group(mode: :online, hub_id: team.id).id
|
|
assert_receive {:deployment_group_created, %{id: ^id} = deployment_group}
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
view
|
|
|> element("a", "Deploy with Livebook Teams")
|
|
|> render_click()
|
|
|
|
# Step: configuring valid app settings
|
|
|
|
assert render(view) =~ "You must configure your app before deploying it."
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
|
|
view
|
|
|> element(~s/#app-settings-modal form/)
|
|
|> render_submit(%{"app_settings" => %{"slug" => slug}})
|
|
|
|
# From this point forward we are in a child LV
|
|
view = find_live_child(view, "app-teams")
|
|
assert render(view) =~ "App deployment with Livebook Teams"
|
|
|
|
# Step: selecting deployment group
|
|
|
|
view
|
|
|> element(~s/[phx-click="select_deployment_group"][phx-value-id="#{deployment_group.id}"]/)
|
|
|> render_click()
|
|
|
|
assert_receive {:operation, {:set_notebook_deployment_group, _, ^id}}
|
|
assert render(view) =~ "The selected deployment group has no app servers."
|
|
|
|
view
|
|
|> element(~s/button/, "Add app server")
|
|
|> render_click()
|
|
|
|
# Step: agent instance setup
|
|
|
|
assert render(view) =~ "Step: add app server"
|
|
assert render(view) =~ "Awaiting an app server to be set up."
|
|
|
|
[deployment_group] = Livebook.Hubs.TeamClient.get_deployment_groups(team.id)
|
|
simulate_agent_join(team, deployment_group)
|
|
|
|
assert render(view) =~ "An app server is running"
|
|
|
|
# Step: deploy
|
|
|
|
view
|
|
|> element("button", "Deploy")
|
|
|> render_click()
|
|
|
|
assert render(view) =~
|
|
"App deployment created successfully"
|
|
end
|
|
|
|
test "shows tooltip message if user is unauthorized to deploy apps",
|
|
%{team: team, node: node, org: org, conn: conn, session: session} do
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
deployment_group = TeamsRPC.create_deployment_group(node, mode: :online, org: org)
|
|
id = to_string(deployment_group.id)
|
|
assert_receive {:deployment_group_created, %{id: ^id, deploy_auth: false}}
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}")
|
|
|
|
view
|
|
|> element("a", "Deploy with Livebook Teams")
|
|
|> render_click()
|
|
|
|
# Step: configuring valid app settings
|
|
|
|
assert render(view) =~ "You must configure your app before deploying it."
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
|
|
view
|
|
|> element(~s/#app-settings-modal form/)
|
|
|> render_submit(%{"app_settings" => %{"slug" => slug}})
|
|
|
|
# From this point forward we are in a child LV
|
|
view = find_live_child(view, "app-teams")
|
|
assert render(view) =~ "App deployment with Livebook Teams"
|
|
|
|
# show the deployment group being able to select to deploy an app
|
|
assert has_element?(
|
|
view,
|
|
~s/[phx-click="select_deployment_group"][phx-value-id="#{deployment_group.id}"]/
|
|
)
|
|
|
|
# then, we update the deployment group, so it will
|
|
# update the view and show the tooltip with unauthorized error message
|
|
{:ok, deployment_group} = TeamsRPC.toggle_deployment_authorization(node, deployment_group)
|
|
assert_receive {:deployment_group_updated, %{id: ^id, deploy_auth: true}}
|
|
|
|
refute has_element?(
|
|
view,
|
|
~s/[phx-click="select_deployment_group"][phx-value-id="#{deployment_group.id}"]/
|
|
)
|
|
|
|
assert has_element?(
|
|
view,
|
|
~s/[data-tooltip="You are not authorized to deploy to this deployment group"][phx-value-id="#{deployment_group.id}"]/
|
|
)
|
|
end
|
|
|
|
test "shows an error when the deployment size is higher than the maximum size of 20MB",
|
|
%{team: team, conn: conn, session: session} do
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
app_settings = %{Livebook.Notebook.AppSettings.new() | slug: slug}
|
|
Session.set_app_settings(session.pid, app_settings)
|
|
|
|
id = insert_deployment_group(mode: :online, hub_id: team.id).id
|
|
assert_receive {:deployment_group_created, %{id: ^id}}
|
|
|
|
Session.set_notebook_deployment_group(session.pid, id)
|
|
assert_receive {:operation, {:set_notebook_deployment_group, _, ^id}}
|
|
|
|
%{files_dir: files_dir} = session
|
|
image_file = FileSystem.File.resolve(files_dir, "image.jpg")
|
|
:ok = FileSystem.File.write(image_file, :crypto.strong_rand_bytes(20 * 1024 * 1024))
|
|
Session.add_file_entries(session.pid, [%{type: :attachment, name: "image.jpg"}])
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-teams")
|
|
|
|
# From this point forward we are in a child LV
|
|
view = find_live_child(view, "app-teams")
|
|
assert render(view) =~ "App deployment with Livebook Teams"
|
|
|
|
view
|
|
|> element("button", "Deploy")
|
|
|> render_click()
|
|
|
|
assert render(view) =~
|
|
"Failed to pack files: the notebook and its attachments have exceeded the maximum size of 20MB"
|
|
end
|
|
|
|
test "shows an error when the deployment is unauthorized",
|
|
%{team: team, org: org, node: node, conn: conn, session: session} do
|
|
Session.set_notebook_hub(session.pid, team.id)
|
|
|
|
slug = Livebook.Utils.random_short_id()
|
|
app_settings = %{Livebook.Notebook.AppSettings.new() | slug: slug}
|
|
Session.set_app_settings(session.pid, app_settings)
|
|
|
|
deployment_group = TeamsRPC.create_deployment_group(node, mode: :online, org: org)
|
|
id = to_string(deployment_group.id)
|
|
assert_receive {:deployment_group_created, %{id: ^id, deploy_auth: false}}
|
|
|
|
{:ok, _} = TeamsRPC.toggle_deployment_authorization(node, deployment_group)
|
|
assert_receive {:deployment_group_updated, %{id: ^id, deploy_auth: true}}
|
|
|
|
Session.set_notebook_deployment_group(session.pid, id)
|
|
assert_receive {:operation, {:set_notebook_deployment_group, _, ^id}}
|
|
|
|
%{files_dir: files_dir} = session
|
|
image_file = FileSystem.File.resolve(files_dir, "image.jpg")
|
|
:ok = FileSystem.File.write(image_file, :crypto.strong_rand_bytes(1024 * 1024))
|
|
Session.add_file_entries(session.pid, [%{type: :attachment, name: "image.jpg"}])
|
|
|
|
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-teams")
|
|
|
|
# From this point forward we are in a child LV
|
|
view = find_live_child(view, "app-teams")
|
|
assert render(view) =~ "App deployment with Livebook Teams"
|
|
|
|
view
|
|
|> element("button", "Deploy")
|
|
|> render_click()
|
|
|
|
assert render(view) =~
|
|
"You are not authorized to perform this action, make sure you have the access to deploy apps to this deployment group"
|
|
end
|
|
end
|
|
end
|