Redmine 3.4.4

This commit is contained in:
Manuel Cillero 2018-02-02 22:19:29 +01:00
commit 64924a6376
2112 changed files with 259028 additions and 0 deletions

View file

@ -0,0 +1,59 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::AccessControlTest < ActiveSupport::TestCase
def setup
@access_module = Redmine::AccessControl
end
def test_permissions
perms = @access_module.permissions
assert perms.is_a?(Array)
assert perms.first.is_a?(Redmine::AccessControl::Permission)
end
def test_module_permission
perm = @access_module.permission(:view_issues)
assert perm.is_a?(Redmine::AccessControl::Permission)
assert_equal :view_issues, perm.name
assert_equal :issue_tracking, perm.project_module
assert perm.actions.is_a?(Array)
assert perm.actions.include?('issues/index')
end
def test_no_module_permission
perm = @access_module.permission(:edit_project)
assert perm.is_a?(Redmine::AccessControl::Permission)
assert_equal :edit_project, perm.name
assert_nil perm.project_module
assert perm.actions.is_a?(Array)
assert perm.actions.include?('projects/settings')
end
def test_read_action_should_return_true_for_read_actions
assert_equal true, @access_module.read_action?(:view_project)
assert_equal true, @access_module.read_action?(:controller => 'projects', :action => 'show')
end
def test_read_action_should_return_false_for_update_actions
assert_equal false, @access_module.read_action?(:edit_project)
assert_equal false, @access_module.read_action?(:controller => 'projects', :action => 'edit')
end
end

View file

@ -0,0 +1,53 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::Acts::PositionedWithScopeTest < ActiveSupport::TestCase
fixtures :projects, :boards
def test_create_should_default_to_last_position
b = Board.generate!(:project_id => 1)
assert_equal 3, b.reload.position
b = Board.generate!(:project_id => 3)
assert_equal 1, b.reload.position
end
def test_create_should_insert_at_given_position
b = Board.generate!(:project_id => 1, :position => 2)
assert_equal 2, b.reload.position
assert_equal [1, 3, 1, 2], Board.order(:id).pluck(:position)
end
def test_destroy_should_remove_position
b = Board.generate!(:project_id => 1, :position => 2)
b.destroy
assert_equal [1, 2, 1], Board.order(:id).pluck(:position)
end
def test_update_should_update_positions
b = Board.generate!(:project_id => 1)
assert_equal 3, b.position
b.position = 2
b.save!
assert_equal [1, 3, 1, 2], Board.order(:id).pluck(:position)
end
end

View file

@ -0,0 +1,55 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::Acts::PositionedWithoutScopeTest < ActiveSupport::TestCase
fixtures :trackers, :issue_statuses
def test_create_should_default_to_last_position
t = Tracker.generate
t.save!
assert_equal 4, t.reload.position
end
def test_create_should_insert_at_given_position
t = Tracker.generate
t.position = 2
t.save!
assert_equal 2, t.reload.position
assert_equal [1, 3, 4, 2], Tracker.order(:id).pluck(:position)
end
def test_destroy_should_remove_position
t = Tracker.generate!
Tracker.generate!
t.destroy
assert_equal [1, 2, 3, 4], Tracker.order(:id).pluck(:position)
end
def test_update_should_update_positions
t = Tracker.generate!
assert_equal 4, t.position
t.position = 2
t.save!
assert_equal [1, 3, 4, 2], Tracker.order(:id).pluck(:position)
end
end

View file

@ -0,0 +1,106 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::CipheringTest < ActiveSupport::TestCase
def test_password_should_be_encrypted
Redmine::Configuration.with 'database_cipher_key' => 'secret' do
r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
assert_equal 'foo', r.password
assert r.read_attribute(:password).match(/\Aaes-256-cbc:.+\Z/)
end
end
def test_password_should_be_clear_with_blank_key
Redmine::Configuration.with 'database_cipher_key' => '' do
r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
assert_equal 'foo', r.password
assert_equal 'foo', r.read_attribute(:password)
end
end
def test_password_should_be_clear_with_nil_key
Redmine::Configuration.with 'database_cipher_key' => nil do
r = Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'svn')
assert_equal 'foo', r.password
assert_equal 'foo', r.read_attribute(:password)
end
end
def test_blank_password_should_be_clear
Redmine::Configuration.with 'database_cipher_key' => 'secret' do
r = Repository::Subversion.create!(:password => '', :url => 'file:///tmp', :identifier => 'svn')
assert_equal '', r.password
assert_equal '', r.read_attribute(:password)
end
end
def test_unciphered_password_should_be_readable
Redmine::Configuration.with 'database_cipher_key' => nil do
r = Repository::Subversion.create!(:password => 'clear', :url => 'file:///tmp', :identifier => 'svn')
end
Redmine::Configuration.with 'database_cipher_key' => 'secret' do
r = Repository.order('id DESC').first
assert_equal 'clear', r.password
end
end
def test_ciphered_password_with_no_cipher_key_configured_should_be_returned_ciphered
Redmine::Configuration.with 'database_cipher_key' => 'secret' do
r = Repository::Subversion.create!(:password => 'clear', :url => 'file:///tmp', :identifier => 'svn')
end
Redmine::Configuration.with 'database_cipher_key' => '' do
r = Repository.order('id DESC').first
# password can not be deciphered
assert_nothing_raised do
assert r.password.match(/\Aaes-256-cbc:.+\Z/)
end
end
end
def test_encrypt_all
Repository.delete_all
Redmine::Configuration.with 'database_cipher_key' => nil do
Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'foo')
Repository::Subversion.create!(:password => 'bar', :url => 'file:///tmp', :identifier => 'bar')
end
Redmine::Configuration.with 'database_cipher_key' => 'secret' do
assert Repository.encrypt_all(:password)
r = Repository.order('id DESC').first
assert_equal 'bar', r.password
assert r.read_attribute(:password).match(/\Aaes-256-cbc:.+\Z/)
end
end
def test_decrypt_all
Repository.delete_all
Redmine::Configuration.with 'database_cipher_key' => 'secret' do
Repository::Subversion.create!(:password => 'foo', :url => 'file:///tmp', :identifier => 'foo')
Repository::Subversion.create!(:password => 'bar', :url => 'file:///tmp', :identifier => 'bar')
assert Repository.decrypt_all(:password)
r = Repository.order('id DESC').first
assert_equal 'bar', r.password
assert_equal 'bar', r.read_attribute(:password)
end
end
end

View file

@ -0,0 +1,104 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::CodesetUtilTest < ActiveSupport::TestCase
def test_to_utf8_by_setting_from_latin1
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
s1 = "Texte encod\xc3\xa9".force_encoding("UTF-8")
s2 = "Texte encod\xe9".force_encoding("ASCII-8BIT")
s3 = s2.dup.force_encoding("UTF-8")
assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
end
end
def test_to_utf8_by_setting_from_euc_jp
with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
s1 = "\xe3\x83\xac\xe3\x83\x83\xe3\x83\x89\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xb3".force_encoding("UTF-8")
s2 = "\xa5\xec\xa5\xc3\xa5\xc9\xa5\xde\xa5\xa4\xa5\xf3".force_encoding("ASCII-8BIT")
s3 = s2.dup.force_encoding("UTF-8")
assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
end
end
def test_to_utf8_by_setting_should_be_converted_all_latin1
with_settings :repositories_encodings => 'ISO-8859-1' do
s1 = "\xc3\x82\xc2\x80".force_encoding("UTF-8")
s2 = "\xC2\x80".force_encoding("ASCII-8BIT")
s3 = s2.dup.force_encoding("UTF-8")
assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s2)
assert_equal s1, Redmine::CodesetUtil.to_utf8_by_setting(s3)
end
end
def test_to_utf8_by_setting_blank_string
assert_equal "", Redmine::CodesetUtil.to_utf8_by_setting("")
assert_nil Redmine::CodesetUtil.to_utf8_by_setting(nil)
end
def test_to_utf8_by_setting_returns_ascii_as_utf8
s1 = "ASCII".force_encoding("UTF-8")
s2 = s1.dup.force_encoding("ISO-8859-1")
str1 = Redmine::CodesetUtil.to_utf8_by_setting(s1)
str2 = Redmine::CodesetUtil.to_utf8_by_setting(s2)
assert_equal s1, str1
assert_equal s1, str2
assert_equal "UTF-8", str1.encoding.to_s
assert_equal "UTF-8", str2.encoding.to_s
end
def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped
with_settings :repositories_encodings => '' do
# s1 = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
s1 = "Texte encod\xe9 en ISO-8859-1.".force_encoding("ASCII-8BIT")
str = Redmine::CodesetUtil.to_utf8_by_setting(s1)
assert str.valid_encoding?
assert_equal "UTF-8", str.encoding.to_s
assert_equal "Texte encod? en ISO-8859-1.", str
end
end
def test_to_utf8_by_setting_invalid_utf8_sequences_should_be_stripped_ja_jis
with_settings :repositories_encodings => 'ISO-2022-JP' do
s1 = "test\xb5\xfetest\xb5\xfe".force_encoding("ASCII-8BIT")
str = Redmine::CodesetUtil.to_utf8_by_setting(s1)
assert str.valid_encoding?
assert_equal "UTF-8", str.encoding.to_s
assert_equal "test??test??", str
end
end
test "#replace_invalid_utf8 should replace invalid utf8" do
s1 = "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xE3\x81\xFF".force_encoding("UTF-8")
s2 = Redmine::CodesetUtil.replace_invalid_utf8(s1)
assert s2.valid_encoding?
assert_equal "UTF-8", s2.encoding.to_s
assert_equal "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1??".force_encoding("UTF-8"), s2
end
test "#to_utf8 should replace invalid non utf8" do
s1 = "\xa4\xb3\xa4\xf3\xa4\xcb\xa4\xc1\xa4".force_encoding("EUC-JP")
s2 = Redmine::CodesetUtil.to_utf8(s1, "EUC-JP")
assert s2.valid_encoding?
assert_equal "UTF-8", s2.encoding.to_s
assert_equal "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1?".force_encoding("UTF-8"), s2
end
end

View file

@ -0,0 +1,61 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::ConfigurationTest < ActiveSupport::TestCase
def setup
@conf = Redmine::Configuration
end
def test_empty
assert_kind_of Hash, load_conf('empty.yml', 'test')
end
def test_default
assert_kind_of Hash, load_conf('default.yml', 'test')
assert_equal 'foo', @conf['somesetting']
end
def test_no_default
assert_kind_of Hash, load_conf('no_default.yml', 'test')
assert_equal 'foo', @conf['somesetting']
end
def test_overrides
assert_kind_of Hash, load_conf('overrides.yml', 'test')
assert_equal 'bar', @conf['somesetting']
end
def test_with
load_conf('default.yml', 'test')
assert_equal 'foo', @conf['somesetting']
@conf.with 'somesetting' => 'bar' do
assert_equal 'bar', @conf['somesetting']
end
assert_equal 'foo', @conf['somesetting']
end
private
def load_conf(file, env)
@conf.load(
:file => File.join(Rails.root, 'test', 'fixtures', 'configuration', file),
:env => env
)
end
end

View file

@ -0,0 +1,31 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class CsvTest < ActiveSupport::TestCase
BOM = "\xEF\xBB\xBF".force_encoding('UTF-8')
def test_should_include_bom_when_utf8_encoded
with_locale 'sk' do
string = Redmine::Export::CSV.generate {|csv| csv << %w(Foo Bar)}
assert_equal 'UTF-8', string.encoding.name
assert string.starts_with?(BOM)
end
end
end

View file

@ -0,0 +1,104 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class PdfTest < ActiveSupport::TestCase
fixtures :users, :projects, :roles, :members, :member_roles,
:enabled_modules, :issues, :trackers, :attachments
def test_fix_text_encoding_nil
assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(nil, "UTF-8")
assert_equal '', Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(nil, "ISO-8859-1")
end
def test_rdm_pdf_iconv_cannot_convert_ja_cp932
utf8_txt_1 = "\xe7\x8b\x80\xe6\x85\x8b"
utf8_txt_2 = "\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
utf8_txt_3 = "\xe7\x8b\x80\xe7\x8b\x80\xe6\x85\x8b\xe7\x8b\x80"
["CP932", "SJIS"].each do |encoding|
txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_1, encoding)
txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_2, encoding)
txt_3 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(utf8_txt_3, encoding)
assert_equal "?\x91\xd4".force_encoding("ASCII-8BIT"), txt_1
assert_equal "?\x91\xd4?".force_encoding("ASCII-8BIT"), txt_2
assert_equal "??\x91\xd4?".force_encoding("ASCII-8BIT"), txt_3
assert_equal "ASCII-8BIT", txt_1.encoding.to_s
assert_equal "ASCII-8BIT", txt_2.encoding.to_s
assert_equal "ASCII-8BIT", txt_3.encoding.to_s
end
end
def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_en
str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8")
str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, 'UTF-8')
txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, 'UTF-8')
assert_equal "ASCII-8BIT", txt_1.encoding.to_s
assert_equal "ASCII-8BIT", txt_2.encoding.to_s
assert_equal "Texte encod? en ISO-8859-1", txt_1
assert_equal "?a?b?c?d?e test", txt_2
end
def test_rdm_pdf_iconv_invalid_utf8_should_be_replaced_ja
str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8")
str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
encoding = ( RUBY_PLATFORM == 'java' ? "SJIS" : "CP932" )
txt_1 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str1, encoding)
txt_2 = Redmine::Export::PDF::RDMPdfEncoding::rdm_from_utf8(str2, encoding)
assert_equal "ASCII-8BIT", txt_1.encoding.to_s
assert_equal "ASCII-8BIT", txt_2.encoding.to_s
assert_equal "Texte encod? en ISO-8859-1", txt_1
assert_equal "?a?b?c?d?e test", txt_2
end
def test_attach
["CP932", "SJIS"].each do |encoding|
set_fixtures_attachments_directory
str2 = "\x83e\x83X\x83g".force_encoding("ASCII-8BIT")
a1 = Attachment.find(17)
a2 = Attachment.find(19)
User.current = User.find(1)
assert a1.readable?
assert a1.visible?
assert a2.readable?
assert a2.visible?
aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
assert_not_nil aa1
assert_equal 17, aa1.id
aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
assert_not_nil aa2
assert_equal 19, aa2.id
User.current = nil
assert a1.readable?
assert (! a1.visible?)
assert a2.readable?
assert (! a2.visible?)
aa1 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "Testfile.PNG", "UTF-8")
assert_nil aa1
aa2 = Redmine::Export::PDF::RDMPdfEncoding::attach(Attachment.all, "test#{str2}.png", encoding)
assert_nil aa2
set_tmp_attachments_directory
end
end
end

View file

@ -0,0 +1,163 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::AttachmentFieldFormatTest < ActionView::TestCase
include ApplicationHelper
include Redmine::I18n
fixtures :users
def setup
set_language_if_valid 'en'
set_tmp_attachments_directory
end
def test_should_accept_a_hash_with_upload_on_create
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
attachment = nil
custom_value = new_record(CustomValue) do
attachment = new_record(Attachment) do
group.custom_field_values = {field.id => {:file => mock_file}}
assert group.save
end
end
assert_equal 'a_file.png', attachment.filename
assert_equal custom_value, attachment.container
assert_equal field, attachment.container.custom_field
assert_equal group, attachment.container.customized
end
def test_should_accept_a_hash_with_no_upload_on_create
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
attachment = nil
custom_value = new_record(CustomValue) do
assert_no_difference 'Attachment.count' do
group.custom_field_values = {field.id => {}}
assert group.save
end
end
assert_equal '', custom_value.value
end
def test_should_not_validate_with_invalid_upload_on_create
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
with_settings :attachment_max_size => 0 do
assert_no_difference 'CustomValue.count' do
assert_no_difference 'Attachment.count' do
group.custom_field_values = {field.id => {:file => mock_file}}
assert_equal false, group.save
end
end
end
end
def test_should_accept_a_hash_with_token_on_create
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
attachment = Attachment.create!(:file => mock_file, :author => User.find(2))
assert_nil attachment.container
custom_value = new_record(CustomValue) do
assert_no_difference 'Attachment.count' do
group.custom_field_values = {field.id => {:token => attachment.token}}
assert group.save
end
end
attachment.reload
assert_equal custom_value, attachment.container
assert_equal field, attachment.container.custom_field
assert_equal group, attachment.container.customized
end
def test_should_not_validate_with_invalid_token_on_create
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
assert_no_difference 'CustomValue.count' do
assert_no_difference 'Attachment.count' do
group.custom_field_values = {field.id => {:token => "123.0123456789abcdef"}}
assert_equal false, group.save
end
end
end
def test_should_replace_attachment_on_update
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
attachment = nil
custom_value = new_record(CustomValue) do
attachment = new_record(Attachment) do
group.custom_field_values = {field.id => {:file => mock_file}}
assert group.save
end
end
group.reload
assert_no_difference 'Attachment.count' do
assert_no_difference 'CustomValue.count' do
group.custom_field_values = {field.id => {:file => mock_file}}
assert group.save
end
end
assert !Attachment.exists?(attachment.id)
assert CustomValue.exists?(custom_value.id)
new_attachment = Attachment.order(:id => :desc).first
custom_value.reload
assert_equal custom_value, new_attachment.container
end
def test_should_delete_attachment_on_update
field = GroupCustomField.generate!(:name => "File", :field_format => 'attachment')
group = Group.new(:name => 'Group')
attachment = nil
custom_value = new_record(CustomValue) do
attachment = new_record(Attachment) do
group.custom_field_values = {field.id => {:file => mock_file}}
assert group.save
end
end
group.reload
assert_difference 'Attachment.count', -1 do
assert_no_difference 'CustomValue.count' do
group.custom_field_values = {field.id => {}}
assert group.save
end
end
assert !Attachment.exists?(attachment.id)
assert CustomValue.exists?(custom_value.id)
custom_value.reload
assert_equal '', custom_value.value
end
end

View file

@ -0,0 +1,59 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class AttachmentFormatVisibilityTest < ActionView::TestCase
fixtures :projects, :enabled_modules, :projects_trackers,
:roles, :members, :member_roles,
:users, :email_addresses,
:trackers, :issue_statuses, :enumerations, :issue_categories,
:versions, :issues
def setup
set_tmp_attachments_directory
end
def test_attachment_should_be_visible_with_visible_custom_field
field = IssueCustomField.generate!(:field_format => 'attachment', :visible => true)
attachment = new_record(Attachment) do
issue = Issue.generate
issue.custom_field_values = {field.id => {:file => mock_file}}
issue.save!
end
assert attachment.visible?(manager = User.find(2))
assert attachment.visible?(developer = User.find(3))
assert attachment.visible?(non_member = User.find(7))
assert attachment.visible?(User.anonymous)
end
def test_attachment_should_be_visible_with_limited_visibility_custom_field
field = IssueCustomField.generate!(:field_format => 'attachment', :visible => false, :role_ids => [1])
attachment = new_record(Attachment) do
issue = Issue.generate
issue.custom_field_values = {field.id => {:file => mock_file}}
issue.save!
end
assert attachment.visible?(manager = User.find(2))
assert !attachment.visible?(developer = User.find(3))
assert !attachment.visible?(non_member = User.find(7))
assert !attachment.visible?(User.anonymous)
end
end

View file

@ -0,0 +1,63 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::BoolFieldFormatTest < ActionView::TestCase
include ApplicationHelper
include Redmine::I18n
def setup
set_language_if_valid 'en'
end
def test_check_box_style_should_render_edit_tag_as_check_box
field = IssueCustomField.new(:field_format => 'bool', :is_required => false, :edit_tag_style => 'check_box')
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'abc', 'xyz', value)
assert_select_in tag, 'input[name=xyz]', 2
assert_select_in tag, 'input[id=abc]', 1
assert_select_in tag, 'input[type=hidden][value="0"]'
assert_select_in tag, 'input[type=checkbox][value="1"]'
end
def test_check_box_should_be_checked_when_value_is_set
field = IssueCustomField.new(:field_format => 'bool', :is_required => false, :edit_tag_style => 'check_box')
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new, :value => '1')
tag = field.format.edit_tag(self, 'abc', 'xyz', value)
assert_select_in tag, 'input[type=checkbox][value="1"][checked=checked]'
end
def test_radio_style_should_render_edit_tag_as_radio_buttons
field = IssueCustomField.new(:field_format => 'bool', :is_required => false, :edit_tag_style => 'radio')
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'abc', 'xyz', value)
assert_select_in tag, 'input[type=radio][name=xyz]', 3
end
def test_default_style_should_render_edit_tag_as_select
field = IssueCustomField.new(:field_format => 'bool', :is_required => false)
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'abc', 'xyz', value)
assert_select_in tag, 'select[name=xyz]', 1
end
end

View file

@ -0,0 +1,100 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::EnumerationFieldFormatTest < ActionView::TestCase
include ApplicationHelper
def setup
set_language_if_valid 'en'
@field = IssueCustomField.create!(:name => 'List', :field_format => 'enumeration', :is_required => false)
@foo = CustomFieldEnumeration.new(:name => 'Foo')
@bar = CustomFieldEnumeration.new(:name => 'Bar')
@field.enumerations << @foo
@field.enumerations << @bar
end
def test_edit_tag_should_contain_possible_values
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new)
tag = @field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'select' do
assert_select 'option', 3
assert_select 'option[value=""]'
assert_select 'option[value=?]', @foo.id.to_s, :text => 'Foo'
assert_select 'option[value=?]', @bar.id.to_s, :text => 'Bar'
end
end
def test_edit_tag_should_select_current_value
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new, :value => @bar.id.to_s)
tag = @field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'select' do
assert_select 'option[selected=selected]', 1
assert_select 'option[value=?][selected=selected]', @bar.id.to_s, :text => 'Bar'
end
end
def test_edit_tag_with_multiple_should_select_current_values
@field.multiple = true
@field.save!
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new, :value => [@foo.id.to_s, @bar.id.to_s])
tag = @field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'select[multiple=multiple]' do
assert_select 'option[selected=selected]', 2
assert_select 'option[value=?][selected=selected]', @foo.id.to_s, :text => 'Foo'
assert_select 'option[value=?][selected=selected]', @bar.id.to_s, :text => 'Bar'
end
end
def test_edit_tag_with_check_box_style_should_contain_possible_values
@field.edit_tag_style = 'check_box'
@field.save!
value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new)
tag = @field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'span' do
assert_select 'input[type=radio]', 3
assert_select 'label', :text => '(none)' do
assert_select 'input[value=""]'
end
assert_select 'label', :text => 'Foo' do
assert_select 'input[value=?]', @foo.id.to_s
end
assert_select 'label', :text => 'Bar' do
assert_select 'input[value=?]', @bar.id.to_s
end
end
end
def test_value_from_keyword_should_return_enumeration_id
assert_equal @foo.id, @field.value_from_keyword('foo', nil)
assert_nil @field.value_from_keyword('baz', nil)
end
def test_value_from_keyword_for_multiple_custom_field_should_return_enumeration_ids
@field.multiple = true
@field.save!
assert_equal [@foo.id, @bar.id], @field.value_from_keyword('foo, bar', nil)
assert_equal [@foo.id], @field.value_from_keyword('foo, baz', nil)
assert_equal [], @field.value_from_keyword('baz', nil)
end
end

View file

