cookies_test.rb 18.0 KB
Newer Older
1
require 'abstract_unit'
2 3
# FIXME remove DummyKeyGenerator and this require in 4.1
require 'active_support/key_generator'
D
Initial  
David Heinemeier Hansson 已提交
4

5
class CookiesTest < ActionController::TestCase
D
Initial  
David Heinemeier Hansson 已提交
6
  class TestController < ActionController::Base
7 8
    def authenticate
      cookies["user_name"] = "david"
J
Jeremy Kemper 已提交
9
      head :ok
10 11
    end

12 13
    def set_with_with_escapable_characters
      cookies["that & guy"] = "foo & bar => baz"
J
Jeremy Kemper 已提交
14
      head :ok
15 16
    end

17
    def authenticate_for_fourteen_days
F
Frederick Cheung 已提交
18
      cookies["user_name"] = { "value" => "david", "expires" => Time.utc(2005, 10, 10,5) }
J
Jeremy Kemper 已提交
19
      head :ok
20 21
    end

22
    def authenticate_for_fourteen_days_with_symbols
F
Frederick Cheung 已提交
23
      cookies[:user_name] = { :value => "david", :expires => Time.utc(2005, 10, 10,5) }
J
Jeremy Kemper 已提交
24
      head :ok
25 26
    end

27
    def set_multiple_cookies
F
Frederick Cheung 已提交
28
      cookies["user_name"] = { "value" => "david", "expires" => Time.utc(2005, 10, 10,5) }
29
      cookies["login"]     = "XJ-122"
J
Jeremy Kemper 已提交
30
      head :ok
31
    end
J
Joshua Peek 已提交
32

33
    def access_frozen_cookies
J
Jeremy Kemper 已提交
34
      cookies["will"] = "work"
J
Jeremy Kemper 已提交
35
      head :ok
36 37
    end

38 39
    def logout
      cookies.delete("user_name")
J
Jeremy Kemper 已提交
40
      head :ok
41 42
    end

43 44
    alias delete_cookie logout

45 46
    def delete_cookie_with_path
      cookies.delete("user_name", :path => '/beaten')
J
Jeremy Kemper 已提交
47
      head :ok
48 49
    end

50
    def authenticate_with_http_only
51
      cookies["user_name"] = { :value => "david", :httponly => true }
J
Jeremy Kemper 已提交
52
      head :ok
53
    end
54

55 56 57 58
    def authenticate_with_secure
      cookies["user_name"] = { :value => "david", :secure => true }
      head :ok
    end
59 60 61 62 63

    def set_permanent_cookie
      cookies.permanent[:user_name] = "Jamie"
      head :ok
    end
J
Joshua Peek 已提交
64

65 66 67 68
    def set_signed_cookie
      cookies.signed[:user_id] = 45
      head :ok
    end
J
Joshua Peek 已提交
69

70 71 72 73 74 75 76 77 78 79 80
    def raise_data_overflow
      cookies.signed[:foo] = 'bye!' * 1024
      head :ok
    end

    def tampered_cookies
      cookies[:tampered] = "BAh7BjoIZm9vIghiYXI%3D--123456780"
      cookies.signed[:tampered]
      head :ok
    end

81 82 83 84
    def set_permanent_signed_cookie
      cookies.permanent.signed[:remember_me] = 100
      head :ok
    end
85 86 87 88 89 90

    def delete_and_set_cookie
      cookies.delete :user_name
      cookies[:user_name] = { :value => "david", :expires => Time.utc(2005, 10, 10,5) }
      head :ok
    end
91 92 93 94 95 96 97 98 99 100

    def set_cookie_with_domain
      cookies[:user_name] = {:value => "rizwanreza", :domain => :all}
      head :ok
    end

    def delete_cookie_with_domain
      cookies.delete(:user_name, :domain => :all)
      head :ok
    end
101

102 103 104 105 106 107 108 109 110 111
    def set_cookie_with_domain_and_tld
      cookies[:user_name] = {:value => "rizwanreza", :domain => :all, :tld_length => 2}
      head :ok
    end

    def delete_cookie_with_domain_and_tld
      cookies.delete(:user_name, :domain => :all, :tld_length => 2)
      head :ok
    end

112 113 114 115 116 117 118 119 120 121
    def set_cookie_with_domains
      cookies[:user_name] = {:value => "rizwanreza", :domain => %w(example1.com example2.com .example3.com)}
      head :ok
    end

    def delete_cookie_with_domains
      cookies.delete(:user_name, :domain => %w(example1.com example2.com .example3.com))
      head :ok
    end

122 123 124 125 126 127
    def symbol_key
      cookies[:user_name] = "david"
      head :ok
    end

    def string_key
