From c674a0ec5d14eaa058ca73df6b0734c6bb3af6bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Sat, 26 Jun 2021 00:53:12 +0200 Subject: [PATCH] Normalize textarea newlines (#402) * Normalize textarea newlines * Add test --- lib/livebook_web/live/session_live.ex | 4 ++ test/livebook_web/live/session_live_test.exs | 40 +++++++++++++++----- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/livebook_web/live/session_live.ex b/lib/livebook_web/live/session_live.ex index bc4302669..46a61f476 100644 --- a/lib/livebook_web/live/session_live.ex +++ b/lib/livebook_web/live/session_live.ex @@ -432,6 +432,10 @@ defmodule LivebookWeb.SessionLive do end def handle_event("set_cell_value", %{"cell_id" => cell_id, "value" => value}, socket) do + # The browser may normalize newlines to \r\n, but we want \n + # to more closely imitate an actual shell + value = String.replace(value, "\r\n", "\n") + Session.set_cell_attributes(socket.assigns.session_id, cell_id, %{value: value}) {:noreply, socket} diff --git a/test/livebook_web/live/session_live_test.exs b/test/livebook_web/live/session_live_test.exs index 59515cc79..0b87fd4cf 100644 --- a/test/livebook_web/live/session_live_test.exs +++ b/test/livebook_web/live/session_live_test.exs @@ -52,14 +52,14 @@ defmodule LivebookWeb.SessionLiveTest do {:ok, view, _} = live(conn, "/sessions/#{session_id}") - cell_id = insert_cell(session_id, section_id, :markdown) + cell_id = insert_text_cell(session_id, section_id, :markdown) assert render(view) =~ cell_id end test "un-renders a deleted cell", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :markdown) + cell_id = insert_text_cell(session_id, section_id, :markdown) {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -96,7 +96,7 @@ defmodule LivebookWeb.SessionLiveTest do test "queueing cell evaluation", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir, "Process.sleep(10)") + cell_id = insert_text_cell(session_id, section_id, :elixir, "Process.sleep(10)") {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -110,7 +110,7 @@ defmodule LivebookWeb.SessionLiveTest do test "cancelling cell evaluation", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir, "Process.sleep(2000)") + cell_id = insert_text_cell(session_id, section_id, :elixir, "Process.sleep(2000)") {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -128,7 +128,7 @@ defmodule LivebookWeb.SessionLiveTest do test "inserting a cell below the given cell", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir) + cell_id = insert_text_cell(session_id, section_id, :elixir) {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -142,7 +142,7 @@ defmodule LivebookWeb.SessionLiveTest do test "inserting a cell above the given cell", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir) + cell_id = insert_text_cell(session_id, section_id, :elixir) {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -156,7 +156,7 @@ defmodule LivebookWeb.SessionLiveTest do test "deleting the given cell", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir) + cell_id = insert_text_cell(session_id, section_id, :elixir) {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -166,6 +166,20 @@ defmodule LivebookWeb.SessionLiveTest do assert %{notebook: %{sections: [%{cells: []}]}} = Session.get_data(session_id) end + + test "newlines in input values are normalized", %{conn: conn, session_id: session_id} do + section_id = insert_section(session_id) + cell_id = insert_input_cell(session_id, section_id) + + {:ok, view, _} = live(conn, "/sessions/#{session_id}") + + view + |> element(~s/form[phx-change="set_cell_value"]/) + |> render_change(%{"value" => "line\r\nline"}) + + assert %{notebook: %{sections: [%{cells: [%{id: ^cell_id, value: "line\nline"}]}]}} = + Session.get_data(session_id) + end end describe "runtime settings" do @@ -220,7 +234,7 @@ defmodule LivebookWeb.SessionLiveTest do test "replies with nil completion reference when no runtime is started", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir, "Process.sleep(10)") + cell_id = insert_text_cell(session_id, section_id, :elixir, "Process.sleep(10)") {:ok, view, _} = live(conn, "/sessions/#{session_id}") @@ -234,7 +248,7 @@ defmodule LivebookWeb.SessionLiveTest do test "replies with completion reference and then sends asynchronous response", %{conn: conn, session_id: session_id} do section_id = insert_section(session_id) - cell_id = insert_cell(session_id, section_id, :elixir, "Process.sleep(10)") + cell_id = insert_text_cell(session_id, section_id, :elixir, "Process.sleep(10)") {:ok, runtime} = Livebook.Runtime.Embedded.init() Session.connect_runtime(session_id, runtime) @@ -364,7 +378,7 @@ defmodule LivebookWeb.SessionLiveTest do section.id end - defp insert_cell(session_id, section_id, type, content \\ "") do + defp insert_text_cell(session_id, section_id, type, content \\ "") do Session.insert_cell(session_id, section_id, 0, type) %{notebook: %{sections: [%{cells: [cell]}]}} = Session.get_data(session_id) @@ -380,6 +394,12 @@ defmodule LivebookWeb.SessionLiveTest do cell.id end + defp insert_input_cell(session_id, section_id) do + Session.insert_cell(session_id, section_id, 0, :input) + %{notebook: %{sections: [%{cells: [cell]}]}} = Session.get_data(session_id) + cell.id + end + defp create_user_with_name(name) do {:ok, user} = User.new() |> User.change(%{"name" => name}) user