@ -0,0 +1,101 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::FieldFormatTest < ActionView::TestCase
include ApplicationHelper
def setup
set_language_if_valid 'en'
end
def test_string_field_with_text_formatting_disabled_should_not_format_text
field = IssueCustomField.new(:field_format => 'string')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "*foo*")
assert_equal "*foo*", field.format.formatted_custom_value(self, custom_value, false)
assert_equal "*foo*", field.format.formatted_custom_value(self, custom_value, true)
end
def test_string_field_with_text_formatting_enabled_should_format_text
field = IssueCustomField.new(:field_format => 'string', :text_formatting => 'full')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "*foo*")
assert_equal "*foo*", field.format.formatted_custom_value(self, custom_value, false)
assert_include "<strong>foo</strong>", field.format.formatted_custom_value(self, custom_value, true)
end
def test_text_field_with_text_formatting_disabled_should_not_format_text
field = IssueCustomField.new(:field_format => 'text')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "*foo*\nbar")
assert_equal "*foo*\nbar", field.format.formatted_custom_value(self, custom_value, false)
assert_include "*foo*\n<br />bar", field.format.formatted_custom_value(self, custom_value, true)
end
def test_text_field_with_text_formatting_enabled_should_format_text
field = IssueCustomField.new(:field_format => 'text', :text_formatting => 'full')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "*foo*\nbar")
assert_equal "*foo*\nbar", field.format.formatted_custom_value(self, custom_value, false)
assert_include "<strong>foo</strong>", field.format.formatted_custom_value(self, custom_value, true)
end
def test_should_validate_url_pattern_with_safe_scheme
field = IssueCustomField.new(:field_format => 'string', :name => 'URL', :url_pattern => 'http://foo/%value%')
assert_save field
end
def test_should_not_validate_url_pattern_with_unsafe_scheme
field = IssueCustomField.new(:field_format => 'string', :name => 'URL', :url_pattern => 'foo://foo/%value%')
assert !field.save
assert_include "URL is invalid", field.errors.full_messages
end
def test_text_field_with_url_pattern_should_format_as_link
field = IssueCustomField.new(:field_format => 'string', :url_pattern => 'http://foo/%value%')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "bar")
assert_equal "bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/bar">bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_text_field_with_url_pattern_and_value_containing_a_space_should_format_as_link
field = IssueCustomField.new(:field_format => 'string', :url_pattern => 'http://foo/%value%')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "foo bar")
assert_equal "foo bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/foo%20bar">foo bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_text_field_with_url_pattern_should_not_encode_url_pattern
field = IssueCustomField.new(:field_format => 'string', :url_pattern => 'http://foo/bar#anchor')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "1")
assert_equal "1", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/bar#anchor">1</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_text_field_with_url_pattern_should_encode_values
field = IssueCustomField.new(:field_format => 'string', :url_pattern => 'http://foo/%value%#anchor')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "foo bar")
assert_equal "foo bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/foo%20bar#anchor">foo bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
end

View file

@ -0,0 +1,90 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::LinkFieldFormatTest < ActionView::TestCase
def test_link_field_should_substitute_value
field = IssueCustomField.new(:field_format => 'link', :url_pattern => 'http://foo/%value%')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "bar")
assert_equal "bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/bar">bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_link_field_should_substitute_object_id_in_url
object = Issue.new
object.stubs(:id).returns(10)
field = IssueCustomField.new(:field_format => 'link', :url_pattern => 'http://foo/%id%')
custom_value = CustomValue.new(:custom_field => field, :customized => object, :value => "bar")
assert_equal "bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/10">bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_link_field_should_substitute_project_id_in_url
project = Project.new
project.stubs(:id).returns(52)
object = Issue.new
object.stubs(:project).returns(project)
field = IssueCustomField.new(:field_format => 'link', :url_pattern => 'http://foo/%project_id%')
custom_value = CustomValue.new(:custom_field => field, :customized => object, :value => "bar")
assert_equal "bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/52">bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_link_field_should_substitute_project_identifier_in_url
project = Project.new
project.stubs(:identifier).returns('foo_project-00')
object = Issue.new
object.stubs(:project).returns(project)
field = IssueCustomField.new(:field_format => 'link', :url_pattern => 'http://foo/%project_identifier%')
custom_value = CustomValue.new(:custom_field => field, :customized => object, :value => "bar")
assert_equal "bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/foo_project-00">bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_link_field_should_substitute_regexp_groups
field = IssueCustomField.new(:field_format => 'link', :regexp => /^(.+)-(.+)$/, :url_pattern => 'http://foo/%m2%/%m1%')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "56-142")
assert_equal "56-142", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/142/56">56-142</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_link_field_without_url_pattern_should_link_to_value
field = IssueCustomField.new(:field_format => 'link')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "http://foo/bar")
assert_equal "http://foo/bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/bar">http://foo/bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
def test_link_field_without_url_pattern_should_link_to_value_with_http_by_default
field = IssueCustomField.new(:field_format => 'link')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "foo.bar")
assert_equal "foo.bar", field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo.bar">foo.bar</a>', field.format.formatted_custom_value(self, custom_value, true)
end
end

View file

@ -0,0 +1,188 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::ListFieldFormatTest < ActionView::TestCase
include ApplicationHelper
include Redmine::I18n
def setup
set_language_if_valid 'en'
end
def test_possible_existing_value_should_be_valid
field = GroupCustomField.create!(:name => 'List', :field_format => 'list', :possible_values => ['Foo', 'Bar'])
group = Group.new(:name => 'Group')
group.custom_field_values = {field.id => 'Baz'}
assert group.save(:validate => false)
group = Group.order('id DESC').first
assert_equal ['Foo', 'Bar', 'Baz'], field.possible_custom_value_options(group.custom_value_for(field))
assert group.valid?
end
def test_edit_tag_should_have_id_and_name
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_required => false)
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'abc', 'xyz', value)
assert_select_in tag, 'select[id=abc][name=xyz]'
end
def test_edit_tag_should_contain_possible_values
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_required => false)
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'select' do
assert_select 'option', 3
assert_select 'option[value=""]'
assert_select 'option[value=Foo]', :text => 'Foo'
assert_select 'option[value=Bar]', :text => 'Bar'
end
end
def test_edit_tag_should_select_current_value
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_required => false)
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new, :value => 'Bar')
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'select' do
assert_select 'option[selected=selected]', 1
assert_select 'option[value=Bar][selected=selected]', :text => 'Bar'
end
end
def test_edit_tag_with_multiple_should_select_current_values
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar', 'Baz'], :is_required => false,
:multiple => true)
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new, :value => ['Bar', 'Baz'])
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'select[multiple=multiple]' do
assert_select 'option[selected=selected]', 2
assert_select 'option[value=Bar][selected=selected]', :text => 'Bar'
assert_select 'option[value=Baz][selected=selected]', :text => 'Baz'
end
end
def test_edit_tag_with_check_box_style_should_contain_possible_values
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_required => false,
:edit_tag_style => 'check_box')
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'span' do
assert_select 'input[type=radio]', 3
assert_select 'label', :text => '(none)' do
assert_select 'input[value=""]'
end
assert_select 'label', :text => 'Foo' do
assert_select 'input[value=Foo]'
end
assert_select 'label', :text => 'Bar' do
assert_select 'input[value=Bar]'
end
end
end
def test_edit_tag_with_check_box_style_should_select_current_value
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_required => false,
:edit_tag_style => 'check_box')
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new, :value => 'Bar')
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'span' do
assert_select 'input[type=radio][checked=checked]', 1
assert_select 'label', :text => 'Bar' do
assert_select 'input[value=Bar][checked=checked]'
end
end
end
def test_edit_tag_with_check_box_style_and_multiple_values_should_contain_hidden_field_to_clear_value
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar'], :is_required => false,
:edit_tag_style => 'check_box', :multiple => true)
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new)
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'span' do
assert_select 'input[type=checkbox]', 2
assert_select 'input[type=hidden]', 1
end
end
def test_field_with_url_pattern_should_link_value
field = IssueCustomField.new(:field_format => 'list', :url_pattern => 'http://localhost/%value%')
formatted = field.format.formatted_value(self, field, 'foo', Issue.new, true)
assert_equal '<a href="http://localhost/foo">foo</a>', formatted
assert formatted.html_safe?
end
def test_field_with_url_pattern_and_multiple_values_should_link_values
field = IssueCustomField.new(:field_format => 'list', :url_pattern => 'http://localhost/%value%')
formatted = field.format.formatted_value(self, field, ['foo', 'bar'], Issue.new, true)
assert_equal '<a href="http://localhost/bar">bar</a>, <a href="http://localhost/foo">foo</a>', formatted
assert formatted.html_safe?
end
def test_field_with_url_pattern_should_not_link_blank_value
field = IssueCustomField.new(:field_format => 'list', :url_pattern => 'http://localhost/%value%')
formatted = field.format.formatted_value(self, field, '', Issue.new, true)
assert_equal '', formatted
assert formatted.html_safe?
end
def test_edit_tag_with_check_box_style_and_multiple_should_select_current_values
field = IssueCustomField.new(:field_format => 'list', :possible_values => ['Foo', 'Bar', 'Baz'], :is_required => false,
:multiple => true, :edit_tag_style => 'check_box')
value = CustomFieldValue.new(:custom_field => field, :customized => Issue.new, :value => ['Bar', 'Baz'])
tag = field.format.edit_tag(self, 'id', 'name', value)
assert_select_in tag, 'span' do
assert_select 'input[type=checkbox][checked=checked]', 2
assert_select 'label', :text => 'Bar' do
assert_select 'input[value=Bar][checked=checked]'
end
assert_select 'label', :text => 'Baz' do
assert_select 'input[value=Baz][checked=checked]'
end
end
end
def test_value_from_keyword_should_return_value
field = GroupCustomField.create!(:name => 'List', :field_format => 'list', :possible_values => ['Foo', 'Bar', 'Baz,qux'])
assert_equal 'Foo', field.value_from_keyword('foo', nil)
assert_equal 'Baz,qux', field.value_from_keyword('baz,qux', nil)
assert_nil field.value_from_keyword('invalid', nil)
end
def test_value_from_keyword_for_multiple_custom_field_should_return_values
field = GroupCustomField.create!(:name => 'List', :field_format => 'list', :possible_values => ['Foo', 'Bar', 'Baz,qux'], :multiple => true)
assert_equal ['Foo','Bar'], field.value_from_keyword('foo,bar', nil)
assert_equal ['Baz,qux'], field.value_from_keyword('baz,qux', nil)
assert_equal ['Baz,qux', 'Foo'], field.value_from_keyword('baz,qux,foo', nil)
assert_equal ['Foo'], field.value_from_keyword('foo,invalid', nil)
assert_equal ['Foo'], field.value_from_keyword(',foo,', nil)
assert_equal ['Foo'], field.value_from_keyword(',foo, ,,', nil)
assert_equal [], field.value_from_keyword('invalid', nil)
end
end

View file

@ -0,0 +1,31 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::NumericFieldFormatTest < ActionView::TestCase
include ApplicationHelper
def test_integer_field_with_url_pattern_should_format_as_link
field = IssueCustomField.new(:field_format => 'int', :url_pattern => 'http://foo/%value%')
custom_value = CustomValue.new(:custom_field => field, :customized => Issue.new, :value => "3")
assert_equal 3, field.format.formatted_custom_value(self, custom_value, false)
assert_equal '<a href="http://foo/3">3</a>', field.format.formatted_custom_value(self, custom_value, true)
end
end

View file

@ -0,0 +1,79 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::UserFieldFormatTest < ActionView::TestCase
fixtures :projects, :roles, :users, :members, :member_roles,
:trackers,
:issue_statuses, :issue_categories, :issue_relations, :workflows,
:enumerations
def test_user_role_should_reject_blank_values
field = IssueCustomField.new(:name => 'Foo', :field_format => 'user', :user_role => ["1", ""])
field.save!
assert_equal ["1"], field.user_role
end
def test_existing_values_should_be_valid
field = IssueCustomField.create!(:name => 'Foo', :field_format => 'user', :is_for_all => true, :trackers => Tracker.all)
project = Project.generate!
user = User.generate!
User.add_to_project(user, project, Role.find_by_name('Manager'))
issue = Issue.generate!(:project_id => project.id, :tracker_id => 1, :custom_field_values => {field.id => user.id})
field.user_role = [Role.find_by_name('Developer').id]
field.save!
issue = Issue.order('id DESC').first
assert_include [user.name, user.id.to_s], field.possible_custom_value_options(issue.custom_value_for(field))
assert issue.valid?
end
def test_possible_values_options_should_return_project_members
field = IssueCustomField.new(:field_format => 'user')
project = Project.find(1)
assert_equal ['Dave Lopper', 'John Smith'], field.possible_values_options(project).map(&:first)
end
def test_possible_values_options_should_return_project_members_with_selected_role
field = IssueCustomField.new(:field_format => 'user', :user_role => ["2"])
project = Project.find(1)
assert_equal ['Dave Lopper'], field.possible_values_options(project).map(&:first)
end
def test_value_from_keyword_should_return_user_id
field = IssueCustomField.new(:field_format => 'user')
project = Project.find(1)
assert_equal 2, field.value_from_keyword('jsmith', project)
assert_equal 3, field.value_from_keyword('Dave Lopper', project)
assert_nil field.value_from_keyword('Unknown User', project)
end
def test_value_from_keyword_for_multiple_custom_field_should_return_enumeration_ids
field = IssueCustomField.new(:field_format => 'user', :multiple => true)
project = Project.find(1)
assert_equal [2, 3], field.value_from_keyword('jsmith, Dave Lopper', project)
assert_equal [2], field.value_from_keyword('jsmith', project)
assert_equal [], field.value_from_keyword('Unknown User', project)
end
end

View file

@ -0,0 +1,105 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'redmine/field_format'
class Redmine::VersionFieldFormatTest < ActionView::TestCase
fixtures :projects, :versions, :trackers,
:roles, :users, :members, :member_roles,
:issue_statuses, :issue_categories, :issue_relations, :workflows,
:enumerations
def setup
super
User.current = nil
end
def test_version_status_should_reject_blank_values
field = IssueCustomField.new(:name => 'Foo', :field_format => 'version', :version_status => ["open", ""])
field.save!
assert_equal ["open"], field.version_status
end
def test_existing_values_should_be_valid
field = IssueCustomField.create!(:name => 'Foo', :field_format => 'version', :is_for_all => true, :trackers => Tracker.all)
project = Project.generate!
version = Version.generate!(:project => project, :status => 'open')
issue = Issue.generate!(:project_id => project.id, :tracker_id => 1, :custom_field_values => {field.id => version.id})
field.version_status = ["open"]
field.save!
issue = Issue.order('id DESC').first
assert_include [version.name, version.id.to_s], field.possible_custom_value_options(issue.custom_value_for(field))
assert issue.valid?
end
def test_possible_values_options_should_return_project_versions
field = IssueCustomField.new(:field_format => 'version')
project = Project.find(1)
expected = project.shared_versions.sort.map(&:name)
assert_equal expected, field.possible_values_options(project).map(&:first)
end
def test_possible_values_options_should_return_system_shared_versions_without_project
field = IssueCustomField.new(:field_format => 'version')
version = Version.generate!(:project => Project.find(1), :status => 'open', :sharing => 'system')
expected = Version.visible.where(:sharing => 'system').sort.map(&:name)
assert_include version.name, expected
assert_equal expected, field.possible_values_options.map(&:first)
end
def test_possible_values_options_should_return_project_versions_with_selected_status
field = IssueCustomField.new(:field_format => 'version', :version_status => ["open"])
project = Project.find(1)
expected = project.shared_versions.sort.select {|v| v.status == "open"}.map(&:name)
assert_equal expected, field.possible_values_options(project).map(&:first)
end
def test_cast_value_should_not_raise_error_when_array_contains_value_casted_to_nil
field = IssueCustomField.new(:field_format => 'version')
assert_nothing_raised do
field.cast_value([1,2, 42])
end
end
def test_query_filter_options_should_include_versions_with_any_status
field = IssueCustomField.new(:field_format => 'version', :version_status => ["open"])
project = Project.find(1)
version = Version.generate!(:project => project, :status => 'locked')
query = Query.new(:project => project)
full_name = "#{version.project} - #{version.name}"
assert_not_include full_name, field.possible_values_options(project).map(&:first)
assert_include full_name, field.query_filter_options(query)[:values].call.map(&:first)
end
def test_query_filter_options_should_include_version_status_for_grouping
field = IssueCustomField.new(:field_format => 'version', :version_status => ["open"])
project = Project.find(1)
version = Version.generate!(:project => project, :status => 'locked')
query = Query.new(:project => project)
full_name = "#{version.project} - #{version.name}"
assert_include [full_name, version.id.to_s, l(:version_status_locked)],
field.query_filter_options(query)[:values].call
end
end

View file

@ -0,0 +1,63 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class CalendarTest < ActiveSupport::TestCase
def test_monthly
c = Redmine::Helpers::Calendar.new(Date.today, :fr, :month)
assert_equal [1, 7], [c.startdt.cwday, c.enddt.cwday]
c = Redmine::Helpers::Calendar.new('2007-07-14'.to_date, :fr, :month)
assert_equal ['2007-06-25'.to_date, '2007-08-05'.to_date], [c.startdt, c.enddt]
c = Redmine::Helpers::Calendar.new(Date.today, :en, :month)
assert_equal [7, 6], [c.startdt.cwday, c.enddt.cwday]
end
def test_weekly
c = Redmine::Helpers::Calendar.new(Date.today, :fr, :week)
assert_equal [1, 7], [c.startdt.cwday, c.enddt.cwday]
c = Redmine::Helpers::Calendar.new('2007-07-14'.to_date, :fr, :week)
assert_equal ['2007-07-09'.to_date, '2007-07-15'.to_date], [c.startdt, c.enddt]
c = Redmine::Helpers::Calendar.new(Date.today, :en, :week)
assert_equal [7, 6], [c.startdt.cwday, c.enddt.cwday]
end
def test_monthly_start_day
[1, 6, 7].each do |day|
with_settings :start_of_week => day do
c = Redmine::Helpers::Calendar.new(Date.today, :en, :month)
assert_equal day , c.startdt.cwday
assert_equal (day + 5) % 7 + 1, c.enddt.cwday
end
end
end
def test_weekly_start_day
[1, 6, 7].each do |day|
with_settings :start_of_week => day do
c = Redmine::Helpers::Calendar.new(Date.today, :en, :week)
assert_equal day, c.startdt.cwday
assert_equal (day + 5) % 7 + 1, c.enddt.cwday
end
end
end
end

View file

@ -0,0 +1,37 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class DiffTest < ActiveSupport::TestCase
def test_diff
diff = Redmine::Helpers::Diff.new("foo", "bar")
assert_not_nil diff
end
def test_dont_double_escape
# 3 cases to test in the before: first word, last word, everything inbetween
before = "<stuff> with html & special chars</danger>"
# all words in after are treated equal
after = "other stuff <script>alert('foo');</alert>"
computed_diff = Redmine::Helpers::Diff.new(before, after).to_html
expected_diff = '<span class="diff_in">&lt;stuff&gt; with html &amp; special chars&lt;/danger&gt;</span> <span class="diff_out">other stuff &lt;script&gt;alert(&#39;foo&#39;);&lt;/alert&gt;</span>'
assert_equal computed_diff, expected_diff
end
end

View file