S
steve 已提交
128
      cookies['user_name'] = "dhh"
129 130
      head :ok
    end
131 132 133 134 135 136 137 138 139 140 141 142 143 144

    def symbol_key_mock
      cookies[:user_name] = "david" if cookies[:user_name] == "andrew"
      head :ok
    end

    def string_key_mock
      cookies['user_name'] = "david" if cookies['user_name'] == "andrew"
      head :ok
    end

    def noop
      head :ok
    end
D
Initial  
David Heinemeier Hansson 已提交
145 146
  end

147
  tests TestController
D
Initial  
David Heinemeier Hansson 已提交
148

149
  def setup
150
    super
151
    @request.env["action_dispatch.key_generator"] = ActiveSupport::DummyKeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33")
D
Initial  
David Heinemeier Hansson 已提交
152 153 154
    @request.host = "www.nextangle.com"
  end

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
  def test_each
    request.cookie_jar['foo'] = :bar
    list = []
    request.cookie_jar.each do |k,v|
      list << [k, v]
    end

    assert_equal [['foo', :bar]], list
  end

  def test_enumerable
    request.cookie_jar['foo'] = :bar
    actual = request.cookie_jar.map { |k,v| [k.to_s, v.to_s] }
    assert_equal [['foo', 'bar']], actual
  end

171 172 173 174 175 176 177 178 179
  def test_key_methods
    assert !request.cookie_jar.key?(:foo)
    assert !request.cookie_jar.has_key?("foo")

    request.cookie_jar[:foo] = :bar
    assert request.cookie_jar.key?(:foo)
    assert request.cookie_jar.has_key?("foo")
  end

D
Initial  
David Heinemeier Hansson 已提交
180
  def test_setting_cookie
181
    get :authenticate
J
Jeremy Kemper 已提交
182
    assert_cookie_header "user_name=david; path=/"
183
    assert_equal({"user_name" => "david"}, @response.cookies)
D
Initial  
David Heinemeier Hansson 已提交
184 185
  end

186 187 188 189 190 191 192 193 194
  def test_setting_the_same_value_to_cookie
    request.cookies[:user_name] = 'david'
    get :authenticate
    assert response.cookies.empty?
  end

  def test_setting_the_same_value_to_permanent_cookie
    request.cookies[:user_name] = 'Jamie'
    get :set_permanent_cookie
195
    assert_equal response.cookies, 'user_name' => 'Jamie'
196 197
  end

198 199
  def test_setting_with_escapable_characters
    get :set_with_with_escapable_characters
J
Jeremy Kemper 已提交
200
    assert_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/"
201 202 203
    assert_equal({"that & guy" => "foo & bar => baz"}, @response.cookies)
  end

204
  def test_setting_cookie_for_fourteen_days
205
    get :authenticate_for_fourteen_days
J
Jeremy Kemper 已提交
206
    assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"
207
    assert_equal({"user_name" => "david"}, @response.cookies)
208
  end
209

210
  def test_setting_cookie_for_fourteen_days_with_symbols
P
Pratik Naik 已提交
211
    get :authenticate_for_fourteen_days_with_symbols
J
Jeremy Kemper 已提交
212
    assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"
213
    assert_equal({"user_name" => "david"}, @response.cookies)
214 215
  end

216 217
  def test_setting_cookie_with_http_only
    get :authenticate_with_http_only
J
Jeremy Kemper 已提交
218
    assert_cookie_header "user_name=david; path=/; HttpOnly"
219
    assert_equal({"user_name" => "david"}, @response.cookies)
220
  end
221

222
  def test_setting_cookie_with_secure
223
    @request.env["HTTPS"] = "on"
224 225 226 227
    get :authenticate_with_secure
    assert_cookie_header "user_name=david; path=/; secure"
    assert_equal({"user_name" => "david"}, @response.cookies)
  end
228

L
lest 已提交
229 230
  def test_setting_cookie_with_secure_when_always_write_cookie_is_true
    ActionDispatch::Cookies::CookieJar.any_instance.stubs(:always_write_cookie).returns(true)
231 232 233 234 235 236 237 238 239 240 241
    get :authenticate_with_secure
    assert_cookie_header "user_name=david; path=/; secure"
    assert_equal({"user_name" => "david"}, @response.cookies)
  end

  def test_not_setting_cookie_with_secure
    get :authenticate_with_secure
    assert_not_cookie_header "user_name=david; path=/; secure"
    assert_not_equal({"user_name" => "david"}, @response.cookies)
  end

242
  def test_multiple_cookies
243 244
    get :set_multiple_cookies
    assert_equal 2, @response.cookies.size
