1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/test/dispatch/request/session_test.rb
claudiob 398267b142
Add #dig to ActionDispatch::Request::Session
### Summary

The `session` object is not a real Hash but responds to many methods of Hash
such as `[]`, `[]`, `fetch`, `has_key?`.

Since Ruby 2.3, Hash also supports a `dig` method.

This commit adds a `dig` method to `ActionDispatch::Request::Session` with the
same behavior as `Hash#dig`.

This is useful if you store a hash in your session, such as:

```ruby
session[:user] = { id: 1, avatar_url: "http://example.org/nyancat.jpg" }
```

Then you can shorten your code from `session[:user][:avatar_url]` to `session.dig :user, :avatar_url`.

### Other Information

I cherry-picked a commit from https://github.com/rails/rails/pull/23864, and modify a bit.
The changes are below:

* Converts only the first key to a string adjust to the `fetch` method.
* Fixes a test case because we cannot use the indifferent access since ee5b621e2f.
2018-04-04 16:20:16 +09:00

177 lines
4.4 KiB
Ruby

# frozen_string_literal: true
require "abstract_unit"
require "action_dispatch/middleware/session/abstract_store"
module ActionDispatch
class Request
class SessionTest < ActiveSupport::TestCase
attr_reader :req
def setup
@req = ActionDispatch::Request.empty
end
def test_create_adds_itself_to_env
s = Session.create(store, req, {})
assert_equal s, req.env[Rack::RACK_SESSION]
end
def test_to_hash
s = Session.create(store, req, {})
s["foo"] = "bar"
assert_equal "bar", s["foo"]
assert_equal({ "foo" => "bar" }, s.to_hash)
assert_equal({ "foo" => "bar" }, s.to_h)
end
def test_create_merges_old
s = Session.create(store, req, {})
s["foo"] = "bar"
s1 = Session.create(store, req, {})
assert_not_equal s, s1
assert_equal "bar", s1["foo"]
end
def test_find
assert_nil Session.find(req)
s = Session.create(store, req, {})
assert_equal s, Session.find(req)
end
def test_destroy
s = Session.create(store, req, {})
s["rails"] = "ftw"
s.destroy
assert_empty s
end
def test_keys
s = Session.create(store, req, {})
s["rails"] = "ftw"
s["adequate"] = "awesome"
assert_equal %w[rails adequate], s.keys
end
def test_keys_with_deferred_loading
s = Session.create(store_with_data, req, {})
assert_equal %w[sample_key], s.keys
end
def test_values
s = Session.create(store, req, {})
s["rails"] = "ftw"
s["adequate"] = "awesome"
assert_equal %w[ftw awesome], s.values
end
def test_values_with_deferred_loading
s = Session.create(store_with_data, req, {})
assert_equal %w[sample_value], s.values
end
def test_clear
s = Session.create(store, req, {})
s["rails"] = "ftw"
s["adequate"] = "awesome"
s.clear
assert_empty(s.values)
end
def test_update
s = Session.create(store, req, {})
s["rails"] = "ftw"
s.update(rails: "awesome")
assert_equal(["rails"], s.keys)
assert_equal("awesome", s["rails"])
end
def test_delete
s = Session.create(store, req, {})
s["rails"] = "ftw"
s.delete("rails")
assert_empty(s.keys)
end
def test_fetch
session = Session.create(store, req, {})
session["one"] = "1"
assert_equal "1", session.fetch(:one)
assert_equal "2", session.fetch(:two, "2")
assert_nil session.fetch(:two, nil)
assert_equal "three", session.fetch(:three) { |el| el.to_s }
assert_raise KeyError do
session.fetch(:three)
end
end
def test_dig
session = Session.create(store, req, {})
session["one"] = { "two" => "3" }
assert_equal "3", session.dig("one", "two")
assert_equal "3", session.dig(:one, "two")
assert_nil session.dig("three", "two")
assert_nil session.dig("one", "three")
assert_nil session.dig("one", :two)
end
private
def store
Class.new {
def load_session(env); [1, {}]; end
def session_exists?(env); true; end
def delete_session(env, id, options); 123; end
}.new
end
def store_with_data
Class.new {
def load_session(env); [1, { "sample_key" => "sample_value" }]; end
def session_exists?(env); true; end
def delete_session(env, id, options); 123; end
}.new
end
end
class SessionIntegrationTest < ActionDispatch::IntegrationTest
class MySessionApp
def call(env)
request = Rack::Request.new(env)
request.session["hello"] = "Hello from MySessionApp!"
[ 200, {}, ["Hello from MySessionApp!"] ]
end
end
Router = ActionDispatch::Routing::RouteSet.new
Router.draw do
get "/mysessionapp" => MySessionApp.new
end
def app
@app ||= RoutedRackApp.new(Router)
end
def test_session_follows_rack_api_contract_1
get "/mysessionapp"
assert_response :ok
assert_equal "Hello from MySessionApp!", @response.body
assert_equal "Hello from MySessionApp!", session["hello"]
end
end
end
end