Skip to content

Commit f2ca315

Browse files
committed
Improve flaky Broadcast tests
First, don't render HTML with the `<turbo-stream-source>` element. Instead, append the element when clicking a `<button>`. Next, remove all waiting from Capybara tests, and rely on default values.
1 parent ab7f64f commit f2ca315

File tree

7 files changed

+52
-45
lines changed

7 files changed

+52
-45
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121

2222
env:
2323
RAILS_VERSION: "${{ matrix.rails-version }}"
24+
VERBOSE: true
2425

2526
name: ${{ format('Tests (Ruby {0}, Rails {1})', matrix.ruby-version, matrix.rails-version) }}
2627
runs-on: ubuntu-latest
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<button type="button">
2+
<%= content %>
3+
4+
<script>
5+
document.currentScript.parentElement.addEventListener("click", ({ currentTarget }) => {
6+
for (const { content } of currentTarget.querySelectorAll("template")) {
7+
currentTarget.parentElement.insertBefore(content, currentTarget)
8+
}
9+
currentTarget.remove()
10+
})
11+
</script>
12+
13+
<template><%= yield %></template>
14+
</button>
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<h1>Echo Messages</h1>
22

3-
<%= turbo_stream_from "messages", channel: EchoChannel, data: {message: "Hello, world!"} %>
3+
<%= render "template_button", content: "Start listening for broadcasts" do %>
4+
<%= turbo_stream_from "messages", channel: EchoChannel, data: {message: "Hello, world!"} %>
5+
<% end %>
6+
47
<div id="messages">
58
</div>
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<h1>Messages</h1>
22

3-
<span id="message-count">
4-
<%= @messages.count %> messages sent
5-
</span>
3+
<%= render "template_button", content: "Start listening for broadcasts" do %>
4+
<%= turbo_stream_from "messages" %>
5+
<% end %>
66

7-
<%= turbo_stream_from "messages" %>
87
<div id="messages">
98
</div>
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<h1>Users::Profiles</h1>
22

3-
<%= turbo_stream_from "users_profiles" %>
3+
<%= render "template_button", content: "Start listening for broadcasts" do %>
4+
<%= turbo_stream_from "users_profiles" %>
5+
<% end %>
6+
47
<div id="users_profiles"></div>

test/dummy/config/cable.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ development:
22
adapter: async
33

44
test:
5-
adapter: async
5+
adapter: inline
66

77
production:
88
adapter: redis

test/system/broadcasts_test.rb

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,56 @@
11
require "application_system_test_case"
22

33
class BroadcastsTest < ApplicationSystemTestCase
4-
include ActionCable::TestHelper
5-
64
test "Message broadcasts Turbo Streams" do
75
visit messages_path
8-
wait_for_subscriber
6+
subscribe_to_broadcasts
97

10-
assert_text "Messages"
11-
assert_broadcasts_text "Message 1" do |text|
12-
Message.create(content: text).broadcast_append_to(:messages)
8+
assert_broadcasts_text "Message 1", to: :messages do |text, target|
9+
Message.create(content: text).broadcast_append_to(target)
1310
end
1411
end
1512

16-
test "New messages update the message count with html" do
13+
test "Message broadcasts with html: render option" do
1714
visit messages_path
18-
wait_for_subscriber
19-
20-
assert_text "Messages"
21-
message = Message.create(content: "A new message")
15+
subscribe_to_broadcasts
2216

23-
message.broadcast_update_to(:messages, target: "message-count",
24-
html: "#{Message.count} messages sent")
25-
assert_selector("#message-count", text: Message.count, wait: 10)
17+
assert_broadcasts_text "Hello, with html: option", to: :messages do |text, target|
18+
Message.create(content: "Ignored").broadcast_append_to(target, html: text)
19+
end
2620
end
2721

2822
test "Users::Profile broadcasts Turbo Streams" do
2923
visit users_profiles_path
30-
wait_for_subscriber
24+
subscribe_to_broadcasts
3125

32-
assert_text "Users::Profiles"
33-
assert_broadcasts_text "Profile 1" do |text|
34-
Users::Profile.new(id: 1, name: text).broadcast_append_to(:users_profiles)
26+
assert_broadcasts_text "Profile 1", to: :users_profiles do |text, target|
27+
Users::Profile.new(id: 1, name: text).broadcast_append_to(target)
3528
end
3629
end
3730

3831
test "passing extra parameters to channel" do
3932
visit echo_messages_path
40-
wait_for_subscriber
4133

42-
assert_text "Hello, world!", wait: 100
34+
assert_broadcasts_text "Hello, world!", to: :messages do
35+
subscribe_to_broadcasts
36+
end
4337
end
4438

4539
private
4640

47-
def assert_broadcasts_text(text, wait: 5, &block)
48-
assert_no_text text
49-
perform_enqueued_jobs { block.call(text) }
50-
assert_text text, wait: wait
41+
def subscribe_to_broadcasts
42+
click_on "Start listening for broadcasts"
43+
44+
assert_no_button "Start listening for broadcasts"
5145
end
5246

53-
def wait_for_subscriber(timeout: 10)
54-
time = Time.now
55-
loop do
56-
subscriber_map = pubsub_adapter.instance_variable_get(:@subscriber_map)
57-
if subscriber_map.is_a?(ActionCable::SubscriptionAdapter::SubscriberMap)
58-
subscribers = subscriber_map.instance_variable_get(:@subscribers)
59-
sync = subscriber_map.instance_variable_get(:@sync)
60-
sync.synchronize do
61-
return unless subscribers.empty?
62-
end
63-
end
64-
assert_operator(Time.now - time, :<, timeout, "subscriber waiting timed out")
65-
sleep 0.1
47+
def assert_broadcasts_text(text, to:, wait: 10, &block)
48+
using_wait_time wait do
49+
assert_no_text text
50+
51+
[text, to].yield_self(&block)
52+
53+
assert_text text
6654
end
6755
end
68-
6956
end

0 commit comments

Comments
 (0)