mongo_session_store 2.0.0 → 3.0.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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