request.rb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. module ZammadSpecSupportRequest
  3. # This ruby meta programming action creates the methods to perform:
  4. # GET, POST, PATCH, PUT, DELETE and HEAD
  5. # HTTP "requests".
  6. # They overwrite the ones of `ActionDispatch::Integration::RequestHelpers`
  7. # to add the headers set by #add_headers before
  8. %i[get post patch put delete head].each do |method_id|
  9. define_method(method_id) do |path, **args|
  10. args = args.with_indifferent_access
  11. args[:headers] = Hash(args[:headers]).merge!(Hash(@headers))
  12. super(path, **args.symbolize_keys)
  13. end
  14. end
  15. # Adds one or more HTTP headers to all requests of the current example.
  16. #
  17. # @param [Hash{String => String}] headers Hash of HTTP headers
  18. #
  19. # @example
  20. # add_headers('Eg Some X-Header' => 'Some value')
  21. # @example
  22. # add_headers(
  23. # 'Header 1' => 'Some value',
  24. # 'Header 2' => 'Some value',
  25. # ...
  26. # )
  27. #
  28. # @return [Hash] The current headers Hash
  29. def add_headers(headers)
  30. @headers = Hash(@headers).merge(headers)
  31. end
  32. # Parses the response.body as JSON.
  33. #
  34. # @example
  35. # json_response
  36. # @example
  37. # json_response.is_a?(Array)
  38. #
  39. # @return [Array, Hash, ...] Parsed JSON structure as Ruby object
  40. def json_response
  41. JSON.parse(response.body)
  42. end
  43. # Authenticates all requests of the current example as the given user.
  44. #
  45. # @example
  46. # authenticated_as(some_admin_user)
  47. #
  48. # @example
  49. # authenticated_as(some_admin_user, on_behalf_of: customer_user)
  50. #
  51. # @example
  52. # authenticated_as(some_admin_user, password: 'wrongpw')
  53. #
  54. # @example
  55. # authenticated_as(some_admin_user, password: 'wrongpw', token: create(:token, action: 'api', user_id: some_admin_user.id) )
  56. #
  57. # @example
  58. # authenticated_as(nil, login: 'not_existing', password: 'wrongpw' )
  59. #
  60. # @return nil
  61. def authenticated_as(user, via: :api_client, **options)
  62. password = options[:password] || user.try(:password_plain) || user.password.to_s
  63. login = options[:login] || user.login
  64. case via
  65. when :api_client
  66. # ensure that always the correct header value is set
  67. # otherwise previous header configurations will be re-used
  68. add_headers('From' => options[:from])
  69. # if we want to authenticate by token
  70. credentials = if options[:token].present?
  71. "Token token=#{options[:token].name}"
  72. else
  73. ActionController::HttpAuthentication::Basic.encode_credentials(login, password)
  74. end
  75. add_headers('Authorization' => credentials)
  76. when :browser
  77. post '/api/v1/signin', params: { username: login, password: password, fingerprint: Faker::Number.number(digits: 9) }
  78. end
  79. end
  80. # Provides a Hash of attributes for the given FactoryBot
  81. # factory parameters which can be used as the params payload.
  82. # Note that the attributes are "cleaned" so no created_by_id etc.
  83. # is present.
  84. #
  85. # @see FactoryBot#attributes_for
  86. #
  87. # @example
  88. # attributes_params_for(:admin, email: 'custom@example.com')
  89. # # => {firstname: 'Nicole', email: 'custom@example.com', ...}
  90. #
  91. # @return [Hash{Symbol => <String, Array, Hash>}] request cleaned attributes
  92. def attributes_params_for(*args)
  93. filter_unused_params(attributes_for(*args))
  94. end
  95. # Provides a Hash of attributes for the given Model instance which can
  96. # be used as the params payload.
  97. # Note that the attributes are "cleaned" so no created_by_id etc.
  98. # is present.
  99. #
  100. # @param [Hash] instance An ActiveRecord instance
  101. #
  102. # @example
  103. # cleaned_params_for(some_admin_user)
  104. # # => {firstname: 'Nicole', email: 'admin@example.com', ...}
  105. #
  106. # @return [Hash{Symbol => <String, Array, Hash>}] request cleaned attributes
  107. def cleaned_params_for(instance)
  108. filter_unused_params(instance.attributes)
  109. end
  110. # This is a self explaining internal method.
  111. #
  112. # @see ApplicationModel#filter_unused_params
  113. def filter_unused_params(unfiltered)
  114. # let's get private
  115. ApplicationModel.send(:filter_unused_params, unfiltered)
  116. end
  117. end
  118. RSpec.configure do |config|
  119. config.include ZammadSpecSupportRequest, type: :request
  120. config.before(:each, type: :request) do
  121. Setting.set('system_init_done', true)
  122. end
  123. # This helper allows you to authenticate as a given user in request specs
  124. # via the example metadata, rather than directly:
  125. #
  126. # it 'does something', authenticated_as: :user
  127. #
  128. # In order for this to work, you must define the user in a `let` block first:
  129. #
  130. # let(:user) { create(:customer) }
  131. #
  132. config.before(:each, :authenticated_as, type: :request) do |example|
  133. user = authenticated_as_get_user example.metadata[:authenticated_as], return_type: :user
  134. authenticated_as user if user
  135. end
  136. end