Skip to content

Rack::Events on_finish callback is not called in a Rails ActionDispatch::IntegrationTest with a streaming body #2422

@tavianator

Description

@tavianator

With a controller that uses a pattern similar to https://github.com/socketry/falcon-rails-examples/blob/main/app/controllers/sse_controller.rb for SSE:

class SseController < ApplicationController
  def index
  end

  EVENT_STREAM_HEADERS = {
    'content-type' => 'text/event-stream',
  }

  def events
    body = proc do |stream|
      5.times do
        stream.write("data: #{Time.now}\n\n")
        sleep 0.05
      end
    end

    self.response = Rack::Response[200, EVENT_STREAM_HEADERS.dup, body]
  end
end

and a Rack::Events middleware like this:

class RecordEvents
  include Rack::Events::Abstract

  EVENTS = []

  def on_start(request, response)
    EVENTS << "on_start"
  end

  def on_finish(request, response)
    EVENTS << "on_finish"
  end
end

the following test case

class SseControllerTest < ActionDispatch::IntegrationTest
  test "should get index" do
    RecordEvents::EVENTS.clear

    get sse_index_url
    assert_response :success

    assert_equal ["on_start", "on_finish"], RecordEvents::EVENTS
  end

  test "should get events" do
    RecordEvents::EVENTS.clear

    get sse_events_url
    assert_response :success

    assert_equal ["on_start", "on_finish"], RecordEvents::EVENTS
  end
end

does not pass:

Failure:
SseControllerTest#test_should_get_events [test/controllers/sse_controller_test.rb:19]:
Expected: ["on_start", "on_finish"]
  Actual: ["on_start"]

The "should get index" test works fine, but "should get events" fails to call the on_finish handler.

I have an end-to-end reproduction in this branch: https://github.com/tavianator/falcon-rails-examples/tree/rack-events-sse-test. Just run

$ bundle exec rails test ./test/controllers/sse_controller_test.rb

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions