# frozen_string_literal: true # Redmine - project management software # Copyright (C) 2006- Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. if ENV["COVERAGE"] require 'simplecov' require_relative 'coverage/html_formatter' SimpleCov.formatter = Redmine::Coverage::HtmlFormatter SimpleCov.start 'rails' end $redmine_test_ldap_server = ENV['REDMINE_TEST_LDAP_SERVER'] || '127.0.0.1' ENV["RAILS_ENV"] = "test" require_relative '../config/environment' require 'rails/test_help' require_relative 'object_helpers' include ObjectHelpers require 'net/ldap' require 'mocha/minitest' require 'fileutils' Redmine::SudoMode.disable! $redmine_tmp_attachments_directory = "#{Rails.root}/tmp/test/attachments" FileUtils.mkdir_p $redmine_tmp_attachments_directory $redmine_tmp_pdf_directory = "#{Rails.root}/tmp/test/pdf" FileUtils.mkdir_p $redmine_tmp_pdf_directory FileUtils.rm Dir.glob('#$redmine_tmp_pdf_directory/*.pdf') class ActionView::TestCase helper :application include ApplicationHelper end class ActiveSupport::TestCase parallelize(workers: 1) include ActionDispatch::TestProcess fixtures :all self.use_transactional_tests = true self.use_instantiated_fixtures = false # Clear Settings cache after each test to prevent test interference teardown do Setting.clear_cache end def uploaded_test_file(name, mime) fixture_file_upload(name.to_s, mime, true) end def mock_file(options=nil) options ||= { :original_filename => 'a_file.png', :content_type => 'image/png', :size => 32 } Redmine::MockFile.new(options) end def mock_file_with_options(options={}) mock_file(options) end # Use a temporary directory for attachment related tests def set_tmp_attachments_directory Attachment.storage_path = $redmine_tmp_attachments_directory end def set_fixtures_attachments_directory Attachment.storage_path = "#{Rails.root}/test/fixtures/files" end def with_settings(options, &) saved_settings = options.keys.inject({}) do |h, k| h[k] = case Setting[k] when Symbol, false, true, nil Setting[k] else Setting[k].dup end h end options.each {|k, v| Setting[k] = v} yield ensure saved_settings.each {|k, v| Setting[k] = v} if saved_settings end # Yields the block with user as the current user def with_current_user(user, &) saved_user = User.current User.current = user yield ensure User.current = saved_user end def with_locale(locale, &) saved_localed = ::I18n.locale ::I18n.locale = locale yield ensure ::I18n.locale = saved_localed end def self.ldap_configured? @test_ldap = Net::LDAP.new(:host => $redmine_test_ldap_server, :port => 389) return @test_ldap.bind rescue => e # LDAP is not listening return false end def self.convert_installed? Redmine::Thumbnail.convert_available? end def convert_installed? self.class.convert_installed? end def self.gs_installed? Redmine::Thumbnail.gs_available? end def gs_installed? self.class.gs_installed? end # Returns the path to the test +vendor+ repository def self.repository_path(vendor) path = Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s # Unlike ruby, JRuby returns Rails.root with backslashes under Windows path.tr("\\", "/") end # Returns the url of the subversion test repository def self.subversion_repository_url path = repository_path('subversion') path = '/' + path unless path.starts_with?('/') "file://#{path}" end # Returns true if the +vendor+ test repository is configured def self.repository_configured?(vendor) File.directory?(repository_path(vendor)) end def repository_configured?(vendor) self.class.repository_configured?(vendor) end def self.is_mysql_utf8mb4 return false unless Redmine::Database.mysql? character_sets = %w[ character_set_connection character_set_database character_set_results character_set_server ] ActiveRecord::Base.connection. select_rows('show variables like "character%"').each do |r| return false if character_sets.include?(r[0]) && r[1] != "utf8mb4" end return true end def is_mysql_utf8mb4 self.class.is_mysql_utf8mb4 end def repository_path_hash(arr) hs = {} hs[:path] = arr.join("/") hs[:param] = arr.join("/") hs end def sqlite? Redmine::Database.sqlite? end def mysql? Redmine::Database.mysql? end def mysql8? version = Redmine::Database.mysql_version.sub(/^(\d+\.\d+\.\d+).*/, '\1') Gem::Version.new(version) >= Gem::Version.new('8.0.0') end def postgresql? Redmine::Database.postgresql? end def quoted_date(date) date = Date.parse(date) if date.is_a?(String) ActiveRecord::Base.connection.quoted_date(date) end # Asserts that a new record for the given class is created # and returns it def new_record(klass, &) new_records(klass, 1, &).first end # Asserts that count new records for the given class are created # and returns them as an array order by object id def new_records(klass, count, &) assert_difference "#{klass}.count", count do yield end klass.order(:id => :desc).limit(count).to_a.reverse end def assert_save(object) saved = object.save message = "#{object.class} could not be saved" errors = object.errors.full_messages.map {|m| "- #{m}"} message += ":\n#{errors.join("\n")}" if errors.any? assert_equal true, saved, message end def assert_select_error(arg) assert_select '#errorExplanation', :text => arg end def assert_include(expected, s, message=nil) assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"") end def assert_not_include(expected, s, message=nil) assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"") end def assert_select_in(text, ...) d = Nokogiri::HTML(CGI.unescapeHTML(String.new(text))).root assert_select(d, ...) end def assert_select_email(...) email = ActionMailer::Base.deliveries.last assert_not_nil email html_body = email.parts.detect {|part| part.content_type.include?('text/html')}.try(&:body) assert_not_nil html_body assert_select_in(html_body.encoded, ...) end def assert_mail_body_match(expected, mail, message=nil) if expected.is_a?(String) assert_include expected, mail_body(mail), message else assert_match expected, mail_body(mail), message end end def assert_mail_body_no_match(expected, mail, message=nil) if expected.is_a?(String) assert_not_include expected, mail_body(mail), message else assert_no_match expected, mail_body(mail), message end end def mail_body(mail) (mail.multipart? ? mail.parts.first : mail).body.encoded end # Returns the lft value for a new root issue def new_issue_lft 1 end end module Redmine class MockFile attr_reader :size, :original_filename, :content_type def initialize(options={}) @size = options[:size] || 32 @original_filename = options[:original_filename] || options[:filename] @content_type = options[:content_type] @content = options[:content] || 'x'*size end def read(*args) if @eof false else @eof = true @content end end end class RoutingTest < ActionDispatch::IntegrationTest def should_route(arg) arg = arg.dup request = arg.keys.detect {|key| key.is_a?(String)} raise ArgumentError unless request options = arg.slice!(request) raise ArgumentError unless request =~ /\A(GET|POST|PUT|PATCH|DELETE)\s+(.+)\z/ method, path = $1.downcase.to_sym, $2 raise ArgumentError unless arg.values.first =~ /\A(.+)#(.+)\z/ controller, action = $1, $2 assert_routing( {:method => method, :path => path}, options.merge(:controller => controller, :action => action) ) end end class HelperTest < ActionView::TestCase include Redmine::I18n include Propshaft::Helper include IconsHelper def setup super User.current = nil ::I18n.locale = 'en' end def pre_wrapper(text) icon = sprite_icon('copy-pre-content', size: 18) '