Skip to content

Commit 41f5eb9

Browse files
Enhance helper spec to support Async::Queue for chunk processing
1 parent 60895cd commit 41f5eb9

File tree

1 file changed

+55
-7
lines changed

1 file changed

+55
-7
lines changed

spec/dummy/spec/helpers/react_on_rails_pro_helper_spec.rb

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require "async"
4+
require "async/queue"
35
require "rails_helper"
46
require "support/script_tag_utils"
57

@@ -327,6 +329,7 @@ def response; end
327329
HTML
328330
end
329331

332+
# Mock chunks can be Async::Queue or Array
330333
def mock_request_and_response(mock_chunks = chunks, count: 1)
331334
# Reset connection instance variables to ensure clean state for tests
332335
ReactOnRailsPro::Request.instance_variable_set(:@connection, nil)
@@ -339,9 +342,16 @@ def mock_request_and_response(mock_chunks = chunks, count: 1)
339342
chunks_read.clear
340343
mock_streaming_response(%r{http://localhost:3800/bundles/[a-f0-9]{32}-test/render/[a-f0-9]{32}}, 200,
341344
count: count) do |yielder|
342-
mock_chunks.each do |chunk|
343-
chunks_read << chunk
344-
yielder.call("#{chunk.to_json}\n")
345+
if mock_chunks.is_a?(Async::Queue)
346+
while (chunk = mock_chunks.dequeue)
347+
chunks_read << chunk
348+
yielder.call("#{chunk.to_json}\n")
349+
end
350+
else
351+
mock_chunks.each do |chunk|
352+
chunks_read << chunk
353+
yielder.call("#{chunk.to_json}\n")
354+
end
345355
end
346356
end
347357
end
@@ -411,6 +421,7 @@ def mock_request_and_response(mock_chunks = chunks, count: 1)
411421
describe "stream_view_containing_react_components" do # rubocop:disable RSpec/MultipleMemoizedHelpers
412422
let(:mocked_stream) { instance_double(ActionController::Live::Buffer) }
413423
let(:written_chunks) { [] }
424+
let(:chunks_queue) { Async::Queue.new }
414425

415426
before do
416427
written_chunks.clear
@@ -428,18 +439,55 @@ def mock_request_and_response(mock_chunks = chunks, count: 1)
428439

429440
allow(mocked_stream).to receive(:write) do |chunk|
430441
written_chunks << chunk
431-
# Ensures that any chunk received is written immediately to the stream
432-
expect(written_chunks.count).to eq(chunks_read.count) # rubocop:disable RSpec/ExpectInHook
433442
end
434443
allow(mocked_stream).to receive(:close)
435444
mocked_response = instance_double(ActionDispatch::Response)
436445
allow(mocked_response).to receive(:stream).and_return(mocked_stream)
437446
allow(self).to receive(:response).and_return(mocked_response)
438-
mock_request_and_response
447+
mock_request_and_response(chunks_queue)
448+
end
449+
450+
def run_stream
451+
queue = chunks_queue
452+
Sync do |parent|
453+
parent.async do
454+
stream_view_containing_react_components(template: template_path)
455+
end
456+
457+
writer = Object.new
458+
chunks_to_write = chunks.dup
459+
writer.define_singleton_method(:write_next_chunk) do
460+
chunk = chunks_to_write.shift
461+
if chunk.nil?
462+
queue.close
463+
parent.sleep 0.05
464+
return nil
465+
end
466+
467+
queue.enqueue(chunk)
468+
parent.sleep 0.05
469+
chunk
470+
end
471+
writer.define_singleton_method(:write_rest_of_chunks) do
472+
while (chunk = chunks_to_write.shift)
473+
queue.enqueue(chunk)
474+
end
475+
parent.sleep 0.1
476+
end
477+
yield(writer)
478+
end
439479
end
440480

441481
it "writes the chunk to stream as soon as it is received" do
442-
stream_view_containing_react_components(template: template_path)
482+
run_stream do |writer|
483+
expect(self).to have_received(:render_to_string)
484+
485+
while writer.write_next_chunk
486+
# Ensures that any chunk received is written immediately to the stream
487+
expect(written_chunks.count).to eq(chunks_read.count)
488+
end
489+
end
490+
443491
expect(self).to have_received(:render_to_string).once.with(template: template_path)
444492
expect(chunks_read.count).to eq(chunks.count)
445493
expect(written_chunks.count).to eq(chunks.count)

0 commit comments

Comments
 (0)