mirror of
				https://github.com/livebook-dev/livebook.git
				synced 2025-10-31 15:56:05 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			147 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
| defmodule Livebook.TestHelpers do
 | |
|   import Phoenix.LiveViewTest
 | |
| 
 | |
|   alias Livebook.Session.Data
 | |
| 
 | |
|   @doc """
 | |
|   Creates file structure according to the given specification.
 | |
|   """
 | |
|   def create_tree!(path, items) do
 | |
|     for {name, content} <- items do
 | |
|       child_path = Path.join(path, to_string(name))
 | |
| 
 | |
|       case content do
 | |
|         items when is_list(items) ->
 | |
|           File.mkdir!(child_path)
 | |
|           create_tree!(child_path, items)
 | |
| 
 | |
|         content when is_binary(content) ->
 | |
|           File.write!(child_path, content)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Creates the given number of subdirectories and returns their paths.
 | |
|   """
 | |
|   def create_subdirs!(path, number) do
 | |
|     for n <- 1..number//1 do
 | |
|       child_path = Path.join(path, "subdir#{n}")
 | |
|       File.mkdir_p!(child_path)
 | |
|       child_path
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Applies the given list of operations to `Livebook.Session.Data`.
 | |
| 
 | |
|   Raises if any of the operations results in an error.
 | |
|   """
 | |
|   def data_after_operations!(data \\ Data.new(), operations) do
 | |
|     operations
 | |
|     |> List.flatten()
 | |
|     |> Enum.reduce(data, fn operation, data ->
 | |
|       case Data.apply_operation(data, operation) do
 | |
|         {:ok, data, _action} ->
 | |
|           data
 | |
| 
 | |
|         :error ->
 | |
|           raise "failed to set up test data, operation #{inspect(operation)} returned an error"
 | |
|       end
 | |
|     end)
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Converts a Unix-like absolute path into OS-compatible absolute path.
 | |
|   """
 | |
|   defmacro p("/" <> path), do: Path.expand("/") <> path
 | |
| 
 | |
|   @doc """
 | |
|   Confirms the action guarded by `LivebookWeb.Confirm/3` and
 | |
|   returns the rendered result.
 | |
|   """
 | |
|   def render_confirm(view, options \\ %{}) do
 | |
|     options =
 | |
|       for {option, value} <- options,
 | |
|           into: %{},
 | |
|           do: {Atom.to_string(option), Atom.to_string(value)}
 | |
| 
 | |
|     view
 | |
|     |> element(~s/[data-el-confirm-form]/)
 | |
|     |> render_submit(%{"options" => options})
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Builds code that renders the given output as part of evaluation.
 | |
|   """
 | |
|   def source_for_output(output) do
 | |
|     quote do
 | |
|       send(
 | |
|         Process.group_leader(),
 | |
|         {:io_request, self(), make_ref(), {:livebook_put_output, unquote(Macro.escape(output))}}
 | |
|       )
 | |
|     end
 | |
|     |> Macro.to_string()
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Builds code that renders the given output as part of evaluation.
 | |
|   """
 | |
|   def source_for_input_read(input_id) do
 | |
|     quote do
 | |
|       send(
 | |
|         Process.group_leader(),
 | |
|         {:io_request, self(), make_ref(), {:livebook_get_input_value, unquote(input_id)}}
 | |
|       )
 | |
|     end
 | |
|     |> Macro.to_string()
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Builds code that awaits for a messages before finishing.
 | |
| 
 | |
|   Returns `{code, continue_fun}`, where calling `continue_fun` should
 | |
|   continue execution. Embedded runtime must be used for this to work.
 | |
|   """
 | |
|   def source_for_blocking() do
 | |
|     name = Livebook.Utils.random_short_id() |> String.to_atom()
 | |
| 
 | |
|     code =
 | |
|       quote do
 | |
|         # This test uses the Embedded runtime, so we can target the
 | |
|         # process by name
 | |
|         Process.register(self(), unquote(name))
 | |
|         receive do: (:stop -> :ok)
 | |
|       end
 | |
|       |> Macro.to_string()
 | |
| 
 | |
|     ack_fun = fn ->
 | |
|       send(Process.whereis(name), :pong)
 | |
|     end
 | |
| 
 | |
|     {code, ack_fun}
 | |
|   end
 | |
| 
 | |
|   @doc """
 | |
|   Builds a terminal output map.
 | |
|   """
 | |
|   defmacro terminal_text(text, chunk \\ false) do
 | |
|     quote do
 | |
|       %{type: :terminal_text, text: unquote(text), chunk: unquote(chunk)}
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def clean_message(message) do
 | |
|     message
 | |
|     |> remove_trailing_whitespace()
 | |
|     |> remove_ansi()
 | |
|   end
 | |
| 
 | |
|   defp remove_trailing_whitespace(string) do
 | |
|     String.replace(string, ~r/ +$/m, "")
 | |
|   end
 | |
| 
 | |
|   defp remove_ansi(string) do
 | |
|     String.replace(string, ~r/\e\[\d+m/, "")
 | |
|   end
 | |
| end
 |