@ -0,0 +1,498 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::Helpers::GanttHelperTest < Redmine::HelperTest
fixtures :projects, :trackers, :issue_statuses,
:enumerations, :users, :issue_categories
include ProjectsHelper
include IssuesHelper
include ERB::Util
include Rails.application.routes.url_helpers
def setup
setup_with_controller
User.current = User.find(1)
end
def today
@today ||= Date.today
end
private :today
def gantt_start
@gantt.date_from
end
# Creates a Gantt chart for a 4 week span
def create_gantt(project=Project.generate!, options={})
@project = project
@gantt = Redmine::Helpers::Gantt.new(options)
@gantt.project = @project
@gantt.query = IssueQuery.new(:project => @project, :name => 'Gantt')
@gantt.view = self
@gantt.instance_variable_set('@date_from', options[:date_from] || (today - 14))
@gantt.instance_variable_set('@date_to', options[:date_to] || (today + 14))
end
private :create_gantt
test "#number_of_rows with one project should return the number of rows just for that project" do
p1, p2 = Project.generate!, Project.generate!
i1, i2 = Issue.generate!(:project => p1), Issue.generate!(:project => p2)
create_gantt(p1)
assert_equal 2, @gantt.number_of_rows
end
test "#number_of_rows with no project should return the total number of rows for all the projects, recursively" do
p1, p2 = Project.generate!, Project.generate!
create_gantt(nil)
# fix the return value of #number_of_rows_on_project() to an arbitrary value
# so that we really only test #number_of_rows
@gantt.stubs(:number_of_rows_on_project).returns(7)
# also fix #projects because we want to test #number_of_rows in isolation
@gantt.stubs(:projects).returns(Project.all)
# actual test
assert_equal Project.count*7, @gantt.number_of_rows
end
test "#number_of_rows should not exceed max_rows option" do
p = Project.generate!
5.times do
Issue.generate!(:project => p)
end
create_gantt(p)
@gantt.render
assert_equal 6, @gantt.number_of_rows
assert !@gantt.truncated
create_gantt(p, :max_rows => 3)
@gantt.render
assert_equal 3, @gantt.number_of_rows
assert @gantt.truncated
end
test "#number_of_rows_on_project should count 0 for an empty the project" do
create_gantt
assert_equal 0, @gantt.number_of_rows_on_project(@project)
end
test "#number_of_rows_on_project should count the number of issues without a version" do
create_gantt
@project.issues << Issue.generate!(:project => @project, :fixed_version => nil)
assert_equal 2, @gantt.number_of_rows_on_project(@project)
end
test "#number_of_rows_on_project should count the number of issues on versions, including cross-project" do
create_gantt
version = Version.generate!
@project.versions << version
@project.issues << Issue.generate!(:project => @project, :fixed_version => version)
assert_equal 3, @gantt.number_of_rows_on_project(@project)
end
def setup_subjects
create_gantt
@project.enabled_module_names = [:issue_tracking]
@tracker = Tracker.generate!
@project.trackers << @tracker
@version = Version.generate!(:effective_date => (today + 7), :sharing => 'none')
@project.versions << @version
@issue = Issue.generate!(:fixed_version => @version,
:subject => "gantt#line_for_project",
:tracker => @tracker,
:project => @project,
:done_ratio => 30,
:start_date => (today - 1),
:due_date => (today + 7))
@project.issues << @issue
end
private :setup_subjects
# TODO: more of an integration test
test "#subjects project should be rendered" do
setup_subjects
@output_buffer = @gantt.subjects
assert_select "div.project-name a", /#{@project.name}/
assert_select 'div.project-name[style*="left:4px"]'
end
test "#subjects version should be rendered" do
setup_subjects
@output_buffer = @gantt.subjects
assert_select "div.version-name a", /#{@version.name}/
assert_select 'div.version-name[style*="left:24px"]'
end
test "#subjects version without assigned issues should not be rendered" do
setup_subjects
@version = Version.generate!(:effective_date => (today + 14),
:sharing => 'none',
:name => 'empty_version')
@project.versions << @version
@output_buffer = @gantt.subjects
assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
end
test "#subjects issue should be rendered" do
setup_subjects
@output_buffer = @gantt.subjects
assert_select "div.issue-subject", /#{@issue.subject}/
assert_select 'div.issue-subject[style*="left:44px"]'
end
test "#subjects issue assigned to a shared version of another project should be rendered" do
setup_subjects
p = Project.generate!
p.enabled_module_names = [:issue_tracking]
@shared_version = Version.generate!(:sharing => 'system')
p.versions << @shared_version
# Reassign the issue to a shared version of another project
@issue = Issue.generate!(:fixed_version => @shared_version,
:subject => "gantt#assigned_to_shared_version",
:tracker => @tracker,
:project => @project,
:done_ratio => 30,
:start_date => (today - 1),
:due_date => (today + 7))
@project.issues << @issue
@output_buffer = @gantt.subjects
assert_select "div.issue-subject", /#{@issue.subject}/
end
test "#subjects issue with subtasks should indent subtasks" do
setup_subjects
attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
@child1 = Issue.generate!(
attrs.merge(:subject => 'child1',
:parent_issue_id => @issue.id,
:start_date => (today - 1),
:due_date => (today + 2))
)
@child2 = Issue.generate!(
attrs.merge(:subject => 'child2',
:parent_issue_id => @issue.id,
:start_date => today,
:due_date => (today + 7))
)
@grandchild = Issue.generate!(
attrs.merge(:subject => 'grandchild',
:parent_issue_id => @child1.id,
:start_date => (today - 1),
:due_date => (today + 2))
)
@output_buffer = @gantt.subjects
# parent task 44px
assert_select 'div.issue-subject[style*="left:44px"]', /#{@issue.subject}/
# children 64px
assert_select 'div.issue-subject[style*="left:64px"]', /child1/
assert_select 'div.issue-subject[style*="left:64px"]', /child2/
# grandchild 84px
assert_select 'div.issue-subject[style*="left:84px"]', /grandchild/, @output_buffer
end
test "#lines" do
create_gantt
@project.enabled_module_names = [:issue_tracking]
@tracker = Tracker.generate!
@project.trackers << @tracker
@version = Version.generate!(:effective_date => (today + 7))
@project.versions << @version
@issue = Issue.generate!(:fixed_version => @version,
:subject => "gantt#line_for_project",
:tracker => @tracker,
:project => @project,
:done_ratio => 30,
:start_date => (today - 1),
:due_date => (today + 7))
@project.issues << @issue
@output_buffer = @gantt.lines
assert_select "div.project.task_todo"
assert_select "div.project.starting"
assert_select "div.project.ending"
assert_select "div.label.project", /#{@project.name}/
assert_select "div.version.task_todo"
assert_select "div.version.starting"
assert_select "div.version.ending"
assert_select "div.label.version", /#{@version.name}/
assert_select "div.task_todo"
assert_select "div.task.label", /#{@issue.done_ratio}/
assert_select "div.tooltip", /#{@issue.subject}/
end
test "#subject_for_project" do
create_gantt
@output_buffer = @gantt.subject_for_project(@project, :format => :html)
assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
end
test "#subject_for_project should style overdue projects" do
create_gantt
@project.stubs(:overdue?).returns(true)
@output_buffer = @gantt.subject_for_project(@project, :format => :html)
assert_select 'div span.project-overdue'
end
test "#subject_for_version" do
create_gantt
version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
@output_buffer = @gantt.subject_for_version(version, :format => :html)
assert_select 'a[href=?]', "/versions/#{version.to_param}", :text => /Foo/
end
test "#subject_for_version should style overdue versions" do
create_gantt
version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
version.stubs(:overdue?).returns(true)
@output_buffer = @gantt.subject_for_version(version, :format => :html)
assert_select 'div span.version-overdue'
end
test "#subject_for_version should style behind schedule versions" do
create_gantt
version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
version.stubs(:behind_schedule?).returns(true)
@output_buffer = @gantt.subject_for_version(version, :format => :html)
assert_select 'div span.version-behind-schedule'
end
test "#subject_for_issue" do
create_gantt
issue = Issue.generate!(:project => @project)
@output_buffer = @gantt.subject_for_issue(issue, :format => :html)
assert_select 'div', :text => /#{issue.subject}/
assert_select 'a[href=?]', "/issues/#{issue.to_param}", :text => /#{issue.tracker.name} ##{issue.id}/
end
test "#subject_for_issue should style overdue issues" do
create_gantt
issue = Issue.generate!(:project => @project)
issue.stubs(:overdue?).returns(true)
@output_buffer = @gantt.subject_for_issue(issue, :format => :html)
assert_select 'div span.issue-overdue'
end
test "#subject should add an absolute positioned div" do
create_gantt
@output_buffer = @gantt.subject('subject', :format => :html)
assert_select "div[style*=absolute]", :text => 'subject'
end
test "#subject should use the indent option to move the div to the right" do
create_gantt
@output_buffer = @gantt.subject('subject', :format => :html, :indent => 40)
assert_select 'div[style*="left:40"]'
end
test "#line_for_project" do
create_gantt
@project.stubs(:start_date).returns(today - 7)
@project.stubs(:due_date).returns(today + 7)
@output_buffer = @gantt.line_for_project(@project, :format => :html)
assert_select "div.project.label", :text => @project.name
end
test "#line_for_version" do
create_gantt
version = Version.generate!(:name => 'Foo', :project => @project)
version.stubs(:start_date).returns(today - 7)
version.stubs(:due_date).returns(today + 7)
version.stubs(:completed_percent).returns(30)
@output_buffer = @gantt.line_for_version(version, :format => :html)
assert_select "div.version.label", :text => /Foo/
assert_select "div.version.label", :text => /30%/
end
test "#line_for_issue" do
create_gantt
issue = Issue.generate!(:project => @project, :start_date => today - 7, :due_date => today + 7, :done_ratio => 30)
@output_buffer = @gantt.line_for_issue(issue, :format => :html)
assert_select "div.task.label", :text => /#{issue.status.name}/
assert_select "div.task.label", :text => /30%/
assert_select "div.tooltip", /#{issue.subject}/
end
test "#line todo line should start from the starting point on the left" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_todo[style*="left:28px"]', 1
end
test "#line todo line should be the total width" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_todo[style*="width:58px"]', 1
end
test "#line late line should start from the starting point on the left" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_late[style*="left:28px"]', 1
end
test "#line late line should be the total delayed width" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_late[style*="width:30px"]', 1
end
test "#line done line should start from the starting point on the left" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_done[style*="left:28px"]', 1
end
test "#line done line should be the width for the done ratio" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
# 15 days * 4 px * 30% - 2 px for borders = 16 px
assert_select 'div.task_done[style*="width:16px"]', 1
end
test "#line done line should be the total width for 100% done ratio" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
# 15 days * 4 px - 2 px for borders = 58 px
assert_select 'div.task_done[style*="width:58px"]', 1
end
test "#line done line should be the total width for 100% done ratio with same start and end dates" do
create_gantt
@output_buffer = @gantt.line(today + 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_done[style*="width:2px"]', 1
end
test "#line done line should not be the total done width if the gantt starts after start date" do
create_gantt
@output_buffer = @gantt.line(today - 16, today - 2, 30, false, 'line', :format => :html, :zoom => 4)
assert_select 'div.task_done[style*="left:0px"]', 1
assert_select 'div.task_done[style*="width:8px"]', 1
end
test "#line starting marker should appear at the start date" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
assert_select "div.starting", 1
assert_select 'div.starting[style*="left:28px"]', 1
end
test "#line starting marker should not appear if the start date is before gantt start date" do
create_gantt
@output_buffer = @gantt.line(gantt_start - 2, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
assert_select "div.starting", 0
end
test "#line ending marker should appear at the end date" do
create_gantt
@output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
assert_select "div.ending", 1
assert_select 'div.ending[style*="left:88px"]', 1
end
test "#line ending marker should not appear if the end date is before gantt start date" do
create_gantt
@output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
assert_select "div.ending", 0
end
test "#line label should appear at the far left, even if it's before gantt start date" do
create_gantt
@output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
assert_select "div.label", :text => 'line'
end
def test_sort_issues_no_date
project = Project.generate!
issue1 = Issue.generate!(:subject => "test", :project => project)
issue2 = Issue.generate!(:subject => "test", :project => project)
assert issue1.root_id < issue2.root_id
child1 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
:project => project)
child2 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
:project => project)
child3 = Issue.generate!(:parent_issue_id => child1.id, :subject => 'child',
:project => project)
assert_equal child1.root_id, child2.root_id
assert child1.lft < child2.lft
assert child3.lft < child2.lft
issues = [child3, child2, child1, issue2, issue1]
Redmine::Helpers::Gantt.sort_issues!(issues)
assert_equal [issue1.id, child1.id, child3.id, child2.id, issue2.id],
issues.map{|v| v.id}
end
def test_sort_issues_root_only
project = Project.generate!
issue1 = Issue.generate!(:subject => "test", :project => project)
issue2 = Issue.generate!(:subject => "test", :project => project)
issue3 = Issue.generate!(:subject => "test", :project => project,
:start_date => (today - 1))
issue4 = Issue.generate!(:subject => "test", :project => project,
:start_date => (today - 2))
issues = [issue4, issue3, issue2, issue1]
Redmine::Helpers::Gantt.sort_issues!(issues)
assert_equal [issue1.id, issue2.id, issue4.id, issue3.id],
issues.map{|v| v.id}
end
def test_sort_issues_tree
project = Project.generate!
issue1 = Issue.generate!(:subject => "test", :project => project)
issue2 = Issue.generate!(:subject => "test", :project => project,
:start_date => (today - 2))
issue1_child1 =
Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
:project => project)
issue1_child2 =
Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
:project => project, :start_date => (today - 10))
issue1_child1_child1 =
Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
:project => project, :start_date => (today - 8))
issue1_child1_child2 =
Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
:project => project, :start_date => (today - 9))
issue1_child1_child1_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child1)
assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
[today - 8, issue1_child1_child1.id]],
issue1_child1_child1_logic
issue1_child1_child2_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child2)
assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
[today - 9, issue1_child1_child2.id]],
issue1_child1_child2_logic
issues = [issue1_child1_child2, issue1_child1_child1, issue1_child2,
issue1_child1, issue2, issue1]
Redmine::Helpers::Gantt.sort_issues!(issues)
assert_equal [issue1.id, issue1_child1.id, issue1_child2.id,
issue1_child1_child2.id, issue1_child1_child1.id, issue2.id],
issues.map{|v| v.id}
end
def test_sort_versions
project = Project.generate!
versions = []
versions << Version.create!(:project => project, :name => 'test1')
versions << Version.create!(:project => project, :name => 'test2', :effective_date => '2013-10-25')
versions << Version.create!(:project => project, :name => 'test3')
versions << Version.create!(:project => project, :name => 'test4', :effective_date => '2013-10-02')
assert_equal versions.sort, Redmine::Helpers::Gantt.sort_versions!(versions.dup)
end
end

View file

@ -0,0 +1,189 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::Hook::ManagerTest < ActionView::TestCase
fixtures :projects, :users, :members, :member_roles, :roles,
:groups_users,
:email_addresses,
:trackers, :projects_trackers,
:enabled_modules,
:versions,
:issue_statuses, :issue_categories, :issue_relations,
:enumerations,
:issues
# Some hooks that are manually registered in these tests
class TestHook < Redmine::Hook::ViewListener; end
class TestHook1 < TestHook
def view_layouts_base_html_head(context)
'Test hook 1 listener.'
end
end
class TestHook2 < TestHook
def view_layouts_base_html_head(context)
'Test hook 2 listener.'
end
end
class TestHook3 < TestHook
def view_layouts_base_html_head(context)
"Context keys: #{context.keys.collect(&:to_s).sort.join(', ')}."
end
end
class TestLinkToHook < TestHook
def view_layouts_base_html_head(context)
link_to('Issues', :controller => 'issues')
end
end
class TestHookHelperController < ActionController::Base
include Redmine::Hook::Helper
end
class TestHookHelperView < ActionView::Base
include Redmine::Hook::Helper
end
Redmine::Hook.clear_listeners
def setup
@hook_module = Redmine::Hook
@hook_module.clear_listeners
end
def teardown
@hook_module.clear_listeners
end
def test_clear_listeners
assert_equal 0, @hook_module.hook_listeners(:view_layouts_base_html_head).size
@hook_module.add_listener(TestHook1)
@hook_module.add_listener(TestHook2)
assert_equal 2, @hook_module.hook_listeners(:view_layouts_base_html_head).size
@hook_module.clear_listeners
assert_equal 0, @hook_module.hook_listeners(:view_layouts_base_html_head).size
end
def test_add_listener
assert_equal 0, @hook_module.hook_listeners(:view_layouts_base_html_head).size
@hook_module.add_listener(TestHook1)
assert_equal 1, @hook_module.hook_listeners(:view_layouts_base_html_head).size
end
def test_call_hook
@hook_module.add_listener(TestHook1)
assert_equal ['Test hook 1 listener.'], hook_helper.call_hook(:view_layouts_base_html_head)
end
def test_call_hook_with_context
@hook_module.add_listener(TestHook3)
assert_equal ['Context keys: bar, controller, foo, hook_caller, project, request.'],
hook_helper.call_hook(:view_layouts_base_html_head, :foo => 1, :bar => 'a')
end
def test_call_hook_with_multiple_listeners
@hook_module.add_listener(TestHook1)
@hook_module.add_listener(TestHook2)
assert_equal ['Test hook 1 listener.', 'Test hook 2 listener.'], hook_helper.call_hook(:view_layouts_base_html_head)
end
# Context: Redmine::Hook::Helper.call_hook default_url
def test_call_hook_default_url_options
@hook_module.add_listener(TestLinkToHook)
assert_equal ['<a href="/issues">Issues</a>'], hook_helper.call_hook(:view_layouts_base_html_head)
end
def test_view_hook_should_generate_links_with_relative_url_root
Redmine::Utils.relative_url_root = '/foo'
@hook_module.add_listener(TestLinkToHook)
assert_equal ['<a href="/foo/issues">Issues</a>'], hook_helper.call_hook(:view_layouts_base_html_head)
ensure
Redmine::Utils.relative_url_root = ''
end
# Context: Redmine::Hook::Helper.call_hook
def test_call_hook_with_project_added_to_context
@hook_module.add_listener(TestHook3)
assert_match /project/i, hook_helper.call_hook(:view_layouts_base_html_head)[0]
end
def test_call_hook_from_controller_with_controller_added_to_context
@hook_module.add_listener(TestHook3)
assert_match /controller/i, hook_helper.call_hook(:view_layouts_base_html_head)[0]
end
def test_call_hook_from_controller_with_request_added_to_context
@hook_module.add_listener(TestHook3)
assert_match /request/i, hook_helper.call_hook(:view_layouts_base_html_head)[0]
end
def test_call_hook_from_view_with_project_added_to_context
@hook_module.add_listener(TestHook3)
assert_match /project/i, view_hook_helper.call_hook(:view_layouts_base_html_head)
end
def test_call_hook_from_view_with_controller_added_to_context
@hook_module.add_listener(TestHook3)
assert_match /controller/i, view_hook_helper.call_hook(:view_layouts_base_html_head)
end
def test_call_hook_from_view_with_request_added_to_context
@hook_module.add_listener(TestHook3)
assert_match /request/i, view_hook_helper.call_hook(:view_layouts_base_html_head)
end
def test_call_hook_from_view_should_join_responses_with_a_space
@hook_module.add_listener(TestHook1)
@hook_module.add_listener(TestHook2)
assert_equal 'Test hook 1 listener. Test hook 2 listener.',
view_hook_helper.call_hook(:view_layouts_base_html_head)
end
def test_call_hook_should_not_change_the_default_url_for_email_notifications
issue = Issue.find(1)
ActionMailer::Base.deliveries.clear
Mailer.deliver_issue_add(issue)
mail = ActionMailer::Base.deliveries.last
@hook_module.add_listener(TestLinkToHook)
hook_helper.call_hook(:view_layouts_base_html_head)
ActionMailer::Base.deliveries.clear
Mailer.deliver_issue_add(issue)
mail2 = ActionMailer::Base.deliveries.last
assert_equal mail_body(mail), mail_body(mail2)
end
def hook_helper
@hook_helper ||= TestHookHelperController.new
end
def view_hook_helper
@view_hook_helper ||= TestHookHelperView.new(Rails.root.to_s + '/app/views')
end
end

View file

@ -0,0 +1,261 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::I18nTest < ActiveSupport::TestCase
include Redmine::I18n
include ActionView::Helpers::NumberHelper
def setup
User.current = nil
end
def teardown
set_language_if_valid 'en'
end
def test_date_format_default
set_language_if_valid 'en'
today = Date.today
with_settings :date_format => '' do
assert_equal I18n.l(today), format_date(today)
end
end
def test_date_format
set_language_if_valid 'en'
today = Date.today
with_settings :date_format => '%d %m %Y' do
assert_equal today.strftime('%d %m %Y'), format_date(today)
end
end
def test_date_format_with_month_name_should_translate_with_current_locale
set_language_if_valid 'es'
date = Date.parse('2011-02-20 14:00:00')
with_settings :date_format => '%d %B %Y' do
assert_equal '20 Febrero 2011', format_date(date)
end
end
def test_date_and_time_for_each_language
with_settings :date_format => '' do
valid_languages.each do |lang|
set_language_if_valid lang
assert_nothing_raised do
format_date(Date.today)
format_time(Time.now)
format_time(Time.now, false)
assert_not_equal 'default', ::I18n.l(Date.today, :format => :default),
"date.formats.default missing in #{lang}"
assert_not_equal 'time', ::I18n.l(Time.now, :format => :time),
"time.formats.time missing in #{lang}"
end
assert l('date.day_names').is_a?(Array)
assert_equal 7, l('date.day_names').size
assert l('date.month_names').is_a?(Array)
assert_equal 13, l('date.month_names').size
end
end
end
def test_time_for_each_zone
ActiveSupport::TimeZone.all.each do |zone|
User.current.stubs(:time_zone).returns(zone.name)
assert_nothing_raised do
format_time(Time.now)
end
end
end
def test_time_format
set_language_if_valid 'en'
now = Time.parse('2011-02-20 15:45:22')
with_settings :time_format => '%H:%M' do
with_settings :date_format => '' do
assert_equal '02/20/2011 15:45', format_time(now)
assert_equal '15:45', format_time(now, false)
end
with_settings :date_format => '%Y-%m-%d' do
assert_equal '2011-02-20 15:45', format_time(now)
assert_equal '15:45', format_time(now, false)
end
end
end
def test_time_format_default
set_language_if_valid 'en'
now = Time.parse('2011-02-20 15:45:22')
with_settings :time_format => '' do
with_settings :date_format => '' do
assert_equal '02/20/2011 03:45 PM', format_time(now)
assert_equal '03:45 PM', format_time(now, false)
end
with_settings :date_format => '%Y-%m-%d' do
assert_equal '2011-02-20 03:45 PM', format_time(now)
assert_equal '03:45 PM', format_time(now, false)
end
end
end
def test_utc_time_format
set_language_if_valid 'en'
now = Time.now
with_settings :date_format => '%d %m %Y', :time_format => '%H %M' do
assert_equal now.localtime.strftime('%d %m %Y %H %M'), format_time(now.utc), "User time zone was #{User.current.time_zone}"
assert_equal now.localtime.strftime('%H %M'), format_time(now.utc, false)
end
end
def test_number_to_human_size_for_each_language
valid_languages.each do |lang|
set_language_if_valid lang
assert_nothing_raised do
size = number_to_human_size(257024)
assert_match /251/, size, "#{lang} failure"
end
end
end
def test_day_name
set_language_if_valid 'fr'
assert_equal 'dimanche', day_name(0)
assert_equal 'jeudi', day_name(4)
end
def test_day_letter
set_language_if_valid 'fr'
assert_equal 'd', day_letter(0)
assert_equal 'j', day_letter(4)
end
def test_number_to_currency_for_each_language
valid_languages.each do |lang|
set_language_if_valid lang
assert_nothing_raised do
number_to_currency(-1000.2)
end
end
end
def test_l_hours_short
set_language_if_valid 'en'
assert_equal '2.00 h', l_hours_short(2.0)
end
def test_number_to_currency_default
set_language_if_valid 'bs'
assert_equal "KM -1000,20", number_to_currency(-1000.2)
set_language_if_valid 'de'
euro_sign = "\xe2\x82\xac".force_encoding('UTF-8')
assert_equal "-1000,20 #{euro_sign}", number_to_currency(-1000.2)
end
def test_lu_should_not_error_when_user_language_is_an_empty_string
user = User.new
user.language = ''
assert_nothing_raised do
lu(user, :label_issue)
end
end
def test_valid_languages
assert valid_languages.is_a?(Array)
assert valid_languages.first.is_a?(Symbol)
end
def test_languages_options
options = languages_options
assert options.is_a?(Array)
assert_equal valid_languages.size, options.size
assert_nil options.detect {|option| !option.is_a?(Array)}
assert_nil options.detect {|option| option.size != 2}
assert_nil options.detect {|option| !option.first.is_a?(String) || !option.last.is_a?(String)}
assert_include ["English", "en"], options
ja = "Japanese (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)".force_encoding('UTF-8')
assert_include [ja, "ja"], options
end
def test_languages_options_should_return_strings_with_utf8_encoding
strings = languages_options.flatten
assert_equal ["UTF-8"], strings.map(&:encoding).uniq.map(&:name).sort
end
def test_languages_options_should_ignore_locales_without_general_lang_name_key
stubs(:valid_languages).returns([:en, :foo])
assert_equal [["English", "en"]], languages_options(:cache => false)
end
def test_locales_validness
lang_files_count = Dir["#{Rails.root}/config/locales/*.yml"].size
assert_equal lang_files_count, valid_languages.size
valid_languages.each do |lang|
assert set_language_if_valid(lang)
end
set_language_if_valid('en')
end
def test_valid_language
to_test = {'fr' => :fr,
'Fr' => :fr,
'zh' => :zh,
'zh-tw' => :"zh-TW",
'zh-TW' => :"zh-TW"}
to_test.each {|lang, expected| assert_equal expected, find_language(lang)}
end
def test_find_language_with_invalid_language_should_return_nil
assert_nil find_language('zh-ZZ')
end
def test_fallback
::I18n.backend.store_translations(:en, {:untranslated => "Untranslated string"})
::I18n.locale = 'en'
assert_equal "Untranslated string", l(:untranslated)
::I18n.locale = 'fr'
assert_equal "Untranslated string", l(:untranslated)
::I18n.backend.store_translations(:fr, {:untranslated => "Pas de traduction"})
::I18n.locale = 'en'
assert_equal "Untranslated string", l(:untranslated)
::I18n.locale = 'fr'
assert_equal "Pas de traduction", l(:untranslated)
end
def test_utf8
set_language_if_valid 'ja'
str_ja_yes = "\xe3\x81\xaf\xe3\x81\x84".force_encoding('UTF-8')
i18n_ja_yes = l(:general_text_Yes)
assert_equal str_ja_yes, i18n_ja_yes
assert_equal "UTF-8", i18n_ja_yes.encoding.to_s
end
def test_traditional_chinese_locale
set_language_if_valid 'zh-TW'
str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)".force_encoding('UTF-8')
assert_equal str_tw, l(:general_lang_name)
end
def test_french_locale
set_language_if_valid 'fr'
str_fr = "French (Fran\xc3\xa7ais)".force_encoding('UTF-8')
assert_equal str_fr, l(:general_lang_name)
end
end

View file

@ -0,0 +1,27 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::InfoTest < ActiveSupport::TestCase
def test_environment
env = Redmine::Info.environment
assert_kind_of String, env
assert_match 'Redmine version', env
end
end

View file

@ -0,0 +1,191 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::MenuManager::MapperTest < ActiveSupport::TestCase
test "Mapper#initialize should define a root MenuNode if menu is not present in items" do
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
node = menu_mapper.menu_items
assert_not_nil node
assert_equal :root, node.name
end
test "Mapper#initialize should use existing MenuNode if present" do
node = "foo" # just an arbitrary reference
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {:test_menu => node})
assert_equal node, menu_mapper.menu_items
end
def test_push_onto_root
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.exists?(:test_overview)
end
def test_push_onto_parent
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_child, { :controller => 'projects', :action => 'show'}, {:parent => :test_overview}
assert menu_mapper.exists?(:test_child)
assert_equal :test_child, menu_mapper.find(:test_child).name
end
def test_push_onto_grandparent
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_child, { :controller => 'projects', :action => 'show'}, {:parent => :test_overview}
menu_mapper.push :test_grandchild, { :controller => 'projects', :action => 'show'}, {:parent => :test_child}
assert menu_mapper.exists?(:test_grandchild)
grandchild = menu_mapper.find(:test_grandchild)
assert_equal :test_grandchild, grandchild.name
assert_equal :test_child, grandchild.parent.name
end
def test_push_first
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {:first => true}
root = menu_mapper.find(:root)
assert_equal 5, root.children.size
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
assert_not_nil root.children[position]
assert_equal name, root.children[position].name
end
end
def test_push_before
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {:before => :test_fourth}
root = menu_mapper.find(:root)
assert_equal 5, root.children.size
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
assert_not_nil root.children[position]
assert_equal name, root.children[position].name
end
end
def test_push_after
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {:after => :test_third}
root = menu_mapper.find(:root)
assert_equal 5, root.children.size
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
assert_not_nil root.children[position]
assert_equal name, root.children[position].name
end
end
def test_push_last
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_first, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_second, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_third, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_fifth, { :controller => 'projects', :action => 'show'}, {:last => true}
menu_mapper.push :test_fourth, { :controller => 'projects', :action => 'show'}, {}
root = menu_mapper.find(:root)
assert_equal 5, root.children.size
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
assert_not_nil root.children[position]
assert_equal name, root.children[position].name
end
end
def test_exists_for_child_node
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
menu_mapper.push :test_child, { :controller => 'projects', :action => 'show'}, {:parent => :test_overview }
assert menu_mapper.exists?(:test_child)
end
def test_exists_for_invalid_node
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
assert !menu_mapper.exists?(:nothing)
end
def test_find
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
item = menu_mapper.find(:test_overview)
assert_equal :test_overview, item.name
assert_equal({:controller => 'projects', :action => 'show'}, item.url)
end
def test_find_missing
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
item = menu_mapper.find(:nothing)
assert_nil item
end
def test_delete
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
menu_mapper.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
assert_not_nil menu_mapper.delete(:test_overview)
assert_nil menu_mapper.find(:test_overview)
end
def test_delete_missing
menu_mapper = Redmine::MenuManager::Mapper.new(:test_menu, {})
assert_nil menu_mapper.delete(:test_missing)
end
test 'deleting all items' do
# Exposed by deleting :last items
Redmine::MenuManager.map :test_menu do |menu|
menu.push :not_last, Redmine::Info.help_url
menu.push :administration, { :controller => 'projects', :action => 'show'}, {:last => true}
menu.push :help, Redmine::Info.help_url, :last => true
end
assert_nothing_raised do
Redmine::MenuManager.map :test_menu do |menu|
menu.delete(:administration)
menu.delete(:help)
menu.push :test_overview, { :controller => 'projects', :action => 'show'}, {}
end
end
end
end

View file

@ -0,0 +1,342 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::MenuManager::MenuHelperTest < Redmine::HelperTest
include Redmine::MenuManager::MenuHelper
include ERB::Util
include Rails.application.routes.url_helpers
fixtures :users, :members, :projects, :enabled_modules, :roles, :member_roles
def setup
setup_with_controller
# Stub the current menu item in the controller
def current_menu_item
:index
end
end
def test_render_single_menu_node
node = Redmine::MenuManager::MenuItem.new(:testing, '/test', { })
@output_buffer = render_single_menu_node(node, 'This is a test', node.url, false)
assert_select("a.testing", "This is a test")
end
def test_render_menu_node
single_node = Redmine::MenuManager::MenuItem.new(:single_node, '/test', { })
@output_buffer = render_menu_node(single_node, nil)
assert_select("li") do
assert_select("a.single-node", "Single node")
end
end
def test_render_menu_node_with_symbol_as_url
node = Redmine::MenuManager::MenuItem.new(:testing, :issues_path)
@output_buffer = render_menu_node(node, nil)
assert_select 'a[href="/issues"]', "Testing"
end
def test_render_menu_node_with_symbol_as_url_and_project
node = Redmine::MenuManager::MenuItem.new(:testing, :project_issues_path)
@output_buffer = render_menu_node(node, Project.find(1))
assert_select 'a[href="/projects/ecookbook/issues"]', "Testing"
end
def test_render_menu_node_with_nested_items
parent_node = Redmine::MenuManager::MenuItem.new(:parent_node, '/test', { })
parent_node << Redmine::MenuManager::MenuItem.new(:child_one_node, '/test', { })
parent_node << Redmine::MenuManager::MenuItem.new(:child_two_node, '/test', { })
parent_node <<
Redmine::MenuManager::MenuItem.new(:child_three_node, '/test', { }) <<
Redmine::MenuManager::MenuItem.new(:child_three_inner_node, '/test', { })
@output_buffer = render_menu_node(parent_node, nil)
assert_select("li") do
assert_select("a.parent-node", "Parent node")
assert_select("ul") do
assert_select("li a.child-one-node", "Child one node")
assert_select("li a.child-two-node", "Child two node")
assert_select("li") do
assert_select("a.child-three-node", "Child three node")
assert_select("ul") do
assert_select("li a.child-three-inner-node", "Child three inner node")
end
end
end
end
end
def test_render_menu_node_with_children
User.current = User.find(2)
parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
'/test',
{
:children => Proc.new {|p|
children = []
3.times do |time|
children << Redmine::MenuManager::MenuItem.new("test_child_#{time}",
{:controller => 'issues', :action => 'index'},
{})
end
children
}
})
@output_buffer = render_menu_node(parent_node, Project.find(1))
assert_select("li") do
assert_select("a.parent-node", "Parent node")
assert_select("ul") do
assert_select("li a.test-child-0", "Test child 0")
assert_select("li a.test-child-1", "Test child 1")
assert_select("li a.test-child-2", "Test child 2")
end
end
end
def test_render_menu_node_with_nested_items_and_children
User.current = User.find(2)
parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
{:controller => 'issues', :action => 'index'},
{
:children => Proc.new {|p|
children = []
3.times do |time|
children << Redmine::MenuManager::MenuItem.new("test_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
end
children
}
})
parent_node << Redmine::MenuManager::MenuItem.new(:child_node,
{:controller => 'issues', :action => 'index'},
{
:children => Proc.new {|p|
children = []
6.times do |time|
children << Redmine::MenuManager::MenuItem.new("test_dynamic_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
end
children
}
})
@output_buffer = render_menu_node(parent_node, Project.find(1))
assert_select("li") do
assert_select("a.parent-node", "Parent node")
assert_select("ul") do
assert_select("li a.child-node", "Child node")
assert_select("ul") do
assert_select("li a.test-dynamic-child-0", "Test dynamic child 0")
assert_select("li a.test-dynamic-child-1", "Test dynamic child 1")
assert_select("li a.test-dynamic-child-2", "Test dynamic child 2")
assert_select("li a.test-dynamic-child-3", "Test dynamic child 3")
assert_select("li a.test-dynamic-child-4", "Test dynamic child 4")
assert_select("li a.test-dynamic-child-5", "Test dynamic child 5")
end
assert_select("li a.test-child-0", "Test child 0")
assert_select("li a.test-child-1", "Test child 1")
assert_select("li a.test-child-2", "Test child 2")
end
end
end
def test_render_menu_node_with_allowed_and_unallowed_unattached_children
User.current = User.find(2)
parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
{:controller => 'issues', :action => 'index'},
{
:children => Proc.new {|p|
[
Redmine::MenuManager::MenuItem.new("test_child_allowed", {:controller => 'issues', :action => 'index'}, {}),
Redmine::MenuManager::MenuItem.new("test_child_unallowed", {:controller => 'issues', :action => 'unallowed'}, {}),
]
}
})
@output_buffer = render_menu_node(parent_node, Project.find(1))
assert_select("li") do
assert_select("a.parent-node", "Parent node")
assert_select("ul.menu-children.unattached") do
assert_select("li a.test-child-allowed", "Test child allowed")
assert_select("li a.test-child-unallowed", false)
end
end
end
def test_render_menu_node_with_allowed_and_unallowed_standard_children
User.current = User.find(6)
Redmine::MenuManager.map :some_menu do |menu|
menu.push(:parent_node, {:controller => 'issues', :action => 'index'}, { })
menu.push(:test_child_allowed, {:controller => 'issues', :action => 'index'}, {:parent => :parent_node})
menu.push(:test_child_unallowed, {:controller => 'issues', :action => 'new'}, {:parent => :parent_node})
end
@output_buffer = render_menu(:some_menu, Project.find(1))
assert_select("li") do
assert_select("a.parent-node", "Parent node")
assert_select("ul.menu-children.unattached", false)
assert_select("ul.menu-children") do
assert_select("li a.test-child-allowed", "Test child allowed")
assert_select("li a.test-child-unallowed", false)
end
end
end
def test_render_empty_virtual_menu_node_with_children
# only empty item with no click target
Redmine::MenuManager.map :menu1 do |menu|
menu.push(:parent_node, nil, { })
end
# parent with unallowed unattached child
Redmine::MenuManager.map :menu2 do |menu|
menu.push(:parent_node, nil, {:children => Proc.new {|p|
[Redmine::MenuManager::MenuItem.new("test_child_unallowed", {:controller => 'issues', :action => 'new'}, {})]
} })
end
# parent with unallowed standard child
Redmine::MenuManager.map :menu3 do |menu|
menu.push(:parent_node, nil, {})
menu.push(:test_child_unallowed, {:controller =>'issues', :action => 'new'}, {:parent => :parent_node})
end
# should not be displayed to anonymous
User.current = User.find(6)
assert_nil render_menu(:menu1, Project.find(1))
assert_nil render_menu(:menu2, Project.find(1))
assert_nil render_menu(:menu3, Project.find(1))
# should be displayed to an admin
User.current = User.find(1)
@output_buffer = render_menu(:menu2, Project.find(1))
assert_select("ul li a.parent-node", "Parent node")
@output_buffer = render_menu(:menu3, Project.find(1))
assert_select("ul li a.parent-node", "Parent node")
end
def test_render_menu_node_with_children_without_an_array
parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
'/test',
{
:children => Proc.new {|p| Redmine::MenuManager::MenuItem.new("test_child", "/testing", {})}
})
assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
@output_buffer = render_menu_node(parent_node, Project.find(1))
end
end
def test_render_menu_node_with_incorrect_children
parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
'/test',
{
:children => Proc.new {|p| ["a string"] }
})
assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
@output_buffer = render_menu_node(parent_node, Project.find(1))
end
end
def test_menu_items_for_should_yield_all_items_if_passed_a_block
menu_name = :test_menu_items_for_should_yield_all_items_if_passed_a_block
Redmine::MenuManager.map menu_name do |menu|
menu.push(:a_menu, '/', { })
menu.push(:a_menu_2, '/', { })
menu.push(:a_menu_3, '/', { })
end
items_yielded = []
menu_items_for(menu_name) do |item|
items_yielded << item
end
assert_equal 3, items_yielded.size
end
def test_menu_items_for_should_return_all_items
menu_name = :test_menu_items_for_should_return_all_items
Redmine::MenuManager.map menu_name do |menu|
menu.push(:a_menu, '/', { })
menu.push(:a_menu_2, '/', { })
menu.push(:a_menu_3, '/', { })
end
items = menu_items_for(menu_name)
assert_equal 3, items.size
end
def test_menu_items_for_should_skip_unallowed_items_on_a_project
menu_name = :test_menu_items_for_should_skip_unallowed_items_on_a_project
Redmine::MenuManager.map menu_name do |menu|
menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
menu.push(:a_menu_2, {:controller => 'issues', :action => 'index' }, { })
menu.push(:unallowed, {:controller => 'issues', :action => 'unallowed' }, { })
end
User.current = User.find(2)
items = menu_items_for(menu_name, Project.find(1))
assert_equal 2, items.size
end
def test_menu_items_for_should_skip_items_that_fail_the_permission
menu_name = :test_menu_items_for_should_skip_items_that_fail_the_permission
Redmine::MenuManager.map menu_name do |menu|
menu.push(:a_menu, :project_issues_path)
menu.push(:unallowed, :project_issues_path, :permission => :unallowed)
end
User.current = User.find(2)
items = menu_items_for(menu_name, Project.find(1))
assert_equal 1, items.size
end
def test_menu_items_for_should_skip_items_that_fail_the_conditions
menu_name = :test_menu_items_for_should_skip_items_that_fail_the_conditions
Redmine::MenuManager.map menu_name do |menu|
menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
menu.push(:unallowed,
{:controller => 'issues', :action => 'index' },
{ :if => Proc.new { false }})
end
User.current = User.find(2)
items = menu_items_for(menu_name, Project.find(1))
assert_equal 1, items.size
end
end

View file

@ -0,0 +1,108 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
module RedmineMenuTestHelper
# Helpers
def get_menu_item(menu_name, item_name)
Redmine::MenuManager.items(menu_name).find {|item| item.name == item_name.to_sym}
end
end
class Redmine::MenuManager::MenuItemTest < ActiveSupport::TestCase
include RedmineMenuTestHelper
Redmine::MenuManager.map :test_menu do |menu|
menu.push(:parent, '/test', { })
menu.push(:child_menu, '/test', { :parent => :parent})
menu.push(:child2_menu, '/test', { :parent => :parent})
end
# context new menu item
def test_new_menu_item_should_require_a_name
assert_raises ArgumentError do
Redmine::MenuManager::MenuItem.new
end
end
def test_new_menu_item_should_require_an_url
assert_raises ArgumentError do
Redmine::MenuManager::MenuItem.new(:test_missing_url)
end
end
def test_new_menu_item_with_all_required_parameters
assert Redmine::MenuManager::MenuItem.new(:test_good_menu, '/test', {})
end
def test_new_menu_item_should_require_a_proc_to_use_for_the_if_condition
assert_raises ArgumentError do
Redmine::MenuManager::MenuItem.new(:test_error, '/test',
{
:if => ['not_a_proc']
})
end
assert Redmine::MenuManager::MenuItem.new(:test_good_if, '/test',
{
:if => Proc.new{}
})
end
def test_new_menu_item_should_allow_a_hash_for_extra_html_options
assert_raises ArgumentError do
Redmine::MenuManager::MenuItem.new(:test_error, '/test',
{
:html => ['not_a_hash']
})
end
assert Redmine::MenuManager::MenuItem.new(:test_good_html, '/test',
{
:html => { :onclick => 'doSomething'}
})
end
def test_new_menu_item_should_require_a_proc_to_use_the_children_option
assert_raises ArgumentError do
Redmine::MenuManager::MenuItem.new(:test_error, '/test',
{
:children => ['not_a_proc']
})
end
assert Redmine::MenuManager::MenuItem.new(:test_good_children, '/test',
{
:children => Proc.new{}
})
end
def test_new_should_not_allow_setting_the_parent_item_to_the_current_item
assert_raises ArgumentError do
Redmine::MenuManager::MenuItem.new(:test_error, '/test', { :parent => :test_error })
end
end
def test_has_children
parent_item = get_menu_item(:test_menu, :parent)
assert parent_item.children.present?
assert_equal 2, parent_item.children.size
assert_equal get_menu_item(:test_menu, :child_menu), parent_item.children[0]
assert_equal get_menu_item(:test_menu, :child2_menu), parent_item.children[1]
end
end

View file

@ -0,0 +1,34 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::MenuManagerTest < ActiveSupport::TestCase
def test_map_should_yield_a_mapper
assert_difference 'Redmine::MenuManager.items(:project_menu).size' do
Redmine::MenuManager.map :project_menu do |mapper|
assert_kind_of Redmine::MenuManager::Mapper, mapper
mapper.push :new_item, '/'
end
end
end
def test_items_should_return_menu_items
items = Redmine::MenuManager.items(:project_menu)
assert_kind_of Redmine::MenuManager::MenuNode, items.first
end
end

View file

@ -0,0 +1,75 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::MimeTypeTest < ActiveSupport::TestCase
def test_of
to_test = {'test.txt' => 'text/plain',
'test.c' => 'text/x-c',
}
to_test.each do |name, expected|
assert_equal expected, Redmine::MimeType.of(name)
end
end
def test_of_with_unknown_type
assert_nil Redmine::MimeType.of('test.unk')
end
def test_css_class_of
to_test = {'test.txt' => 'text-plain',
'test.c' => 'text-x-c',
}
to_test.each do |name, expected|
assert_equal expected, Redmine::MimeType.css_class_of(name)
end
end
def test_css_class_of_with_unknown_type
assert_nil Redmine::MimeType.css_class_of('test.unk')
end
def test_main_mimetype_of
to_test = {'test.txt' => 'text',
'test.c' => 'text',
}
to_test.each do |name, expected|
assert_equal expected, Redmine::MimeType.main_mimetype_of(name)
end
end
def test_main_mimetype_of_with_unknown_type
assert_nil Redmine::MimeType.main_mimetype_of('test.unk')
end
def test_is_type
to_test = {['text', 'test.unk'] => false,
['text', 'test.txt'] => true,
['text', 'test.c'] => true,
}
to_test.each do |args, expected|
assert_equal expected, Redmine::MimeType.is_type?(*args)
end
end
def test_should_default_to_mime_type_gem
assert !Redmine::MimeType::EXTENSIONS.keys.include?("zip")
assert_equal "application/zip", Redmine::MimeType.of("file.zip")
end
end

View file

@ -0,0 +1,29 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::NotifiableTest < ActiveSupport::TestCase
def setup
end
def test_all
%w(issue_added issue_updated issue_note_added issue_status_updated issue_assigned_to_updated issue_priority_updated news_added news_comment_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable|
assert Redmine::Notifiable.all.collect(&:name).include?(notifiable), "missing #{notifiable}"
end
end
end

View file

@ -0,0 +1,34 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class PaginationHelperTest < ActionView::TestCase
include Redmine::Pagination::Helper
def test_per_page_options_should_return_usefull_values
with_settings :per_page_options => '10, 25, 50, 100' do
assert_equal [], per_page_options(10, 3)
assert_equal [], per_page_options(25, 3)
assert_equal [10, 25], per_page_options(10, 22)
assert_equal [10, 25], per_page_options(25, 22)
assert_equal [10, 25, 50], per_page_options(50, 22)
assert_equal [10, 25, 50], per_page_options(25, 26)
assert_equal [10, 25, 50, 100], per_page_options(25, 120)
end
end
end

View file

@ -0,0 +1,94 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::PaginationTest < ActiveSupport::TestCase
def setup
@klass = Redmine::Pagination::Paginator
end
def test_count_is_zero
p = @klass.new 0, 10, 1
assert_equal 0, p.offset
assert_equal 10, p.per_page
%w(first_page previous_page next_page last_page).each do |method|
assert_nil p.send(method), "#{method} was not nil"
end
assert_equal 0, p.first_item
assert_equal 0, p.last_item
assert_equal [], p.linked_pages
end
def test_count_is_less_than_per_page
p = @klass.new 7, 10, 1
assert_equal 0, p.offset
assert_equal 10, p.per_page
assert_equal 1, p.first_page
assert_nil p.previous_page
assert_nil p.next_page
assert_equal 1, p.last_page
assert_equal 1, p.first_item
assert_equal 7, p.last_item
assert_equal [], p.linked_pages
end
def test_count_is_equal_to_per_page
p = @klass.new 10, 10, 1
assert_equal 0, p.offset
assert_equal 10, p.per_page
assert_equal 1, p.first_page
assert_nil p.previous_page
assert_nil p.next_page
assert_equal 1, p.last_page
assert_equal 1, p.first_item
assert_equal 10, p.last_item
assert_equal [], p.linked_pages
end
def test_2_pages
p = @klass.new 16, 10, 1
assert_equal 0, p.offset
assert_equal 10, p.per_page
assert_equal 1, p.first_page
assert_nil p.previous_page
assert_equal 2, p.next_page
assert_equal 2, p.last_page
assert_equal 1, p.first_item
assert_equal 10, p.last_item
assert_equal [1, 2], p.linked_pages
end
def test_many_pages
p = @klass.new 155, 10, 1
assert_equal 0, p.offset
assert_equal 10, p.per_page
assert_equal 1, p.first_page
assert_nil p.previous_page
assert_equal 2, p.next_page
assert_equal 16, p.last_page
assert_equal 1, p.first_item
assert_equal 10, p.last_item
assert_equal [1, 2, 3, 16], p.linked_pages
end
end

View file

@ -0,0 +1,186 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::PluginTest < ActiveSupport::TestCase
def setup
@klass = Redmine::Plugin
# In case some real plugins are installed
@klass.clear
end
def teardown
@klass.clear
end
def test_register
@klass.register :foo do
name 'Foo plugin'
url 'http://example.net/plugins/foo'
author 'John Smith'
author_url 'http://example.net/jsmith'
description 'This is a test plugin'
version '0.0.1'
settings :default => {'sample_setting' => 'value', 'foo'=>'bar'}, :partial => 'foo/settings'
end
assert_equal 1, @klass.all.size
plugin = @klass.find('foo')
assert plugin.is_a?(Redmine::Plugin)
assert_equal :foo, plugin.id
assert_equal 'Foo plugin', plugin.name
assert_equal 'http://example.net/plugins/foo', plugin.url
assert_equal 'John Smith', plugin.author
assert_equal 'http://example.net/jsmith', plugin.author_url
assert_equal 'This is a test plugin', plugin.description
assert_equal '0.0.1', plugin.version
end
def test_installed
@klass.register(:foo) {}
assert_equal true, @klass.installed?(:foo)
assert_equal false, @klass.installed?(:bar)
end
def test_menu
assert_difference 'Redmine::MenuManager.items(:project_menu).size' do
@klass.register :foo do
menu :project_menu, :foo_menu_item, '/foo', :caption => 'Foo'
end
end
menu_item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name == :foo_menu_item}
assert_not_nil menu_item
assert_equal 'Foo', menu_item.caption
assert_equal '/foo', menu_item.url
ensure
Redmine::MenuManager.map(:project_menu).delete(:foo_menu_item)
end
def test_delete_menu_item
Redmine::MenuManager.map(:project_menu).push(:foo_menu_item, '/foo', :caption => 'Foo')
assert_difference 'Redmine::MenuManager.items(:project_menu).size', -1 do
@klass.register :foo do
delete_menu_item :project_menu, :foo_menu_item
end
end
assert_nil Redmine::MenuManager.items(:project_menu).detect {|i| i.name == :foo_menu_item}
ensure
Redmine::MenuManager.map(:project_menu).delete(:foo_menu_item)
end
def test_directory_with_override
@klass.register(:foo) do
directory '/path/to/foo'
end
assert_equal '/path/to/foo', @klass.find('foo').directory
end
def test_directory_without_override
@klass.register(:foo) {}
assert_equal File.join(@klass.directory, 'foo'), @klass.find('foo').directory
end
def test_requires_redmine
plugin = Redmine::Plugin.register(:foo) {}
Redmine::VERSION.stubs(:to_a).returns([2, 1, 3, "stable", 10817])
# Specific version without hash
assert plugin.requires_redmine('2.1.3')
assert plugin.requires_redmine('2.1')
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine('2.1.4')
end
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine('2.2')
end
# Specific version
assert plugin.requires_redmine(:version => '2.1.3')
assert plugin.requires_redmine(:version => ['2.1.3', '2.2.0'])
assert plugin.requires_redmine(:version => '2.1')
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine(:version => '2.2.0')
end
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine(:version => ['2.1.4', '2.2.0'])
end
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine(:version => '2.2')
end
# Version range
assert plugin.requires_redmine(:version => '2.0.0'..'2.2.4')
assert plugin.requires_redmine(:version => '2.1.3'..'2.2.4')
assert plugin.requires_redmine(:version => '2.0.0'..'2.1.3')
assert plugin.requires_redmine(:version => '2.0'..'2.2')
assert plugin.requires_redmine(:version => '2.1'..'2.2')
assert plugin.requires_redmine(:version => '2.0'..'2.1')
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine(:version => '2.1.4'..'2.2.4')
end
# Version or higher
assert plugin.requires_redmine(:version_or_higher => '0.1.0')
assert plugin.requires_redmine(:version_or_higher => '2.1.3')
assert plugin.requires_redmine(:version_or_higher => '2.1')
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine(:version_or_higher => '2.2.0')
end
assert_raise Redmine::PluginRequirementError do
plugin.requires_redmine(:version_or_higher => '2.2')
end
end
def test_requires_redmine_plugin
test = self
other_version = '0.5.0'
@klass.register :other do
name 'Other'
version other_version
end
@klass.register :foo do
test.assert requires_redmine_plugin(:other, :version_or_higher => '0.1.0')
test.assert requires_redmine_plugin(:other, :version_or_higher => other_version)
test.assert requires_redmine_plugin(:other, other_version)
test.assert_raise Redmine::PluginRequirementError do
requires_redmine_plugin(:other, :version_or_higher => '99.0.0')
end
test.assert requires_redmine_plugin(:other, :version => other_version)
test.assert requires_redmine_plugin(:other, :version => [other_version, '99.0.0'])
test.assert_raise Redmine::PluginRequirementError do
requires_redmine_plugin(:other, :version => '99.0.0')
end
test.assert_raise Redmine::PluginRequirementError do
requires_redmine_plugin(:other, :version => ['98.0.0', '99.0.0'])
end
# Missing plugin
test.assert_raise Redmine::PluginNotFound do
requires_redmine_plugin(:missing, :version_or_higher => '0.1.0')
end
test.assert_raise Redmine::PluginNotFound do
requires_redmine_plugin(:missing, '0.1.0')
end
test.assert_raise Redmine::PluginNotFound do
requires_redmine_plugin(:missing, :version => '0.1.0')
end
end
end
def test_settings_warns_about_possible_partial_collision
@klass.register(:foo) { settings :partial => 'foo/settings' }
Rails.logger.expects(:warn)
@klass.register(:bar) { settings :partial => 'foo/settings' }
end
end

View file

@ -0,0 +1,102 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::SafeAttributesTest < ActiveSupport::TestCase
fixtures :users
class Base
def attributes=(attrs)
attrs.each do |key, value|
send("#{key}=", value)
end
end
end
class Person < Base
attr_accessor :firstname, :lastname, :login
include Redmine::SafeAttributes
safe_attributes :firstname, :lastname
safe_attributes :login, :if => lambda {|person, user| user.admin?}
end
class Book < Base
attr_accessor :title
include Redmine::SafeAttributes
safe_attributes :title
end
def test_safe_attribute_names
p = Person.new
user = User.anonymous
assert_equal ['firstname', 'lastname'], p.safe_attribute_names(user)
assert p.safe_attribute?('firstname', user)
assert !p.safe_attribute?('login', user)
p = Person.new
user = User.find(1)
assert_equal ['firstname', 'lastname', 'login'], p.safe_attribute_names(user)
assert p.safe_attribute?('firstname', user)
assert p.safe_attribute?('login', user)
end
def test_safe_attribute_names_without_user
p = Person.new
User.current = nil
assert_equal ['firstname', 'lastname'], p.safe_attribute_names
assert p.safe_attribute?('firstname')
assert !p.safe_attribute?('login')
p = Person.new
User.current = User.find(1)
assert_equal ['firstname', 'lastname', 'login'], p.safe_attribute_names
assert p.safe_attribute?('firstname')
assert p.safe_attribute?('login')
end
def test_set_safe_attributes
p = Person.new
p.send('safe_attributes=', {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}, User.anonymous)
assert_equal 'John', p.firstname
assert_equal 'Smith', p.lastname
assert_nil p.login
p = Person.new
User.current = User.find(1)
p.send('safe_attributes=', {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}, User.find(1))
assert_equal 'John', p.firstname
assert_equal 'Smith', p.lastname
assert_equal 'jsmith', p.login
end
def test_set_safe_attributes_without_user
p = Person.new
User.current = nil
p.safe_attributes = {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}
assert_equal 'John', p.firstname
assert_equal 'Smith', p.lastname
assert_nil p.login
p = Person.new
User.current = User.find(1)
p.safe_attributes = {'firstname' => 'John', 'lastname' => 'Smith', 'login' => 'jsmith'}
assert_equal 'John', p.firstname
assert_equal 'Smith', p.lastname
assert_equal 'jsmith', p.login
end
end

View file

@ -0,0 +1,218 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class BazaarAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
REPOSITORY_PATH.gsub!(/\/+/, '/')
if File.directory?(REPOSITORY_PATH)
def setup
@adapter = Redmine::Scm::Adapters::BazaarAdapter.new(
File.join(REPOSITORY_PATH, "trunk")
)
end
def test_scm_version
to_test = { "Bazaar (bzr) 2.1.2\n" => [2,1,2],
"2.1.1\n1.7\n1.8" => [2,1,1],
"2.0.1\r\n1.8.1\r\n1.9.1" => [2,0,1]}
to_test.each do |s, v|
test_scm_version_for(s, v)
end
end
def test_cat
cat = @adapter.cat('directory/document.txt')
assert cat =~ /Write the contents of a file as of a given revision to standard output/
end
def test_cat_path_invalid
assert_nil @adapter.cat('invalid')
end
def test_cat_revision_invalid
assert_nil @adapter.cat('doc-mkdir.txt', '12345678')
end
def test_diff
diff1 = @adapter.diff('doc-mkdir.txt', 3, 2)
assert_equal 21, diff1.size
buf = diff1[14].gsub(/\r\n|\r|\n/, "")
assert_equal "-Display more information.", buf
end
def test_diff_path_invalid
assert_equal [], @adapter.diff('invalid', 1)
end
def test_diff_revision_invalid
assert_equal [], @adapter.diff(nil, 12345678)
assert_equal [], @adapter.diff(nil, 12345678, 87654321)
end
def test_annotate
annotate = @adapter.annotate('doc-mkdir.txt')
assert_equal 17, annotate.lines.size
assert_equal '1', annotate.revisions[0].identifier
assert_equal 'jsmith@', annotate.revisions[0].author
assert_equal 'mkdir', annotate.lines[0]
end
def test_annotate_path_invalid
assert_nil @adapter.annotate('invalid')
end
def test_annotate_revision_invalid
assert_nil @adapter.annotate('doc-mkdir.txt', '12345678')
end
def test_branch_conf_path
p = "c:\\test\\test\\"
bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
p = "c:\\test\\test\\.bzr"
bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
p = "c:\\test\\test\\.bzr\\"
bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
p = "c:\\test\\test"
bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
assert_equal File.join("c:\\test\\test", ".bzr", "branch", "branch.conf"), bcp
p = "\\\\server\\test\\test\\"
bcp = Redmine::Scm::Adapters::BazaarAdapter.branch_conf_path(p)
assert_equal File.join("\\\\server\\test\\test", ".bzr", "branch", "branch.conf"), bcp
end
def test_append_revisions_only_true
assert_equal true, @adapter.append_revisions_only
end
def test_append_revisions_only_false
adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
File.join(REPOSITORY_PATH, "empty-branch")
)
assert_equal false, adpt.append_revisions_only
end
def test_append_revisions_only_shared_repo
adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
REPOSITORY_PATH
)
assert_equal false, adpt.append_revisions_only
end
def test_info_not_nil
assert_not_nil @adapter.info
end
def test_info_nil
adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
"/invalid/invalid/"
)
assert_nil adpt.info
end
def test_info
info = @adapter.info
assert_equal 4, info.lastrev.identifier.to_i
end
def test_info_emtpy
adpt = Redmine::Scm::Adapters::BazaarAdapter.new(
File.join(REPOSITORY_PATH, "empty-branch")
)
assert_equal 0, adpt.info.lastrev.identifier.to_i
end
def test_entries_path_invalid
assert_equal [], @adapter.entries('invalid')
end
def test_entries_revision_invalid
assert_nil @adapter.entries(nil, 12345678)
end
def test_revisions
revisions = @adapter.revisions(nil, 4, 2)
assert_equal 3, revisions.size
assert_equal 2, revisions[2].identifier
assert_equal 'jsmith@foo.bar-20071203175224-v0eog5d5wrgdrshg', revisions[2].scmid
assert_equal 4, revisions[0].identifier
assert_equal 'jsmith@foo.bar-20071203175422-t40bf8li5zz0c4cg', revisions[0].scmid
assert_equal 2, revisions[0].paths.size
assert_equal 'D', revisions[0].paths[0][:action]
assert_equal '/doc-deleted.txt', revisions[0].paths[0][:path]
assert_equal 'docdeleted.txt-20071203175320-iwwj561ojuubs3gt-1', revisions[0].paths[0][:revision]
assert_equal 'M', revisions[0].paths[1][:action]
assert_equal '/directory/doc-ls.txt', revisions[0].paths[1][:path]
assert_equal 'docls.txt-20071203175005-a3hyc3mn0shl7cgu-1', revisions[0].paths[1][:revision]
end
def test_revisions_path_invalid
assert_nil @adapter.revisions('invalid')
end
def test_revisions_revision_invalid
assert_nil @adapter.revisions(nil, 12345678)
assert_nil @adapter.revisions(nil, 12345678, 87654321)
end
def test_entry
entry = @adapter.entry()
assert_equal "", entry.path
assert_equal "dir", entry.kind
entry = @adapter.entry('')
assert_equal "", entry.path
assert_equal "dir", entry.kind
assert_nil @adapter.entry('invalid')
assert_nil @adapter.entry('/invalid')
assert_nil @adapter.entry('/invalid/')
assert_nil @adapter.entry('invalid/invalid')
assert_nil @adapter.entry('invalid/invalid/')
assert_nil @adapter.entry('/invalid/invalid')
assert_nil @adapter.entry('/invalid/invalid/')
["doc-ls.txt", "/doc-ls.txt"].each do |path|
entry = @adapter.entry(path, 2)
assert_equal "doc-ls.txt", entry.path
assert_equal "file", entry.kind
end
["directory", "/directory", "/directory/"].each do |path|
entry = @adapter.entry(path, 2)
assert_equal "directory", entry.path
assert_equal "dir", entry.kind
end
["directory/document.txt", "/directory/document.txt"].each do |path|
entry = @adapter.entry(path, 2)
assert_equal "directory/document.txt", entry.path
assert_equal "file", entry.kind
end
end
private
def test_scm_version_for(scm_command_version, version)
@adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
assert_equal version, @adapter.class.scm_command_version
end
else
puts "Bazaar test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end
end
end

View file

@ -0,0 +1,106 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class CvsAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
MODULE_NAME = 'test'
if File.directory?(REPOSITORY_PATH)
def setup
@adapter = Redmine::Scm::Adapters::CvsAdapter.new(MODULE_NAME, REPOSITORY_PATH)
end
def test_scm_version
to_test = { "\nConcurrent Versions System (CVS) 1.12.13 (client/server)\n" => [1,12,13],
"\r\n1.12.12\r\n1.12.11" => [1,12,12],
"1.12.11\r\n1.12.10\r\n" => [1,12,11]}
to_test.each do |s, v|
test_scm_version_for(s, v)
end
end
def test_revisions_all
cnt = 0
@adapter.revisions('', nil, nil, :log_encoding => 'UTF-8') do |revision|
cnt += 1
end
assert_equal 16, cnt
end
def test_revisions_from_rev3
rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
cnt = 0
@adapter.revisions('', rev3_committed_on, nil, :log_encoding => 'UTF-8') do |revision|
cnt += 1
end
assert_equal 4, cnt
end
def test_entries_rev3
rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22)
entries = @adapter.entries('sources', rev3_committed_on)
assert_equal 2, entries.size
assert_equal entries[0].name, "watchers_controller.rb"
assert_equal entries[0].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22)
end
def test_path_encoding_default_utf8
adpt1 = Redmine::Scm::Adapters::CvsAdapter.new(
MODULE_NAME,
REPOSITORY_PATH
)
assert_equal "UTF-8", adpt1.path_encoding
adpt2 = Redmine::Scm::Adapters::CvsAdapter.new(
MODULE_NAME,
REPOSITORY_PATH,
nil,
nil,
""
)
assert_equal "UTF-8", adpt2.path_encoding
end
def test_root_url_path
to_test = {
':pserver:cvs_user:cvs_password@123.456.789.123:9876/repo' => '/repo',
':pserver:cvs_user:cvs_password@123.456.789.123/repo' => '/repo',
':pserver:cvs_user:cvs_password@cvs_server:/repo' => '/repo',
':pserver:cvs_user:cvs_password@cvs_server:9876/repo' => '/repo',
':pserver:cvs_user:cvs_password@cvs_server/repo' => '/repo',
':pserver:cvs_user:cvs_password@cvs_server/path/repo' => '/path/repo',
':ext:cvsservername:/path' => '/path'
}
to_test.each do |string, expected|
assert_equal expected, Redmine::Scm::Adapters::CvsAdapter.new('foo', string).send(:root_url_path), "#{string} failed"
end
end
private
def test_scm_version_for(scm_command_version, version)
@adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
assert_equal version, @adapter.class.scm_command_version
end
else
puts "Cvs test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end
end
end

View file

@ -0,0 +1,60 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class DarcsAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
if File.directory?(REPOSITORY_PATH)
def setup
@adapter = Redmine::Scm::Adapters::DarcsAdapter.new(REPOSITORY_PATH)
end
def test_darcsversion
to_test = { "1.0.9 (release)\n" => [1,0,9] ,
"2.2.0 (release)\n" => [2,2,0] }
to_test.each do |s, v|
test_darcsversion_for(s, v)
end
end
def test_revisions
id1 = '20080308225258-98289-761f654d669045eabee90b91b53a21ce5593cadf.gz'
revs = @adapter.revisions('', nil, nil, {:with_path => true})
assert_equal 6, revs.size
assert_equal id1, revs[5].scmid
paths = revs[5].paths
assert_equal 5, paths.size
assert_equal 'A', paths[0][:action]
assert_equal '/README', paths[0][:path]
assert_equal 'A', paths[1][:action]
assert_equal '/images', paths[1][:path]
end
private
def test_darcsversion_for(darcsversion, version)
@adapter.class.expects(:darcs_binary_version_from_command_line).returns(darcsversion)
assert_equal version, @adapter.class.darcs_binary_version
end
else
puts "Darcs test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end
end
end

View file

@ -0,0 +1,68 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class FilesystemAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
if File.directory?(REPOSITORY_PATH)
def setup
@adapter = Redmine::Scm::Adapters::FilesystemAdapter.new(REPOSITORY_PATH)
end
def test_entries
assert_equal 3, @adapter.entries.size
assert_equal ["dir", "japanese", "test"], @adapter.entries.collect(&:name)
assert_equal ["dir", "japanese", "test"], @adapter.entries(nil).collect(&:name)
assert_equal ["dir", "japanese", "test"], @adapter.entries("/").collect(&:name)
["dir", "/dir", "/dir/", "dir/"].each do |path|
assert_equal ["subdir", "dirfile"], @adapter.entries(path).collect(&:name)
end
# If y try to use "..", the path is ignored
["/../","dir/../", "..", "../", "/..", "dir/.."].each do |path|
assert_equal ["dir", "japanese", "test"], @adapter.entries(path).collect(&:name),
".. must be ignored in path argument"
end
end
def test_cat
assert_equal "TEST CAT\n", @adapter.cat("test")
assert_equal "TEST CAT\n", @adapter.cat("/test")
# Revision number is ignored
assert_equal "TEST CAT\n", @adapter.cat("/test", 1)
end
def test_path_encoding_default_utf8
adpt1 = Redmine::Scm::Adapters::FilesystemAdapter.new(
REPOSITORY_PATH
)
assert_equal "UTF-8", adpt1.path_encoding
adpt2 = Redmine::Scm::Adapters::FilesystemAdapter.new(
REPOSITORY_PATH,
nil,
nil,
nil,
""
)
assert_equal "UTF-8", adpt2.path_encoding
end
else
puts "Filesystem test repository NOT FOUND. Skipping unit tests !!! See doc/RUNNING_TESTS."
def test_fake; assert true end
end
end

View file

@ -0,0 +1,597 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class GitAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
FELIX_HEX = "Felix Sch\xC3\xA4fer"
CHAR_1_HEX = "\xc3\x9c"
## Git, Mercurial and CVS path encodings are binary.
## Subversion supports URL encoding for path.
## Redmine Mercurial adapter and extension use URL encoding.
## Git accepts only binary path in command line parameter.
## So, there is no way to use binary command line parameter in JRuby.
JRUBY_SKIP = (RUBY_PLATFORM == 'java')
JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
if File.directory?(REPOSITORY_PATH)
## Ruby uses ANSI api to fork a process on Windows.
## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
## and these are incompatible with ASCII.
## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
## http://code.google.com/p/msysgit/issues/detail?id=80
## So, Latin-1 path tests fail on Japanese Windows
WINDOWS_PASS = (Redmine::Platform.mswin? &&
Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
def setup
adapter_class = Redmine::Scm::Adapters::GitAdapter
assert adapter_class
assert adapter_class.client_command
assert_equal true, adapter_class.client_available
assert_equal true, adapter_class.client_version_above?([1])
assert_equal true, adapter_class.client_version_above?([1, 0])
@adapter = Redmine::Scm::Adapters::GitAdapter.new(
REPOSITORY_PATH,
nil,
nil,
nil,
'ISO-8859-1'
)
assert @adapter
@char_1 = CHAR_1_HEX.dup.force_encoding('UTF-8')
@str_felix_hex = FELIX_HEX.dup.force_encoding('ASCII-8BIT')
end
def test_scm_version
to_test = { "git version 1.7.3.4\n" => [1,7,3,4],
"1.6.1\n1.7\n1.8" => [1,6,1],
"1.6.2\r\n1.8.1\r\n1.9.1" => [1,6,2]}
to_test.each do |s, v|
test_scm_version_for(s, v)
end
end
def test_branches
brs = []
@adapter.branches.each do |b|
brs << b
end
assert_equal 6, brs.length
br_issue_8857 = brs[0]
assert_equal 'issue-8857', br_issue_8857.to_s
assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
assert_equal br_issue_8857.scmid, br_issue_8857.revision
assert_equal false, br_issue_8857.is_default
br_latin_1_path = brs[1]
assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
assert_equal false, br_latin_1_path.is_default
br_master = brs[2]
assert_equal 'master', br_master.to_s
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
assert_equal br_master.scmid, br_master.revision
assert_equal false, br_master.is_default
br_master_20120212 = brs[3]
assert_equal 'master-20120212', br_master_20120212.to_s
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision
assert_equal br_master_20120212.scmid, br_master_20120212.revision
assert_equal true, br_master_20120212.is_default
br_latin_1 = brs[-2]
assert_equal 'test-latin-1', br_latin_1.to_s
assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
assert_equal br_latin_1.scmid, br_latin_1.revision
assert_equal false, br_latin_1.is_default
br_test = brs[-1]
assert_equal 'test_branch', br_test.to_s
assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
assert_equal br_test.scmid, br_test.revision
assert_equal false, br_test.is_default
end
def test_default_branch
assert_equal 'master-20120212', @adapter.default_branch
end
def test_tags
assert_equal [
"tag00.lightweight",
"tag01.annotated",
], @adapter.tags
end
def test_revisions_master_all
revs1 = []
@adapter.revisions('', nil, "master",{}) do |rev|
revs1 << rev
end
assert_equal 15, revs1.length
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
revs2 = []
@adapter.revisions('', nil, "master",
{:reverse => true}) do |rev|
revs2 << rev
end
assert_equal 15, revs2.length
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
end
def test_revisions_master_merged_rev
revs1 = []
@adapter.revisions('',
"713f4944648826f558cf548222f813dabe7cbb04",
"master",
{:reverse => true}) do |rev|
revs1 << rev
end
assert_equal 8, revs1.length
assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
# 4a07fe31b is not a child of 713f49446
assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
# Merged revision
assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
revs2 = []
@adapter.revisions('',
"fba357b886984ee71185ad2065e65fc0417d9b92",
"master",
{:reverse => true}) do |rev|
revs2 << rev
end
assert_equal 7, revs2.length
assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
# 4a07fe31b is not a child of fba357b8869
assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
# Merged revision
assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
end
def test_revisions_branch_latin_1_path_encoding_all
revs1 = []
@adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
revs1 << rev
end
assert_equal 8, revs1.length
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
revs2 = []
@adapter.revisions('', nil, "latin-1-path-encoding",
{:reverse => true}) do |rev|
revs2 << rev
end
assert_equal 8, revs2.length
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
end
def test_revisions_branch_latin_1_path_encoding_with_rev
revs1 = []
@adapter.revisions('',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
"latin-1-path-encoding",
{:reverse => true}) do |rev|
revs1 << rev
end
assert_equal 7, revs1.length
assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
revs2 = []
@adapter.revisions('',
'57ca437c0acbbcb749821fdf3726a1367056d364',
"latin-1-path-encoding",
{:reverse => true}) do |rev|
revs2 << rev
end
assert_equal 3, revs2.length
assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
end
def test_revisions_invalid_rev
assert_equal [], @adapter.revisions('', '1234abcd', "master")
assert_raise Redmine::Scm::Adapters::CommandFailed do
revs1 = []
@adapter.revisions('',
'1234abcd',
"master",
{:reverse => true}) do |rev|
revs1 << rev
end
end
end
def test_revisions_includes_master_two_revs
revs1 = []
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
:excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
revs1 << rev
end
assert_equal 2, revs1.length
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
end
def test_revisions_includes_master_two_revs_from_origin
revs1 = []
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'],
:excludes => []}) do |rev|
revs1 << rev
end
assert_equal 2, revs1.length
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
end
def test_revisions_includes_merged_revs
revs1 = []
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
:excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
revs1 << rev
end
assert_equal 7, revs1.length
assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
end
def test_revisions_includes_two_heads
revs1 = []
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
'1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
:excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
'4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
revs1 << rev
end
assert_equal 4, revs1.length
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
end
def test_revisions_disjointed_histories_revisions
revs1 = []
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
'92397af84d22f27389c822848ecd5b463c181583'],
:excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
'4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
revs1 << rev
end
assert_equal 4, revs1.length
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
end
def test_revisions_invalid_rev_excludes
assert_equal [],
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
:excludes => ['0123abcd4567']})
assert_raise Redmine::Scm::Adapters::CommandFailed do
revs1 = []
@adapter.revisions('', nil, nil,
{:reverse => true,
:includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
:excludes => ['0123abcd4567']}) do |rev|
revs1 << rev
end
end
end
def test_getting_revisions_with_spaces_in_filename
assert_equal 1, @adapter.revisions("filemane with spaces.txt",
nil, "master").length
end
def test_parents
revs1 = []
@adapter.revisions('',
nil,
"master",
{:reverse => true}) do |rev|
revs1 << rev
end
assert_equal 15, revs1.length
assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
revs1[0].identifier
assert_nil revs1[0].parents
assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
revs1[1].identifier
assert_equal 1, revs1[1].parents.length
assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
revs1[1].parents[0]
assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
revs1[10].identifier
assert_equal 2, revs1[10].parents.length
assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
revs1[10].parents[0]
assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
revs1[10].parents[1]
end
def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
assert_equal " filename with a leading space.txt ",
@adapter.revisions(" filename with a leading space.txt ",
nil, "master")[0].paths[0][:path]
end
def test_getting_entries_with_leading_and_trailing_spaces_in_filename
assert_equal " filename with a leading space.txt ",
@adapter.entries('',
'83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
end
def test_annotate
annotate = @adapter.annotate('sources/watchers_controller.rb')
assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
assert_equal 41, annotate.lines.size
assert_equal "# This program is free software; you can redistribute it and/or",
annotate.lines[4].strip
assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
annotate.revisions[4].identifier
assert_equal "jsmith", annotate.revisions[4].author
end
def test_annotate_moved_file
annotate = @adapter.annotate('renamed_test.txt')
assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
assert_equal 2, annotate.lines.size
end
def test_last_rev
last_rev = @adapter.lastrev("README",
"4f26664364207fa8b1af9f8722647ab2d4ac5d43")
assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author
assert_equal Time.gm(2009, 6, 24, 5, 27, 38), last_rev.time
end
def test_last_rev_with_spaces_in_filename
last_rev = @adapter.lastrev("filemane with spaces.txt",
"ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
last_rev_author = last_rev.author
assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
assert_equal "#{@str_felix_hex} <felix@fachschaften.org>",
last_rev.author
assert_equal Time.gm(2010, 9, 18, 19, 59, 46), last_rev.time
end
def test_latin_1_path
if WINDOWS_PASS
puts WINDOWS_SKIP_STR
elsif JRUBY_SKIP
puts JRUBY_SKIP_STR
else
p2 = "latin-1-dir/test-#{@char_1}-2.txt"
['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
assert @adapter.diff(p2, r1)
assert @adapter.cat(p2, r1)
assert_equal 1, @adapter.annotate(p2, r1).lines.length
['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
assert @adapter.diff(p2, r1, r2)
end
end
end
end
def test_latin_1_user_annotate
['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
annotate = @adapter.annotate(" filename with a leading space.txt ", r1)
assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
assert_equal 1, annotate.lines.size
assert_equal "And this is a file with a leading and trailing space...",
annotate.lines[0].strip
assert_equal "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
annotate.revisions[0].identifier
assert_equal @str_felix_hex, annotate.revisions[0].author
end
end
def test_entries_tag
entries1 = @adapter.entries(nil, 'tag01.annotated',
options = {:report_last_commit => true})
assert entries1
assert_equal 3, entries1.size
assert_equal 'sources', entries1[1].name
assert_equal 'sources', entries1[1].path
assert_equal 'dir', entries1[1].kind
readme = entries1[2]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 27, readme.size
assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
end
def test_entries_branch
entries1 = @adapter.entries(nil, 'test_branch',
options = {:report_last_commit => true})
assert entries1
assert_equal 4, entries1.size
assert_equal 'sources', entries1[1].name
assert_equal 'sources', entries1[1].path
assert_equal 'dir', entries1[1].kind
readme = entries1[2]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 159, readme.size
assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
end
def test_entries_wrong_path_encoding
adpt = Redmine::Scm::Adapters::GitAdapter.new(
REPOSITORY_PATH,
nil,
nil,
nil,
'EUC-JP'
)
entries1 = adpt.entries('latin-1-dir', '64f1f3e8')
assert entries1
assert_equal 3, entries1.size
f1 = entries1[1]
assert_nil f1.name
assert_nil f1.path
assert_equal 'file', f1.kind
end
def test_entries_latin_1_files
entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
assert entries1
assert_equal 3, entries1.size
f1 = entries1[1]
assert_equal "test-#{@char_1}-2.txt", f1.name
assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
assert_equal 'file', f1.kind
end
def test_entries_latin_1_dir
if WINDOWS_PASS
puts WINDOWS_SKIP_STR
elsif JRUBY_SKIP
puts JRUBY_SKIP_STR
else
entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
'1ca7f5ed')
assert entries1
assert_equal 3, entries1.size
f1 = entries1[1]
assert_equal "test-#{@char_1}-2.txt", f1.name
assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
assert_equal 'file', f1.kind
end
end
def test_entry
entry = @adapter.entry()
assert_equal "", entry.path
assert_equal "dir", entry.kind
entry = @adapter.entry('')
assert_equal "", entry.path
assert_equal "dir", entry.kind
assert_nil @adapter.entry('invalid')
assert_nil @adapter.entry('/invalid')
assert_nil @adapter.entry('/invalid/')
assert_nil @adapter.entry('invalid/invalid')
assert_nil @adapter.entry('invalid/invalid/')
assert_nil @adapter.entry('/invalid/invalid')
assert_nil @adapter.entry('/invalid/invalid/')
["README", "/README"].each do |path|
entry = @adapter.entry(path, '7234cb2750b63f')
assert_equal "README", entry.path
assert_equal "file", entry.kind
end
["sources", "/sources", "/sources/"].each do |path|
entry = @adapter.entry(path, '7234cb2750b63f')
assert_equal "sources", entry.path
assert_equal "dir", entry.kind
end
["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
entry = @adapter.entry(path, '7234cb2750b63f')
assert_equal "sources/watchers_controller.rb", entry.path
assert_equal "file", entry.kind
end
end
def test_path_encoding_default_utf8
adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
REPOSITORY_PATH
)
assert_equal "UTF-8", adpt1.path_encoding
adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
REPOSITORY_PATH,
nil,
nil,
nil,
""
)
assert_equal "UTF-8", adpt2.path_encoding
end
def test_cat_path_invalid
assert_nil @adapter.cat('invalid')
end
def test_cat_revision_invalid
assert @adapter.cat('README')
assert_nil @adapter.cat('README', '1234abcd5678')
end
def test_diff_path_invalid
assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
end
def test_diff_revision_invalid
assert_nil @adapter.diff(nil, '1234abcd5678')
assert_nil @adapter.diff(nil, '713f4944648826f5', '1234abcd5678')
assert_nil @adapter.diff(nil, '1234abcd5678', '713f4944648826f5')
end
def test_annotate_path_invalid
assert_nil @adapter.annotate('invalid')
end
def test_annotate_revision_invalid
assert @adapter.annotate('README')
assert_nil @adapter.annotate('README', '1234abcd5678')
end
private
def test_scm_version_for(scm_command_version, version)
@adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
assert_equal version, @adapter.class.scm_command_version
end
else
puts "Git test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end
end
end

View file

@ -0,0 +1,485 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class MercurialAdapterTest < ActiveSupport::TestCase
HELPERS_DIR = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
TEMPLATE_NAME = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
HgCommandAborted = Redmine::Scm::Adapters::MercurialAdapter::HgCommandAborted
HgCommandArgumentError = Redmine::Scm::Adapters::MercurialAdapter::HgCommandArgumentError
REPOSITORY_PATH = repository_path('mercurial')
CHAR_1_HEX = "\xc3\x9c"
if File.directory?(REPOSITORY_PATH)
def setup
adapter_class = Redmine::Scm::Adapters::MercurialAdapter
assert adapter_class
assert adapter_class.client_command
assert_equal true, adapter_class.client_available
assert_equal true, adapter_class.client_version_above?([0, 9, 5])
@adapter = Redmine::Scm::Adapters::MercurialAdapter.new(
REPOSITORY_PATH,
nil,
nil,
nil,
'ISO-8859-1')
@diff_c_support = true
@char_1 = CHAR_1_HEX.dup.force_encoding('UTF-8')
@tag_char_1 = "tag-#{CHAR_1_HEX}-00".force_encoding('UTF-8')
@branch_char_0 = "branch-#{CHAR_1_HEX}-00".force_encoding('UTF-8')
@branch_char_1 = "branch-#{CHAR_1_HEX}-01".force_encoding('UTF-8')
end
def test_hgversion
to_test = { "Mercurial Distributed SCM (version 0.9.5)\n" => [0,9,5],
"Mercurial Distributed SCM (1.0)\n" => [1,0],
"Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
"Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
"Mercurial Distributed SCM (1916e629a29d)\n" => nil,
"Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
"(1.6)\n(1.7)\n(1.8)" => [1,6],
"(1.7.1)\r\n(1.8.1)\r\n(1.9.1)" => [1,7,1]}
to_test.each do |s, v|
test_hgversion_for(s, v)
end
end
def test_template_path
to_test = {
[1,2] => "1.0",
[] => "1.0",
[1,2,1] => "1.0",
[1,7] => "1.0",
[1,7,1] => "1.0",
[2,0] => "1.0",
}
to_test.each do |v, template|
test_template_path_for(v, template)
end
end
def test_info
[REPOSITORY_PATH, REPOSITORY_PATH + "/",
REPOSITORY_PATH + "//"].each do |repo|
adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo)
repo_path = adp.info.root_url.gsub(/\\/, "/")
assert_equal REPOSITORY_PATH, repo_path
assert_equal '33', adp.info.lastrev.revision
assert_equal '2e6d546429230f377d7d19c2078abd2dd909f235',adp.info.lastrev.scmid
end
end
def test_revisions
revisions = @adapter.revisions(nil, 2, 4)
assert_equal 3, revisions.size
assert_equal '2', revisions[0].revision
assert_equal '400bb86721098697c7d17b3724c794c57636de70', revisions[0].scmid
assert_equal '4', revisions[2].revision
assert_equal 'def6d2f1254a56fb8fbe9ec3b5c0451674dbd8b8', revisions[2].scmid
revisions = @adapter.revisions(nil, 2, 4, {:limit => 2})
assert_equal 2, revisions.size
assert_equal '2', revisions[0].revision
assert_equal '400bb86721098697c7d17b3724c794c57636de70', revisions[0].scmid
end
def test_parents
revs1 = @adapter.revisions(nil, 0, 0)
assert_equal 1, revs1.size
assert_equal [], revs1[0].parents
revs2 = @adapter.revisions(nil, 1, 1)
assert_equal 1, revs2.size
assert_equal 1, revs2[0].parents.size
assert_equal "0885933ad4f68d77c2649cd11f8311276e7ef7ce", revs2[0].parents[0]
revs3 = @adapter.revisions(nil, 30, 30)
assert_equal 1, revs3.size
assert_equal 2, revs3[0].parents.size
assert_equal "a94b0528f24fe05ebaef496ae0500bb050772e36", revs3[0].parents[0]
assert_equal "3a330eb329586ea2adb3f83237c23310e744ebe9", revs3[0].parents[1]
end
def test_diff
if @adapter.class.client_version_above?([1, 2])
assert_nil @adapter.diff(nil, '100000')
end
assert_nil @adapter.diff(nil, '100000', '200000')
[2, '400bb8672109', '400', 400].each do |r1|
diff1 = @adapter.diff(nil, r1)
if @diff_c_support
assert_equal 28, diff1.size
buf = diff1[24].gsub(/\r\n|\r|\n/, "")
assert_equal "+ return true unless klass.respond_to?('watched_by')", buf
else
assert_equal 0, diff1.size
end
[4, 'def6d2f1254a'].each do |r2|
diff2 = @adapter.diff(nil, r1, r2)
assert_equal 49, diff2.size
buf = diff2[41].gsub(/\r\n|\r|\n/, "")
assert_equal "+class WelcomeController < ApplicationController", buf
diff3 = @adapter.diff('sources/watchers_controller.rb', r1, r2)
assert_equal 20, diff3.size
buf = diff3[12].gsub(/\r\n|\r|\n/, "")
assert_equal "+ @watched.remove_watcher(user)", buf
diff4 = @adapter.diff(nil, r2, r1)
assert_equal 49, diff4.size
buf = diff4[41].gsub(/\r\n|\r|\n/, "")
assert_equal "-class WelcomeController < ApplicationController", buf
diff5 = @adapter.diff('sources/watchers_controller.rb', r2, r1)
assert_equal 20, diff5.size
buf = diff5[9].gsub(/\r\n|\r|\n/, "")
assert_equal "- @watched.remove_watcher(user)", buf
end
end
end
def test_diff_made_by_revision
if @diff_c_support
[24, '24', '4cddb4e45f52'].each do |r1|
diff1 = @adapter.diff(nil, r1)
assert_equal 5, diff1.size
buf = diff1[4].gsub(/\r\n|\r|\n/, "")
assert_equal '+0885933ad4f68d77c2649cd11f8311276e7ef7ce tag-init-revision', buf
end
end
end
def test_cat
[2, '400bb8672109', '400', 400].each do |r|
buf = @adapter.cat('sources/welcome_controller.rb', r)
assert buf
lines = buf.split("\r\n")
assert_equal 25, lines.length
assert_equal 'class WelcomeController < ApplicationController', lines[17]
end
assert_nil @adapter.cat('sources/welcome_controller.rb')
end
def test_annotate
assert_equal [], @adapter.annotate("sources/welcome_controller.rb").lines
[2, '400bb8672109', '400', 400].each do |r|
ann = @adapter.annotate('sources/welcome_controller.rb', r)
assert ann
assert_equal '1', ann.revisions[17].revision
assert_equal '9d5b5b004199', ann.revisions[17].identifier
assert_equal 'jsmith', ann.revisions[0].author
assert_equal 25, ann.lines.length
assert_equal 'class WelcomeController < ApplicationController', ann.lines[17]
end
end
def test_entries
assert_nil @adapter.entries(nil, '100000')
assert_equal 1, @adapter.entries("sources", 3).size
assert_equal 1, @adapter.entries("sources", 'b3a615152df8').size
[2, '400bb8672109', '400', 400].each do |r|
entries1 = @adapter.entries(nil, r)
assert entries1
assert_equal 3, entries1.size
assert_equal 'sources', entries1[1].name
assert_equal 'sources', entries1[1].path
assert_equal 'dir', entries1[1].kind
readme = entries1[2]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 27, readme.size
assert_equal '1', readme.lastrev.revision
assert_equal '9d5b5b00419901478496242e0768deba1ce8c51e', readme.lastrev.identifier
# 2007-12-14 10:24:01 +0100
assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
entries2 = @adapter.entries('sources', r)
assert entries2
assert_equal 2, entries2.size
assert_equal 'watchers_controller.rb', entries2[0].name
assert_equal 'sources/watchers_controller.rb', entries2[0].path
assert_equal 'file', entries2[0].kind
assert_equal 'welcome_controller.rb', entries2[1].name
assert_equal 'sources/welcome_controller.rb', entries2[1].path
assert_equal 'file', entries2[1].kind
end
end
def test_entries_tag
entries1 = @adapter.entries(nil, 'tag_test.00')
assert entries1
assert_equal 3, entries1.size
assert_equal 'sources', entries1[1].name
assert_equal 'sources', entries1[1].path
assert_equal 'dir', entries1[1].kind
readme = entries1[2]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 21, readme.size
assert_equal '0', readme.lastrev.revision
assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', readme.lastrev.identifier
# 2007-12-14 10:22:52 +0100
assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time
end
def test_entries_branch
entries1 = @adapter.entries(nil, 'test-branch-00')
assert entries1
assert_equal 5, entries1.size
assert_equal 'sql_escape', entries1[2].name
assert_equal 'sql_escape', entries1[2].path
assert_equal 'dir', entries1[2].kind
readme = entries1[4]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 365, readme.size
assert_equal '8', readme.lastrev.revision
assert_equal 'c51f5bb613cd60793c2a9fe9df29332e74bb949f', readme.lastrev.identifier
# 2001-02-01 00:00:00 -0900
assert_equal Time.gm(2001, 2, 1, 9, 0, 0), readme.lastrev.time
end
def test_entry
entry = @adapter.entry()
assert_equal "", entry.path
assert_equal "dir", entry.kind
entry = @adapter.entry('')
assert_equal "", entry.path
assert_equal "dir", entry.kind
assert_nil @adapter.entry('invalid')
assert_nil @adapter.entry('/invalid')
assert_nil @adapter.entry('/invalid/')
assert_nil @adapter.entry('invalid/invalid')
assert_nil @adapter.entry('invalid/invalid/')
assert_nil @adapter.entry('/invalid/invalid')
assert_nil @adapter.entry('/invalid/invalid/')
["README", "/README"].each do |path|
["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
entry = @adapter.entry(path, rev)
assert_equal "README", entry.path
assert_equal "file", entry.kind
assert_equal '0', entry.lastrev.revision
assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', entry.lastrev.identifier
end
end
["sources", "/sources", "/sources/"].each do |path|
["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
entry = @adapter.entry(path, rev)
assert_equal "sources", entry.path
assert_equal "dir", entry.kind
end
end
["sources/watchers_controller.rb", "/sources/watchers_controller.rb"].each do |path|
["0", "0885933ad4f6", "0885933ad4f68d77c2649cd11f8311276e7ef7ce"].each do |rev|
entry = @adapter.entry(path, rev)
assert_equal "sources/watchers_controller.rb", entry.path
assert_equal "file", entry.kind
assert_equal '0', entry.lastrev.revision
assert_equal '0885933ad4f68d77c2649cd11f8311276e7ef7ce', entry.lastrev.identifier
end
end
end
def test_locate_on_outdated_repository
assert_equal 1, @adapter.entries("images", 0).size
assert_equal 2, @adapter.entries("images").size
assert_equal 2, @adapter.entries("images", 2).size
end
def test_access_by_nodeid
path = 'sources/welcome_controller.rb'
assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109')
end
def test_access_by_fuzzy_nodeid
path = 'sources/welcome_controller.rb'
# falls back to nodeid
assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400')
end
def test_tags
assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags
end
def test_tagmap
tm = {
@tag_char_1 => 'adf805632193500ad3b615cd04f58f9b0769f576',
'tag_test.00' => '6987191f453a5f6557018d522feea2c450d5588d',
'tag-init-revision' => '0885933ad4f68d77c2649cd11f8311276e7ef7ce',
}
assert_equal tm, @adapter.tagmap
end
def test_branches
brs = []
@adapter.branches.each do |b|
brs << b
end
assert_equal 7, brs.length
assert_equal 'default', brs[0].to_s
assert_equal '31', brs[0].revision
assert_equal '31eeee7395c8c78e66dd54c50addd078d10b2355', brs[0].scmid
assert_equal 'test-branch-01', brs[1].to_s
assert_equal '30', brs[1].revision
assert_equal 'ad4dc4f80284a4f9168b77e0b6de288e5d207ee7', brs[1].scmid
assert_equal @branch_char_1, brs[2].to_s
assert_equal '27', brs[2].revision
assert_equal '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914', brs[2].scmid
assert_equal 'branch (1)[2]&,%.-3_4', brs[3].to_s
assert_equal '25', brs[3].revision
assert_equal 'afc61e85bde74de930e5846c8451bd55b5bafc9c', brs[3].scmid
assert_equal @branch_char_0, brs[4].to_s
assert_equal '23', brs[4].revision
assert_equal 'c8d3e4887474af6a589190140508037ebaa9d9c3', brs[4].scmid
assert_equal 'test_branch.latin-1', brs[5].to_s
assert_equal '22', brs[5].revision
assert_equal 'c2ffe7da686aa3d956e59f2a2854cf8980a8b768', brs[5].scmid
assert_equal 'test-branch-00', brs[6].to_s
assert_equal '13', brs[6].revision
assert_equal '3a330eb329586ea2adb3f83237c23310e744ebe9', brs[6].scmid
end
def test_branchmap
bm = {
'default' => '31eeee7395c8c78e66dd54c50addd078d10b2355',
'test_branch.latin-1' => 'c2ffe7da686aa3d956e59f2a2854cf8980a8b768',
'branch (1)[2]&,%.-3_4' => 'afc61e85bde74de930e5846c8451bd55b5bafc9c',
'test-branch-00' => '3a330eb329586ea2adb3f83237c23310e744ebe9',
"test-branch-01" => 'ad4dc4f80284a4f9168b77e0b6de288e5d207ee7',
@branch_char_0 => 'c8d3e4887474af6a589190140508037ebaa9d9c3',
@branch_char_1 => '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914',
}
assert_equal bm, @adapter.branchmap
end
def test_path_space
p = 'README (1)[2]&,%.-3_4'
[15, '933ca60293d7'].each do |r1|
assert @adapter.diff(p, r1)
assert @adapter.cat(p, r1)
assert_equal 1, @adapter.annotate(p, r1).lines.length
[25, 'afc61e85bde7'].each do |r2|
assert @adapter.diff(p, r1, r2)
end
end
end
def test_tag_non_ascii
p = "latin-1-dir/test-#{@char_1}-1.txt"
assert @adapter.cat(p, @tag_char_1)
assert_equal 1, @adapter.annotate(p, @tag_char_1).lines.length
end
def test_branch_non_ascii
p = "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-1.txt"
assert @adapter.cat(p, @branch_char_1)
assert_equal 1, @adapter.annotate(p, @branch_char_1).lines.length
end
def test_nodes_in_branch
[
'default',
@branch_char_1,
'branch (1)[2]&,%.-3_4',
@branch_char_0,
'test_branch.latin-1',
'test-branch-00',
].each do |bra|
nib0 = @adapter.nodes_in_branch(bra)
assert nib0
nib1 = @adapter.nodes_in_branch(bra, :limit => 1)
assert_equal 1, nib1.size
case bra
when 'branch (1)[2]&,%.-3_4'
if @adapter.class.client_version_above?([1, 6])
assert_equal 3, nib0.size
assert_equal 'afc61e85bde74de930e5846c8451bd55b5bafc9c', nib0[0]
nib2 = @adapter.nodes_in_branch(bra, :limit => 2)
assert_equal 2, nib2.size
assert_equal '933ca60293d78f7c7979dd123cc0c02431683575', nib2[1]
end
when @branch_char_1
if @adapter.class.client_version_above?([1, 6])
assert_equal 2, nib0.size
assert_equal '08ff3227303ec0dfcc818efa8e9cc652fe81859f', nib0[1]
nib2 = @adapter.nodes_in_branch(bra, :limit => 1)
assert_equal 1, nib2.size
assert_equal '7bbf4c738e7145149d2e5eb1eed1d3a8ddd3b914', nib2[0]
end
end
end
end
def test_path_encoding_default_utf8
adpt1 = Redmine::Scm::Adapters::MercurialAdapter.new(
REPOSITORY_PATH
)
assert_equal "UTF-8", adpt1.path_encoding
adpt2 = Redmine::Scm::Adapters::MercurialAdapter.new(
REPOSITORY_PATH,
nil,
nil,
nil,
""
)
assert_equal "UTF-8", adpt2.path_encoding
end
def test_bad_early_options
assert_nil @adapter.diff('sources/welcome_controller.rb',
'--config=alias.rhdiff=!xterm')
assert_raise HgCommandArgumentError do
@adapter.entries('--debugger')
end
assert_raise HgCommandAborted do
@adapter.revisions(nil, nil, nil, limit: '--repo=otherrepo')
end
assert_raise HgCommandAborted do
@adapter.nodes_in_branch('default', limit: '--repository=otherrepo')
end
assert_raise HgCommandAborted do
@adapter.nodes_in_branch('-Rotherrepo')
end
end
private
def test_hgversion_for(hgversion, version)
@adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
if version
assert_equal version, @adapter.class.hgversion
else
assert_nil @adapter.class.hgversion
end
end
def test_template_path_for(version, template)
assert_equal "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
@adapter.class.template_path_for(version)
assert File.exist?(@adapter.class.template_path_for(version))
end
else
puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end
end
end

View file

@ -0,0 +1,63 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class SubversionAdapterTest < ActiveSupport::TestCase
if repository_configured?('subversion')
def setup
@adapter = Redmine::Scm::Adapters::SubversionAdapter.new(self.class.subversion_repository_url)
end
def test_client_version
v = Redmine::Scm::Adapters::SubversionAdapter.client_version
assert v.is_a?(Array)
end
def test_scm_version
to_test = { "svn, version 1.6.13 (r1002816)\n" => [1,6,13],
"svn, versione 1.6.13 (r1002816)\n" => [1,6,13],
"1.6.1\n1.7\n1.8" => [1,6,1],
"1.6.2\r\n1.8.1\r\n1.9.1" => [1,6,2]}
to_test.each do |s, v|
test_scm_version_for(s, v)
end
end
def test_info_not_nil
assert_not_nil @adapter.info
end
def test_info_nil
adpt = Redmine::Scm::Adapters::SubversionAdapter.new(
"file:///invalid/invalid/"
)
assert_nil adpt.info
end
private
def test_scm_version_for(scm_version, version)
@adapter.class.expects(:scm_version_from_command_line).returns(scm_version)
assert_equal version, @adapter.class.svn_binary_version
end
else
puts "Subversion test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end
end
end

View file

@ -0,0 +1,37 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::SyntaxHighlighting::CodeRayTest < ActiveSupport::TestCase
def test_retrieve_supported_languages_should_return_array_of_symbols
assert_kind_of Array, Redmine::SyntaxHighlighting::CodeRay.send(:retrieve_supported_languages)
assert_kind_of Symbol, Redmine::SyntaxHighlighting::CodeRay.send(:retrieve_supported_languages).first
end
def test_retrieve_supported_languages_should_return_array_of_symbols_holding_languages
assert_includes Redmine::SyntaxHighlighting::CodeRay.send(:retrieve_supported_languages), :ruby
end
def test_retrieve_supported_languages_should_return_array_of_symbols_holding_languages_aliases
assert_includes Redmine::SyntaxHighlighting::CodeRay.send(:retrieve_supported_languages), :javascript
end
def test_retrieve_supported_languages_should_return_array_of_symbols_not_holding_internal_languages
refute_includes Redmine::SyntaxHighlighting::CodeRay.send(:retrieve_supported_languages), :default
end
end

View file

@ -0,0 +1,61 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::ThemesTest < ActiveSupport::TestCase
def test_themes
themes = Redmine::Themes.themes
assert_kind_of Array, themes
assert_kind_of Redmine::Themes::Theme, themes.first
end
def test_rescan
Redmine::Themes.themes.pop
assert_difference 'Redmine::Themes.themes.size' do
Redmine::Themes.rescan
end
end
def test_theme_loaded
theme = Redmine::Themes.themes.last
assert_equal theme, Redmine::Themes.theme(theme.id)
end
def test_theme_loaded_without_rescan
theme = Redmine::Themes.themes.last
assert_equal theme, Redmine::Themes.theme(theme.id, :rescan => false)
end
def test_theme_not_loaded
theme = Redmine::Themes.themes.pop
assert_equal theme, Redmine::Themes.theme(theme.id)
end
def test_theme_not_loaded_without_rescan
theme = Redmine::Themes.themes.pop
assert_nil Redmine::Themes.theme(theme.id, :rescan => false)
ensure
Redmine::Themes.rescan
end
end

View file

@ -0,0 +1,352 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::UnifiedDiffTest < ActiveSupport::TestCase
def test_subversion_diff
diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'))
# number of files
assert_equal 4, diff.size
assert diff.detect {|file| file.file_name =~ %r{^config/settings.yml}}
end
def test_truncate_diff
diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'), :max_lines => 20)
assert_equal 2, diff.size
end
def test_inline_partials
diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'))
assert_equal 1, diff.size
diff = diff.first
assert_equal 43, diff.size
assert_equal [51, -1], diff[0].offsets
assert_equal [51, -1], diff[1].offsets
assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line
assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[1].html_line
assert_nil diff[2].offsets
assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[2].html_line
assert_equal [0, -14], diff[3].offsets
assert_equal [0, -14], diff[4].offsets
assert_equal '<span>Ut sed</span> auctor justo', diff[3].html_line
assert_equal '<span>xxx</span> auctor justo', diff[4].html_line
assert_equal [13, -19], diff[6].offsets
assert_equal [13, -19], diff[7].offsets
assert_equal [24, -8], diff[9].offsets
assert_equal [24, -8], diff[10].offsets
assert_equal [37, -1], diff[12].offsets
assert_equal [37, -1], diff[13].offsets
assert_equal [0, -38], diff[15].offsets
assert_equal [0, -38], diff[16].offsets
end
def test_side_by_side_partials
diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'), :type => 'sbs')
assert_equal 1, diff.size
diff = diff.first
assert_equal 32, diff.size
assert_equal [51, -1], diff[0].offsets
assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line_left
assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[0].html_line_right
assert_nil diff[1].offsets
assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_left
assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_right
assert_equal [0, -14], diff[2].offsets
assert_equal '<span>Ut sed</span> auctor justo', diff[2].html_line_left
assert_equal '<span>xxx</span> auctor justo', diff[2].html_line_right
assert_equal [13, -19], diff[4].offsets
assert_equal [24, -8], diff[6].offsets
assert_equal [37, -1], diff[8].offsets
assert_equal [0, -38], diff[10].offsets
end
def test_partials_with_html_entities
raw = <<-DIFF
--- test.orig.txt Wed Feb 15 16:10:39 2012
+++ test.new.txt Wed Feb 15 16:11:25 2012
@@ -1,5 +1,5 @@
Semicolons were mysteriously appearing in code diffs in the repository
-void DoSomething(std::auto_ptr<MyClass> myObj)
+void DoSomething(const MyClass& myObj)
DIFF
diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
assert_equal 1, diff.size
assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line_left
assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[2].html_line_right
diff = Redmine::UnifiedDiff.new(raw, :type => 'inline')
assert_equal 1, diff.size
assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line
assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[3].html_line
end
def test_line_starting_with_dashes
diff = Redmine::UnifiedDiff.new(<<-DIFF
--- old.txt Wed Nov 11 14:24:58 2009
+++ new.txt Wed Nov 11 14:25:02 2009
@@ -1,8 +1,4 @@
-Lines that starts with dashes:
-
-------------------------
--- file.c
-------------------------
+A line that starts with dashes:
and removed.
@@ -23,4 +19,4 @@
-Another chunk of change
+Another chunk of changes
DIFF
)
assert_equal 1, diff.size
end
def test_one_line_new_files
diff = Redmine::UnifiedDiff.new(<<-DIFF
diff -r 000000000000 -r ea98b14f75f0 README1
--- /dev/null
+++ b/README1
@@ -0,0 +1,1 @@
+test1
diff -r 000000000000 -r ea98b14f75f0 README2
--- /dev/null
+++ b/README2
@@ -0,0 +1,1 @@
+test2
diff -r 000000000000 -r ea98b14f75f0 README3
--- /dev/null
+++ b/README3
@@ -0,0 +1,3 @@
+test4
+test5
+test6
diff -r 000000000000 -r ea98b14f75f0 README4
--- /dev/null
+++ b/README4
@@ -0,0 +1,3 @@
+test4
+test5
+test6
DIFF
)
assert_equal 4, diff.size
assert_equal "README1", diff[0].file_name
end
def test_both_git_diff
diff = Redmine::UnifiedDiff.new(<<-DIFF
# HG changeset patch
# User test
# Date 1348014182 -32400
# Node ID d1c871b8ef113df7f1c56d41e6e3bfbaff976e1f
# Parent 180b6605936cdc7909c5f08b59746ec1a7c99b3e
modify test1.txt
diff -r 180b6605936c -r d1c871b8ef11 test1.txt
--- a/test1.txt
+++ b/test1.txt
@@ -1,1 +1,1 @@
-test1
+modify test1
DIFF
)
assert_equal 1, diff.size
assert_equal "test1.txt", diff[0].file_name
end
def test_include_a_b_slash
diff = Redmine::UnifiedDiff.new(<<-DIFF
--- test1.txt
+++ b/test02.txt
@@ -1 +0,0 @@
-modify test1
DIFF
)
assert_equal 1, diff.size
assert_equal "b/test02.txt", diff[0].file_name
diff = Redmine::UnifiedDiff.new(<<-DIFF
--- a/test1.txt
+++ a/test02.txt
@@ -1 +0,0 @@
-modify test1
DIFF
)
assert_equal 1, diff.size
assert_equal "a/test02.txt", diff[0].file_name
diff = Redmine::UnifiedDiff.new(<<-DIFF
--- a/test1.txt
+++ test02.txt
@@ -1 +0,0 @@
-modify test1
DIFF
)
assert_equal 1, diff.size
assert_equal "test02.txt", diff[0].file_name
end
def test_utf8_ja
ja = " text_tip_issue_end_day: "
ja += "\xe3\x81\x93\xe3\x81\xae\xe6\x97\xa5\xe3\x81\xab\xe7\xb5\x82\xe4\xba\x86\xe3\x81\x99\xe3\x82\x8b<span>\xe3\x82\xbf\xe3\x82\xb9\xe3\x82\xaf</span>".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(read_diff_fixture('issue-12641-ja.diff'), :type => 'inline')
assert_equal 1, diff.size
assert_equal 12, diff.first.size
assert_equal ja, diff.first[4].html_line_left
end
end
def test_utf8_ru
ru = " other: &quot;\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbb\xd0\xbe %{count} \xd1\x87\xd0\xb0\xd1\x81<span>\xd0\xb0</span>&quot;".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(read_diff_fixture('issue-12641-ru.diff'), :type => 'inline')
assert_equal 1, diff.size
assert_equal 8, diff.first.size
assert_equal ru, diff.first[3].html_line_left
end
end
def test_offset_range_ascii_1
raw = <<-DIFF
--- a.txt 2013-04-05 14:19:39.000000000 +0900
+++ b.txt 2013-04-05 14:19:51.000000000 +0900
@@ -1,3 +1,3 @@
aaaa
-abc
+abcd
bbbb
DIFF
diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal "abc<span></span>", diff.first[1].html_line_left
assert_equal "abc<span>d</span>", diff.first[1].html_line_right
end
def test_offset_range_ascii_2
raw = <<-DIFF
--- a.txt 2013-04-05 14:19:39.000000000 +0900
+++ b.txt 2013-04-05 14:19:51.000000000 +0900
@@ -1,3 +1,3 @@
aaaa
-abc
+zabc
bbbb
DIFF
diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal "<span></span>abc", diff.first[1].html_line_left
assert_equal "<span>z</span>abc", diff.first[1].html_line_right
end
def test_offset_range_japanese_1
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span></span>".force_encoding('UTF-8')
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x9e</span>".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-1.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
def test_offset_range_japanese_2
ja1 = "<span></span>\xe6\x97\xa5\xe6\x9c\xac".force_encoding('UTF-8')
ja2 = "<span>\xe3\x81\xab\xe3\x81\xa3\xe3\x81\xbd\xe3\x82\x93</span>\xe6\x97\xa5\xe6\x9c\xac".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-2.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
def test_offset_range_japanese_3
# UTF-8 The 1st byte differs.
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>".force_encoding('UTF-8')
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe5\xa8\x98</span>".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-3.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
def test_offset_range_japanese_4
# UTF-8 The 2nd byte differs.
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>".force_encoding('UTF-8')
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-4.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
def test_offset_range_japanese_5
# UTF-8 The 2nd byte differs.
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>ok".force_encoding('UTF-8')
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>ok".force_encoding('UTF-8')
with_settings :repositories_encodings => '' do
diff = Redmine::UnifiedDiff.new(
read_diff_fixture('issue-13644-5.diff'), :type => 'sbs')
assert_equal 1, diff.size
assert_equal 3, diff.first.size
assert_equal ja1, diff.first[1].html_line_left
assert_equal ja2, diff.first[1].html_line_right
end
end
private
def read_diff_fixture(filename)
File.new(File.join(File.dirname(__FILE__), '/../../../fixtures/diffs', filename)).read
end
end

View file

@ -0,0 +1,76 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::Utils::DateCalculationTest < ActiveSupport::TestCase
include Redmine::Utils::DateCalculation
def test_working_days_without_non_working_week_days
with_settings :non_working_week_days => [] do
assert_working_days 18, '2012-10-09', '2012-10-27'
assert_working_days 6, '2012-10-09', '2012-10-15'
assert_working_days 5, '2012-10-09', '2012-10-14'
assert_working_days 3, '2012-10-09', '2012-10-12'
assert_working_days 3, '2012-10-14', '2012-10-17'
assert_working_days 16, '2012-10-14', '2012-10-30'
end
end
def test_working_days_with_non_working_week_days
with_settings :non_working_week_days => %w(6 7) do
assert_working_days 14, '2012-10-09', '2012-10-27'
assert_working_days 4, '2012-10-09', '2012-10-15'
assert_working_days 4, '2012-10-09', '2012-10-14'
assert_working_days 3, '2012-10-09', '2012-10-12'
assert_working_days 8, '2012-10-09', '2012-10-19'
assert_working_days 8, '2012-10-11', '2012-10-23'
assert_working_days 2, '2012-10-14', '2012-10-17'
assert_working_days 11, '2012-10-14', '2012-10-30'
end
end
def test_add_working_days_without_non_working_week_days
with_settings :non_working_week_days => [] do
assert_add_working_days '2012-10-10', '2012-10-10', 0
assert_add_working_days '2012-10-11', '2012-10-10', 1
assert_add_working_days '2012-10-12', '2012-10-10', 2
assert_add_working_days '2012-10-13', '2012-10-10', 3
assert_add_working_days '2012-10-25', '2012-10-10', 15
end
end
def test_add_working_days_with_non_working_week_days
with_settings :non_working_week_days => %w(6 7) do
assert_add_working_days '2012-10-10', '2012-10-10', 0
assert_add_working_days '2012-10-11', '2012-10-10', 1
assert_add_working_days '2012-10-12', '2012-10-10', 2
assert_add_working_days '2012-10-15', '2012-10-10', 3
assert_add_working_days '2012-10-31', '2012-10-10', 15
assert_add_working_days '2012-10-19', '2012-10-09', 8
assert_add_working_days '2012-10-23', '2012-10-11', 8
end
end
def assert_working_days(expected_days, from, to)
assert_equal expected_days, working_days(from.to_date, to.to_date)
end
def assert_add_working_days(expected_date, from, working_days)
assert_equal expected_date.to_date, add_working_days(from.to_date, working_days)
end
end

View file

@ -0,0 +1,94 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class Redmine::Views::Builders::JsonTest < ActiveSupport::TestCase
def test_hash
assert_json_output({'person' => {'name' => 'Ryan', 'age' => 32}}) do |b|
b.person do
b.name 'Ryan'
b.age 32
end
end
end
def test_hash_hash
assert_json_output({'person' => {'name' => 'Ryan', 'birth' => {'city' => 'London', 'country' => 'UK'}}}) do |b|
b.person do
b.name 'Ryan'
b.birth :city => 'London', :country => 'UK'
end
end
assert_json_output({'person' => {'id' => 1, 'name' => 'Ryan', 'birth' => {'city' => 'London', 'country' => 'UK'}}}) do |b|
b.person :id => 1 do
b.name 'Ryan'
b.birth :city => 'London', :country => 'UK'
end
end
end
def test_array
assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
b.array :books do |b|
b.book :title => 'Book 1', :author => 'B. Smith'
b.book :title => 'Book 2', :author => 'G. Cooper'
end
end
assert_json_output({'books' => [{'title' => 'Book 1', 'author' => 'B. Smith'}, {'title' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
b.array :books do |b|
b.book :title => 'Book 1' do
b.author 'B. Smith'
end
b.book :title => 'Book 2' do
b.author 'G. Cooper'
end
end
end
end
def test_array_with_content_tags
assert_json_output({'books' => [{'value' => 'Book 1', 'author' => 'B. Smith'}, {'value' => 'Book 2', 'author' => 'G. Cooper'}]}) do |b|
b.array :books do |b|
b.book 'Book 1', :author => 'B. Smith'
b.book 'Book 2', :author => 'G. Cooper'
end
end
end
def test_nested_arrays
assert_json_output({'books' => [{'authors' => ['B. Smith', 'G. Cooper']}]}) do |b|
b.array :books do |books|
books.book do |book|
book.array :authors do |authors|
authors.author 'B. Smith'
authors.author 'G. Cooper'
end
end
end
end
end
def assert_json_output(expected, &block)
builder = Redmine::Views::Builders::Json.new(ActionDispatch::TestRequest.new, ActionDispatch::TestResponse.new)
block.call(builder)
assert_equal(expected, ActiveSupport::JSON.decode(builder.output))
end
end

View file

@ -0,0 +1,67 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../../test_helper', __FILE__)
class Redmine::Views::Builders::XmlTest < ActiveSupport::TestCase
def test_hash
assert_xml_output('<person><name>Ryan</name><age>32</age></person>') do |b|
b.person do
b.name 'Ryan'
b.age 32
end
end
end
def test_array
assert_xml_output('<books type="array"><book title="Book 1"/><book title="Book 2"/></books>') do |b|
b.array :books do |b|
b.book :title => 'Book 1'
b.book :title => 'Book 2'
end
end
end
def test_array_with_content_tags
assert_xml_output('<books type="array"><book author="B. Smith">Book 1</book><book author="G. Cooper">Book 2</book></books>') do |b|
b.array :books do |b|
b.book 'Book 1', :author => 'B. Smith'
b.book 'Book 2', :author => 'G. Cooper'
end
end
end
def test_nested_arrays
assert_xml_output('<books type="array"><book><authors type="array"><author>B. Smith</author><author>G. Cooper</author></authors></book></books>') do |b|
b.array :books do |books|
books.book do |book|
book.array :authors do |authors|
authors.author 'B. Smith'
authors.author 'G. Cooper'
end
end
end
end
end
def assert_xml_output(expected, &block)
builder = Redmine::Views::Builders::Xml.new(ActionDispatch::TestRequest.new, ActionDispatch::TestResponse.new)
block.call(builder)
assert_equal('<?xml version="1.0" encoding="UTF-8"?>' + expected, builder.output)
end
end

View file

@ -0,0 +1,48 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::Views::LabelledFormBuilderTest < Redmine::HelperTest
include Rails.application.routes.url_helpers
def test_label_should_output_one_element
set_language_if_valid 'en'
labelled_form_for(Issue.new) do |f|
output = f.label :subject
assert_equal output, '<label for="issue_subject">Subject</label>'
end
end
def test_hours_field_should_display_formatted_value_if_valid
entry = TimeEntry.new(:hours => '2.5')
entry.validate
labelled_form_for(entry) do |f|
assert_include 'value="2.50"', f.hours_field(:hours)
end
end
def test_hours_field_should_display_entered_value_if_invalid
entry = TimeEntry.new(:hours => '2.z')
entry.validate
labelled_form_for(entry) do |f|
assert_include 'value="2.z"', f.hours_field(:hours)
end
end
end

View file

@ -0,0 +1,35 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::WikiFormatting::HtmlParserTest < ActiveSupport::TestCase
def setup
@parser = Redmine::WikiFormatting::HtmlParser
end
def test_convert_line_breaks
assert_equal "A html snippet with\na new line.",
@parser.to_text('<p>A html snippet with<br>a new line.</p>')
end
def test_should_remove_style_tags_from_body
assert_equal "Text",
@parser.to_text('<html><body><style>body {font-size: 0.8em;}</style>Text</body></html>')
end
end

View file

@ -0,0 +1,404 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::WikiFormatting::MacrosTest < Redmine::HelperTest
include ApplicationHelper
include ActionView::Helpers::TextHelper
include ActionView::Helpers::SanitizeHelper
include ERB::Util
include Rails.application.routes.url_helpers
extend ActionView::Helpers::SanitizeHelper::ClassMethods
fixtures :projects, :roles, :enabled_modules, :users,
:repositories, :changesets,
:trackers, :issue_statuses, :issues,
:versions, :documents,
:wikis, :wiki_pages, :wiki_contents,
:boards, :messages,
:attachments
def setup
super
@project = nil
end
def teardown
end
def test_macro_registration
Redmine::WikiFormatting::Macros.register do
macro :foo do |obj, args|
"Foo: #{args.size} (#{args.join(',')}) (#{args.class.name})"
end
end
assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo}}")
assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo()}}")
assert_equal '<p>Foo: 1 (arg1) (Array)</p>', textilizable("{{foo(arg1)}}")
assert_equal '<p>Foo: 2 (arg1,arg2) (Array)</p>', textilizable("{{foo(arg1, arg2)}}")
end
def test_macro_registration_parse_args_set_to_false_should_disable_arguments_parsing
Redmine::WikiFormatting::Macros.register do
macro :bar, :parse_args => false do |obj, args|
"Bar: (#{args}) (#{args.class.name})"
end
end
assert_equal '<p>Bar: (args, more args) (String)</p>', textilizable("{{bar(args, more args)}}")
assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar}}")
assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar()}}")
end
def test_macro_registration_with_3_args_should_receive_text_argument
Redmine::WikiFormatting::Macros.register do
macro :baz do |obj, args, text|
"Baz: (#{args.join(',')}) (#{text.class.name}) (#{text})"
end
end
assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz}}")
assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz()}}")
assert_equal "<p>Baz: () (String) (line1\nline2)</p>", textilizable("{{baz()\nline1\nline2\n}}")
assert_equal "<p>Baz: (arg1,arg2) (String) (line1\nline2)</p>", textilizable("{{baz(arg1, arg2)\nline1\nline2\n}}")
end
def test_macro_name_with_upper_case
Redmine::WikiFormatting::Macros.macro(:UpperCase) {|obj, args| "Upper"}
assert_equal "<p>Upper</p>", textilizable("{{UpperCase}}")
end
def test_multiple_macros_on_the_same_line
Redmine::WikiFormatting::Macros.macro :foo do |obj, args|
args.any? ? "args: #{args.join(',')}" : "no args"
end
assert_equal '<p>no args no args</p>', textilizable("{{foo}} {{foo}}")
assert_equal '<p>args: a,b no args</p>', textilizable("{{foo(a,b)}} {{foo}}")
assert_equal '<p>args: a,b args: c,d</p>', textilizable("{{foo(a,b)}} {{foo(c,d)}}")
assert_equal '<p>no args args: c,d</p>', textilizable("{{foo}} {{foo(c,d)}}")
end
def test_macro_should_receive_the_object_as_argument_when_with_object_and_attribute
issue = Issue.find(1)
issue.description = "{{hello_world}}"
assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(issue, :description)
end
def test_macro_should_receive_the_object_as_argument_when_called_with_object_option
text = "{{hello_world}}"
assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(text, :object => Issue.find(1))
end
def test_extract_macro_options_should_with_args
options = extract_macro_options(["arg1", "arg2"], :foo, :size)
assert_equal([["arg1", "arg2"], {}], options)
end
def test_extract_macro_options_should_with_options
options = extract_macro_options(["foo=bar", "size=2"], :foo, :size)
assert_equal([[], {:foo => "bar", :size => "2"}], options)
end
def test_extract_macro_options_should_with_args_and_options
options = extract_macro_options(["arg1", "arg2", "foo=bar", "size=2"], :foo, :size)
assert_equal([["arg1", "arg2"], {:foo => "bar", :size => "2"}], options)
end
def test_extract_macro_options_should_parse_options_lazily
options = extract_macro_options(["params=x=1&y=2"], :params)
assert_equal([[], {:params => "x=1&y=2"}], options)
end
def test_macro_exception_should_be_displayed
Redmine::WikiFormatting::Macros.macro :exception do |obj, args|
raise "My message"
end
text = "{{exception}}"
assert_include '<div class="flash error">Error executing the <strong>exception</strong> macro (My message)</div>', textilizable(text)
end
def test_macro_arguments_should_not_be_parsed_by_formatters
text = '{{hello_world(http://www.redmine.org, #1)}}'
assert_include 'Arguments: http://www.redmine.org, #1', textilizable(text)
end
def test_exclamation_mark_should_not_run_macros
text = "!{{hello_world}}"
assert_equal '<p>{{hello_world}}</p>', textilizable(text)
end
def test_exclamation_mark_should_escape_macros
text = "!{{hello_world(<tag>)}}"
assert_equal '<p>{{hello_world(&lt;tag&gt;)}}</p>', textilizable(text)
end
def test_unknown_macros_should_not_be_replaced
text = "{{unknown}}"
assert_equal '<p>{{unknown}}</p>', textilizable(text)
end
def test_unknown_macros_should_parsed_as_text
text = "{{unknown(*test*)}}"
assert_equal '<p>{{unknown(<strong>test</strong>)}}</p>', textilizable(text)
end
def test_unknown_macros_should_be_escaped
text = "{{unknown(<tag>)}}"
assert_equal '<p>{{unknown(&lt;tag&gt;)}}</p>', textilizable(text)
end
def test_html_safe_macro_output_should_not_be_escaped
Redmine::WikiFormatting::Macros.macro :safe_macro do |obj, args|
"<tag>".html_safe
end
assert_equal '<p><tag></p>', textilizable("{{safe_macro}}")
end
def test_macro_hello_world
text = "{{hello_world}}"
assert textilizable(text).match(/Hello world!/)
end
def test_macro_hello_world_should_escape_arguments
text = "{{hello_world(<tag>)}}"
assert_include 'Arguments: &lt;tag&gt;', textilizable(text)
end
def test_macro_macro_list
text = "{{macro_list}}"
assert_match %r{<code>hello_world</code>}, textilizable(text)
end
def test_macro_include
@project = Project.find(1)
# include a page of the current project wiki
text = "{{include(Another page)}}"
assert_include 'This is a link to a ticket', textilizable(text)
@project = nil
# include a page of a specific project wiki
text = "{{include(ecookbook:Another page)}}"
assert_include 'This is a link to a ticket', textilizable(text)
text = "{{include(ecookbook:)}}"
assert_include 'CookBook documentation', textilizable(text)
text = "{{include(unknowidentifier:somepage)}}"
assert_include 'Page not found', textilizable(text)
end
def test_macro_collapse
text = "{{collapse\n*Collapsed* block of text\n}}"
with_locale 'en' do
result = textilizable(text)
assert_select_in result, 'div.collapsed-text'
assert_select_in result, 'strong', :text => 'Collapsed'
assert_select_in result, 'a.collapsible.collapsed', :text => 'Show'
assert_select_in result, 'a.collapsible', :text => 'Hide'
end
end
def test_macro_collapse_with_one_arg
text = "{{collapse(Example)\n*Collapsed* block of text\n}}"
result = textilizable(text)
assert_select_in result, 'div.collapsed-text'
assert_select_in result, 'strong', :text => 'Collapsed'
assert_select_in result, 'a.collapsible.collapsed', :text => 'Example'
assert_select_in result, 'a.collapsible', :text => 'Example'
end
def test_macro_collapse_with_two_args
text = "{{collapse(Show example, Hide example)\n*Collapsed* block of text\n}}"
result = textilizable(text)
assert_select_in result, 'div.collapsed-text'
assert_select_in result, 'strong', :text => 'Collapsed'
assert_select_in result, 'a.collapsible.collapsed', :text => 'Show example'
assert_select_in result, 'a.collapsible', :text => 'Hide example'
end
def test_macro_collapse_should_not_break_toc
set_language_if_valid 'en'
text = <<-RAW
{{toc}}
h1. Title
{{collapse(Show example, Hide example)
h2. Heading
}}"
RAW
expected_toc = '<ul class="toc"><li><strong>Table of contents</strong></li><li><a href="#Title">Title</a><ul><li><a href="#Heading">Heading</a></li></ul></li></ul>'
assert_include expected_toc, textilizable(text).gsub(/[\r\n]/, '')
end
def test_macro_child_pages
expected = "<p><ul class=\"pages-hierarchy\">\n" +
"<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
"<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
"<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
"</ul>\n</p>"
@project = Project.find(1)
# child pages of the current wiki page
assert_equal expected, textilizable("{{child_pages}}", :object => WikiPage.find(2).content)
# child pages of another page
assert_equal expected, textilizable("{{child_pages(Another_page)}}", :object => WikiPage.find(1).content)
@project = Project.find(2)
assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page)}}", :object => WikiPage.find(1).content)
end
def test_macro_child_pages_with_parent_option
expected = "<p><ul class=\"pages-hierarchy\">\n" +
"<li><a href=\"/projects/ecookbook/wiki/Another_page\">Another page</a>\n" +
"<ul class=\"pages-hierarchy\">\n" +
"<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
"<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
"<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
"</ul>\n</li>\n</ul>\n</p>"
@project = Project.find(1)
# child pages of the current wiki page
assert_equal expected, textilizable("{{child_pages(parent=1)}}", :object => WikiPage.find(2).content)
# child pages of another page
assert_equal expected, textilizable("{{child_pages(Another_page, parent=1)}}", :object => WikiPage.find(1).content)
@project = Project.find(2)
assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page, parent=1)}}", :object => WikiPage.find(1).content)
end
def test_macro_child_pages_with_depth_option
expected = "<p><ul class=\"pages-hierarchy\">\n" +
"<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a></li>\n" +
"<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
"</ul>\n</p>"
@project = Project.find(1)
assert_equal expected, textilizable("{{child_pages(depth=1)}}", :object => WikiPage.find(2).content)
end
def test_macro_child_pages_without_wiki_page_should_fail
assert_match /can be called from wiki pages only/, textilizable("{{child_pages}}")
end
def test_macro_thumbnail
link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17" />'.html_safe,
"/attachments/17",
:class => "thumbnail",
:title => "testfile.PNG")
assert_equal "<p>#{link}</p>",
textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14))
end
def test_macro_thumbnail_with_full_path
link = link_to('<img alt="testfile.PNG" src="http://test.host/attachments/thumbnail/17" />'.html_safe,
"http://test.host/attachments/17",
:class => "thumbnail",
:title => "testfile.PNG")
assert_equal "<p>#{link}</p>",
textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14), :only_path => false)
end
def test_macro_thumbnail_with_size
link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17/200" />'.html_safe,
"/attachments/17",
:class => "thumbnail",
:title => "testfile.PNG")
assert_equal "<p>#{link}</p>",
textilizable("{{thumbnail(testfile.png, size=200)}}", :object => Issue.find(14))
end
def test_macro_thumbnail_with_title
link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17" />'.html_safe,
"/attachments/17",
:class => "thumbnail",
:title => "Cool image")
assert_equal "<p>#{link}</p>",
textilizable("{{thumbnail(testfile.png, title=Cool image)}}", :object => Issue.find(14))
end
def test_macro_thumbnail_with_invalid_filename_should_fail
assert_include 'test.png not found',
textilizable("{{thumbnail(test.png)}}", :object => Issue.find(14))
end
def test_macros_should_not_be_executed_in_pre_tags
text = <<-RAW
{{hello_world(foo)}}
<pre>
{{hello_world(pre)}}
!{{hello_world(pre)}}
</pre>
{{hello_world(bar)}}
RAW
expected = <<-EXPECTED
<p>Hello world! Object: NilClass, Arguments: foo and no block of text.</p>
<pre>
{{hello_world(pre)}}
!{{hello_world(pre)}}
</pre>
<p>Hello world! Object: NilClass, Arguments: bar and no block of text.</p>
EXPECTED
assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
end
def test_macros_should_be_escaped_in_pre_tags
text = "<pre>{{hello_world(<tag>)}}</pre>"
assert_equal "<pre>{{hello_world(&lt;tag&gt;)}}</pre>", textilizable(text)
end
def test_macros_should_not_mangle_next_macros_outputs
text = '{{macro(2)}} !{{macro(2)}} {{hello_world(foo)}}'
assert_equal '<p>{{macro(2)}} {{macro(2)}} Hello world! Object: NilClass, Arguments: foo and no block of text.</p>', textilizable(text)
end
def test_macros_with_text_should_not_mangle_following_macros
text = <<-RAW
{{hello_world
Line of text
}}
{{hello_world
Another line of text
}}
RAW
expected = <<-EXPECTED
<p>Hello world! Object: NilClass, Called with no argument and a 12 bytes long block of text.</p>
<p>Hello world! Object: NilClass, Called with no argument and a 20 bytes long block of text.</p>
EXPECTED
assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
end
end

View file

@ -0,0 +1,93 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::WikiFormatting::MarkdownFormatterTest < ActionView::TestCase
if Object.const_defined?(:Redcarpet)
def setup
@formatter = Redmine::WikiFormatting::Markdown::Formatter
end
def test_syntax_error_in_image_reference_should_not_raise_exception
assert @formatter.new("!>[](foo.png)").to_html
end
def test_empty_image_should_not_raise_exception
assert @formatter.new("![]()").to_html
end
# re-using the formatter after getting above error crashes the
# ruby interpreter. This seems to be related to
# https://github.com/vmg/redcarpet/issues/318
def test_should_not_crash_redcarpet_after_syntax_error
@formatter.new("!>[](foo.png)").to_html rescue nil
assert @formatter.new("![](foo.png)").to_html.present?
end
def test_inline_style
assert_equal "<p><strong>foo</strong></p>", @formatter.new("**foo**").to_html.strip
end
def test_not_set_intra_emphasis
assert_equal "<p>foo_bar_baz</p>", @formatter.new("foo_bar_baz").to_html.strip
end
def test_wiki_links_should_be_preserved
text = 'This is a wiki link: [[Foo]]'
assert_include '[[Foo]]', @formatter.new(text).to_html
end
def test_redmine_links_with_double_quotes_should_be_preserved
text = 'This is a redmine link: version:"1.0"'
assert_include 'version:"1.0"', @formatter.new(text).to_html
end
def test_should_support_syntax_highligth
text = <<-STR
~~~ruby
def foo
end
~~~
STR
assert_select_in @formatter.new(text).to_html, 'pre code.ruby.syntaxhl' do
assert_select 'span.keyword', :text => 'def'
end
end
def test_should_not_allow_invalid_language_for_code_blocks
text = <<-STR
~~~foo
test
~~~
STR
assert_equal "<pre>test\n</pre>", @formatter.new(text).to_html
end
def test_external_links_should_have_external_css_class
text = 'This is a [link](http://example.net/)'
assert_equal '<p>This is a <a href="http://example.net/" class="external">link</a></p>', @formatter.new(text).to_html.strip
end
def test_locals_links_should_not_have_external_css_class
text = 'This is a [link](/issues)'
assert_equal '<p>This is a <a href="/issues">link</a></p>', @formatter.new(text).to_html.strip
end
end
end

