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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions