Current section

5 Versions

Jump to

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(),