英文:
Set Session in RSpec with Rails 7 API
问题
以下是您要翻译的代码部分:
class Users::RegistrationsController < Devise::RegistrationsController
def create
super
if @user
# 如果用户在会话中有群组,我们为该用户创建一个群组成员
Membership.create(user: @user, group: session[:group]) if session[:group]
# 移除会话中的群组信息
reset_session
end
end
end
context "当用户通过邀请注册时" do
let(:group) {create :group}
before do
# 我们需要创建一个图标,以便在创建用户时将其附加到用户
create :icon
post user_registration_path,
params: { "user": { "username": "test", "email": "myemail@email.com", "password": "mypassword" }},
session: { "group": group.id }
end
it "保存了一个带有群组ID的会话" do
expect(session[:group]).to eq group.id
end
end
我希望这些代码部分对您有所帮助。如果您需要更多帮助,请随时告诉我。
英文:
I am trying to create a logic where a user gets an invitation from a group. If they signup via that invitation, the group id will be stored in the session and when they signup, they will be automatically added to the group as a member.
I am using Devise
for authentication. So I customized it like this:
class Users::RegistrationsController < Devise::RegistrationsController
def create
super
if @user
# We create a membership to the group if the user had it in the session (it means that it was invited)
Membership.create(user: @user, group: session[:group]) if session[:group]
# We remove the existing session
reset_session
end
end
end
Now, I want to test this behaviour.
I would like to test 2 scenarios:
- User doesn't have the session and signs up just like that
- User has the session and signs up -> a group membership is generated
The first one is fine but the second one is the one I am struggling at:
context "when user signs up via invitation" do
let(:group) {create :group}
before do
# We need to create an icon so that we can attach it to the use when created
create :icon
post user_registration_path,
params: { "user": { "username": "test", "email": "myemail@email.com", "password": "mypassword" }},
session: { "group": group.id }
end
it "has a session saved with group id" do
expect(session[:group]).to eq group.id
end
end
I found this way here, but it throws the following error:
ArgumentError:
unknown keyword: :session
If I try making the call like this instead:
params: { user: { "username": "test", "email": "myemail@email.com", "password": "mypassword" }, session: { "group": group.id}}
It still throws an error:
NoMethodError:
undefined method `enabled?' for {}:Hash
return unless session.enabled?
I also tried setting it like this:
request.session[:group] = group.id
After I make the post
call (with only the params). It does pass the expectation but I cannot fetch it from the controller.
Also, just setting it like this:
session[:group] = group.id
Throws the following error:
NoMethodError:
undefined method `session' for nil:NilClass
@request.session
Finally, if I try to mock it inside the before {}
block:
allow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return( group: group.id )
It gives me the following error:
NoMethodError:
undefined method `enabled?' for {:group=>1}:Hash
return unless session.enabled?
Any ideas on how can I tackle this?
PD. Using Rails 7 API and ruby 3.1.2
and also in my application.rb
I added the following to be able to work with sessions in the app (and when I test manually it does work)
# Configure session storage
config.session_store :cookie_store, key: '_interslice_session'
config.middleware.use ActionDispatch::Cookies
config.middleware.use config.session_store, config.session_options
Thanks!
答案1
得分: 1
I also struggled with this until I followed this approach and included a "session double" support, like this example:
Support:
https://github.com/DFE-Digital/schools-experience/blob/master/spec/support/session_double.rb
Usage:
Your Example
# your test...
RSpec.describe '...', type: :request do
describe '...' do
include_context 'session double'
let(:group) { create :group }
let(:session_hash) { {} }
before do
session_hash[:group] = group.id
end
it 'has a session saved with group id' do
post user_registration_path, params: { "user": { "username": "test", "email": "myemail@email.com", "password": "mypassword" }}
expect(session[:group]).to eq group.id
end
end
end
Add Session Support:
# spec/support/session_double.rb
shared_context 'session double' do
let(:session_hash) { {} }
before do
session_double = instance_double(ActionDispatch::Request::Session, enabled?: true, loaded?: false)
allow(session_double).to receive(:[]) do |key|
session_hash[key]
end
allow(session_double).to receive(:[]=) do |key, value|
session_hash[key] = value
end
allow(session_double).to receive(:delete) do |key|
session_hash.delete(key)
end
allow(session_double).to receive(:clear) do |_key|
session_hash.clear
end
allow(session_double).to receive(:fetch) do |key|
session_hash.fetch(key)
end
allow(session_double).to receive(:key?) do |key|
session_hash.key?(key)
end
allow_any_instance_of(ActionDispatch::Request)
.to receive(:session).and_return(session_double)
end
end
英文:
I also struggled with this until I followed this approach and included a "session double" support, like this example:
Support:
https://github.com/DFE-Digital/schools-experience/blob/master/spec/support/session_double.rb
Usage:
Your Example
# your test...
RSpec.describe '...', type: :request do
describe '...' do
include_context 'session double'
let(:group) {create :group}
let(:session_hash) { {} }
before do
session_hash[:group] = group.id
end
it 'has a session saved with group id' do
post user_registration_path, params: { "user": { "username": "test", "email": "myemail@email.com", "password": "mypassword" }}
expect(session[:group]).to eq group.id
end
end
end
Add Session Support:
# spec/support/session_double.rb
shared_context 'session double' do
let(:session_hash) { {} }
before do
session_double = instance_double(ActionDispatch::Request::Session, enabled?: true, loaded?: false)
allow(session_double).to receive(:[]) do |key|
session_hash[key]
end
allow(session_double).to receive(:[]=) do |key, value|
session_hash[key] = value
end
allow(session_double).to receive(:delete) do |key|
session_hash.delete(key)
end
allow(session_double).to receive(:clear) do |_key|
session_hash.clear
end
allow(session_double).to receive(:fetch) do |key|
session_hash.fetch(key)
end
allow(session_double).to receive(:key?) do |key|
session_hash.key?(key)
end
allow_any_instance_of(ActionDispatch::Request)
.to receive(:session).and_return(session_double)
end
end
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论