Testing: Enhance authenticated_as spec helper
Originally, the `authenticated_as` spec helper made it impossible to persist session state in request specs. This made it impossible to test external_credentials#callback or any other controller actions that rely on session state. This commit fixes that. === How exactly was `authenticated_as` broken? `authenticated_as` passes user credentials via request headers. In practice, this auth method is for API requests by machine clients, since they don't have cookies or store session state. Because machine clients don't use cookies or session state anyway, Zammad disables them for this auth method: # app/controllers/application_controller/authenticates.rb 1 module ApplicationController::Authenticates 42 def authentication_check_only(auth_param = {}) 57 request.session_options[:skip] = true As a result, in tests using `authenticated_as`, session data is discarded between every single request. Some controller actions will not work without session data, so this limitation made testing these actions impossible. === Why couldn't we just set the session values directly in test setup? This is possible in controller tests, but the Rails & RSpec team soft-deprecated controller tests in favor of integration tests (request specs) a long time ago. For more details, consider the following comments: > The session is an internal structure for the controller. > Integration test is more black box than controller tests were. > I don't think we should be testing internals of the controller like this. > I would rework the test to test something visible in the UI instead. > > --@dhh via https://github.com/rails/rails/issues/23386 > Integration tests doesn't allow you to set session. > > --@rafaelfranca via https://github.com/rails/rails/issues/25394 === Solution This commit adds a `via: :browser` option to the spec helper which simply prepends a valid sign-in request to the spec example.
This commit is contained in:
parent
494474f11a
commit
847cf02b49
1 changed files with 16 additions and 11 deletions
|
@ -64,25 +64,30 @@ module ZammadSpecSupportRequest
|
||||||
# authenticated_as(nil, login: 'not_existing', password: 'wrongpw' )
|
# authenticated_as(nil, login: 'not_existing', password: 'wrongpw' )
|
||||||
#
|
#
|
||||||
# @return nil
|
# @return nil
|
||||||
def authenticated_as(user, login: nil, password: nil, token: nil, on_behalf_of: nil)
|
def authenticated_as(user, via: :api_client, **options)
|
||||||
password ||= user.password
|
password = options[:password] || user.password.to_s
|
||||||
login ||= user.login
|
login = options[:login] || user.login
|
||||||
|
|
||||||
# mock authentication otherwise login won't
|
# mock authentication otherwise login won't
|
||||||
# if user has no password (which is expensive to create)
|
# if user has no password (which is expensive to create)
|
||||||
if password.nil?
|
if password.blank?
|
||||||
allow(User).to receive(:authenticate).with(login, '') { user.update_last_login }.and_return(user)
|
allow(User).to receive(:authenticate).with(login, '') { user.update_last_login }.and_return(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
case via
|
||||||
|
when :api_client
|
||||||
# if we want to authenticate by token
|
# if we want to authenticate by token
|
||||||
if token.present?
|
if options[:token].present?
|
||||||
credentials = "Token token=#{token.name}"
|
credentials = "Token token=#{options[:token].name}"
|
||||||
|
|
||||||
return add_headers('Authorization' => credentials)
|
return add_headers('Authorization' => credentials)
|
||||||
end
|
end
|
||||||
|
|
||||||
credentials = ActionController::HttpAuthentication::Basic.encode_credentials(login, password)
|
credentials = ActionController::HttpAuthentication::Basic.encode_credentials(login, password)
|
||||||
add_headers('Authorization' => credentials, 'X-On-Behalf-Of' => on_behalf_of)
|
add_headers('Authorization' => credentials, 'X-On-Behalf-Of' => options[:on_behalf_of])
|
||||||
|
when :browser
|
||||||
|
post '/api/v1/signin', params: { username: login, password: password, fingerprint: Faker::Number.number(9) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Provides a Hash of attributes for the given FactoryBot
|
# Provides a Hash of attributes for the given FactoryBot
|
||||||
|
|
Loading…
Reference in a new issue