Helpers for Phoenix.LiveViewTest, to read and query the grids of a
LiveView with no browser.
import Masu.Test
test "finds the late orders", %{conn: conn} do
{:ok, view, _html} = live(conn, ~p"/orders")
assert total(view, "orders") == 120
view
|> filter("orders", [{"status", :eq, "late"}])
|> sort("orders", {"total", :desc})
assert [%{"number" => "A-1042"} | _] = rows(view, "orders")
endThe functions send the events that the browser sends (see Masu.Grid),
so the grid applies a sort, a filter or a search as it does for a
person: the source sorts, filters and counts, and rows/3 reads the
rows it gives.
Changes broadcast with Masu.Live before a call are in the rows it
reads: the call waits for the LiveView to take them.
A row is a map of each column's key to its value as the browser gets it: numbers and booleans as they are, decimals as strings, dates and times in ISO 8601, and for a column with content the text of its cell.
Summary
Functions
The labels of the items of the app's own (Masu.Action) that the grid
id offers for the column key: in its header menu (:header), or in
the menu of its cells (:cell).
Adds rows to the grid id, as the person does with "New row" or a
paste below the last row: each a map of column keys (or atoms) to
values, as the browser sends them. The grid saves each through its
create, or its changeset of its struct.
Applies a view to the grid id, as a link or a saved view does: params
as view/2 gives them (%{} for the grid's own view). Returns the
keys of the columns of the parts that no longer apply (see
Masu.View.from_params/3).
Asks the grid id for its count, as the person does when they go to
the end of a grid that does not know it (Ctrl+End): {:exact, n}, or
{:at_least, n} from a source that does not know it either.
Runs the item label of the menu of the cell of the row row_id and
the column key of the grid id, as header_action/4 does. The grid
reads the row and the value of the cell from its source.
Closes the panel of an item of the grid id, as Escape does. Returns the view.
Closes the row row_id of a tree in the grid id. Returns the view.
The labels of the columns of the grid id, in order.
What the grid id knows of its count: {:exact, n}, or
{:at_least, n} while it does not know it (count={:none}, a count
not in yet, or a source that does not count). total/2 gives n.
Deletes the rows ids of the grid id, or, with :selection, the
rows selected (select/4, select_all/3), as the person does with
Ctrl+Delete. Returns {:ok, undo}, with the token that brings them back
(restore_rows/3; nil when the grid cannot), or {:error, errors, undo}
with {row_id, message} for each row that was not deleted.
Opens (or, with false, closes) the detail of the row row_id in the
grid id: the grid renders its :detail slot for the row, which
Phoenix.LiveViewTest.render/1 then has. Returns the view.
Edits cells of the grid id, as a person typing in them, pasting or
undoing does: edits is a list of {row_id, key, value}, the value as
the browser sends it (a string, or nil to empty the cell). The grid
saves the edits of each row together.
Opens the row row_id of a tree in the grid id, as a click on its
arrow (or →) does: its children show under it. Returns the view.
Opens every row beside row_id that has children, as * does.
Returns the view.
Exports the grid id as its Export menu does (Masu.Export), and
downloads the file from the link the browser gets, through the
endpoint and the router's export route (Masu.Router): {name, binary}. A conn (Phoenix.ConnTest.build_conn/0, with what the
route's pipeline wants of it, a signed-in user) is given with :conn.
The link the Export menu of the grid id gives the browser, for a
test of the route itself: that it wants a signed-in user, say.
Filters the grid id: filters is a list of {key, op, value} (see
Masu.Filter for the operators), which replaces the grid's filters.
Returns the view.
Groups the rows of the grid id by columns (Masu.Group), as the
header menu does: keys, the first the outermost; [] stops
grouping. Returns the view.
Runs the item label of the header menu of the column key of the
grid id, as a click on it does: its function, its event to the
LiveView, or its panel, which Phoenix.LiveViewTest.render/1 then has.
An item that is only a JS command runs in the browser, not here.
Returns the view.
The ids of the rows of the grid id, as rows/3 reads them.
Changes the layout of the grid id, as its columns menu, its headers
and their edges do: any of order: keys (every column, in order),
hidden: keys, pinned: %{key => :start | :end} and widths: %{key => pixels}. Returns the view.
Goes to a page of the grid id (paging={:pages}), from 1, as its
pager does, and gives the ids of its rows.
The place (from 0) of the row row_id in the grid's current order, or
nil when its query leaves the row out: where the grid scrolls to
follow another person to it.
Brings back the rows of a delete (its undo token, delete_rows/3), as
the person does with Ctrl+Z. Returns {:ok, ids}.
The rows of the grid id, in its current order.
Searches the grid id as its search box does. Returns the view.
Selects rows of the grid id (selectable) by their ids, as their
boxes do, or, with false, takes them out. Returns the view.
Selects every row of the query of the grid id (or, with false, none). Returns the view.
The selection of the grid id: %{all: boolean, ids: [...], except: [...], count: n}.
Sorts the grid id as clicks on its headers do: sorts is a key, a
{key, :asc | :desc}, or a list of them (the first the most
important). [] takes the order away. Returns the view.
How many rows the grid id has for its current query.
The totals of the query of the grid id, by column key: the row of
totals at its bottom (Masu.Group). nil when no column has an
aggregate.
The values that the filter menu of the column key offers: the values
of the column among the rows of the query (without the column's own
filters), each with its count, the most frequent first. :search
narrows them as the menu's search box does.
The view of the grid id, as its params (see Masu.View): what differs
from the grid's own view. %{} is the grid's own view.
Functions
The labels of the items of the app's own (Masu.Action) that the grid
id offers for the column key: in its header menu (:header), or in
the menu of its cells (:cell).
@spec add_rows(struct(), String.t(), map() | [map()]) :: {:ok, [term()]} | {:error, ok: term(), error: [{String.t() | nil, String.t()}]}
Adds rows to the grid id, as the person does with "New row" or a
paste below the last row: each a map of column keys (or atoms) to
values, as the browser sends them. The grid saves each through its
create, or its changeset of its struct.
Returns {:ok, ids} when every row was saved, or {:error, results},
a result for each row: {:ok, id} or {:error, [{key, message}]} (a
key of nil for an error of the row).
Applies a view to the grid id, as a link or a saved view does: params
as view/2 gives them (%{} for the grid's own view). Returns the
keys of the columns of the parts that no longer apply (see
Masu.View.from_params/3).
@spec ask_count(struct(), String.t()) :: {:exact | :at_least, non_neg_integer()}
Asks the grid id for its count, as the person does when they go to
the end of a grid that does not know it (Ctrl+End): {:exact, n}, or
{:at_least, n} from a source that does not know it either.
@spec cell_action( struct(), String.t(), String.t(), String.t() | atom(), term(), keyword() ) :: struct()
Runs the item label of the menu of the cell of the row row_id and
the column key of the grid id, as header_action/4 does. The grid
reads the row and the value of the cell from its source.
Options: :range, {ids, keys}: a range of cells selected, its rows'
ids and its columns' keys, that the cell is in.
Closes the panel of an item of the grid id, as Escape does. Returns the view.
Closes the row row_id of a tree in the grid id. Returns the view.
The labels of the columns of the grid id, in order.
@spec count(struct(), String.t()) :: {:exact | :at_least, non_neg_integer()}
What the grid id knows of its count: {:exact, n}, or
{:at_least, n} while it does not know it (count={:none}, a count
not in yet, or a source that does not count). total/2 gives n.
@spec delete_rows(struct(), String.t(), [term()] | :selection) :: {:ok, String.t() | nil} | {:error, [{term(), String.t()}], String.t() | nil}
Deletes the rows ids of the grid id, or, with :selection, the
rows selected (select/4, select_all/3), as the person does with
Ctrl+Delete. Returns {:ok, undo}, with the token that brings them back
(restore_rows/3; nil when the grid cannot), or {:error, errors, undo}
with {row_id, message} for each row that was not deleted.
Opens (or, with false, closes) the detail of the row row_id in the
grid id: the grid renders its :detail slot for the row, which
Phoenix.LiveViewTest.render/1 then has. Returns the view.
@spec edit(struct(), String.t(), [{term(), String.t() | atom(), term()}]) :: :ok | {:error, [{term(), String.t(), String.t()}]}
Edits cells of the grid id, as a person typing in them, pasting or
undoing does: edits is a list of {row_id, key, value}, the value as
the browser sends it (a string, or nil to empty the cell). The grid
saves the edits of each row together.
An edit may be {row_id, key, value, before}, with the value the person
saw: the grid refuses it when the cell's value changed meanwhile, as it
does for the browser.
Returns :ok when every edit was saved, or {:error, errors} with
{row_id, key, message} for each cell that was not.
Opens the row row_id of a tree in the grid id, as a click on its
arrow (or →) does: its children show under it. Returns the view.
Opens every row beside row_id that has children, as * does.
Returns the view.
Exports the grid id as its Export menu does (Masu.Export), and
downloads the file from the link the browser gets, through the
endpoint and the router's export route (Masu.Router): {name, binary}. A conn (Phoenix.ConnTest.build_conn/0, with what the
route's pipeline wants of it, a signed-in user) is given with :conn.
The link the Export menu of the grid id gives the browser, for a
test of the route itself: that it wants a signed-in user, say.
Filters the grid id: filters is a list of {key, op, value} (see
Masu.Filter for the operators), which replaces the grid's filters.
Returns the view.
Groups the rows of the grid id by columns (Masu.Group), as the
header menu does: keys, the first the outermost; [] stops
grouping. Returns the view.
The rows of a grouped grid id that are groups, in order, as maps of
:id (what expand/3 takes), :key, :value, :count, :level,
:expanded and :totals (by column key). Options as rows/3.
Runs the item label of the header menu of the column key of the
grid id, as a click on it does: its function, its event to the
LiveView, or its panel, which Phoenix.LiveViewTest.render/1 then has.
An item that is only a JS command runs in the browser, not here.
Returns the view.
The ids of the rows of the grid id, as rows/3 reads them.
Changes the layout of the grid id, as its columns menu, its headers
and their edges do: any of order: keys (every column, in order),
hidden: keys, pinned: %{key => :start | :end} and widths: %{key => pixels}. Returns the view.
The rows of a tree (Masu.Tree) in the grid id, in order, as maps
of :id, :level (0 for a root), :children (whether it has any) and
:expanded. Options as rows/3.
@spec page(struct(), String.t(), pos_integer()) :: [term()]
Goes to a page of the grid id (paging={:pages}), from 1, as its
pager does, and gives the ids of its rows.
@spec place(struct(), String.t(), term()) :: non_neg_integer() | nil
The place (from 0) of the row row_id in the grid's current order, or
nil when its query leaves the row out: where the grid scrolls to
follow another person to it.
Brings back the rows of a delete (its undo token, delete_rows/3), as
the person does with Ctrl+Z. Returns {:ok, ids}.
The rows of the grid id, in its current order.
Options: :from (0), the first row, and :count (100), how many
(at most 500, as the browser asks).
Searches the grid id as its search box does. Returns the view.
Selects rows of the grid id (selectable) by their ids, as their
boxes do, or, with false, takes them out. Returns the view.
Selects every row of the query of the grid id (or, with false, none). Returns the view.
The selection of the grid id: %{all: boolean, ids: [...], except: [...], count: n}.
Sorts the grid id as clicks on its headers do: sorts is a key, a
{key, :asc | :desc}, or a list of them (the first the most
important). [] takes the order away. Returns the view.
@spec total(struct(), String.t()) :: non_neg_integer()
How many rows the grid id has for its current query.
The totals of the query of the grid id, by column key: the row of
totals at its bottom (Masu.Group). nil when no column has an
aggregate.
The values that the filter menu of the column key offers: the values
of the column among the rows of the query (without the column's own
filters), each with its count, the most frequent first. :search
narrows them as the menu's search box does.
The view of the grid id, as its params (see Masu.View): what differs
from the grid's own view. %{} is the grid's own view.