Skip to content

Commit 92a79b0

Browse files
Adds guards support in assert_push, assert_broadcast and assert_reply (#6595)
1 parent ac12eec commit 92a79b0

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

lib/phoenix/test/channel_test.ex

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -557,12 +557,15 @@ defmodule Phoenix.ChannelTest do
557557
assert_push "some_event", expected_payload
558558
# The code above does not assert the payload matches the described map.
559559
560+
Guards can also be given to the payload pattern:
561+
562+
assert_push "some_event", %{"counter" => c} when c > 0
560563
"""
561564
defmacro assert_push(event, payload, timeout \\ Application.fetch_env!(:ex_unit, :assert_receive_timeout)) do
565+
pattern = extract_pattern_and_apply_guard(event, payload, Phoenix.Socket.Message)
566+
562567
quote do
563-
assert_receive %Phoenix.Socket.Message{
564-
event: unquote(event),
565-
payload: unquote(payload)}, unquote(timeout)
568+
assert_receive unquote(pattern), unquote(timeout)
566569
end
567570
end
568571

@@ -579,6 +582,7 @@ defmodule Phoenix.ChannelTest do
579582
will certainly slow down your test suite.
580583
"""
581584
defmacro refute_push(event, payload, timeout \\ Application.fetch_env!(:ex_unit, :refute_receive_timeout)) do
585+
582586
quote do
583587
refute_receive %Phoenix.Socket.Message{
584588
event: unquote(event),
@@ -600,14 +604,27 @@ defmodule Phoenix.ChannelTest do
600604
601605
The timeout is in milliseconds and defaults to the `:assert_receive_timeout`
602606
set on the `:ex_unit` application (which defaults to 100ms).
607+
608+
Guards can also be given to the payload pattern:
609+
610+
ref = push(channel, "some_event")
611+
assert_reply ref, :ok, %{"counter" => c} when c > 0
603612
"""
604613
defmacro assert_reply(ref, status, payload \\ Macro.escape(%{}), timeout \\ Application.fetch_env!(:ex_unit, :assert_receive_timeout)) do
605-
quote do
606-
ref = unquote(ref)
607-
assert_receive %Phoenix.Socket.Reply{
614+
{payload, guard} = extract_guard(payload)
615+
616+
pattern = quote do
617+
%Phoenix.Socket.Reply{
608618
ref: ^ref,
609619
status: unquote(status),
610-
payload: unquote(payload)}, unquote(timeout)
620+
payload: unquote(payload)}
621+
end
622+
623+
struct_pattern = apply_guard(pattern, guard)
624+
625+
quote do
626+
ref = unquote(ref)
627+
assert_receive unquote(struct_pattern), unquote(timeout)
611628
end
612629
end
613630

@@ -650,11 +667,16 @@ defmodule Phoenix.ChannelTest do
650667
651668
The timeout is in milliseconds and defaults to the `:assert_receive_timeout`
652669
set on the `:ex_unit` application (which defaults to 100ms).
670+
671+
Guards can also be given to the payload pattern:
672+
673+
assert_broadcast "some_event", %{"counter" => c} when c > 0
653674
"""
654675
defmacro assert_broadcast(event, payload, timeout \\ Application.fetch_env!(:ex_unit, :assert_receive_timeout)) do
676+
pattern = extract_pattern_and_apply_guard(event, payload, Phoenix.Socket.Broadcast)
677+
655678
quote do
656-
assert_receive %Phoenix.Socket.Broadcast{event: unquote(event),
657-
payload: unquote(payload)}, unquote(timeout)
679+
assert_receive unquote(pattern), unquote(timeout)
658680
end
659681
end
660682

@@ -695,6 +717,22 @@ defmodule Phoenix.ChannelTest do
695717
end
696718
end
697719

720+
defp extract_guard({:when, _, [payload, guard]}), do: {payload, guard}
721+
defp extract_guard(payload), do: {payload, nil}
722+
723+
defp apply_guard(pattern, nil), do: pattern
724+
defp apply_guard(pattern, guard), do: {:when, [], [pattern, guard]}
725+
726+
defp extract_pattern_and_apply_guard(event, payload, struct_module) do
727+
{payload, guard} = extract_guard(payload)
728+
729+
pattern_struct = quote do
730+
%{__struct__: unquote(struct_module), event: unquote(event), payload: unquote(payload)}
731+
end
732+
733+
apply_guard(pattern_struct, guard)
734+
end
735+
698736
@doc false
699737
def __stringify__(%{__struct__: _} = struct),
700738
do: struct

test/phoenix/test/channel_test.exs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ defmodule Phoenix.Test.ChannelTest do
272272

273273
## handle_in
274274

275+
test "assert_push with guards" do
276+
{:ok, _, socket} = join(socket(UserSocket), Channel, "foo:ok")
277+
push(socket, "noreply", %{"req" => "foo"})
278+
assert_push "noreply", %{"resp" => resp} when is_binary(resp)
279+
end
280+
275281
test "pushes and receives pushed messages" do
276282
{:ok, _, socket} = join(socket(UserSocket), Channel, "foo:ok")
277283
ref = push(socket, "noreply", %{"req" => "foo"})
@@ -344,6 +350,12 @@ defmodule Phoenix.Test.ChannelTest do
344350
assert_graceful_exit(pid)
345351
end
346352

353+
test "assert_broadcast with guards" do
354+
socket = subscribe_and_join!(socket(UserSocket), Channel, "foo:ok")
355+
push(socket, "broadcast", %{"foo" => "bar"})
356+
assert_broadcast "broadcast", %{"foo" => resp} when is_binary(resp)
357+
end
358+
347359
test "pushes and broadcast messages" do
348360
socket = subscribe_and_join!(socket(UserSocket), Channel, "foo:ok")
349361
refute_broadcast "broadcast", _params
@@ -387,6 +399,13 @@ defmodule Phoenix.Test.ChannelTest do
387399
assert_reply ref, :ok, %{"resp" => %{"parameter" => 1}}
388400
end
389401

402+
test "assert_reply with guards" do
403+
{:ok, _, socket} = join(socket(UserSocket), Channel, "foo:ok")
404+
405+
ref = push(socket, "reply", %{req: %{parameter: 1}})
406+
assert_reply ref, :ok, %{"resp" => resp} when is_map(resp)
407+
end
408+
390409
test "pushes structs without modifying them" do
391410
{:ok, _, socket} = join(socket(UserSocket), Channel, "foo:ok")
392411
date = ~D[2010-04-17]

0 commit comments

Comments
 (0)