J
Jeremy Kemper 已提交
245
    assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT\nlogin=XJ-122; path=/"
246
    assert_equal({"login" => "XJ-122", "user_name" => "david"}, @response.cookies)
247
  end
248

249
  def test_setting_test_cookie
250 251
    assert_nothing_raised { get :access_frozen_cookies }
  end
J
Joshua Peek 已提交
252

253
  def test_expiring_cookie
254
    request.cookies[:user_name] = 'Joe'
255
    get :logout
J
Jeremy Kemper 已提交
256
    assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
257
    assert_equal({"user_name" => nil}, @response.cookies)
258
  end
J
Joshua Peek 已提交
259

260
  def test_delete_cookie_with_path
261
    request.cookies[:user_name] = 'Joe'
262
    get :delete_cookie_with_path
J
Jeremy Kemper 已提交
263
    assert_cookie_header "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT"
264
  end
J
Jeremy Kemper 已提交
265

266 267 268 269 270 271
  def test_delete_unexisting_cookie
    request.cookies.clear
    get :delete_cookie
    assert @response.cookies.empty?
  end

272
  def test_deleted_cookie_predicate
273
    cookies[:user_name] = 'Joe'
274 275 276 277 278 279
    cookies.delete("user_name")
    assert cookies.deleted?("user_name")
    assert_equal false, cookies.deleted?("another")
  end

  def test_deleted_cookie_predicate_with_mismatching_options
280
    cookies[:user_name] = 'Joe'
281 282 283 284
    cookies.delete("user_name", :path => "/path")
    assert_equal false, cookies.deleted?("user_name", :path => "/different")
  end

285
  def test_cookies_persist_throughout_request
Y
Yehuda Katz 已提交
286 287
    response = get :authenticate
    assert response.headers["Set-Cookie"] =~ /user_name=david/
288
  end
289 290 291

  def test_permanent_cookie
    get :set_permanent_cookie
