Current section
5 Versions
Jump to
Current section
5 Versions
Compare versions
5
files changed
+214
additions
-5
deletions
| @@ -1,5 +1,31 @@ | |
| 1 1 | # Used by "mix format" |
| 2 2 | [ |
| 3 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], |
| 4 | - import_deps: [:phoenix_live_view] |
| 4 | + import_deps: [:phoenix_live_view], |
| 5 | + locals_without_parens: [ |
| 6 | + assert_receive_event: 3, |
| 7 | + assert_receive_event: 4, |
| 8 | + assert_receive_event: 5, |
| 9 | + assert_received_event: 3, |
| 10 | + assert_received_event: 4, |
| 11 | + refute_receive_event: 3, |
| 12 | + refute_receive_event: 4, |
| 13 | + refute_receive_event: 5, |
| 14 | + refute_received_event: 3, |
| 15 | + refute_received_event: 4 |
| 16 | + ], |
| 17 | + export: [ |
| 18 | + locals_without_parens: [ |
| 19 | + assert_receive_event: 3, |
| 20 | + assert_receive_event: 4, |
| 21 | + assert_receive_event: 5, |
| 22 | + assert_received_event: 3, |
| 23 | + assert_received_event: 4, |
| 24 | + refute_receive_event: 3, |
| 25 | + refute_receive_event: 4, |
| 26 | + refute_receive_event: 5, |
| 27 | + refute_received_event: 3, |
| 28 | + refute_received_event: 4 |
| 29 | + ] |
| 30 | + ] |
| 5 31 | ] |
| @@ -9,6 +9,35 @@ LiveEvent standardizes the API for emitting and handling events between LiveView | |
| 9 9 | |
| 10 10 | Please see [the docs](https://hexdocs.pm/live_event/) for full documentation and examples. |
| 11 11 | |
| 12 | + ## Usage |
| 13 | + |
| 14 | + Simply add `use LiveEvent.LiveView` and `use LiveEvent.LiveComponent` to any LiveView or LiveComponent, respectively, to opt-in to LiveEvent's functionality. |
| 15 | + |
| 16 | + Imagine a LiveComponent that has an `:on_selected` event assign that is raised like so: |
| 17 | + |
| 18 | + ```elixir |
| 19 | + emit(socket, :on_selected) |
| 20 | + ``` |
| 21 | + |
| 22 | + To handle the event on a LiveView, pass a pid to the event assign. |
| 23 | + |
| 24 | + ```heex |
| 25 | + <.live_component module={MyComponent} id="foo" on_selected={self()}> |
| 26 | + ``` |
| 27 | + |
| 28 | + To handle the event on a LiveComponent, pass `{module, id}` to the event assign. |
| 29 | + |
| 30 | + ```heex |
| 31 | + <.live_component module={MyComponent} id="foo" on_selected={{__MODULE__, @id}}> |
| 32 | + ``` |
| 33 | + |
| 34 | + In both cases, the event is handled by the `c:LiveEvent.handle_event/4` callback. |
| 35 | + |
| 36 | + ```elixir |
| 37 | + # On a LiveView OR LiveComponent |
| 38 | + def handle_event(:on_selected, {MyComponent, "foo"}, _payload, socket), do: ... |
| 39 | + ``` |
| 40 | + |
| 12 41 | ## Example |
| 13 42 | |
| 14 43 | ```elixir |
| @@ -6,8 +6,9 @@ | |
| 6 6 | [<<"lib">>,<<"lib/live_event">>,<<"lib/live_event/event.ex">>, |
| 7 7 | <<"lib/live_event/internal.ex">>,<<"lib/live_event/live_view.ex">>, |
| 8 8 | <<"lib/live_event/live_component.ex">>,<<"lib/live_event.ex">>, |
| 9 | - <<"lib/live_event_test">>,<<"lib/live_event_test/endpoint.ex">>, |
| 10 | - <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}. |
| 9 | + <<"lib/live_event_test">>,<<"lib/live_event_test/assertions.ex">>, |
| 10 | + <<"lib/live_event_test/endpoint.ex">>,<<".formatter.exs">>,<<"mix.exs">>, |
| 11 | + <<"README.md">>,<<"LICENSE">>]}. |
| 11 12 | {<<"licenses">>,[<<"MIT">>]}. |
| 12 13 | {<<"links">>,[{<<"GitHub">>,<<"https://github.com/schrockwell/live_event">>}]}. |
| 13 14 | {<<"name">>,<<"live_event">>}. |
| @@ -17,4 +18,4 @@ | |
| 17 18 | {<<"optional">>,false}, |
| 18 19 | {<<"repository">>,<<"hexpm">>}, |
| 19 20 | {<<"requirement">>,<<"~> 0.16">>}]]}. |
| 20 | - {<<"version">>,<<"0.1.0">>}. |
| 21 | + {<<"version">>,<<"0.1.1">>}. |
| @@ -0,0 +1,153 @@ | |
| 1 | + defmodule LiveEventTest.Assertions do |
| 2 | + @moduledoc """ |
| 3 | + Test assertion helpers for LiveEvent. |
| 4 | + |
| 5 | + These assertions are designed to work by passing `self()` to the event assign under test, and then asserting that |
| 6 | + the test process received the LiveEvent message. |
| 7 | + """ |
| 8 | + import ExUnit.Assertions |
| 9 | + |
| 10 | + @doc """ |
| 11 | + Asserts that an event is or was received by the test process. |
| 12 | + |
| 13 | + This is a thin wrapper around `ExUnit.Assertions.assert_receive/3`, so look there |
| 14 | + for more docs. |
| 15 | + |
| 16 | + ## Example |
| 17 | + |
| 18 | + # On a LiveComponent with the :on_clicked event assign set to self() |
| 19 | + emit(socket, :on_clicked, %{id: 123}) |
| 20 | + |
| 21 | + # In the test |
| 22 | + assert_receive_event :on_clicked, _source, %{id: 123} |
| 23 | + |
| 24 | + """ |
| 25 | + @spec assert_receive_event( |
| 26 | + event_name :: atom, |
| 27 | + source :: any, |
| 28 | + payload :: any, |
| 29 | + timeout :: non_neg_integer() | nil, |
| 30 | + failure_message :: String.t() | nil |
| 31 | + ) :: any |
| 32 | + defmacro assert_receive_event( |
| 33 | + event_name, |
| 34 | + source, |
| 35 | + payload, |
| 36 | + timeout \\ nil, |
| 37 | + failure_message \\ nil |
| 38 | + ) do |
| 39 | + quote do |
| 40 | + assert_receive %LiveEvent.Event{ |
| 41 | + name: unquote(event_name), |
| 42 | + source: unquote(source), |
| 43 | + payload: unquote(payload) |
| 44 | + }, |
| 45 | + unquote(timeout), |
| 46 | + unquote(failure_message) |
| 47 | + end |
| 48 | + end |
| 49 | + |
| 50 | + @doc """ |
| 51 | + Asserts that an event was received by the test process. |
| 52 | + |
| 53 | + This is a thin wrapper around `ExUnit.Assertions.assert_received/2`, so look there |
| 54 | + for more docs. |
| 55 | + |
| 56 | + ## Example |
| 57 | + |
| 58 | + # On a LiveComponent with the :on_clicked event assign set to self() |
| 59 | + emit(socket, :on_clicked, %{id: 123}) |
| 60 | + |
| 61 | + # In the test |
| 62 | + assert_received_event :on_clicked, _source, %{id: 123} |
| 63 | + |
| 64 | + """ |
| 65 | + @spec assert_received_event( |
| 66 | + event_name :: atom, |
| 67 | + source :: any, |
| 68 | + payload :: any, |
| 69 | + failure_message :: String.t() | nil |
| 70 | + ) :: any |
| 71 | + defmacro assert_received_event(event_name, source, payload, failure_message \\ nil) do |
| 72 | + quote do |
| 73 | + assert_received %LiveEvent.Event{ |
| 74 | + name: unquote(event_name), |
| 75 | + source: unquote(source), |
| 76 | + payload: unquote(payload) |
| 77 | + }, |
| 78 | + unquote(failure_message) |
| 79 | + end |
| 80 | + end |
| 81 | + |
| 82 | + @doc """ |
| 83 | + Asserts that an event isn't or wasn't received by the test process. |
| 84 | + |
| 85 | + This is a thin wrapper around `ExUnit.Assertions.refute_receive/3`, so look there |
| 86 | + for more docs. |
| 87 | + |
| 88 | + ## Example |
| 89 | + |
| 90 | + # On a LiveComponent with the :on_clicked event assign set to self() |
| 91 | + emit(socket, :on_clicked, %{id: 123}) |
| 92 | + |
| 93 | + # In the test |
| 94 | + refute_receive_event :on_clicked, _source, %{id: 123} |
| 95 | + |
| 96 | + """ |
| 97 | + @spec refute_receive_event( |
| 98 | + event_name :: atom, |
| 99 | + source :: any, |
| 100 | + payload :: any, |
| 101 | + timeout :: non_neg_integer() | nil, |
| 102 | + failure_message :: String.t() | nil |
| 103 | + ) :: any |
| 104 | + defmacro refute_receive_event( |
| 105 | + event_name, |
| 106 | + source, |
| 107 | + payload, |
| 108 | + timeout \\ nil, |
| 109 | + failure_message \\ nil |
| 110 | + ) do |
| 111 | + quote do |
| 112 | + refute_receive %LiveEvent.Event{ |
| 113 | + name: unquote(event_name), |
| 114 | + source: unquote(source), |
| 115 | + payload: unquote(payload) |
| 116 | + }, |
| 117 | + unquote(timeout), |
| 118 | + unquote(failure_message) |
| 119 | + end |
| 120 | + end |
| 121 | + |
| 122 | + @doc """ |
| 123 | + Asserts that an event wasn't received by the test process. |
| 124 | + |
| 125 | + This is a thin wrapper around `ExUnit.Assertions.refute_received/2`, so look there |
| 126 | + for more docs. |
| 127 | + |
| 128 | + ## Example |
| 129 | + |
| 130 | + # On a LiveComponent with the :on_clicked event assign set to self() |
| 131 | + emit(socket, :on_clicked, %{id: 123}) |
| 132 | + |
| 133 | + # In the test |
| 134 | + refute_received_event :on_clicked, _source, %{id: 123} |
| 135 | + |
| 136 | + """ |
| 137 | + @spec refute_received_event( |
| 138 | + event_name :: atom, |
| 139 | + source :: any, |
| 140 | + payload :: any, |
| 141 | + failure_message :: String.t() | nil |
| 142 | + ) :: any |
| 143 | + defmacro refute_received_event(event_name, source, payload, failure_message \\ nil) do |
| 144 | + quote do |
| 145 | + refute_received %LiveEvent.Event{ |
| 146 | + name: unquote(event_name), |
| 147 | + source: unquote(source), |
| 148 | + payload: unquote(payload) |
| 149 | + }, |
| 150 | + unquote(failure_message) |
| 151 | + end |
| 152 | + end |
| 153 | + end |
| @@ -4,7 +4,7 @@ defmodule LiveEvent.MixProject do | |
| 4 4 | def project do |
| 5 5 | [ |
| 6 6 | app: :live_event, |
| 7 | - version: "0.1.0", |
| 7 | + version: "0.1.1", |
| 8 8 | elixir: "~> 1.14", |
| 9 9 | start_permanent: Mix.env() == :prod, |
| 10 10 | deps: deps(), |