<commit_before>module ZammadSpecSupportRequest

  # This ruby meta programming action creates the methods to perform:
  # GET, POST, PATCH, PUT, DELETE and HEAD
  # HTTP "requests".
  # They overwrite the ones of `ActionDispatch::Integration::RequestHelpers`
  # to add the headers set by #add_headers before
  %i[get post patch put delete head].each do |method_id|

    define_method(method_id) do |path, **args|
      args = args.with_indifferent_access
      args[:headers] = Hash(args[:headers]).merge!(Hash(@headers))
      super(path, **args.symbolize_keys)
    end
  end

  # Adds one or more HTTP headers to all requests of the current example.
  #
  # @param [Hash{String => String}] headers Hash of HTTP headers
  #
  # @example
  #  add_headers('Eg Some X-Header' => 'Some value')

  # @example
  #  add_headers(
  #    'Header 1' => 'Some value',
  #    'Header 2' => 'Some value',
  #    ...
  #  )
  #
  # @return [Hash] The current headers Hash
  def add_headers(headers)
    @headers = Hash(@headers).merge(headers)
  end

  # Parses the response.body as JSON.
  #
  # @example
  #  json_response

  # @example
  #  json_response.is_a?(Array)
  #
  # @return [Array, Hash, ...] Parsed JSON structure as Ruby object
  def json_response
    JSON.parse(response.body)
  end

  # Authenticates all requests of the current example as the given user.
  #
  # @example
  #  authenticated_as(some_admin_user)
  #
  # @example
  #  authenticated_as(some_admin_user, on_behalf_of: customer_user)
  #
  # @example
  #  authenticated_as(some_admin_user, password: '<PASSWORD>')
  #
  # @example
  #  authenticated_as(some_admin_user, password: '<PASSWORD>', token: create(:token, action: 'api', user_id: some_admin_user.id) )
  #
  # @example
  #  authenticated_as(nil, login: 'not_existing', password: '<PASSWORD>' )
  #
  # @return nil
  def authenticated_as(user, login: nil, password: nil, token: nil, on_behalf_of: nil)
    password ||= user.password
    login    ||= user.login

    # mock authentication otherwise login won't
    # if user has no password (which is expensive to create)
    if password.nil?
      allow(User).to receive(:authenticate).with(login, '') { user.update_last_login }.and_return(user)
    end

    # if we want to authenticate by token
    if token.present?
      credentials = "Token token=#{token.name}"

      return add_headers('Authorization' => credentials)
    end

    credentials = ActionController::HttpAuthentication::Basic.encode_credentials(login, password)
    add_headers('Authorization' => credentials, 'X-On-Behalf-Of' => on_behalf_of)
  end

  # Provides a Hash of attributes for the given FactoryBot
  #  factory parameters which can be used as the params payload.
  #  Note that the attributes are "cleaned" so no created_by_id etc.
  #  is present.
  #
  # @see FactoryBot#attributes_for
  #
  # @example
  #  attributes_params_for(:admin_user, email: '<EMAIL>')
  #  # => {firstname: 'Nicole', email: '<EMAIL>', ...}
  #
  # @return [Hash{Symbol => <String, Array, Hash>}] request cleaned attributes
  def attributes_params_for(*args)
    filter_unused_params(attributes_for(*args))
  end
<commit_msg>Testing: Enhance authenticated_as spec helper<commit_after>module ZammadSpecSupportRequest

  # This ruby meta programming action creates the methods to perform:
  # GET, POST, PATCH, PUT, DELETE and HEAD
  # HTTP "requests".
  # They overwrite the ones of `ActionDispatch::Integration::RequestHelpers`
  # to add the headers set by #add_headers before
  %i[get post patch put delete head].each do |method_id|

    define_method(method_id) do |path, **args|
      args = args.with_indifferent_access
      args[:headers] = Hash(args[:headers]).merge!(Hash(@headers))
      super(path, **args.symbolize_keys)
    end
  end

  # Adds one or more HTTP headers to all requests of the current example.
  #
  # @param [Hash{String => String}] headers Hash of HTTP headers
  #
  # @example
  #  add_headers('Eg Some X-Header' => 'Some value')

  # @example
  #  add_headers(
  #    'Header 1' => 'Some value',
  #    'Header 2' => 'Some value',
  #    ...
  #  )
  #
  # @return [Hash] The current headers Hash
  def add_headers(headers)
    @headers = Hash(@headers).merge(headers)
  end

  # Parses the response.body as JSON.
  #
  # @example
  #  json_response

  # @example
  #  json_response.is_a?(Array)
  #
  # @return [Array, Hash, ...] Parsed JSON structure as Ruby object
  def json_response
    JSON.parse(response.body)
  end

  # Authenticates all requests of the current example as the given user.
  #
  # @example
  #  authenticated_as(some_admin_user)
  #
  # @example
  #  authenticated_as(some_admin_user, on_behalf_of: customer_user)
  #
  # @example
  #  authenticated_as(some_admin_user, password: '<PASSWORD>')
  #
  # @example
  #  authenticated_as(some_admin_user, password: '<PASSWORD>', token: create(:token, action: 'api', user_id: some_admin_user.id) )
  #
  # @example
  #  authenticated_as(nil, login: 'not_existing', password: '<PASSWORD>' )
  #
  # @return nil
  def authenticated_as(user, via: :api_client, **options)
    password = options[:password] || <PASSWORD>
    login    = options[:login] || user.login

    # mock authentication otherwise login won't
    # if user has no password (which is expensive to create)
    if password.blank?
      allow(User).to receive(:authenticate).with(login, '') { user.update_last_login }.and_return(user)
    end

    case via
    when :api_client
      # if we want to authenticate by token
      if options[:token].present?
        credentials = "Token token=#{options[:token].name}"

        return add_headers('Authorization' => credentials)
      end

      credentials = ActionController::HttpAuthentication::Basic.encode_credentials(login, password)
      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

  # Provides a Hash of attributes for the given FactoryBot
  #  factory parameters which can be used as the params payload.
  #  Note that the attributes are "cleaned" so no created_by_id etc.
  #  is present.
  #
  # @see FactoryBot#attributes_for
  #
  # @example
  #  attributes_params_for(:admin_user, email: '<EMAIL>')
  #  # => {firstname: 'Nicole', email: '<EMAIL>', ...}
  #
  # @return [Hash{Symbol => <String, Array, Hash>}] request cleaned attributes
  def attributes_params_for(*args)
    filter_unused_params(attributes_for(*args))
  end

{'fraction_non_alphanumeric': 0.11884498480243161, 'fraction_numerical': 0.000911854103343465, 'mean_word_length': 3.6640680368532954, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1272247', 'n_tokens_mistral': 2133, 'n_tokens_neox': 2089, 'n_words': 571}