292 293
    assert_match(/Jamie/, @response.headers["Set-Cookie"])
    assert_match(%r(#{20.years.from_now.utc.year}), @response.headers["Set-Cookie"])
294
  end
J
Joshua Peek 已提交
295

296 297 298 299
  def test_signed_cookie
    get :set_signed_cookie
    assert_equal 45, @controller.send(:cookies).signed[:user_id]
  end
J
Joshua Peek 已提交
300

301 302 303 304 305
  def test_accessing_nonexistant_signed_cookie_should_not_raise_an_invalid_signature
    get :set_signed_cookie
    assert_nil @controller.send(:cookies).signed[:non_existant_attribute]
  end

306 307
  def test_permanent_signed_cookie
    get :set_permanent_signed_cookie
308
    assert_match(%r(#{20.years.from_now.utc.year}), @response.headers["Set-Cookie"])
309 310 311
    assert_equal 100, @controller.send(:cookies).signed[:remember_me]
  end

312
  def test_delete_and_set_cookie
313
    request.cookies[:user_name] = 'Joe'
314 315 316 317
    get :delete_and_set_cookie
    assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT"
    assert_equal({"user_name" => "david"}, @response.cookies)
  end
J
Joshua Peek 已提交
318

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
  def test_raise_data_overflow
    assert_raise(ActionDispatch::Cookies::CookieOverflow) do
      get :raise_data_overflow
    end
  end

  def test_tampered_cookies
    assert_nothing_raised do
      get :tampered_cookies
      assert_response :success
    end
  end

  def test_raises_argument_error_if_missing_secret
    assert_raise(ArgumentError, nil.inspect) {
334
      @request.env["action_dispatch.key_generator"] = ActiveSupport::DummyKeyGenerator.new(nil)
335 336 337 338
      get :set_signed_cookie
    }

    assert_raise(ArgumentError, ''.inspect) {
339
      @request.env["action_dispatch.key_generator"] = ActiveSupport::DummyKeyGenerator.new("")
340 341 342 343 344 345
      get :set_signed_cookie
    }
  end

  def test_raises_argument_error_if_secret_is_probably_insecure
    assert_raise(ArgumentError, "password".inspect) {
346
      @request.env["action_dispatch.key_generator"] = ActiveSupport::DummyKeyGenerator.new("password")
347 348 349 350
      get :set_signed_cookie
    }

    assert_raise(ArgumentError, "secret".inspect) {
351
      @request.env["action_dispatch.key_generator"] = ActiveSupport::DummyKeyGenerator.new("secret")
352 353 354 355
      get :set_signed_cookie
    }

    assert_raise(ArgumentError, "12345678901234567890123456789".inspect) {
356
      @request.env["action_dispatch.key_generator"] = ActiveSupport::DummyKeyGenerator.new("12345678901234567890123456789")
357 358 359 360
      get :set_signed_cookie
    }
  end

361 362 363 364 365 366
  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=/"
  end

367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
  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=/"
  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=/"
  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=/"
  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=/"
  end

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
  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=/"
  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=/"
  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=/"
  end

416
  def test_deleting_cookie_with_all_domain_option
417
    request.cookies[:user_name] = 'Joe'
418 419 420 421 422
    get :delete_cookie_with_domain
    assert_response :success
    assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
  end

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
  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=/"
  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=/"
  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=/"
  end

  def test_deleting_cookie_with_all_domain_option_and_tld_length
444
    request.cookies[:user_name] = 'Joe'
445 446 447 448 449
    get :delete_cookie_with_domain_and_tld
    assert_response :success
    assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
  end

450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
  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=/"
  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=/"
  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=/"
  end

  def test_deletings_cookie_with_several_preset_domains_using_one_of_these_domains
    @request.host = "example2.com"
473
    request.cookies[:user_name] = 'Joe'
474 475 476 477 478 479 480
    get :delete_cookie_with_domains
    assert_response :success
    assert_cookie_header "user_name=; domain=example2.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
  end

  def test_deletings_cookie_with_several_preset_domains_using_other_domain
    @request.host = "other-domain.com"
481
    request.cookies[:user_name] = 'Joe'
482 483 484 485 486
    get :delete_cookie_with_domains
    assert_response :success
    assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
  end

487
  def test_cookies_hash_is_indifferent_access
488 489 490 491 492 493
    get :symbol_key
    assert_equal "david", cookies[:user_name]
    assert_equal "david", cookies['user_name']
    get :string_key
    assert_equal "dhh", cookies[:user_name]
    assert_equal "dhh", cookies['user_name']
494 495
  end

S
steve 已提交
496 497


498
  def test_setting_request_cookies_is_indifferent_access
499 500
    cookies.clear
    cookies[:user_name] = "andrew"
501
    get :string_key_mock
502
    assert_equal "david", cookies['user_name']
503

504 505
    cookies.clear
    cookies['user_name'] = "andrew"
506
    get :symbol_key_mock
507
    assert_equal "david", cookies[:user_name]
508 509 510 511
  end

  def test_cookies_retained_across_requests
    get :symbol_key
512
    assert_cookie_header "user_name=david; path=/"
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
    assert_equal "david", cookies[:user_name]

    get :noop
    assert_nil @response.headers["Set-Cookie"]
    assert_equal "david", cookies[:user_name]

    get :noop
    assert_nil @response.headers["Set-Cookie"]
    assert_equal "david", cookies[:user_name]
  end

  def test_cookies_can_be_cleared
    get :symbol_key
    assert_equal "david", cookies[:user_name]

528
    cookies.clear
529 530 531 532 533 534 535
    get :noop
    assert_nil cookies[:user_name]

    get :symbol_key
    assert_equal "david", cookies[:user_name]
  end

536
  def test_can_set_http_cookie_header
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
    @request.env['HTTP_COOKIE'] = 'user_name=david'
    get :noop
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]

    get :noop
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]

    @request.env['HTTP_COOKIE'] = 'user_name=andrew'
    get :noop
    assert_equal 'andrew', cookies['user_name']
    assert_equal 'andrew', cookies[:user_name]
  end

  def test_can_set_request_cookies
    @request.cookies['user_name'] = 'david'
    get :noop
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]

    get :noop
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]

    @request.cookies[:user_name] = 'andrew'
    get :noop
    assert_equal 'andrew', cookies['user_name']
    assert_equal 'andrew', cookies[:user_name]
  end

  def test_cookies_precedence_over_http_cookie
    @request.env['HTTP_COOKIE'] = 'user_name=andrew'
    get :authenticate
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]

    get :noop
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]
  end

  def test_cookies_precedence_over_request_cookies
    @request.cookies['user_name'] = 'andrew'
    get :authenticate
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]

585
    get :noop
586 587
    assert_equal 'david', cookies['user_name']
    assert_equal 'david', cookies[:user_name]
588 589
  end

J
Jeremy Kemper 已提交
590 591 592 593
  private
    def assert_cookie_header(expected)
      header = @response.headers["Set-Cookie"]
      if header.respond_to?(:to_str)
594
        assert_equal expected.split("\n").sort, header.split("\n").sort
J
Jeremy Kemper 已提交
595 596 597 598
      else
        assert_equal expected.split("\n"), header
      end
    end
599 600 601 602 603 604 605 606 607

    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
608
end