2021-03-04 05:56:28 +08:00
|
|
|
defmodule LivebookWeb.HomeLiveTest do
|
2022-01-29 23:39:41 +08:00
|
|
|
use LivebookWeb.ConnCase, async: true
|
2021-01-08 04:16:54 +08:00
|
|
|
|
|
|
|
import Phoenix.LiveViewTest
|
2023-03-16 01:18:33 +08:00
|
|
|
import Livebook.SessionHelpers
|
2021-01-08 04:16:54 +08:00
|
|
|
|
2021-09-05 01:16:01 +08:00
|
|
|
alias Livebook.{Sessions, Session}
|
2021-02-21 23:54:44 +08:00
|
|
|
|
2021-01-08 04:16:54 +08:00
|
|
|
test "disconnected and connected render", %{conn: conn} do
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, disconnected_html} = live(conn, ~p"/")
|
2021-03-26 02:04:49 +08:00
|
|
|
assert disconnected_html =~ "Running sessions"
|
|
|
|
assert render(view) =~ "Running sessions"
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
test "redirects to session upon creation", %{conn: conn} do
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-02-21 23:54:44 +08:00
|
|
|
|
|
|
|
assert {:error, {:live_redirect, %{to: to}}} =
|
|
|
|
view
|
2022-04-12 02:34:31 +08:00
|
|
|
|> element(~s/[role="navigation"] button/, "New notebook")
|
2021-02-21 23:54:44 +08:00
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
assert to =~ "/sessions/"
|
2022-04-12 02:34:31 +08:00
|
|
|
|
|
|
|
close_session_by_path(to)
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "sessions list" do
|
|
|
|
test "lists running sessions", %{conn: conn} do
|
2021-09-05 01:16:01 +08:00
|
|
|
{:ok, session1} = Sessions.create_session()
|
|
|
|
{:ok, session2} = Sessions.create_session()
|
2021-02-21 23:54:44 +08:00
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-02-21 23:54:44 +08:00
|
|
|
|
2021-09-05 01:16:01 +08:00
|
|
|
assert render(view) =~ session1.id
|
|
|
|
assert render(view) =~ session2.id
|
2022-02-10 22:36:59 +08:00
|
|
|
|
|
|
|
Session.close([session1.pid, session2.pid])
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
test "updates UI whenever a session is added or deleted", %{conn: conn} do
|
2022-04-19 17:29:38 +08:00
|
|
|
Sessions.subscribe()
|
2021-09-05 01:16:01 +08:00
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-02-21 23:54:44 +08:00
|
|
|
|
2021-09-05 01:16:01 +08:00
|
|
|
{:ok, %{id: id} = session} = Sessions.create_session()
|
|
|
|
assert_receive {:session_created, %{id: ^id}}
|
2021-02-21 23:54:44 +08:00
|
|
|
assert render(view) =~ id
|
|
|
|
|
2021-09-05 01:16:01 +08:00
|
|
|
Session.close(session.pid)
|
|
|
|
assert_receive {:session_closed, %{id: ^id}}
|
2021-02-21 23:54:44 +08:00
|
|
|
refute render(view) =~ id
|
|
|
|
end
|
2021-03-26 02:04:49 +08:00
|
|
|
|
2022-02-04 18:36:09 +08:00
|
|
|
test "allows download the source of an existing session", %{conn: conn} do
|
|
|
|
{:ok, session} = Sessions.create_session()
|
|
|
|
Session.set_notebook_name(session.pid, "My notebook")
|
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2022-02-04 18:36:09 +08:00
|
|
|
|
|
|
|
{:error, {:redirect, %{to: to}}} =
|
|
|
|
view
|
|
|
|
|> element(~s{[data-test-session-id="#{session.id}"] a}, "Download source")
|
|
|
|
|> render_click
|
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
assert to == ~p"/sessions/#{session.id}/export/download/livemd?include_outputs=false"
|
2022-02-10 22:36:59 +08:00
|
|
|
|
|
|
|
Session.close(session.pid)
|
2022-02-04 18:36:09 +08:00
|
|
|
end
|
|
|
|
|
2021-03-26 02:04:49 +08:00
|
|
|
test "allows forking existing session", %{conn: conn} do
|
2021-09-05 01:16:01 +08:00
|
|
|
{:ok, session} = Sessions.create_session()
|
|
|
|
Session.set_notebook_name(session.pid, "My notebook")
|
2021-03-26 02:04:49 +08:00
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-03-26 02:04:49 +08:00
|
|
|
|
|
|
|
assert {:error, {:live_redirect, %{to: to}}} =
|
|
|
|
view
|
2021-09-05 01:16:01 +08:00
|
|
|
|> element(~s{[data-test-session-id="#{session.id}"] button}, "Fork")
|
2021-03-26 02:04:49 +08:00
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
assert to =~ "/sessions/"
|
|
|
|
|
|
|
|
{:ok, view, _} = live(conn, to)
|
|
|
|
assert render(view) =~ "My notebook - fork"
|
2022-02-10 22:36:59 +08:00
|
|
|
|
2022-04-12 02:34:31 +08:00
|
|
|
close_session_by_path(to)
|
2022-02-10 22:36:59 +08:00
|
|
|
Session.close(session.pid)
|
2021-03-26 02:04:49 +08:00
|
|
|
end
|
|
|
|
|
2021-04-13 05:24:26 +08:00
|
|
|
test "allows closing session after confirmation", %{conn: conn} do
|
2021-09-05 01:16:01 +08:00
|
|
|
{:ok, session} = Sessions.create_session()
|
2021-03-26 02:04:49 +08:00
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-03-26 02:04:49 +08:00
|
|
|
|
2021-09-05 01:16:01 +08:00
|
|
|
assert render(view) =~ session.id
|
2021-03-26 02:04:49 +08:00
|
|
|
|
|
|
|
view
|
2021-09-05 01:16:01 +08:00
|
|
|
|> element(~s{[data-test-session-id="#{session.id}"] a}, "Close")
|
2021-03-26 02:04:49 +08:00
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
view
|
2022-01-29 04:45:04 +08:00
|
|
|
|> element(~s{button[role=button]}, "Close session")
|
2021-03-26 02:04:49 +08:00
|
|
|
|> render_click()
|
|
|
|
|
2021-09-05 01:16:01 +08:00
|
|
|
refute render(view) =~ session.id
|
2021-03-26 02:04:49 +08:00
|
|
|
end
|
2022-01-29 04:45:04 +08:00
|
|
|
|
|
|
|
test "close all selected sessions using bulk action", %{conn: conn} do
|
|
|
|
{:ok, session1} = Sessions.create_session()
|
|
|
|
{:ok, session2} = Sessions.create_session()
|
|
|
|
{:ok, session3} = Sessions.create_session()
|
|
|
|
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2022-01-29 04:45:04 +08:00
|
|
|
|
|
|
|
assert render(view) =~ session1.id
|
|
|
|
assert render(view) =~ session2.id
|
|
|
|
assert render(view) =~ session3.id
|
|
|
|
|
|
|
|
view
|
|
|
|
|> form("#bulk-action-form", %{
|
|
|
|
"action" => "close_all",
|
|
|
|
"session_ids" => [session1.id, session2.id, session3.id]
|
|
|
|
})
|
|
|
|
|> render_submit()
|
|
|
|
|
|
|
|
assert render(view) =~ "Are you sure you want to close 3 sessions?"
|
|
|
|
|
|
|
|
view
|
|
|
|
|> element(~s{button[role="button"]}, "Close sessions")
|
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
refute render(view) =~ session1.id
|
|
|
|
refute render(view) =~ session2.id
|
|
|
|
refute render(view) =~ session3.id
|
|
|
|
end
|
2021-02-21 23:54:44 +08:00
|
|
|
end
|
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
describe "starred notebooks" do
|
|
|
|
@tag :tmp_dir
|
|
|
|
test "starring and unstarring a notebook", %{conn: conn, tmp_dir: tmp_dir} do
|
|
|
|
notebook_path = Path.join(tmp_dir, "notebook.livemd")
|
|
|
|
file = Livebook.FileSystem.File.local(notebook_path)
|
2021-10-22 05:21:54 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
{:ok, session} = Sessions.create_session()
|
|
|
|
Session.set_file(session.pid, file)
|
|
|
|
Session.set_notebook_name(session.pid, "Special notebook")
|
2021-10-22 05:21:54 +08:00
|
|
|
|
2023-03-16 01:18:33 +08:00
|
|
|
wait_for_session_update(session.pid)
|
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-10-22 05:21:54 +08:00
|
|
|
|
2023-04-18 18:46:54 +08:00
|
|
|
Livebook.NotebookManager.add_starred_notebook(file, "Special notebook")
|
|
|
|
render(view)
|
2021-10-22 05:21:54 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
assert view
|
|
|
|
|> element(~s/#starred-notebooks/, "Special notebook")
|
|
|
|
|> has_element?()
|
2021-10-22 05:21:54 +08:00
|
|
|
|
2023-04-18 18:46:54 +08:00
|
|
|
Livebook.NotebookManager.remove_starred_notebook(file)
|
|
|
|
render(view)
|
2022-04-12 02:34:31 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
refute view
|
|
|
|
|> element(~s/#starred-notebooks/, "Special notebook")
|
|
|
|
|> has_element?()
|
2021-11-12 22:49:22 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
@tag :tmp_dir
|
2023-03-07 01:14:33 +08:00
|
|
|
test "opening a starred notebook", %{conn: conn, tmp_dir: tmp_dir} do
|
2021-11-12 22:49:22 +08:00
|
|
|
notebook_path = Path.join(tmp_dir, "notebook.livemd")
|
2023-03-07 01:14:33 +08:00
|
|
|
File.write!(notebook_path, "# Starred notebook")
|
|
|
|
file = Livebook.FileSystem.File.local(notebook_path)
|
|
|
|
Livebook.NotebookManager.add_starred_notebook(file, "Starred notebook")
|
2022-04-12 02:34:31 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2021-10-16 18:23:08 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
card_html =
|
|
|
|
view
|
|
|
|
|> element(~s/#starred-notebooks [data-test-idx]/, "Starred notebook")
|
|
|
|
|> render()
|
2021-10-16 18:23:08 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
assert [attr] = Regex.run(~r/data-test-idx="\d+"/, card_html)
|
2021-10-16 18:23:08 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
view
|
|
|
|
|> element(~s/#starred-notebooks [#{attr}] button/, "Open")
|
|
|
|
|> render_click()
|
2021-10-16 18:23:08 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
{to, _flash} = assert_redirect(view)
|
2021-10-16 18:23:08 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
assert to =~ "/sessions/"
|
2021-10-16 18:23:08 +08:00
|
|
|
|
|
|
|
{:ok, view, _} = live(conn, to)
|
2023-03-07 01:14:33 +08:00
|
|
|
assert render(view) =~ "Starred notebook"
|
|
|
|
|
|
|
|
close_session_by_path(to)
|
2021-10-16 18:23:08 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
describe "hubs sidebar" do
|
|
|
|
test "render section", %{conn: conn} do
|
|
|
|
{:ok, _view, html} = live(conn, ~p"/")
|
|
|
|
assert html =~ "HUBS"
|
|
|
|
assert html =~ "Add Hub"
|
2022-02-04 03:26:18 +08:00
|
|
|
end
|
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
test "render persisted hubs", %{conn: conn} do
|
|
|
|
fly = insert_hub(:fly, id: "fly-foo-bar-id")
|
2022-02-04 03:26:18 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
{:ok, _view, html} = live(conn, ~p"/")
|
|
|
|
assert html =~ "HUBS"
|
|
|
|
assert html =~ fly.hub_name
|
2022-04-12 02:34:31 +08:00
|
|
|
|
2023-03-07 01:14:33 +08:00
|
|
|
Livebook.Hubs.delete_hub("fly-foo-bar-id")
|
2022-02-04 03:26:18 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-07-11 02:16:55 +08:00
|
|
|
test "handles user profile update", %{conn: conn} do
|
2023-02-23 02:34:54 +08:00
|
|
|
{:ok, view, _} = live(conn, ~p"/")
|
2022-08-23 05:12:54 +08:00
|
|
|
data = %{user: %{name: "Jake Peralta", hex_color: "#123456"}}
|
2022-07-11 02:16:55 +08:00
|
|
|
|
|
|
|
view
|
|
|
|
|> element("#user_form")
|
2022-08-23 05:12:54 +08:00
|
|
|
|> render_change(data)
|
2022-07-11 02:16:55 +08:00
|
|
|
|
2022-08-23 05:12:54 +08:00
|
|
|
view
|
|
|
|
|> element("#user_form")
|
|
|
|
|> render_submit(data)
|
|
|
|
|
|
|
|
assert render(view) =~ "Jake Peralta"
|
2022-07-11 02:16:55 +08:00
|
|
|
assert render(view) =~ "#123456"
|
|
|
|
end
|
|
|
|
|
2021-02-21 23:54:44 +08:00
|
|
|
# Helpers
|
|
|
|
|
2022-04-12 02:34:31 +08:00
|
|
|
defp close_session_by_path("/sessions/" <> session_id) do
|
|
|
|
{:ok, session} = Sessions.fetch_session(session_id)
|
|
|
|
Session.close(session.pid)
|
|
|
|
end
|
2021-01-08 04:16:54 +08:00
|
|
|
end
|