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, a list for a column of many values (field={[:tags, :name]}), and for a column with content the text of its cell.
Summary
Functions
Runs the action label on the rows selected in the grid id (:action,
see Masu.Action), as its button in the bar above the grid does, past
its question (confirm). Rows are selected with select/4 or
select_all/3.
The labels of the actions of your own (Masu.Action) that the grid id
offers: on the rows selected (actions(view, id, :selection), while
rows are selected), on the row row_id (actions(view, id, :row, row_id): those it shows, available or not), or for the column key
in its header menu (:header) or in the menu of its cells (:cell).
Opens the row row_id of the grid id (on_row_activate), as a click
on it or Enter does. The grid reads the row from its source.
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 editor of a cell of the grid id, as Escape does. Returns the view.
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), :async when the grid's
on_delete deletes them later, or {:error, errors, undo} with
{row_id, message} for each row that was not deleted. Options:
:origin, as edit/4.
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 history of the cell of the row row_id and the column key of the
grid id (history, see Masu.History), or of the row when key is
nil, newest first, as its popover shows it (none for a row the grid's
query does not show): maps of :id, :key,
:op, :before, :after (as the browser gets them), :user,
:origin, :batch, :batch_size and :at.
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.
Opens the editor of the cell of the row row_id and the column key
of the grid id, when the column's editor is a form of yours: the
grid renders it, which Phoenix.LiveViewTest.render/1 then has. A
value it would post is saved with edit/4, as the browser saves it.
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 value before an entry of the history of the grid id
(its :id, history/4), or, with {:batch, batch}, every cell of a
batch (someone's paste), as its Restore does: an edit, refused for a
cell that changed since. Returns {:ok, count} of the cells restored,
or {:error, errors} as edit/4 does.
Brings back the rows of a delete (its undo token, delete_rows/3), as
the person does with Ctrl+Z. Returns {:ok, ids}.
Runs the action label on the row row_id of the grid id
(:row_action, see Masu.Action), as its item in the row's menu
does, past its question (confirm). The grid reads the row from its
source.
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
@spec action(struct(), String.t(), String.t()) :: :ok | {:ok, String.t()} | {:error, String.t() | :refused} | :async
Runs the action label on the rows selected in the grid id (:action,
see Masu.Action), as its button in the bar above the grid does, past
its question (confirm). Rows are selected with select/4 or
select_all/3.
Returns the action's result: :ok, {:ok, message}, {:error, message} or :async (see Masu.Action), or {:error, :refused}
when the server refuses it: the grid does not offer it (:if), or no
row is selected.
The labels of the actions of your own (Masu.Action) that the grid id
offers: on the rows selected (actions(view, id, :selection), while
rows are selected), on the row row_id (actions(view, id, :row, row_id): those it shows, available or not), or for the column key
in its header menu (:header) or in the menu of its cells (:cell).
@spec activate_row(struct(), String.t(), term()) :: :ok | {:navigate | :patch, String.t()} | {:error, :refused}
Opens the row row_id of the grid id (on_row_activate), as a click
on it or Enter does. The grid reads the row from its source.
Returns what the grid does: {:patch, path} or {:navigate, path}
when the function gives one, else :ok; {:error, :refused} when the
grid has no on_row_activate or no row row_id in its query.
@spec add_rows(struct(), String.t(), map() | [map()], keyword()) :: {: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). Options: :origin, as edit/4.
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 editor of a cell of the grid id, as Escape does. Returns the view.
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, keyword()) :: {:ok, String.t() | nil} | :async | {: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), :async when the grid's
on_delete deletes them later, or {:error, errors, undo} with
{row_id, message} for each row that was not deleted. Options:
:origin, as edit/4.
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(), [tuple()], keyword()) :: :ok | :async | {: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, :async when the grid's
on_update saves them later (Masu.Write.async/1), or {:error, errors} with {row_id, key, message} for each cell that was not.
Options: :origin, what the person did, as Masu.Write's origin
says (:paste, :fill...); :test unless given.
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.
filter(view, "orders", [{"customer.name", :eq, "Ana"}, {"tags", :all_of, ["gift"]}])
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 history of the cell of the row row_id and the column key of the
grid id (history, see Masu.History), or of the row when key is
nil, newest first, as its popover shows it (none for a row the grid's
query does not show): maps of :id, :key,
:op, :before, :after (as the browser gets them), :user,
:origin, :batch, :batch_size and :at.
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.
Opens the editor of the cell of the row row_id and the column key
of the grid id, when the column's editor is a form of yours: the
grid renders it, which Phoenix.LiveViewTest.render/1 then has. A
value it would post is saved with edit/4, as the browser saves it.
Returns the view.
@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.
@spec restore(struct(), String.t(), String.t() | {:batch, String.t()}) :: {:ok, non_neg_integer()} | {:error, [{term(), String.t(), String.t()}]}
Brings back the value before an entry of the history of the grid id
(its :id, history/4), or, with {:batch, batch}, every cell of a
batch (someone's paste), as its Restore does: an edit, refused for a
cell that changed since. Returns {:ok, count} of the cells restored,
or {:error, errors} as edit/4 does.
Brings back the rows of a delete (its undo token, delete_rows/3), as
the person does with Ctrl+Z. Returns {:ok, ids}.
@spec row_action(struct(), String.t(), String.t(), term()) :: :ok | {:ok, String.t()} | {:error, String.t() | :refused} | :async | {:navigate | :patch, String.t()}
Runs the action label on the row row_id of the grid id
(:row_action, see Masu.Action), as its item in the row's menu
does, past its question (confirm). The grid reads the row from its
source.
Returns the action's result, as action/3 does; for a link, the path
it goes to, {:navigate, path} or {:patch, path}; and {:error, :refused} when the server refuses it: the grid does not offer it, the
row does not show it, or it is disabled for the row.
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.
A column of a related row's field (field={[:customer, :name]}) is
named by its key, the path with dots unless given:
sort(view, "orders", {"customer.name", :desc}).
@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.