Files
prism/test/test_controller_streaming.rb
T

84 lines
2.2 KiB
Ruby

require 'minitest/autorun'
require 'prism'
require 'support'
class StreamingExportController < Prism::Controller
after_action :log_after
def self.after_log
@after_log ||= []
end
def export
headers('Content-Type' => 'text/csv')
stream do |out|
out.write("id,title\n")
%w[one two three].each_with_index do |title, index|
out.write("#{index + 1},#{title}\n")
end
end
end
def plain
json(ok: true)
end
private
def log_after
self.class.after_log << action_name
end
end
class StreamingApp < Prism::Application
get '/export', to: 'streaming_export#export'
get '/plain', to: 'streaming_export#plain'
end
class ControllerStreamingTest < Minitest::Test
include TestSupport
def setup
StreamingExportController.after_log.clear
end
def call(env)
StreamingApp.call(env)
end
def test_streaming_action_returns_a_streaming_body
_status, _headers, body = call(env_for(:get, '/export'))
assert_instance_of Prism::StreamingBody, body
end
def test_streaming_action_produces_chunks_in_order_when_drained
_status, _headers, body = call(env_for(:get, '/export'))
collected = []
body.each { |chunk| collected << chunk }
assert_equal ["id,title\n", "1,one\n", "2,two\n", "3,three\n"], collected
end
def test_streaming_action_keeps_status_and_explicit_headers
status, headers, _body = call(env_for(:get, '/export'))
assert_equal 200, status
assert_equal 'text/csv', headers['Content-Type']
end
# Regression guard: finalize_body used to call `@response.body.empty?`
# unconditionally after every action, which raises NoMethodError against
# a StreamingBody (it deliberately has no #empty?, since a producer
# block's total chunk count is not known up front).
def test_after_actions_still_run_for_a_streaming_action
call(env_for(:get, '/export'))
assert_equal ['export'], StreamingExportController.after_log
end
# Non-streaming actions on the same controller are unaffected by the
# streaming? guard added to finalize_body.
def test_ordinary_action_on_the_same_controller_is_unaffected
status, _headers, body = call(env_for(:get, '/plain'))
assert_equal 200, status
assert_equal ['{"ok":true}'], body
end
end