-
Notifications
You must be signed in to change notification settings - Fork 328
/
test_helper.rb
172 lines (159 loc) · 5.95 KB
/
test_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
module Turbo
module Broadcastable
module TestHelper
extend ActiveSupport::Concern
included do
include ActionCable::TestHelper
include Turbo::Streams::StreamName
end
# Asserts that `<turbo-stream>` elements were broadcast over Action Cable
#
# ==== Arguments
#
# * <tt>stream_name_or_object</tt> the objects used to generate the
# channel Action Cable name, or the name itself
# * <tt>&block</tt> optional block executed before the
# assertion
#
# ==== Options
#
# * <tt>count:</tt> the number of `<turbo-stream>` elements that are
# expected to be broadcast
#
# Asserts `<turbo-stream>` elements were broadcast:
#
# message = Message.find(1)
# message.broadcast_replace_to "messages"
#
# assert_turbo_stream_broadcasts "messages"
#
# Asserts that two `<turbo-stream>` elements were broadcast:
#
# message = Message.find(1)
# message.broadcast_replace_to "messages"
# message.broadcast_remove_to "messages"
#
# assert_turbo_stream_broadcasts "messages", count: 2
#
# You can pass a block to run before the assertion:
#
# message = Message.find(1)
#
# assert_turbo_stream_broadcasts "messages" do
# message.broadcast_append_to "messages"
# end
#
# In addition to a String, the helper also accepts an Object or Array to
# determine the name of the channel the elements are broadcast to:
#
# message = Message.find(1)
#
# assert_turbo_stream_broadcasts message do
# message.broadcast_replace
# end
#
def assert_turbo_stream_broadcasts(stream_name_or_object, count: nil, &block)
payloads = capture_turbo_stream_broadcasts(stream_name_or_object, &block)
stream_name = stream_name_from(stream_name_or_object)
if count.nil?
assert_not_empty payloads, "Expected at least one broadcast on #{stream_name.inspect}, but there were none"
else
broadcasts = "Turbo Stream broadcast".pluralize(count)
assert count == payloads.count, "Expected #{count} #{broadcasts} on #{stream_name.inspect}, but there were #{payloads.count}"
end
end
# Asserts that no `<turbo-stream>` elements were broadcast over Action Cable
#
# ==== Arguments
#
# * <tt>stream_name_or_object</tt> the objects used to generate the
# channel Action Cable name, or the name itself
# * <tt>&block</tt> optional block executed before the
# assertion
#
# Asserts that no `<turbo-stream>` elements were broadcast:
#
# message = Message.find(1)
# message.broadcast_replace_to "messages"
#
# assert_no_turbo_stream_broadcasts "messages" # fails with MiniTest::Assertion error
#
# You can pass a block to run before the assertion:
#
# message = Message.find(1)
#
# assert_no_turbo_stream_broadcasts "messages" do
# # do something other than broadcast to "messages"
# end
#
# In addition to a String, the helper also accepts an Object or Array to
# determine the name of the channel the elements are broadcast to:
#
# message = Message.find(1)
#
# assert_no_turbo_stream_broadcasts message do
# # do something other than broadcast to "message_1"
# end
#
def assert_no_turbo_stream_broadcasts(stream_name_or_object, &block)
block&.call
stream_name = stream_name_from(stream_name_or_object)
payloads = broadcasts(stream_name)
assert payloads.empty?, "Expected no broadcasts on #{stream_name.inspect}, but there were #{payloads.count}"
end
# Captures any `<turbo-stream>` elements that were broadcast over Action Cable
#
# ==== Arguments
#
# * <tt>stream_name_or_object</tt> the objects used to generate the
# channel Action Cable name, or the name itself
# * <tt>&block</tt> optional block to capture broadcasts during execution
#
# Returns any `<turbo-stream>` elements that have been broadcast as an
# Array of <tt>Nokogiri::XML::Element</tt> instances
#
# message = Message.find(1)
# message.broadcast_append_to "messages"
# message.broadcast_prepend_to "messages"
#
# turbo_streams = capture_turbo_stream_broadcasts "messages"
#
# assert_equal "append", turbo_streams.first["action"]
# assert_equal "prepend", turbo_streams.second["action"]
#
# You can pass a block to limit the scope of the broadcasts being captured:
#
# message = Message.find(1)
#
# turbo_streams = capture_turbo_stream_broadcasts "messages" do
# message.broadcast_append_to "messages"
# end
#
# assert_equal "append", turbo_streams.first["action"]
#
# In addition to a String, the helper also accepts an Object or Array to
# determine the name of the channel the elements are broadcast to:
#
# message = Message.find(1)
#
# replace, remove = capture_turbo_stream_broadcasts message do
# message.broadcast_replace
# message.broadcast_remove
# end
#
# assert_equal "replace", replace["action"]
# assert_equal "replace", remove["action"]
#
def capture_turbo_stream_broadcasts(stream_name_or_object, &block)
block&.call
stream_name = stream_name_from(stream_name_or_object)
payloads = broadcasts(stream_name)
payloads.flat_map do |payload|
html = ActiveSupport::JSON.decode(payload)
document = Nokogiri::HTML5.parse(html)
document.at("body").element_children
end
end
end
end
end