Skip to content

Commit

Permalink
Improve matching of headers assertions.
Browse files Browse the repository at this point in the history
The current implementation makes assumptions about the case and format of
headers. Introduce methods to handle headers in a case insensitive manner
and reduce churn when comparing with multi-value headers.
  • Loading branch information
ioquatix committed Jan 20, 2023
1 parent 5b9a246 commit 08510b5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 16 deletions.
33 changes: 33 additions & 0 deletions actionpack/test/abstract_unit.rb
Expand Up @@ -457,6 +457,39 @@ def assert_not_set_cookie_header(expected, header = @response.headers["Set-Cooki
end
end

module HeadersAssertions
def normalize_headers(headers)
headers.transform_keys(&:downcase)
end

def assert_headers(expected, actual = @response.headers)
actual = normalize_headers(actual)
expected.each do |key, value|
assert_equal value, actual[key]
end
end

def assert_header(key, value, actual = @response.headers)
actual = normalize_headers(actual)
assert_equal value, actual[key]
end

def assert_not_header(key, actual = @response.headers)
actual = normalize_headers(actual)
assert_not_includes(actual, key)
end

# This works for most headers, but not all, e.g. `set-cookie`.
def normalized_join_header(header)
header.is_a?(Array) ? header.join(",") : header
end

def assert_header_value(expected, header)
header = normalized_join_header(header)
assert_equal header, expected
end
end

class DrivenByRackTest < ActionDispatch::SystemTestCase
driven_by :rack_test
end
Expand Down
35 changes: 19 additions & 16 deletions actionpack/test/dispatch/response_test.rb
Expand Up @@ -84,8 +84,8 @@ def test_read_body_during_action
# the response can be built.
status, headers, body = @response.to_a
assert_equal 200, status
assert_equal({
"Content-Type" => "text/html; charset=utf-8"
assert_headers({
"content-type" => "text/html; charset=utf-8"
}, headers)

parts = []
Expand Down Expand Up @@ -122,9 +122,8 @@ def test_empty_content_type_returns_nil

status, headers, body = @response.to_a
assert_equal 200, status
assert_equal({
"Content-Type" => "text/html; charset=utf-8"
}, headers)

assert_headers({ "content-type" => "text/html; charset=utf-8" }, headers)

parts = []
body.each { |part| parts << part }
Expand All @@ -147,8 +146,8 @@ def test_only_set_charset_still_defaults_to_text_html

status, headers, _ = @response.to_a
assert_equal 200, status
assert_equal({
"Content-Type" => "text/html; charset=utf-8"
assert_headers({
"content-type" => "text/html; charset=utf-8"
}, headers)
end

Expand Down Expand Up @@ -382,13 +381,15 @@ def test_only_set_charset_still_defaults_to_text_html
assert @response.respond_to?(:method_missing, true)
end

include HeadersAssertions

test "can be explicitly destructured into status, headers and an enumerable body" do
response = ActionDispatch::Response.new(404, { "Content-Type" => "text/plain" }, ["Not Found"])
response.request = ActionDispatch::Request.empty
status, headers, body = *response

assert_equal 404, status
assert_equal({ "Content-Type" => "text/plain" }, headers)
assert_headers({ "content-type" => "text/plain" }, headers)
assert_equal ["Not Found"], body.each.to_a
end

Expand All @@ -407,10 +408,10 @@ def test_only_set_charset_still_defaults_to_text_html
env = Rack::MockRequest.env_for("/")

_status, headers, _body = app.call(env)
assert_nil headers["Content-Length"]
assert_not_header "content-length", headers

_status, headers, _body = Rack::ContentLength.new(app).call(env)
assert_equal "5", headers["Content-Length"]
assert_header "content-length", "5", headers
end
end

Expand Down Expand Up @@ -452,24 +453,26 @@ def setup
assert_not @response.has_header?("Foo")
end

include HeadersAssertions

test "add_header" do
# Add a value to an existing header
assert_equal "1,2", @response.add_header("Foo", "2")
assert_equal "1,2", @response.get_header("Foo")
assert_header_value "1,2", @response.add_header("Foo", "2")
assert_header_value "1,2", @response.get_header("Foo")

# Add nil to an existing header
assert_equal "1,2", @response.add_header("Foo", nil)
assert_equal "1,2", @response.get_header("Foo")
assert_header_value "1,2", @response.add_header("Foo", nil)
assert_header_value "1,2", @response.get_header("Foo")

# Add nil to a nonexistent header
assert_nil @response.add_header("Bar", nil)
assert_not @response.has_header?("Bar")
assert_nil @response.get_header("Bar")

# Add a value to a nonexistent header
assert_equal "1", @response.add_header("Bar", "1")
assert_header_value "1", @response.add_header("Bar", "1")
assert @response.has_header?("Bar")
assert_equal "1", @response.get_header("Bar")
assert_header_value "1", @response.get_header("Bar")
end
end

Expand Down

0 comments on commit 08510b5

Please sign in to comment.