mongo_session_store 2.0.0 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +43 -0
  5. data/.travis.yml +37 -0
  6. data/CHANGELOG.md +49 -0
  7. data/Dangerfile +1 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE +23 -0
  10. data/README.md +106 -43
  11. data/Rakefile +90 -0
  12. data/gemfiles/rails-4.0-mongo.gemfile +9 -0
  13. data/gemfiles/rails-4.0-mongoid.gemfile +9 -0
  14. data/gemfiles/rails-4.1-mongo.gemfile +9 -0
  15. data/gemfiles/rails-4.1-mongoid.gemfile +9 -0
  16. data/gemfiles/rails-4.2-mongo.gemfile +9 -0
  17. data/gemfiles/rails-4.2-mongoid.gemfile +9 -0
  18. data/lib/mongo_session_store.rb +27 -1
  19. data/lib/mongo_session_store/mongo_store.rb +102 -0
  20. data/lib/mongo_session_store/mongo_store_base.rb +65 -0
  21. data/lib/mongo_session_store/mongoid_store.rb +52 -0
  22. data/lib/mongo_session_store/version.rb +3 -0
  23. data/mongo_session_store.gemspec +25 -0
  24. data/perf/benchmark.rb +101 -0
  25. data/spec/.rubocop.yml +4 -0
  26. data/spec/integrations/devise_spec.rb +109 -0
  27. data/spec/lib/mongo_session_store/mongo_store/session_spec.rb +247 -0
  28. data/spec/lib/mongo_session_store/mongo_store_base_spec.rb +269 -0
  29. data/spec/lib/mongo_session_store/mongo_store_spec.rb +13 -0
  30. data/spec/lib/mongo_session_store/mongoid_store/session_spec.rb +82 -0
  31. data/spec/lib/mongo_session_store/mongoid_store_spec.rb +13 -0
  32. data/spec/lib/mongo_session_store_spec.rb +64 -0
  33. data/spec/rails_helper.rb +19 -0
  34. data/spec/spec_helper.rb +53 -0
  35. data/spec/support/apps/rails_4.0_app/Rakefile +6 -0
  36. data/spec/support/apps/rails_4.0_app/app/controllers/application_controller.rb +5 -0
  37. data/spec/support/apps/rails_4.0_app/app/controllers/home_controller.rb +4 -0
  38. data/spec/support/apps/rails_4.0_app/app/models/user.rb +5 -0
  39. data/spec/support/apps/rails_4.0_app/app/views/home/index.html.erb +10 -0
  40. data/spec/support/apps/rails_4.0_app/app/views/layouts/application.html.erb +17 -0
  41. data/spec/support/apps/rails_4.0_app/bin/bundle +3 -0
  42. data/spec/support/apps/rails_4.0_app/bin/rails +4 -0
  43. data/spec/support/apps/rails_4.0_app/bin/rake +4 -0
  44. data/spec/support/apps/rails_4.0_app/config.ru +4 -0
  45. data/spec/support/apps/rails_4.0_app/config/application.rb +11 -0
  46. data/spec/support/apps/rails_4.0_app/config/boot.rb +4 -0
  47. data/spec/support/apps/rails_4.0_app/config/database.yml +11 -0
  48. data/spec/support/apps/rails_4.0_app/config/environment.rb +5 -0
  49. data/spec/support/apps/rails_4.0_app/config/environments/development.rb +12 -0
  50. data/spec/support/apps/rails_4.0_app/config/environments/test.rb +19 -0
  51. data/spec/support/apps/rails_4.0_app/config/initializers/devise.rb +254 -0
  52. data/spec/support/apps/rails_4.0_app/config/initializers/secret_token.rb +12 -0
  53. data/spec/support/apps/rails_4.0_app/config/initializers/session_store.rb +1 -0
  54. data/spec/support/apps/rails_4.0_app/config/locales/devise.en.yml +59 -0
  55. data/spec/support/apps/rails_4.0_app/config/locales/en.yml +23 -0
  56. data/spec/support/apps/rails_4.0_app/config/mongo.yml +11 -0
  57. data/spec/support/apps/rails_4.0_app/config/mongoid.yml +13 -0
  58. data/spec/support/apps/rails_4.0_app/config/routes.rb +4 -0
  59. data/spec/support/apps/rails_4.0_app/db/migrate/20140301171212_add_devise_users.rb +11 -0
  60. data/spec/support/apps/rails_4.0_app/db/schema.rb +25 -0
  61. data/spec/support/apps/rails_4.0_app/db/seeds.rb +7 -0
  62. data/spec/support/apps/rails_4.0_app/lib/assets/.keep +0 -0
  63. data/spec/support/apps/rails_4.0_app/lib/tasks/.keep +0 -0
  64. data/spec/support/apps/rails_4.0_app/log/.keep +0 -0
  65. data/spec/support/apps/rails_4.0_app/public/404.html +58 -0
  66. data/spec/support/apps/rails_4.0_app/public/422.html +58 -0
  67. data/spec/support/apps/rails_4.0_app/public/500.html +57 -0
  68. data/spec/support/apps/rails_4.0_app/public/favicon.ico +0 -0
  69. data/spec/support/apps/rails_4.0_app/public/robots.txt +5 -0
  70. data/spec/support/apps/rails_4.1_app/Rakefile +3 -0
  71. data/spec/support/apps/rails_4.1_app/app/controllers/application_controller.rb +5 -0
  72. data/spec/support/apps/rails_4.1_app/app/controllers/home_controller.rb +4 -0
  73. data/spec/support/apps/rails_4.1_app/app/models/user.rb +5 -0
  74. data/spec/support/apps/rails_4.1_app/app/views/home/index.html.erb +10 -0
  75. data/spec/support/apps/rails_4.1_app/app/views/layouts/application.html.erb +17 -0
  76. data/spec/support/apps/rails_4.1_app/bin/bundle +3 -0
  77. data/spec/support/apps/rails_4.1_app/bin/rails +4 -0
  78. data/spec/support/apps/rails_4.1_app/bin/rake +4 -0
  79. data/spec/support/apps/rails_4.1_app/config.ru +2 -0
  80. data/spec/support/apps/rails_4.1_app/config/application.rb +11 -0
  81. data/spec/support/apps/rails_4.1_app/config/boot.rb +4 -0
  82. data/spec/support/apps/rails_4.1_app/config/database.yml +11 -0
  83. data/spec/support/apps/rails_4.1_app/config/environment.rb +5 -0
  84. data/spec/support/apps/rails_4.1_app/config/environments/development.rb +12 -0
  85. data/spec/support/apps/rails_4.1_app/config/environments/test.rb +19 -0
  86. data/spec/support/apps/rails_4.1_app/config/initializers/devise.rb +254 -0
  87. data/spec/support/apps/rails_4.1_app/config/initializers/session_store.rb +1 -0
  88. data/spec/support/apps/rails_4.1_app/config/locales/devise.en.yml +59 -0
  89. data/spec/support/apps/rails_4.1_app/config/locales/en.yml +23 -0
  90. data/spec/support/apps/rails_4.1_app/config/mongo.yml +11 -0
  91. data/spec/support/apps/rails_4.1_app/config/mongoid.yml +13 -0
  92. data/spec/support/apps/rails_4.1_app/config/routes.rb +4 -0
  93. data/spec/support/apps/rails_4.1_app/config/secrets.yml +22 -0
  94. data/spec/support/apps/rails_4.1_app/db/migrate/20140301171212_add_devise_users.rb +11 -0
  95. data/spec/support/apps/rails_4.1_app/db/schema.rb +25 -0
  96. data/spec/support/apps/rails_4.1_app/db/seeds.rb +7 -0
  97. data/spec/support/apps/rails_4.1_app/lib/assets/.keep +0 -0
  98. data/spec/support/apps/rails_4.1_app/lib/tasks/.keep +0 -0
  99. data/spec/support/apps/rails_4.1_app/log/.keep +0 -0
  100. data/spec/support/apps/rails_4.1_app/public/404.html +67 -0
  101. data/spec/support/apps/rails_4.1_app/public/422.html +67 -0
  102. data/spec/support/apps/rails_4.1_app/public/500.html +66 -0
  103. data/spec/support/apps/rails_4.1_app/public/favicon.ico +0 -0
  104. data/spec/support/apps/rails_4.1_app/public/robots.txt +5 -0
  105. data/spec/support/apps/rails_4.2_app/Rakefile +2 -0
  106. data/spec/support/apps/rails_4.2_app/app/controllers/application_controller.rb +5 -0
  107. data/spec/support/apps/rails_4.2_app/app/controllers/home_controller.rb +4 -0
  108. data/spec/support/apps/rails_4.2_app/app/models/user.rb +5 -0
  109. data/spec/support/apps/rails_4.2_app/app/views/home/index.html.erb +10 -0
  110. data/spec/support/apps/rails_4.2_app/app/views/layouts/application.html.erb +15 -0
  111. data/spec/support/apps/rails_4.2_app/bin/bundle +3 -0
  112. data/spec/support/apps/rails_4.2_app/bin/rails +8 -0
  113. data/spec/support/apps/rails_4.2_app/bin/rake +4 -0
  114. data/spec/support/apps/rails_4.2_app/config.ru +4 -0
  115. data/spec/support/apps/rails_4.2_app/config/application.rb +11 -0
  116. data/spec/support/apps/rails_4.2_app/config/boot.rb +3 -0
  117. data/spec/support/apps/rails_4.2_app/config/database.yml +11 -0
  118. data/spec/support/apps/rails_4.2_app/config/environment.rb +5 -0
  119. data/spec/support/apps/rails_4.2_app/config/environments/development.rb +12 -0
  120. data/spec/support/apps/rails_4.2_app/config/environments/test.rb +19 -0
  121. data/spec/support/apps/rails_4.2_app/config/initializers/devise.rb +254 -0
  122. data/spec/support/apps/rails_4.2_app/config/initializers/session_store.rb +1 -0
  123. data/spec/support/apps/rails_4.2_app/config/locales/en.yml +23 -0
  124. data/spec/support/apps/rails_4.2_app/config/mongo.yml +11 -0
  125. data/spec/support/apps/rails_4.2_app/config/mongoid.yml +13 -0
  126. data/spec/support/apps/rails_4.2_app/config/routes.rb +4 -0
  127. data/spec/support/apps/rails_4.2_app/config/secrets.yml +22 -0
  128. data/spec/support/apps/rails_4.2_app/db/migrate/20140301171212_add_devise_users.rb +11 -0
  129. data/spec/support/apps/rails_4.2_app/db/schema.rb +25 -0
  130. data/spec/support/apps/rails_4.2_app/db/seeds.rb +7 -0
  131. data/spec/support/helpers/session_id_helper.rb +5 -0
  132. data/spec/support/helpers/test_database_helper.rb +22 -0
  133. metadata +360 -92
  134. data/lib/mongo_session_store/mongo_mapper.rb +0 -60
  135. data/lib/mongo_session_store/mongoid.rb +0 -59
@@ -0,0 +1,4 @@
1
+ inherit_from: ../.rubocop.yml
2
+
3
+ Metrics/LineLength:
4
+ Max: 100
@@ -0,0 +1,109 @@
1
+ require "rails_helper"
2
+
3
+ describe Devise::SessionsController, :type => :request do
4
+ def create_user
5
+ post "/users",
6
+ "user[email]" => "person@example.com",
7
+ "user[password]" => "secret",
8
+ "user[password_confirmation]" => "secret"
9
+ end
10
+
11
+ def sign_in
12
+ post "/users/sign_in",
13
+ "user[email]" => "person@example.com",
14
+ "user[password]" => "secret",
15
+ "user[password_confirmation]" => "secret"
16
+ end
17
+
18
+ def sign_out
19
+ delete "/users/sign_out"
20
+ end
21
+
22
+ def expect_to_be_signed_in
23
+ expect(controller.user_signed_in?).to eq(true)
24
+ get "/"
25
+ expect(response.body.squish).to include "You are signed in as person@example.com"
26
+ end
27
+
28
+ def expect_to_not_be_signed_in
29
+ expect(controller.user_signed_in?).to eq(false)
30
+ get "/"
31
+ expect(response.body.squish).to include "You are signed out"
32
+ end
33
+
34
+ it "creates a user" do
35
+ expect do
36
+ create_user
37
+ expect(response.status).to eq(302)
38
+ end.to change { User.count }.from(0).to(1)
39
+
40
+ get response.redirect_url
41
+ expect(response.body.squish).to include \
42
+ "You are signed in as person@example.com",
43
+ "You have signed up successfully"
44
+ end
45
+
46
+ describe "user session" do
47
+ describe "sign out" do
48
+ before do
49
+ create_user
50
+ expect_to_be_signed_in
51
+ end
52
+
53
+ it "signs out user" do
54
+ sign_out
55
+
56
+ expect(response.status).to eq(302)
57
+ expect_to_not_be_signed_in
58
+ expect(response.body.squish).to include "Signed out successfully"
59
+ end
60
+ end
61
+
62
+ describe "sign in" do
63
+ before do
64
+ create_user
65
+ sign_out
66
+ expect_to_not_be_signed_in
67
+ end
68
+
69
+ it "signs in user" do
70
+ sign_in
71
+
72
+ expect(response.status).to eq(302)
73
+ expect_to_be_signed_in
74
+ expect(response.body.squish).to include "Signed in successfully"
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "session_store" do
80
+ subject { Rails.application.config.session_store.session_class.to_s }
81
+
82
+ it "uses the mongo #{mongo_orm} session store class" do
83
+ expect(subject).to eq \
84
+ "ActionDispatch::Session::#{mongo_orm.camelize}Store::Session"
85
+ end
86
+ end
87
+
88
+ describe "sessions collection" do
89
+ let(:collection) { test_database["sessions"] }
90
+
91
+ it "creates a record in the sessions collection" do
92
+ expect do
93
+ create_user
94
+ end.to change { collection.find.count }.from(0).to(1)
95
+ end
96
+
97
+ describe "custom collection" do
98
+ before { MongoSessionStore.collection_name = "dance_parties" }
99
+ after { MongoSessionStore.collection_name = "sessions" }
100
+ let(:collection) { test_database["dance_parties"] }
101
+
102
+ it "creates a record in the custom sessions collection" do
103
+ expect do
104
+ create_user
105
+ end.to change { collection.find.count }.from(0).to(1)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,247 @@
1
+ require "spec_helper"
2
+
3
+ if mongo_orm == "mongo"
4
+ describe MongoStore::Session do
5
+ before { described_class.collection.drop }
6
+
7
+ describe ".database" do
8
+ subject { described_class.database }
9
+
10
+ context "with database" do
11
+ let(:database) do
12
+ MongoStore::Session.database = Mongo::Client.new(
13
+ ["127.0.0.1:27017"],
14
+ :database => TestDatabaseHelper.test_database_name
15
+ )
16
+ end
17
+ around do |example|
18
+ original_db = described_class.database
19
+ described_class.database = database
20
+ example.run
21
+ described_class.database = original_db
22
+ end
23
+
24
+ it "returns the database" do
25
+ expect(subject).to eq(database)
26
+ end
27
+ end
28
+
29
+ context "without database" do
30
+ it "raises an error" do
31
+ original_db = described_class.database
32
+ described_class.database = nil
33
+
34
+ expect { subject }.to raise_error(described_class::NoMongoClientError)
35
+
36
+ described_class.database = original_db
37
+ end
38
+ end
39
+ end
40
+
41
+ describe ".collection_name" do
42
+ # Where the name comes from:
43
+ # - "test_database" set in spec_helper
44
+ # - "sessions" is derived from model name
45
+ it "saves in the given collection_name" do
46
+ expect(described_class.collection.namespace).to eq("test_database.sessions")
47
+ end
48
+ end
49
+
50
+ describe ".where" do
51
+ subject { described_class.where(:_id => id) }
52
+
53
+ context "without matching records" do
54
+ let(:id) { nil }
55
+
56
+ it "returns an empty array" do
57
+ expect(subject).to eq([])
58
+ end
59
+ end
60
+
61
+ context "with matching records" do
62
+ let(:session) { described_class.new(:_id => generate_sid).tap(&:save) }
63
+ let(:id) { session._id }
64
+ before do
65
+ # Noise
66
+ described_class.new(:_id => generate_sid).tap(&:save)
67
+ end
68
+
69
+ it "returns session model objects" do
70
+ expect(subject.map(&:_id)).to eq([session._id])
71
+ end
72
+ end
73
+ end
74
+
75
+ describe ".load" do
76
+ let(:created_at) { Time.local(2016, 5, 27, 12, 25, 15) }
77
+ let(:updated_at) { Time.local(2016, 5, 28, 16, 15, 55) }
78
+ let(:session) { described_class.load(attributes) }
79
+
80
+ context "without data" do
81
+ let(:attributes) do
82
+ {
83
+ :_id => generate_sid,
84
+ :created_at => created_at,
85
+ :updated_at => updated_at
86
+ }
87
+ end
88
+
89
+ it "creates a session object with empty data" do
90
+ expect(session._id).to be_kind_of(String)
91
+ expect(session.data).to eq({})
92
+ expect(session.created_at).to eq(created_at)
93
+ expect(session.updated_at).to eq(updated_at)
94
+ end
95
+ end
96
+
97
+ context "with data key as a symbol" do
98
+ let(:attributes) do
99
+ {
100
+ :_id => generate_sid,
101
+ :data => BSON::Binary.new(Marshal.dump(:foo => "bar"), :generic),
102
+ :created_at => created_at,
103
+ :updated_at => updated_at
104
+ }
105
+ end
106
+
107
+ it "creates a session object with correct data" do
108
+ expect(session._id).to be_kind_of(String)
109
+ expect(session.data).to eq(:foo => "bar")
110
+ expect(session.created_at).to eq(created_at)
111
+ expect(session.updated_at).to eq(updated_at)
112
+ end
113
+ end
114
+
115
+ context "with data key as a string" do
116
+ let(:attributes) do
117
+ {
118
+ :_id => generate_sid,
119
+ "data" => BSON::Binary.new(Marshal.dump(:foo => "bar"), :generic),
120
+ :created_at => created_at,
121
+ :updated_at => updated_at
122
+ }
123
+ end
124
+
125
+ it "creates a session object with correct data" do
126
+ expect(session._id).to be_kind_of(String)
127
+ expect(session.data).to eq(:foo => "bar")
128
+ expect(session.created_at).to eq(created_at)
129
+ expect(session.updated_at).to eq(updated_at)
130
+ end
131
+ end
132
+ end
133
+
134
+ describe "#save" do
135
+ let(:id) { generate_sid }
136
+ subject { described_class.collection.find(:_id => id).first }
137
+
138
+ describe "_id attribute" do
139
+ let(:session) { described_class.new(:_id => id) }
140
+ before { session.save }
141
+
142
+ it "saves a record in MongoDB" do
143
+ expect(subject[:_id]).to eq(id)
144
+ end
145
+ end
146
+
147
+ describe "timestamps" do
148
+ let!(:time) { Time.now.utc }
149
+ let(:session) { described_class.new(:_id => id) }
150
+
151
+ describe "#created_at" do
152
+ context "without time" do
153
+ before { session.save }
154
+
155
+ it "sets the current time" do
156
+ expect(subject[:created_at]).to be_kind_of(Time)
157
+ expect(subject[:created_at].to_s).to eq(time.to_s)
158
+ end
159
+ end
160
+
161
+ context "with time" do
162
+ let!(:original_created_at) { Time.parse("Thu Nov 29 14:33:20 2001").utc }
163
+ before { session.created_at = original_created_at }
164
+
165
+ it "keeps original created_at time" do
166
+ expect do
167
+ session.save
168
+ end.to_not change { session.created_at.to_s }
169
+
170
+ expect(subject[:created_at]).to be_kind_of(Time)
171
+ expect(subject[:created_at].to_s).to eq(original_created_at.to_s)
172
+ end
173
+ end
174
+ end
175
+
176
+ describe "#updated_at" do
177
+ context "without time" do
178
+ it "sets the current time" do
179
+ expect do
180
+ session.save
181
+ end.to change { session.updated_at.to_s }.from("").to(time.to_s)
182
+
183
+ expect(subject[:updated_at]).to be_kind_of(Time)
184
+ expect(subject[:updated_at].to_s).to eq(time.to_s)
185
+ end
186
+ end
187
+
188
+ context "with time" do
189
+ let!(:original_updated_at) { Time.parse("Thu Nov 29 14:33:20 2001").utc }
190
+ before { session.updated_at = original_updated_at }
191
+
192
+ it "updates the time to the current time" do
193
+ expect do
194
+ session.save
195
+ end.to change { session.updated_at.to_s }.from(original_updated_at.to_s).to(time.to_s)
196
+
197
+ expect(subject[:updated_at]).to be_kind_of(Time)
198
+ expect(subject[:updated_at].to_s).to eq(time.to_s)
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ context "with data attribute" do
205
+ before do
206
+ session = described_class.new(
207
+ :_id => id,
208
+ :data => { :foo => "bar" }
209
+ )
210
+ session.save
211
+ end
212
+
213
+ it "saves the marshalled data" do
214
+ expect(subject[:data]).to be_kind_of(BSON::Binary)
215
+ unmarshalled_data = Marshal.load(StringIO.new(subject[:data].data))
216
+ expect(unmarshalled_data).to eq(:foo => "bar")
217
+ end
218
+ end
219
+
220
+ context "without data attribute" do
221
+ before do
222
+ session = described_class.new(:_id => id)
223
+ session.save
224
+ end
225
+
226
+ it "saves empty hash" do
227
+ expect(subject[:data]).to be_kind_of(BSON::Binary)
228
+ unmarshalled_data = Marshal.load(StringIO.new(subject[:data].data))
229
+ expect(unmarshalled_data).to eq({})
230
+ end
231
+ end
232
+ end
233
+
234
+ describe "#destroy" do
235
+ let(:id) { generate_sid }
236
+ let(:session) { described_class.new(:_id => id) }
237
+ before { session.save }
238
+
239
+ it "removes the record from the collection" do
240
+ expect do
241
+ session.destroy
242
+ end.to change { described_class.collection.count }.from(1).to(0)
243
+ expect(described_class.collection.find(:_id => session._id).count).to eq(0)
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,269 @@
1
+ require "spec_helper"
2
+ require "ostruct"
3
+
4
+ class TestStore < ActionDispatch::Session::MongoStoreBase
5
+ class Session < OpenStruct
6
+ def self.where(_ = {})
7
+ []
8
+ end
9
+ end
10
+ end
11
+
12
+ describe ActionDispatch::Session::MongoStoreBase do
13
+ describe ".session_class" do
14
+ let(:store_class) { TestStore }
15
+ let(:store) { store_class.new(nil) }
16
+ subject { store_class.session_class }
17
+
18
+ it "returns child session class" do
19
+ expect(subject).to eq(TestStore::Session)
20
+ end
21
+ end
22
+
23
+ describe "#get_session" do
24
+ let(:env) { {} }
25
+ let(:store_class) { TestStore }
26
+ let(:store) { store_class.new(nil) }
27
+ let(:session_class) { store_class::Session }
28
+ let(:session_record) { env[store_class::SESSION_RECORD_KEY] }
29
+
30
+ context "when no session exists" do
31
+ it "creates a new session" do
32
+ sid, session_data = store.send(:get_session, env, nil)
33
+
34
+ expect(sid).to be_kind_of(String)
35
+ expect(session_data).to be_nil
36
+ expect(session_record).to be_kind_of(session_class)
37
+ expect(session_record._id).to eq sid
38
+
39
+ env_record = env[described_class::SESSION_RECORD_KEY]
40
+ expect(env_record).to be_kind_of(session_class)
41
+ expect(env_record._id).to eq sid
42
+ end
43
+ end
44
+
45
+ context "when given session is found" do
46
+ let(:session) { session_class.new(:_id => "foo", :data => nil) }
47
+ before do
48
+ expect(session_class).to receive(:where).and_return([session])
49
+ end
50
+
51
+ it "returns the existing session" do
52
+ sid, session_data = store.send(:get_session, env, session._id)
53
+
54
+ expect(sid).to eq(session._id)
55
+ expect(sid).to be_kind_of(String)
56
+ expect(session_data).to be_nil
57
+ expect(session_record).to be_kind_of(session_class)
58
+ expect(session_record._id).to eq sid
59
+
60
+ env_record = env[described_class::SESSION_RECORD_KEY]
61
+ expect(env_record).to be_kind_of(session_class)
62
+ expect(env_record._id).to eq sid
63
+ end
64
+ end
65
+
66
+ context "when given session is not found" do
67
+ let(:not_existing_session_id) { SecureRandom.hex }
68
+
69
+ it "creates a new session" do
70
+ sid, session_data = store.send(:get_session, env, not_existing_session_id)
71
+
72
+ expect(sid).to_not eq(not_existing_session_id)
73
+ expect(sid).to be_kind_of(String)
74
+ expect(session_data).to be_nil
75
+ expect(session_record).to be_kind_of(session_class)
76
+ expect(session_record._id).to eq sid
77
+
78
+ env_record = env[described_class::SESSION_RECORD_KEY]
79
+ expect(env_record).to be_kind_of(session_class)
80
+ expect(env_record._id).to eq sid
81
+ end
82
+ end
83
+
84
+ context "with custom session class" do
85
+ let(:store_class) { TestStore }
86
+
87
+ it "returns a session record from the custom session class" do
88
+ sid, session_data = store.send(:get_session, env, nil)
89
+
90
+ expect(sid).to be_kind_of(String)
91
+ expect(session_data).to be_nil
92
+ expect(session_record).to be_kind_of(session_class)
93
+ expect(session_record._id.to_s).to eq sid
94
+ end
95
+ end
96
+ end
97
+
98
+ describe "#set_session" do
99
+ let(:store_class) { mongo_orm == "mongoid" ? MongoidStore : MongoStore }
100
+ let(:store) { store_class.new(nil) }
101
+ let(:session_class) { store_class::Session }
102
+ subject { store.send(:set_session, env, generate_sid, {}) }
103
+
104
+ context "with existing session record" do
105
+ let(:id) { generate_sid }
106
+ let!(:session_record) { session_class.new(:_id => id).tap(&:save) }
107
+ let(:env) do
108
+ {
109
+ "rack.session" => double(:id => id),
110
+ Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY => { :id => id }
111
+ }
112
+ end
113
+ subject { store.send(:set_session, env, id, {}) }
114
+
115
+ it "uses the existing record" do
116
+ expect do
117
+ subject
118
+ end.to_not change { session_class.collection.find(:_id => id).count }
119
+ expect(subject).to eq(id.to_s)
120
+ end
121
+
122
+ it "yields" do
123
+ yielded_variable = :not_called
124
+ block =
125
+ proc do
126
+ yielded_variable = :called
127
+ end
128
+ store.send(:set_session, env, id, {}, &block)
129
+ expect(yielded_variable).to eq(:called)
130
+ end
131
+
132
+ context "with session record in the ENV" do
133
+ let(:env) do
134
+ {
135
+ "rack.session" => double(:id => id),
136
+ Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY => { :id => id },
137
+ "rack.session.record" => session_record
138
+ }
139
+ end
140
+
141
+ it "uses the record from the ENV" do
142
+ expect do
143
+ expect(session_record).to receive(:data=).and_call_original
144
+ subject
145
+ end.to_not change { session_class.collection.find(:_id => id).count }
146
+ end
147
+ end
148
+ end
149
+
150
+ context "without existing session record" do
151
+ let :env do
152
+ {
153
+ "rack.session" => {},
154
+ Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY => {}
155
+ }
156
+ end
157
+
158
+ it "creates a session record" do
159
+ expect do
160
+ subject
161
+ end.to change { session_class.collection.find.count }.from(0).to(1)
162
+ expect(subject).to be_kind_of(String)
163
+ end
164
+
165
+ it "sets the session record in the env" do
166
+ sid = subject
167
+ expect(env["rack.session.record"]).to be_kind_of(session_class)
168
+ expect(env["rack.session.record"]._id.to_s).to eq(sid)
169
+ end
170
+
171
+ context "when not saved" do
172
+ before do
173
+ record = double("data=" => nil, :save => false)
174
+ expect(store).to receive(:get_session_record).and_return([1, record])
175
+ end
176
+
177
+ it "returns false" do
178
+ expect(subject).to be false
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ describe "#destroy_session" do
185
+ let(:id) { generate_sid }
186
+ let(:store_class) { mongo_orm == "mongoid" ? MongoidStore : MongoStore }
187
+ let(:store) { store_class.new(nil) }
188
+ let(:session_class) { store_class::Session }
189
+ let(:env) do
190
+ {
191
+ "rack.session" => double(:id => id),
192
+ Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY => {}
193
+ }
194
+ end
195
+
196
+ context "without existing session" do
197
+ subject { store.send(:destroy_session, env, id, {}) }
198
+
199
+ it "does not remove any record" do
200
+ expect { subject }.to_not change { session_class.collection.count }
201
+ end
202
+
203
+ it "returns new session id" do
204
+ expect(subject).to be_kind_of(String)
205
+ expect(subject).to_not eq(id)
206
+ end
207
+
208
+ context "with option :drop" do
209
+ subject { store.send(:destroy_session, env, id, :drop => true) }
210
+
211
+ it "does not remove any record" do
212
+ expect { subject }.to_not change { session_class.collection.count }
213
+ end
214
+
215
+ it "returns nothing" do
216
+ expect(subject).to be_nil
217
+ end
218
+ end
219
+ end
220
+
221
+ context "with existing session" do
222
+ let!(:session_record) { session_class.new(:_id => id).tap(&:save) }
223
+ subject { store.send(:destroy_session, env, id, {}) }
224
+
225
+ it "removes the session record" do
226
+ expect do
227
+ subject
228
+ end.to change { session_class.collection.find(:_id => id).count }.from(1).to(0)
229
+ end
230
+
231
+ it "returns new session id" do
232
+ expect(subject).to be_kind_of(String)
233
+ expect(subject).to_not eq(session_record._id)
234
+ end
235
+
236
+ context "with session record in the ENV" do
237
+ let(:env) do
238
+ {
239
+ "rack.session" => double(:id => id),
240
+ Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY => { :id => id },
241
+ "rack.session.record" => session_record
242
+ }
243
+ end
244
+ subject { store.send(:destroy_session, env, id, :drop => true) }
245
+
246
+ it "destroys record in the env" do
247
+ expect do
248
+ expect(session_record).to receive(:destroy).and_call_original
249
+ subject
250
+ end.to change { session_class.collection.find(:_id => id).count }.from(1).to(0)
251
+ end
252
+ end
253
+
254
+ context "with option :drop" do
255
+ subject { store.send(:destroy_session, env, id, :drop => true) }
256
+
257
+ it "removes the session record" do
258
+ expect do
259
+ subject
260
+ end.to change { session_class.collection.find(:_id => id).count }.from(1).to(0)
261
+ end
262
+
263
+ it "returns nothing" do
264
+ expect(subject).to be_nil
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end