View file

@ -0,0 +1,30 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::WikiFormatting::MarkdownHtmlParserTest < ActiveSupport::TestCase
def setup
@parser = Redmine::WikiFormatting::Markdown::HtmlParser
end
def test_should_convert_tags
assert_equal 'A **simple** html snippet.',
@parser.to_text('<p>A <b>simple</b> html snippet.</p>')
end
end

View file

@ -0,0 +1,600 @@
#encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'digest/md5'
class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
def setup
@formatter = Redmine::WikiFormatting::Textile::Formatter
end
MODIFIERS = {
"*" => 'strong', # bold
"_" => 'em', # italic
"+" => 'ins', # underline
"-" => 'del', # deleted
"^" => 'sup', # superscript
"~" => 'sub' # subscript
}
def test_modifiers
assert_html_output(
'*bold*' => '<strong>bold</strong>',
'before *bold*' => 'before <strong>bold</strong>',
'*bold* after' => '<strong>bold</strong> after',
'*two words*' => '<strong>two words</strong>',
'*two*words*' => '<strong>two*words</strong>',
'*two * words*' => '<strong>two * words</strong>',
'*two* *words*' => '<strong>two</strong> <strong>words</strong>',
'*(two)* *(words)*' => '<strong>(two)</strong> <strong>(words)</strong>'
)
end
def test_modifiers_combination
MODIFIERS.each do |m1, tag1|
MODIFIERS.each do |m2, tag2|
next if m1 == m2
text = "#{m2}#{m1}Phrase modifiers#{m1}#{m2}"
html = "<#{tag2}><#{tag1}>Phrase modifiers</#{tag1}></#{tag2}>"
assert_html_output text => html
end
end
end
def test_modifier_should_work_with_one_non_ascii_character
assert_html_output "*Ä*" => "<strong>Ä</strong>"
end
def test_styles
# single style
assert_html_output({
'p{color:red}. text' => '<p style="color:red;">text</p>',
'p{color:red;}. text' => '<p style="color:red;">text</p>',
'p{color: red}. text' => '<p style="color: red;">text</p>',
'p{color:#f00}. text' => '<p style="color:#f00;">text</p>',
'p{color:#ff0000}. text' => '<p style="color:#ff0000;">text</p>',
'p{border:10px}. text' => '<p style="border:10px;">text</p>',
'p{border:10}. text' => '<p style="border:10;">text</p>',
'p{border:10%}. text' => '<p style="border:10%;">text</p>',
'p{border:10em}. text' => '<p style="border:10em;">text</p>',
'p{border:1.5em}. text' => '<p style="border:1.5em;">text</p>',
'p{border-left:1px}. text' => '<p style="border-left:1px;">text</p>',
'p{border-right:1px}. text' => '<p style="border-right:1px;">text</p>',
'p{border-top:1px}. text' => '<p style="border-top:1px;">text</p>',
'p{border-bottom:1px}. text' => '<p style="border-bottom:1px;">text</p>',
}, false)
# multiple styles
assert_html_output({
'p{color:red; border-top:1px}. text' => '<p style="color:red;border-top:1px;">text</p>',
'p{color:red ; border-top:1px}. text' => '<p style="color:red;border-top:1px;">text</p>',
'p{color:red;border-top:1px}. text' => '<p style="color:red;border-top:1px;">text</p>',
}, false)
# styles with multiple values
assert_html_output({
'p{border:1px solid red;}. text' => '<p style="border:1px solid red;">text</p>',
'p{border-top-left-radius: 10px 5px;}. text' => '<p style="border-top-left-radius: 10px 5px;">text</p>',
}, false)
end
def test_invalid_styles_should_be_filtered
assert_html_output({
'p{invalid}. text' => '<p>text</p>',
'p{invalid:red}. text' => '<p>text</p>',
'p{color:(red)}. text' => '<p>text</p>',
'p{color:red;invalid:blue}. text' => '<p style="color:red;">text</p>',
'p{invalid:blue;color:red}. text' => '<p style="color:red;">text</p>',
'p{color:"}. text' => '<p>p{color:"}. text</p>',
}, false)
end
def test_inline_code
assert_html_output(
'this is @some code@' => 'this is <code>some code</code>',
'@<Location /redmine>@' => '<code>&lt;Location /redmine&gt;</code>'
)
end
def test_lang_attribute
assert_html_output(
'*[fr]French*' => '<strong lang="fr">French</strong>',
'*[fr-fr]French*' => '<strong lang="fr-fr">French</strong>',
'*[fr_fr]French*' => '<strong lang="fr_fr">French</strong>'
)
end
def test_lang_attribute_should_ignore_invalid_value
assert_html_output(
'*[fr3]French*' => '<strong>[fr3]French</strong>'
)
end
def test_nested_lists
raw = <<-RAW
# Item 1
# Item 2
** Item 2a
** Item 2b
# Item 3
** Item 3a
RAW
expected = <<-EXPECTED
<ol>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Item 2a</li>
<li>Item 2b</li>
</ul>
</li>
<li>Item 3
<ul>
<li>Item 3a</li>
</ul>
</li>
</ol>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_escaping
assert_html_output(
'this is a <script>' => 'this is a &lt;script&gt;'
)
end
def test_kbd
assert_html_output({
'<kbd>test</kbd>' => '<kbd>test</kbd>'
}, false)
end
def test_use_of_backslashes_followed_by_numbers_in_headers
assert_html_output({
'h1. 2009\02\09' => '<h1>2009\02\09</h1>'
}, false)
end
def test_double_dashes_should_not_strikethrough
assert_html_output(
'double -- dashes -- test' => 'double -- dashes -- test',
'double -- *dashes* -- test' => 'double -- <strong>dashes</strong> -- test'
)
end
def test_abbreviations
assert_html_output(
'this is an abbreviation: GPL(General Public License)' => 'this is an abbreviation: <abbr title="General Public License">GPL</abbr>',
'2 letters JP(Jean-Philippe) abbreviation' => '2 letters <abbr title="Jean-Philippe">JP</abbr> abbreviation',
'GPL(This is a double-quoted "title")' => '<abbr title="This is a double-quoted &quot;title&quot;">GPL</abbr>'
)
end
def test_blockquote
# orig raw text
raw = <<-RAW
John said:
> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
> Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
> * Donec odio lorem,
> * sagittis ac,
> * malesuada in,
> * adipiscing eu, dolor.
>
> >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
> Proin a tellus. Nam vel neque.
He's right.
RAW
# expected html
expected = <<-EXPECTED
<p>John said:</p>
<blockquote>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.<br />
Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
<ul>
<li>Donec odio lorem,</li>
<li>sagittis ac,</li>
<li>malesuada in,</li>
<li>adipiscing eu, dolor.</li>
</ul>
<blockquote>
<p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
</blockquote>
<p>Proin a tellus. Nam vel neque.</p>
</blockquote>
<p>He's right.</p>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_table
raw = <<-RAW
This is a table with empty cells:
|cell11|cell12||
|cell21||cell23|
|cell31|cell32|cell33|
RAW
expected = <<-EXPECTED
<p>This is a table with empty cells:</p>
<table>
<tr><td>cell11</td><td>cell12</td><td></td></tr>
<tr><td>cell21</td><td></td><td>cell23</td></tr>
<tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
</table>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_table_with_alignment
raw = <<-RAW
|>. right|
|<. left|
|<>. justify|
RAW
expected = <<-EXPECTED
<table>
<tr><td style="text-align:right;">right</td></tr>
<tr><td style="text-align:left;">left</td></tr>
<tr><td style="text-align:justify;">justify</td></tr>
</table>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_table_with_trailing_whitespace
raw = <<-RAW
This is a table with trailing whitespace in one row:
|cell11|cell12|
|cell21|cell22|
|cell31|cell32|
RAW
expected = <<-EXPECTED
<p>This is a table with trailing whitespace in one row:</p>
<table>
<tr><td>cell11</td><td>cell12</td></tr>
<tr><td>cell21</td><td>cell22</td></tr>
<tr><td>cell31</td><td>cell32</td></tr>
</table>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_table_with_line_breaks
raw = <<-RAW
This is a table with line breaks:
|cell11
continued|cell12||
|-cell21-||cell23
cell23 line2
cell23 *line3*|
|cell31|cell32
cell32 line2|cell33|
RAW
expected = <<-EXPECTED
<p>This is a table with line breaks:</p>
<table>
<tr>
<td>cell11<br />continued</td>
<td>cell12</td>
<td></td>
</tr>
<tr>
<td><del>cell21</del></td>
<td></td>
<td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
</tr>
<tr>
<td>cell31</td>
<td>cell32<br/>cell32 line2</td>
<td>cell33</td>
</tr>
</table>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_tables_with_lists
raw = <<-RAW
This is a table with lists:
|cell11|cell12|
|cell21|ordered list
# item
# item 2|
|cell31|unordered list
* item
* item 2|
RAW
expected = <<-EXPECTED
<p>This is a table with lists:</p>
<table>
<tr>
<td>cell11</td>
<td>cell12</td>
</tr>
<tr>
<td>cell21</td>
<td>ordered list<br /># item<br /># item 2</td>
</tr>
<tr>
<td>cell31</td>
<td>unordered list<br />* item<br />* item 2</td>
</tr>
</table>
EXPECTED
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
def test_textile_should_not_mangle_brackets
assert_equal '<p>[msg1][msg2]</p>', to_html('[msg1][msg2]')
end
def test_textile_should_escape_image_urls
# this is onclick="alert('XSS');" in encoded form
raw = '!/images/comment.png"onclick=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;;&#x22;!'
expected = '<p><img src="/images/comment.png&quot;onclick=&amp;#x61;&amp;#x6c;&amp;#x65;&amp;#x72;&amp;#x74;&amp;#x28;&amp;#x27;&amp;#x58;&amp;#x53;&amp;#x53;&amp;#x27;&amp;#x29;;&amp;#x22;" alt="" /></p>'
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
STR_WITHOUT_PRE = [
# 0
"h1. Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
# 1
"h2. Heading 2
Maecenas sed elit sit amet mi accumsan vestibulum non nec velit. Proin porta tincidunt lorem, consequat rhoncus dolor fermentum in.
Cras ipsum felis, ultrices at porttitor vel, faucibus eu nunc.",
# 2
"h2. Heading 2
Morbi facilisis accumsan orci non pharetra.
h3. Heading 3
Nulla nunc nisi, egestas in ornare vel, posuere ac libero.",
# 3
"h3. Heading 3
Praesent eget turpis nibh, a lacinia nulla.",
# 4
"h2. Heading 2
Ut rhoncus elementum adipiscing."]
TEXT_WITHOUT_PRE = STR_WITHOUT_PRE.join("\n\n").freeze
def test_get_section_should_return_the_requested_section_and_its_hash
assert_section_with_hash STR_WITHOUT_PRE[1], TEXT_WITHOUT_PRE, 2
assert_section_with_hash STR_WITHOUT_PRE[2..3].join("\n\n"), TEXT_WITHOUT_PRE, 3
assert_section_with_hash STR_WITHOUT_PRE[3], TEXT_WITHOUT_PRE, 5
assert_section_with_hash STR_WITHOUT_PRE[4], TEXT_WITHOUT_PRE, 6
assert_section_with_hash '', TEXT_WITHOUT_PRE, 0
assert_section_with_hash '', TEXT_WITHOUT_PRE, 10
end
def test_update_section_should_update_the_requested_section
replacement = "New text"
assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
assert_equal [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
assert_equal [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
assert_equal [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(10, replacement)
end
def test_update_section_with_hash_should_update_the_requested_section
replacement = "New text"
assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1]))
end
def test_update_section_with_wrong_hash_should_raise_an_error
assert_raise Redmine::WikiFormatting::StaleSectionError do
@formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text"))
end
end
STR_WITH_PRE = [
# 0
"h1. Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
# 1
"h2. Heading 2
<pre><code class=\"ruby\">
def foo
end
</code></pre>
<pre><code><pre><code class=\"ruby\">
Place your code here.
</code></pre>
</code></pre>
Morbi facilisis accumsan orci non pharetra.
<pre>
Pre Content:
h2. Inside pre
<tag> inside pre block
Morbi facilisis accumsan orci non pharetra.
</pre>",
# 2
"h3. Heading 3
Nulla nunc nisi, egestas in ornare vel, posuere ac libero."]
def test_get_section_should_ignore_pre_content
text = STR_WITH_PRE.join("\n\n")
assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
assert_section_with_hash STR_WITH_PRE[2], text, 3
end
def test_update_section_should_not_escape_pre_content_outside_section
text = STR_WITH_PRE.join("\n\n")
replacement = "New text"
assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
@formatter.new(text).update_section(3, replacement)
end
def test_get_section_should_support_lines_with_spaces_before_heading
# the lines after Content 2 and Heading 4 contain a space
text = <<-STR
h1. Heading 1
Content 1
h1. Heading 2
Content 2
h1. Heading 3
Content 3
h1. Heading 4
Content 4
STR
[1, 2, 3, 4].each do |index|
assert_match /\Ah1. Heading #{index}.+Content #{index}/m, @formatter.new(text).get_section(index).first
end
end
def test_get_section_should_support_headings_starting_with_a_tab
text = <<-STR
h1.\tHeading 1
Content 1
h1. Heading 2
Content 2
STR
assert_match /\Ah1.\tHeading 1\s+Content 1\z/, @formatter.new(text).get_section(1).first
end
def test_should_not_allow_arbitrary_class_attribute_on_offtags
%w(code pre kbd).each do |tag|
assert_html_output({"<#{tag} class=\"foo\">test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
end
assert_html_output({"<notextile class=\"foo\">test</notextile>" => "test"}, false)
end
def test_should_allow_valid_language_class_attribute_on_code_tags
assert_html_output({"<code class=\"ruby\">test</code>" => "<code class=\"ruby syntaxhl\"><span class=\"CodeRay\">test</span></code>"}, false)
end
def test_should_not_allow_valid_language_class_attribute_on_non_code_offtags
%w(pre kbd).each do |tag|
assert_html_output({"<#{tag} class=\"ruby\">test</#{tag}>" => "<#{tag}>test</#{tag}>"}, false)
end
assert_html_output({"<notextile class=\"ruby\">test</notextile>" => "test"}, false)
end
def test_should_prefix_class_attribute_on_tags
assert_html_output({
'!(foo)test.png!' => "<p><img src=\"test.png\" class=\"wiki-class-foo\" alt=\"\" /></p>",
'%(foo)test%' => "<p><span class=\"wiki-class-foo\">test</span></p>",
'p(foo). test' => "<p class=\"wiki-class-foo\">test</p>",
'|(foo). test|' => "<table>\n\t\t<tr>\n\t\t\t<td class=\"wiki-class-foo\">test</td>\n\t\t</tr>\n\t</table>",
}, false)
end
def test_should_prefix_id_attribute_on_tags
assert_html_output({
'!(#foo)test.png!' => "<p><img src=\"test.png\" id=\"wiki-id-foo\" alt=\"\" /></p>",
'%(#foo)test%' => "<p><span id=\"wiki-id-foo\">test</span></p>",
'p(#foo). test' => "<p id=\"wiki-id-foo\">test</p>",
'|(#foo). test|' => "<table>\n\t\t<tr>\n\t\t\t<td id=\"wiki-id-foo\">test</td>\n\t\t</tr>\n\t</table>",
}, false)
end
def test_should_not_prefix_class_and_id_attributes_already_prefixed
assert_html_output({
'!(wiki-class-foo#wiki-id-bar)test.png!' => "<p><img src=\"test.png\" class=\"wiki-class-foo\" id=\"wiki-id-bar\" alt=\"\" /></p>",
}, false)
end
private
def assert_html_output(to_test, expect_paragraph = true)
to_test.each do |text, expected|
assert_equal(( expect_paragraph ? "<p>#{expected}</p>" : expected ), @formatter.new(text).to_html, "Formatting the following text failed:\n===\n#{text}\n===\n")
end
end
def to_html(text)
@formatter.new(text).to_html
end
def assert_section_with_hash(expected, text, index)
result = @formatter.new(text).get_section(index)
assert_kind_of Array, result
assert_equal 2, result.size
assert_equal expected, result.first, "section content did not match"
assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match"
end
end

View file

@ -0,0 +1,30 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../../test_helper', __FILE__)
class Redmine::WikiFormatting::TextileHtmlParserTest < ActiveSupport::TestCase
def setup
@parser = Redmine::WikiFormatting::Textile::HtmlParser
end
def test_should_convert_tags
assert_equal 'A *simple* html snippet.',
@parser.to_text('<p>A <b>simple</b> html snippet.</p>')
end
end

View file

@ -0,0 +1,83 @@
# Redmine - project management software
# Copyright (C) 2006-2017 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.
require File.expand_path('../../../../test_helper', __FILE__)
class Redmine::WikiFormattingTest < ActiveSupport::TestCase
fixtures :issues
def test_textile_formatter
assert_equal Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting.formatter_for('textile')
assert_equal Redmine::WikiFormatting::Textile::Helper, Redmine::WikiFormatting.helper_for('textile')
end
def test_null_formatter
assert_equal Redmine::WikiFormatting::NullFormatter::Formatter, Redmine::WikiFormatting.formatter_for('')
assert_equal Redmine::WikiFormatting::NullFormatter::Helper, Redmine::WikiFormatting.helper_for('')
end
def test_formats_for_select
assert_include ['Textile', 'textile'], Redmine::WikiFormatting.formats_for_select
end
def test_should_link_urls_and_email_addresses
raw = <<-DIFF
This is a sample *text* with a link: http://www.redmine.org
and an email address foo@example.net
DIFF
expected = <<-EXPECTED
<p>This is a sample *text* with a link: <a class="external" href="http://www.redmine.org">http://www.redmine.org</a><br />
and an email address <a class="email" href="mailto:foo@example.net">foo@example.net</a></p>
EXPECTED
assert_equal expected.gsub(%r{[\r\n\t]}, ''), Redmine::WikiFormatting::NullFormatter::Formatter.new(raw).to_html.gsub(%r{[\r\n\t]}, '')
end
def test_should_link_email_with_slashes
raw = 'foo/bar@example.net'
expected = '<p><a class="email" href="mailto:foo/bar@example.net">foo/bar@example.net</a></p>'
assert_equal expected.gsub(%r{[\r\n\t]}, ''), Redmine::WikiFormatting::NullFormatter::Formatter.new(raw).to_html.gsub(%r{[\r\n\t]}, '')
end
def test_links_separated_with_line_break_should_link
raw = <<-DIFF
link: https://www.redmine.org
http://www.redmine.org
DIFF
expected = <<-EXPECTED
<p>link: <a class="external" href="https://www.redmine.org">https://www.redmine.org</a><br />
<a class="external" href="http://www.redmine.org">http://www.redmine.org</a></p>
EXPECTED
end
def test_supports_section_edit
with_settings :text_formatting => 'textile' do
assert_equal true, Redmine::WikiFormatting.supports_section_edit?
end
with_settings :text_formatting => '' do
assert_equal false, Redmine::WikiFormatting.supports_section_edit?
end
end
def test_cache_key_for_saved_object_should_no_be_nil
assert_not_nil Redmine::WikiFormatting.cache_key_for('textile', 'Text', Issue.find(1), :description)
end
end