Packages

Canvas for Phoenix: nodes of your own HEEx on an endless sheet, joined by edges, with every change checked on the server and live collaboration.

Current section

Files

Jump to
hakushi guides testing.md
Raw

guides/testing.md

# Testing

`Hakushi.Test` reads and changes the canvases of a LiveView in
`Phoenix.LiveViewTest`, with no browser.

```elixir
import Hakushi.Test

test "a foreign key joins columns of one type", %{conn: conn} do
  {:ok, view, _html} = live(conn, ~p"/schema")

  assert :ok = connect(view, "schema", {"orders", "user_id"}, {"users", "id"})
  assert %{target: "users"} = Enum.find(edges(view, "schema"), &(&1.source == "orders"))

  assert {:error, "These columns are not of one type."} =
           connect(view, "schema", {"orders", "total"}, {"users", "id"})
end
```

The functions send the events the browser sends, so each change goes
the way of a person's: the rules, `on_change`, the room of a shared
canvas. A change the canvas refuses gives `{:error, reason}`, with the
words the person sees.

| | |
| --- | --- |
| `nodes/2`, `edges/2` | what the canvas shows, as maps (a node's `:parent` is its group) |
| `move/4` | `move(view, id, "node", {x, y})`, or several with sizes, or maps with a `:parent` for a drop into a group |
| `connect/4` | ends as a node's id or `{node, handle}` |
| `reconnect/4` | `source:` or `target:`, the new end of an edge |
| `remove/3` | `nodes:` and `edges:` (not `delete`, which `Phoenix.ConnTest` has) |
| `label/4` | an edge's label |
| `copy_paste/4`, `duplicate/3` | `{:ok, ids}` of the copies |
| `drop/4` | an item, through `new_node` |
| `undo/2`, `redo/2` | the LiveView's person's own changes |
| `notice/2` | the reason the canvas shows for its last refusal |
| `people/2` | the others on a shared canvas |

A shared canvas in a test is shared with the other LiveViews of its
topic in the test: open two, as two people, to test what one sees of the
other. Start an Issho instance for the tests (`Issho.Test.start!/1`
starts one per test), and give its rooms a short life with its `:ttl`
(50 milliseconds, say).

A change one person makes reaches the other's LiveView as a message:
before you look at the other's canvas, let its LiveView handle its
mailbox (`:sys.get_state(view.pid)`, twice: once for the change, once
for the update of the canvas it sends itself).