diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 2ab035c76ae21..f3f6af9ab55a2 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -368,6 +368,95 @@ def jruby_skip(message = "") end end +module CookieAssertions + def parse_set_cookie_attributes(fields, attributes = {}) + if fields.is_a?(String) + fields = fields.split(";").map(&:strip) + end + + fields.each do |field| + key, value = field.split("=", 2) + + # Normalize the key to lowercase: + key.downcase! + + if value + attributes[key] = value + else + attributes[key] = true + end + end + + attributes + end + + # Parse the set-cookie header and return a hash of cookie names and values. + # + # Example: + # set_cookies = headers["set-cookie"] + # parse_set_cookies_headers(set_cookies) + def parse_set_cookies_headers(set_cookies) + if set_cookies.is_a?(String) + set_cookies = set_cookies.split("\n") + end + + cookies = {} + + set_cookies&.each do |cookie_string| + attributes = {} + + fields = cookie_string.split(";").map(&:strip) + + # The first one is the cookie name: + name, value = fields.shift.split("=", 2) + + attributes[:value] = value + + cookies[name] = parse_set_cookie_attributes(fields, attributes) + end + + cookies + end + + def assert_set_cookie_header(expected, header = @response.headers["Set-Cookie"]) + # In Rack v2, this is newline delimited. In Rack v3, this is an array. + # Normalize the comparison so that we can assert equality in both cases. + + if header.is_a?(String) + header = header.split("\n").sort + end + + if expected.is_a?(String) + expected = expected.split("\n").sort + end + + # While not strictly speaking correct, this is probably good enough for now: + header = parse_set_cookies_headers(header) + expected = parse_set_cookies_headers(expected) + + expected.each do |key, value| + assert_equal value, header[key] + end + end + + def assert_not_set_cookie_header(expected, header = @response.headers["Set-Cookie"]) + if header.is_a?(String) + header = header.split("\n").sort + end + + if expected.is_a?(String) + expected = expected.split("\n").sort + end + + # While not strictly speaking correct, this is probably good enough for now: + header = parse_set_cookies_headers(header) + + expected.each do |name| + assert_not_includes(header, name) + end + end +end + class DrivenByRackTest < ActionDispatch::SystemTestCase driven_by :rack_test end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 95384cfb41fc3..0d98a60c720f1 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -313,12 +313,14 @@ def test_post end end + include CookieAssertions + test "response cookies are added to the cookie jar for the next request" do with_test_route_set do cookies["cookie_1"] = "sugar" cookies["cookie_2"] = "oatmeal" get "/cookie_monster" - assert_equal "cookie_1=; path=/\ncookie_3=chocolate; path=/", headers["Set-Cookie"] + assert_set_cookie_header "cookie_1=; path=/\ncookie_3=chocolate; path=/", headers["Set-Cookie"] assert_equal({ "cookie_1" => "", "cookie_2" => "oatmeal", "cookie_3" => "chocolate" }, cookies.to_hash) end end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 8152946f27312..6ce19221661c0 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -1241,9 +1241,14 @@ def test_csrf_token_cookie_has_same_site_lax assert_match "SameSite=Lax", @response.headers["Set-Cookie"] end + include CookieAssertions + def test_csrf_token_cookie_is_http_only get :cookie - assert_match "HttpOnly", @response.headers["Set-Cookie"] + + cookies = parse_set_cookies_headers(@response.headers["Set-Cookie"]) + csrf_token_cookie = cookies["csrf_token"] + assert csrf_token_cookie["httponly"] end def test_csrf_token_cookie_is_permanent diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index a248eb4d5babc..7ed108fc73c0d 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -81,6 +81,8 @@ def test_write_doesnt_set_a_nil_header end class CookiesTest < ActionController::TestCase + include CookieAssertions + class CustomSerializer def self.load(value) value.to_s + " and loaded" @@ -391,7 +393,7 @@ def test_setting_cookie_with_no_same_site_protection @request.env["action_dispatch.cookies_same_site_protection"] = proc { :none } get :authenticate - assert_cookie_header "user_name=david; path=/; SameSite=None" + assert_set_cookie_header "user_name=david; path=/; SameSite=None" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -401,7 +403,7 @@ def test_setting_cookie_with_same_site_protection_proc_normal_user_agent end get :authenticate - assert_cookie_header "user_name=david; path=/; SameSite=Strict" + assert_set_cookie_header "user_name=david; path=/; SameSite=Strict" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -412,7 +414,7 @@ def test_setting_cookie_with_same_site_protection_proc_special_user_agent request.user_agent = "spooky browser" get :authenticate - assert_cookie_header "user_name=david; path=/" + assert_set_cookie_header "user_name=david; path=/" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -429,7 +431,7 @@ def test_setting_cookie_with_same_site_strict @request.env["action_dispatch.cookies_same_site_protection"] = proc { :strict } get :authenticate - assert_cookie_header "user_name=david; path=/; SameSite=Strict" + assert_set_cookie_header "user_name=david; path=/; SameSite=Strict" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -437,7 +439,7 @@ def test_setting_cookie_with_same_site_nil @request.env["action_dispatch.cookies_same_site_protection"] = proc { nil } get :authenticate - assert_cookie_header "user_name=david; path=/" + assert_set_cookie_header "user_name=david; path=/" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -445,7 +447,7 @@ def test_setting_cookie_with_specific_same_site_strict @request.env["action_dispatch.cookies_same_site_protection"] = proc { :lax } get :set_same_site_strict - assert_cookie_header "user_name=david; path=/; SameSite=Strict" + assert_set_cookie_header "user_name=david; path=/; SameSite=Strict" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -453,13 +455,13 @@ def test_setting_cookie_with_specific_same_site_nil @request.env["action_dispatch.cookies_same_site_protection"] = proc { :lax } get :set_same_site_nil - assert_cookie_header "user_name=david; path=/" + assert_set_cookie_header "user_name=david; path=/" assert_equal({ "user_name" => "david" }, @response.cookies) end def test_setting_cookie get :authenticate - assert_cookie_header "user_name=david; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -477,46 +479,46 @@ def test_setting_the_same_value_to_permanent_cookie def test_setting_with_escapable_characters get :set_with_with_escapable_characters - assert_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/; SameSite=Lax" + assert_set_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/; SameSite=Lax" assert_equal({ "that & guy" => "foo & bar => baz" }, @response.cookies) end def test_setting_cookie_for_fourteen_days get :authenticate_for_fourteen_days - assert_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end def test_setting_cookie_for_fourteen_days_with_symbols get :authenticate_for_fourteen_days_with_symbols - assert_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end def test_setting_cookie_with_http_only get :authenticate_with_http_only - assert_cookie_header "user_name=david; path=/; HttpOnly; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; HttpOnly; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end def test_setting_cookie_with_secure @request.env["HTTPS"] = "on" get :authenticate_with_secure - assert_cookie_header "user_name=david; path=/; secure; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; secure; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end def test_setting_cookie_with_secure_on_onion_address @request.host = "fake.onion" get :authenticate_with_secure - assert_cookie_header "user_name=david; path=/; secure; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; secure; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end def test_setting_cookie_with_secure_when_always_write_cookie_is_true old_cookie, @request.cookie_jar.always_write_cookie = @request.cookie_jar.always_write_cookie, true get :authenticate_with_secure - assert_cookie_header "user_name=david; path=/; secure; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; secure; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) ensure @request.cookie_jar.always_write_cookie = old_cookie @@ -524,14 +526,14 @@ def test_setting_cookie_with_secure_when_always_write_cookie_is_true def test_not_setting_cookie_with_secure get :authenticate_with_secure - assert_not_cookie_header "user_name=david; path=/; secure" + assert_not_set_cookie_header("user_name") assert_not_equal({ "user_name" => "david" }, @response.cookies) end def test_multiple_cookies get :set_multiple_cookies assert_equal 2, @response.cookies.size - assert_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax\nlogin=XJ-122; path=/; SameSite=Lax" + assert_set_cookie_header ["user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax", "login=XJ-122; path=/; SameSite=Lax"] assert_equal({ "login" => "XJ-122", "user_name" => "david" }, @response.cookies) end @@ -542,14 +544,14 @@ def test_setting_test_cookie def test_expiring_cookie request.cookies[:user_name] = "Joe" get :logout - assert_cookie_header "user_name=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" assert_equal({ "user_name" => nil }, @response.cookies) end def test_delete_cookie_with_path request.cookies[:user_name] = "Joe" get :delete_cookie_with_path - assert_cookie_header "user_name=; path=/beaten; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=; path=/beaten; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" end def test_delete_unexisting_cookie @@ -880,7 +882,7 @@ def test_permanent_signed_cookie def test_delete_and_set_cookie request.cookies[:user_name] = "Joe" get :delete_and_set_cookie - assert_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT; SameSite=Lax" assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -1120,172 +1122,172 @@ def test_cookie_with_hash_value_not_modified_by_rotation def test_cookie_with_all_domain_option get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.com; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_a_non_standard_tld @request.host = "two.subdomains.nextangle.local" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_australian_style_tld @request.host = "nextangle.com.au" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.com.au; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.com.au; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_australian_style_tld_and_two_subdomains @request.host = "x.nextangle.com.au" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.com.au; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.com.au; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_uk_style_tld @request.host = "nextangle.co.uk" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.co.uk; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.co.uk; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_uk_style_tld_and_two_subdomains @request.host = "x.nextangle.co.uk" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.co.uk; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.co.uk; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_host_with_port @request.host = "nextangle.local:3000" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_localhost @request.host = "localhost" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_ipv4_address @request.host = "192.168.1.1" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_ipv6_address @request.host = "2001:0db8:85a3:0000:0000:8a2e:0370:7334" get :set_cookie_with_domain assert_response :success - assert_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" end def test_deleting_cookie_with_all_domain_option request.cookies[:user_name] = "Joe" get :delete_cookie_with_domain assert_response :success - assert_cookie_header "user_name=; domain=.nextangle.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=; domain=.nextangle.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" end def test_cookie_with_all_domain_option_and_tld_length get :set_cookie_with_domain_and_tld assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.com; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_a_non_standard_tld_and_tld_length @request.host = "two.subdomains.nextangle.local" get :set_cookie_with_domain_and_tld assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_a_non_standard_2_letter_tld @request.host = "admin.lvh.me" get :set_cookie_with_domain_and_tld assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.lvh.me; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.lvh.me; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_host_with_port_and_tld_length @request.host = "nextangle.local:3000" get :set_cookie_with_domain_and_tld assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/; SameSite=Lax" end def test_cookie_with_all_domain_option_using_longer_tld_length @request.host = "x.y.z.t.com" get :set_cookie_with_domain_and_longer_tld assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.y.z.t.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.y.z.t.com; path=/; SameSite=Lax" end def test_deleting_cookie_with_all_domain_option_and_tld_length request.cookies[:user_name] = "Joe" get :delete_cookie_with_domain_and_tld assert_response :success - assert_cookie_header "user_name=; domain=.nextangle.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=; domain=.nextangle.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" end def test_cookie_with_several_preset_domains_using_one_of_these_domains @request.host = "example1.com" get :set_cookie_with_domains assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=example1.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=example1.com; path=/; SameSite=Lax" end def test_cookie_with_several_preset_domains_using_subdomain @request.host = "subdomain.example1.com" get :set_cookie_with_domains assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=example1.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=example1.com; path=/; SameSite=Lax" end def test_cookie_with_several_preset_domains_using_similar_tld @request.host = "example1.com.au" get :set_cookie_with_domains assert_response :success - assert_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" end def test_cookie_with_several_preset_domains_using_similar_domain @request.host = "myexample1.com" get :set_cookie_with_domains assert_response :success - assert_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" end def test_cookie_with_several_preset_domains_using_other_domain @request.host = "other-domain.com" get :set_cookie_with_domains assert_response :success - assert_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; path=/; SameSite=Lax" end def test_cookie_with_several_preset_domains_using_shared_domain @request.host = "example3.com" get :set_cookie_with_domains assert_response :success - assert_cookie_header "user_name=rizwanreza; domain=.example3.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=rizwanreza; domain=.example3.com; path=/; SameSite=Lax" end def test_cookie_with_domain_proc get :set_cookie_with_domain_proc assert_response :success - assert_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax" end def test_cookie_with_domain_proc_with_request get :set_cookie_with_domain_proc_with_request assert_response :success - assert_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=braindeaf; domain=.sub.www.nextangle.com; path=/; SameSite=Lax" end def test_deleting_cookie_with_several_preset_domains_using_one_of_these_domains @@ -1293,7 +1295,7 @@ def test_deleting_cookie_with_several_preset_domains_using_one_of_these_domains request.cookies[:user_name] = "Joe" get :delete_cookie_with_domains assert_response :success - assert_cookie_header "user_name=; domain=example2.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=; domain=example2.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" end def test_deleting_cookie_with_several_preset_domains_using_other_domain @@ -1301,7 +1303,7 @@ def test_deleting_cookie_with_several_preset_domains_using_other_domain request.cookies[:user_name] = "Joe" get :delete_cookie_with_domains assert_response :success - assert_cookie_header "user_name=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax" end def test_cookies_hash_is_indifferent_access @@ -1327,7 +1329,7 @@ def test_setting_request_cookies_is_indifferent_access def test_cookies_retained_across_requests get :symbol_key - assert_cookie_header "user_name=david; path=/; SameSite=Lax" + assert_set_cookie_header "user_name=david; path=/; SameSite=Lax" assert_equal "david", cookies[:user_name] get :noop @@ -1446,7 +1448,7 @@ def test_encrypted_cookie_with_expires_set_relatively def test_vanilla_cookie_with_expires_set_relatively travel_to Time.utc(2017, 8, 15) do get :cookie_expires_in_two_hours - assert_cookie_header "user_name=assain; path=/; expires=Tue, 15 Aug 2017 02:00:00 GMT; SameSite=Lax" + assert_set_cookie_header "user_name=assain; path=/; expires=Tue, 15 Aug 2017 02:00:00 GMT; SameSite=Lax" end end @@ -1574,23 +1576,4 @@ def test_read_rails_5_2_stable_signed_cookies_if_use_metadata_config_is_true assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] end - - private - def assert_cookie_header(expected) - header = @response.headers["Set-Cookie"] - if header.respond_to?(:to_str) - assert_equal expected.split("\n").sort, header.split("\n").sort - else - assert_equal expected.split("\n"), header - end - end - - def assert_not_cookie_header(expected) - header = @response.headers["Set-Cookie"] - if header.respond_to?(:to_str) - assert_not_equal expected.split("\n").sort, header.split("\n").sort - else - assert_not_equal expected.split("\n"), header - end - end end diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 4ba9dd78a1c59..4cf41144b3f99 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -227,10 +227,12 @@ def test_only_set_charset_still_defaults_to_text_html assert_equal "OK", @response.message end + include CookieAssertions + test "cookies" do @response.set_cookie("user_name", value: "david", path: "/") _status, headers, _body = @response.to_a - assert_equal "user_name=david; path=/", headers["Set-Cookie"] + assert_set_cookie_header "user_name=david; path=/", headers["Set-Cookie"] assert_equal({ "user_name" => "david" }, @response.cookies) end @@ -238,7 +240,7 @@ def test_only_set_charset_still_defaults_to_text_html @response.set_cookie("user_name", value: "david", path: "/") @response.set_cookie("login", value: "foo&bar", path: "/", expires: Time.utc(2005, 10, 10, 5)) _status, headers, _body = @response.to_a - assert_equal "user_name=david; path=/\nlogin=foo%26bar; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT", headers["Set-Cookie"] + assert_set_cookie_header "user_name=david; path=/\nlogin=foo%26bar; path=/; expires=Mon, 10 Oct 2005 05:00:00 GMT", headers["Set-Cookie"] assert_equal({ "login" => "foo&bar", "user_name" => "david" }, @response.cookies) end diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 95be113be1c36..86238d5557813 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -72,16 +72,23 @@ def renew_session_id end end - def parse_cookie_from_header - cookie_matches = headers["Set-Cookie"].match(/#{SessionKey}=([^;]+)/) - cookie_matches && cookie_matches[1] - end + include CookieAssertions + + def assert_session_cookie(attributes_string, contents) + cookies = parse_set_cookies_headers(headers["Set-Cookie"]) - def assert_session_cookie(cookie_string, contents) - assert_includes headers["Set-Cookie"], cookie_string + if session_cookie = cookies[SessionKey] + if attributes_string + expected_attributes = parse_set_cookie_attributes(attributes_string) - session_value = parse_cookie_from_header - session_data = Encryptor.decrypt_and_verify(Rack::Utils.unescape(session_value)) rescue nil + expected_attributes.each do |key, value| + assert_equal value, session_cookie[key], "expected #{key} to be #{value.inspect}, but was #{session_cookie[key].inspect}" + end + end + + session_value = session_cookie[:value] + session_data = Encryptor.decrypt_and_verify(Rack::Utils.unescape(session_value)) rescue nil + end assert_not_nil session_data, "session failed to decrypt" assert_equal session_data.slice(*contents.keys), contents @@ -92,7 +99,7 @@ def test_setting_session_value get "/set_session_value" assert_response :success - assert_session_cookie "path=/; HttpOnly", "foo" => "bar" + assert_session_cookie "path=/; HttpOnly", { "foo" => "bar" } end end