Redmine 3.4.4
This commit is contained in:
commit
64924a6376
2112 changed files with 259028 additions and 0 deletions
197
test/unit/activity_test.rb
Normal file
197
test/unit/activity_test.rb
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
# 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 ActivityTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :versions, :attachments, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
|
||||
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages, :time_entries,
|
||||
:wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
|
||||
|
||||
def setup
|
||||
@project = Project.find(1)
|
||||
end
|
||||
|
||||
def test_activity_without_subprojects
|
||||
events = find_events(User.anonymous, :project => @project)
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
assert !events.include?(Issue.find(4))
|
||||
# subproject issue
|
||||
assert !events.include?(Issue.find(5))
|
||||
end
|
||||
|
||||
def test_activity_with_subprojects
|
||||
events = find_events(User.anonymous, :project => @project, :with_subprojects => 1)
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
# subproject issue
|
||||
assert events.include?(Issue.find(5))
|
||||
end
|
||||
|
||||
def test_global_activity_anonymous
|
||||
events = find_events(User.anonymous)
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
assert events.include?(Message.find(5))
|
||||
# Issue of a private project
|
||||
assert !events.include?(Issue.find(4))
|
||||
# Private issue and comment
|
||||
assert !events.include?(Issue.find(14))
|
||||
assert !events.include?(Journal.find(5))
|
||||
end
|
||||
|
||||
def test_global_activity_logged_user
|
||||
events = find_events(User.find(2)) # manager
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
# Issue of a private project the user belongs to
|
||||
assert events.include?(Issue.find(4))
|
||||
end
|
||||
|
||||
def test_user_activity
|
||||
user = User.find(2)
|
||||
events = Redmine::Activity::Fetcher.new(User.anonymous, :author => user).events(nil, nil, :limit => 10)
|
||||
|
||||
assert(events.size > 0)
|
||||
assert(events.size <= 10)
|
||||
assert_nil(events.detect {|e| e.event_author != user})
|
||||
end
|
||||
|
||||
def test_journal_with_notes_and_changes_should_be_returned_once
|
||||
f = Redmine::Activity::Fetcher.new(User.anonymous, :project => Project.find(1))
|
||||
f.scope = ['issues']
|
||||
events = f.events
|
||||
|
||||
assert_equal events, events.uniq
|
||||
end
|
||||
|
||||
def test_files_activity
|
||||
f = Redmine::Activity::Fetcher.new(User.anonymous, :project => Project.find(1))
|
||||
f.scope = ['files']
|
||||
events = f.events
|
||||
|
||||
assert_kind_of Array, events
|
||||
assert events.include?(Attachment.find_by_container_type_and_container_id('Project', 1))
|
||||
assert events.include?(Attachment.find_by_container_type_and_container_id('Version', 1))
|
||||
assert_equal [Attachment], events.collect(&:class).uniq
|
||||
assert_equal %w(Project Version), events.collect(&:container_type).uniq.sort
|
||||
end
|
||||
|
||||
def test_event_group_for_issue
|
||||
issue = Issue.find(1)
|
||||
assert_equal issue, issue.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_journal
|
||||
issue = Issue.find(1)
|
||||
journal = issue.journals.first
|
||||
assert_equal issue, journal.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_issue_time_entry
|
||||
time = TimeEntry.where(:issue_id => 1).first
|
||||
assert_equal time.issue, time.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_project_time_entry
|
||||
time = TimeEntry.where(:issue_id => nil).first
|
||||
assert_equal time, time.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_message
|
||||
message = Message.find(1)
|
||||
reply = message.children.first
|
||||
assert_equal message, message.event_group
|
||||
assert_equal message, reply.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_wiki_content_version
|
||||
content = WikiContent::Version.find(1)
|
||||
assert_equal content.page, content.event_group
|
||||
end
|
||||
|
||||
class TestActivityProviderWithPermission
|
||||
def self.activity_provider_options
|
||||
{'test' => {:permission => :custom_permission}}
|
||||
end
|
||||
end
|
||||
|
||||
class TestActivityProviderWithNilPermission
|
||||
def self.activity_provider_options
|
||||
{'test' => {:permission => nil}}
|
||||
end
|
||||
end
|
||||
|
||||
class TestActivityProviderWithoutPermission
|
||||
def self.activity_provider_options
|
||||
{'test' => {}}
|
||||
end
|
||||
end
|
||||
|
||||
class MockUser
|
||||
def initialize(*permissions)
|
||||
@permissions = permissions
|
||||
end
|
||||
|
||||
def allowed_to?(permission, *args)
|
||||
@permissions.include?(permission)
|
||||
end
|
||||
end
|
||||
|
||||
def test_event_types_should_consider_activity_provider_permission
|
||||
Redmine::Activity.register 'test', :class_name => 'ActivityTest::TestActivityProviderWithPermission'
|
||||
user = MockUser.new(:custom_permission)
|
||||
f = Redmine::Activity::Fetcher.new(user, :project => Project.find(1))
|
||||
assert_include 'test', f.event_types
|
||||
ensure
|
||||
Redmine::Activity.delete 'test'
|
||||
end
|
||||
|
||||
def test_event_types_should_include_activity_provider_with_nil_permission
|
||||
Redmine::Activity.register 'test', :class_name => 'ActivityTest::TestActivityProviderWithNilPermission'
|
||||
user = MockUser.new()
|
||||
f = Redmine::Activity::Fetcher.new(user, :project => Project.find(1))
|
||||
assert_include 'test', f.event_types
|
||||
ensure
|
||||
Redmine::Activity.delete 'test'
|
||||
end
|
||||
|
||||
def test_event_types_should_use_default_permission_for_activity_provider_without_permission
|
||||
Redmine::Activity.register 'test', :class_name => 'ActivityTest::TestActivityProviderWithoutPermission'
|
||||
|
||||
user = MockUser.new()
|
||||
f = Redmine::Activity::Fetcher.new(user, :project => Project.find(1))
|
||||
assert_not_include 'test', f.event_types
|
||||
|
||||
user = MockUser.new(:view_test)
|
||||
f = Redmine::Activity::Fetcher.new(user, :project => Project.find(1))
|
||||
assert_include 'test', f.event_types
|
||||
ensure
|
||||
Redmine::Activity.delete 'test'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_events(user, options={})
|
||||
Redmine::Activity::Fetcher.new(user, options).events(Date.today - 30, Date.today + 1)
|
||||
end
|
||||
end
|
||||
450
test/unit/attachment_test.rb
Normal file
450
test/unit/attachment_test.rb
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
# 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__)
|
||||
|
||||
class AttachmentTest < ActiveSupport::TestCase
|
||||
fixtures :users, :email_addresses, :projects, :roles, :members, :member_roles,
|
||||
:enabled_modules, :issues, :trackers, :attachments
|
||||
|
||||
# TODO: remove this with Rails 5 that supports after_commit callbacks
|
||||
# in transactional fixtures (https://github.com/rails/rails/pull/18458)
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_container_for_new_attachment_should_be_nil
|
||||
assert_nil Attachment.new.container
|
||||
end
|
||||
|
||||
def test_filename_should_remove_eols
|
||||
assert_equal "line_feed", Attachment.new(:filename => "line\nfeed").filename
|
||||
assert_equal "line_feed", Attachment.new(:filename => "some\npath/line\nfeed").filename
|
||||
assert_equal "carriage_return", Attachment.new(:filename => "carriage\rreturn").filename
|
||||
assert_equal "carriage_return", Attachment.new(:filename => "some\rpath/carriage\rreturn").filename
|
||||
end
|
||||
|
||||
def test_create
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'testfile.txt', a.filename
|
||||
assert_equal 59, a.filesize
|
||||
assert_equal 'text/plain', a.content_type
|
||||
assert_equal 0, a.downloads
|
||||
assert_equal '6bc2eb7e87cfbf9145065689aaa8b5f513089ca0af68e2dc41f9cc025473d106', a.digest
|
||||
|
||||
assert a.disk_directory
|
||||
assert_match %r{\A\d{4}/\d{2}\z}, a.disk_directory
|
||||
|
||||
assert File.exist?(a.diskfile)
|
||||
assert_equal 59, File.size(a.diskfile)
|
||||
end
|
||||
|
||||
def test_create_should_clear_content_type_if_too_long
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1),
|
||||
:content_type => 'a'*300)
|
||||
assert a.save
|
||||
a.reload
|
||||
assert_nil a.content_type
|
||||
end
|
||||
|
||||
def test_shorted_filename_if_too_long
|
||||
file = mock_file_with_options(:original_filename => "#{'a'*251}.txt")
|
||||
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => file,
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
a.reload
|
||||
assert_equal 12 + 1 + 32 + 4, a.disk_filename.length
|
||||
assert_equal 255, a.filename.length
|
||||
end
|
||||
|
||||
def test_copy_should_preserve_attributes
|
||||
|
||||
# prevent re-use of data from other attachments with equal contents
|
||||
Attachment.where('id <> 1').destroy_all
|
||||
|
||||
a = Attachment.find(1)
|
||||
copy = a.copy
|
||||
|
||||
assert_save copy
|
||||
copy = Attachment.order('id DESC').first
|
||||
%w(filename filesize content_type author_id created_on description digest disk_filename disk_directory diskfile).each do |attribute|
|
||||
assert_equal a.send(attribute), copy.send(attribute), "#{attribute} was different"
|
||||
end
|
||||
end
|
||||
|
||||
def test_size_should_be_validated_for_new_file
|
||||
with_settings :attachment_max_size => 0 do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert !a.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_size_should_not_be_validated_when_copying
|
||||
a = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
with_settings :attachment_max_size => 0 do
|
||||
copy = a.copy
|
||||
assert copy.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_filesize_greater_than_2gb_should_be_supported
|
||||
with_settings :attachment_max_size => (50.gigabyte / 1024) do
|
||||
a = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
a.filesize = 20.gigabyte
|
||||
a.save!
|
||||
assert_equal 20.gigabyte, a.reload.filesize
|
||||
end
|
||||
end
|
||||
|
||||
def test_extension_should_be_validated_against_allowed_extensions
|
||||
with_settings :attachment_extensions_allowed => "txt, png" do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => mock_file_with_options(:original_filename => "test.png"),
|
||||
:author => User.find(1))
|
||||
assert_save a
|
||||
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => mock_file_with_options(:original_filename => "test.jpeg"),
|
||||
:author => User.find(1))
|
||||
assert !a.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_extension_should_be_validated_against_denied_extensions
|
||||
with_settings :attachment_extensions_denied => "txt, png" do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => mock_file_with_options(:original_filename => "test.jpeg"),
|
||||
:author => User.find(1))
|
||||
assert_save a
|
||||
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => mock_file_with_options(:original_filename => "test.png"),
|
||||
:author => User.find(1))
|
||||
assert !a.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_valid_extension_should_be_case_insensitive
|
||||
with_settings :attachment_extensions_allowed => "txt, Png" do
|
||||
assert Attachment.valid_extension?(".pnG")
|
||||
assert !Attachment.valid_extension?(".jpeg")
|
||||
end
|
||||
with_settings :attachment_extensions_denied => "txt, Png" do
|
||||
assert !Attachment.valid_extension?(".pnG")
|
||||
assert Attachment.valid_extension?(".jpeg")
|
||||
end
|
||||
end
|
||||
|
||||
def test_description_length_should_be_validated
|
||||
a = Attachment.new(:description => 'a' * 300)
|
||||
assert !a.save
|
||||
assert_not_equal [], a.errors[:description]
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'testfile.txt', a.filename
|
||||
assert_equal 59, a.filesize
|
||||
assert_equal 'text/plain', a.content_type
|
||||
assert_equal 0, a.downloads
|
||||
assert_equal '6bc2eb7e87cfbf9145065689aaa8b5f513089ca0af68e2dc41f9cc025473d106', a.digest
|
||||
diskfile = a.diskfile
|
||||
assert File.exist?(diskfile)
|
||||
assert_equal 59, File.size(a.diskfile)
|
||||
assert a.destroy
|
||||
assert !File.exist?(diskfile)
|
||||
end
|
||||
|
||||
def test_destroy_should_not_delete_file_referenced_by_other_attachment
|
||||
a = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
diskfile = a.diskfile
|
||||
|
||||
copy = a.copy
|
||||
copy.save!
|
||||
|
||||
assert File.exists?(diskfile)
|
||||
a.destroy
|
||||
assert File.exists?(diskfile)
|
||||
copy.destroy
|
||||
assert !File.exists?(diskfile)
|
||||
end
|
||||
|
||||
def test_create_should_auto_assign_content_type
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", ""),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'text/plain', a.content_type
|
||||
end
|
||||
|
||||
def test_attachments_with_same_content_should_reuse_same_file
|
||||
a1 = Attachment.create!(:container => Issue.find(1), :author => User.find(1),
|
||||
:file => mock_file(:filename => 'foo', :content => 'abcd'))
|
||||
a2 = Attachment.create!(:container => Issue.find(1), :author => User.find(1),
|
||||
:file => mock_file(:filename => 'bar', :content => 'abcd'))
|
||||
assert_equal a1.diskfile, a2.diskfile
|
||||
end
|
||||
|
||||
def test_attachments_with_same_content_should_not_reuse_same_file_if_deleted
|
||||
a1 = Attachment.create!(:container => Issue.find(1), :author => User.find(1),
|
||||
:file => mock_file(:filename => 'foo', :content => 'abcd'))
|
||||
a1.delete_from_disk
|
||||
a2 = Attachment.create!(:container => Issue.find(1), :author => User.find(1),
|
||||
:file => mock_file(:filename => 'bar', :content => 'abcd'))
|
||||
assert_not_equal a1.diskfile, a2.diskfile
|
||||
end
|
||||
|
||||
def test_attachments_with_same_filename_at_the_same_time_should_not_overwrite
|
||||
a1 = Attachment.create!(:container => Issue.find(1), :author => User.find(1),
|
||||
:file => mock_file(:filename => 'foo', :content => 'abcd'))
|
||||
a2 = Attachment.create!(:container => Issue.find(1), :author => User.find(1),
|
||||
:file => mock_file(:filename => 'foo', :content => 'efgh'))
|
||||
assert_not_equal a1.diskfile, a2.diskfile
|
||||
end
|
||||
|
||||
def test_filename_should_be_basenamed
|
||||
a = Attachment.new(:file => mock_file(:original_filename => "path/to/the/file"))
|
||||
assert_equal 'file', a.filename
|
||||
end
|
||||
|
||||
def test_filename_should_be_sanitized
|
||||
a = Attachment.new(:file => mock_file(:original_filename => "valid:[] invalid:?%*|\"'<>chars"))
|
||||
assert_equal 'valid_[] invalid_chars', a.filename
|
||||
end
|
||||
|
||||
def test_diskfilename
|
||||
assert Attachment.disk_filename("test_file.txt") =~ /^\d{12}_test_file.txt$/
|
||||
assert_equal 'test_file.txt', Attachment.disk_filename("test_file.txt")[13..-1]
|
||||
assert_equal '770c509475505f37c2b8fb6030434d6b.txt', Attachment.disk_filename("test_accentué.txt")[13..-1]
|
||||
assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1]
|
||||
assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1]
|
||||
end
|
||||
|
||||
def test_title
|
||||
a = Attachment.new(:filename => "test.png")
|
||||
assert_equal "test.png", a.title
|
||||
|
||||
a = Attachment.new(:filename => "test.png", :description => "Cool image")
|
||||
assert_equal "test.png (Cool image)", a.title
|
||||
end
|
||||
|
||||
def test_new_attachment_should_be_editable_by_author
|
||||
user = User.find(1)
|
||||
a = Attachment.new(:author => user)
|
||||
assert_equal true, a.editable?(user)
|
||||
end
|
||||
|
||||
def test_prune_should_destroy_old_unattached_attachments
|
||||
Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
|
||||
Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
|
||||
Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1)
|
||||
|
||||
assert_difference 'Attachment.count', -2 do
|
||||
Attachment.prune
|
||||
end
|
||||
end
|
||||
|
||||
def test_move_from_root_to_target_directory_should_move_root_files
|
||||
a = Attachment.find(20)
|
||||
assert a.disk_directory.blank?
|
||||
# Create a real file for this fixture
|
||||
File.open(a.diskfile, "w") do |f|
|
||||
f.write "test file at the root of files directory"
|
||||
end
|
||||
assert a.readable?
|
||||
Attachment.move_from_root_to_target_directory
|
||||
|
||||
a.reload
|
||||
assert_equal '2012/05', a.disk_directory
|
||||
assert a.readable?
|
||||
end
|
||||
|
||||
test "Attachmnet.attach_files should attach the file" do
|
||||
issue = Issue.first
|
||||
assert_difference 'Attachment.count' do
|
||||
Attachment.attach_files(issue,
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain'),
|
||||
'description' => 'test'
|
||||
})
|
||||
end
|
||||
attachment = Attachment.order('id DESC').first
|
||||
assert_equal issue, attachment.container
|
||||
assert_equal 'testfile.txt', attachment.filename
|
||||
assert_equal 59, attachment.filesize
|
||||
assert_equal 'test', attachment.description
|
||||
assert_equal 'text/plain', attachment.content_type
|
||||
assert File.exists?(attachment.diskfile)
|
||||
assert_equal 59, File.size(attachment.diskfile)
|
||||
end
|
||||
|
||||
test "Attachmnet.attach_files should add unsaved files to the object as unsaved attachments" do
|
||||
# Max size of 0 to force Attachment creation failures
|
||||
with_settings(:attachment_max_size => 0) do
|
||||
@project = Project.find(1)
|
||||
response = Attachment.attach_files(@project, {
|
||||
'1' => {'file' => mock_file, 'description' => 'test'},
|
||||
'2' => {'file' => mock_file, 'description' => 'test'}
|
||||
})
|
||||
|
||||
assert response[:unsaved].present?
|
||||
assert_equal 2, response[:unsaved].length
|
||||
assert response[:unsaved].first.new_record?
|
||||
assert response[:unsaved].second.new_record?
|
||||
assert_equal response[:unsaved], @project.unsaved_attachments
|
||||
end
|
||||
end
|
||||
|
||||
test "Attachment.attach_files should preserve the content_type of attachments added by token" do
|
||||
@project = Project.find(1)
|
||||
attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
|
||||
assert_equal 'text/plain', attachment.content_type
|
||||
Attachment.attach_files(@project, { '1' => {'token' => attachment.token } })
|
||||
attachment.reload
|
||||
assert_equal 'text/plain', attachment.content_type
|
||||
end
|
||||
|
||||
def test_update_digest_to_sha256_should_update_digest
|
||||
set_fixtures_attachments_directory
|
||||
attachment = Attachment.find 6
|
||||
assert attachment.readable?
|
||||
attachment.update_digest_to_sha256!
|
||||
assert_equal 'ac5c6e99a21ae74b2e3f5b8e5b568be1b9107cd7153d139e822b9fe5caf50938', attachment.digest
|
||||
end
|
||||
|
||||
def test_update_attachments
|
||||
attachments = Attachment.where(:id => [2, 3]).to_a
|
||||
|
||||
assert Attachment.update_attachments(attachments, {
|
||||
'2' => {:filename => 'newname.txt', :description => 'New description'},
|
||||
3 => {:filename => 'othername.txt'}
|
||||
})
|
||||
|
||||
attachment = Attachment.find(2)
|
||||
assert_equal 'newname.txt', attachment.filename
|
||||
assert_equal 'New description', attachment.description
|
||||
|
||||
attachment = Attachment.find(3)
|
||||
assert_equal 'othername.txt', attachment.filename
|
||||
end
|
||||
|
||||
def test_update_attachments_with_failure
|
||||
attachments = Attachment.where(:id => [2, 3]).to_a
|
||||
|
||||
assert !Attachment.update_attachments(attachments, {
|
||||
'2' => {:filename => '', :description => 'New description'},
|
||||
3 => {:filename => 'othername.txt'}
|
||||
})
|
||||
|
||||
attachment = Attachment.find(3)
|
||||
assert_equal 'logo.gif', attachment.filename
|
||||
end
|
||||
|
||||
def test_update_attachments_should_sanitize_filename
|
||||
attachments = Attachment.where(:id => 2).to_a
|
||||
|
||||
assert Attachment.update_attachments(attachments, {
|
||||
2 => {:filename => 'newname?.txt'},
|
||||
})
|
||||
|
||||
attachment = Attachment.find(2)
|
||||
assert_equal 'newname_.txt', attachment.filename
|
||||
end
|
||||
|
||||
def test_latest_attach
|
||||
set_fixtures_attachments_directory
|
||||
a1 = Attachment.find(16)
|
||||
assert_equal "testfile.png", a1.filename
|
||||
assert a1.readable?
|
||||
assert (! a1.visible?(User.anonymous))
|
||||
assert a1.visible?(User.find(2))
|
||||
a2 = Attachment.find(17)
|
||||
assert_equal "testfile.PNG", a2.filename
|
||||
assert a2.readable?
|
||||
assert (! a2.visible?(User.anonymous))
|
||||
assert a2.visible?(User.find(2))
|
||||
assert a1.created_on < a2.created_on
|
||||
|
||||
la1 = Attachment.latest_attach([a1, a2], "testfile.png")
|
||||
assert_equal 17, la1.id
|
||||
la2 = Attachment.latest_attach([a1, a2], "Testfile.PNG")
|
||||
assert_equal 17, la2.id
|
||||
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_latest_attach_should_not_error_with_string_with_invalid_encoding
|
||||
string = "width:50\xFE-Image.jpg".force_encoding('UTF-8')
|
||||
assert_equal false, string.valid_encoding?
|
||||
|
||||
Attachment.latest_attach(Attachment.limit(2).to_a, string)
|
||||
end
|
||||
|
||||
def test_thumbnailable_should_be_true_for_images
|
||||
assert_equal true, Attachment.new(:filename => 'test.jpg').thumbnailable?
|
||||
end
|
||||
|
||||
def test_thumbnailable_should_be_true_for_non_images
|
||||
assert_equal false, Attachment.new(:filename => 'test.txt').thumbnailable?
|
||||
end
|
||||
|
||||
if convert_installed?
|
||||
def test_thumbnail_should_generate_the_thumbnail
|
||||
set_fixtures_attachments_directory
|
||||
attachment = Attachment.find(16)
|
||||
Attachment.clear_thumbnails
|
||||
|
||||
assert_difference "Dir.glob(File.join(Attachment.thumbnails_storage_path, '*.thumb')).size" do
|
||||
thumbnail = attachment.thumbnail
|
||||
assert_equal "16_8e0294de2441577c529f170b6fb8f638_100.thumb", File.basename(thumbnail)
|
||||
assert File.exists?(thumbnail)
|
||||
end
|
||||
end
|
||||
|
||||
def test_thumbnail_should_return_nil_if_generation_fails
|
||||
Redmine::Thumbnail.expects(:generate).raises(SystemCallError, 'Something went wrong')
|
||||
set_fixtures_attachments_directory
|
||||
attachment = Attachment.find(16)
|
||||
assert_nil attachment.thumbnail
|
||||
end
|
||||
else
|
||||
puts '(ImageMagick convert not available)'
|
||||
end
|
||||
|
||||
end
|
||||
76
test/unit/attachment_transaction_test.rb
Normal file
76
test/unit/attachment_transaction_test.rb
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# 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__)
|
||||
|
||||
class AttachmentTest < ActiveSupport::TestCase
|
||||
fixtures :users, :email_addresses, :projects, :roles, :members, :member_roles,
|
||||
:enabled_modules, :issues, :trackers, :attachments
|
||||
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_rollback_after_create_should_remove_file_from_disk
|
||||
diskfile = nil
|
||||
|
||||
Attachment.transaction do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
a.save!
|
||||
diskfile = a.diskfile
|
||||
assert File.exist?(diskfile)
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
assert !File.exist?(diskfile)
|
||||
end
|
||||
|
||||
def test_destroy_should_remove_file_from_disk_after_commit
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
a.save!
|
||||
diskfile = a.diskfile
|
||||
assert File.exist?(diskfile)
|
||||
|
||||
Attachment.transaction do
|
||||
a.destroy
|
||||
assert File.exist?(diskfile)
|
||||
end
|
||||
assert !File.exist?(diskfile)
|
||||
end
|
||||
|
||||
def test_rollback_after_destroy_should_not_remove_file_from_disk
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
a.save!
|
||||
diskfile = a.diskfile
|
||||
assert File.exist?(diskfile)
|
||||
|
||||
Attachment.transaction do
|
||||
a.destroy
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
assert File.exist?(diskfile)
|
||||
end
|
||||
end
|
||||
234
test/unit/auth_source_ldap_test.rb
Normal file
234
test/unit/auth_source_ldap_test.rb
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
# 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 AuthSourceLdapTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
fixtures :auth_sources
|
||||
|
||||
def setup
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
auth_source = AuthSourceLdap.new
|
||||
assert_nil auth_source.id
|
||||
assert_equal "AuthSourceLdap", auth_source.type
|
||||
assert_equal "", auth_source.name
|
||||
assert_nil auth_source.host
|
||||
assert_nil auth_source.port
|
||||
assert_nil auth_source.account
|
||||
assert_equal "", auth_source.account_password
|
||||
assert_nil auth_source.base_dn
|
||||
assert_nil auth_source.attr_login
|
||||
assert_nil auth_source.attr_firstname
|
||||
assert_nil auth_source.attr_lastname
|
||||
assert_nil auth_source.attr_mail
|
||||
assert_equal false, auth_source.onthefly_register
|
||||
assert_equal false, auth_source.tls
|
||||
assert_nil auth_source.filter
|
||||
assert_nil auth_source.timeout
|
||||
end
|
||||
|
||||
def test_create
|
||||
a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName')
|
||||
assert a.save
|
||||
end
|
||||
|
||||
def test_should_strip_ldap_attributes
|
||||
a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
|
||||
:attr_firstname => 'givenName ')
|
||||
assert a.save
|
||||
assert_equal 'givenName', a.reload.attr_firstname
|
||||
end
|
||||
|
||||
def test_replace_port_zero_to_389
|
||||
a = AuthSourceLdap.new(
|
||||
:name => 'My LDAP', :host => 'ldap.example.net', :port => 0,
|
||||
:base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
|
||||
:attr_firstname => 'givenName ')
|
||||
assert a.save
|
||||
assert_equal 389, a.port
|
||||
end
|
||||
|
||||
def test_filter_should_be_validated
|
||||
set_language_if_valid 'en'
|
||||
|
||||
a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :attr_login => 'sn')
|
||||
a.filter = "(mail=*@redmine.org"
|
||||
assert !a.valid?
|
||||
assert_include "LDAP filter is invalid", a.errors.full_messages
|
||||
|
||||
a.filter = "(mail=*@redmine.org)"
|
||||
assert a.valid?
|
||||
end
|
||||
|
||||
if ldap_configured?
|
||||
test '#authenticate with a valid LDAP user should return the user attributes' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
auth.update_attribute :onthefly_register, true
|
||||
|
||||
attributes = auth.authenticate('example1','123456')
|
||||
assert attributes.is_a?(Hash), "An hash was not returned"
|
||||
assert_equal 'Example', attributes[:firstname]
|
||||
assert_equal 'One', attributes[:lastname]
|
||||
assert_equal 'example1@redmine.org', attributes[:mail]
|
||||
assert_equal auth.id, attributes[:auth_source_id]
|
||||
attributes.keys.each do |attribute|
|
||||
assert User.new.respond_to?("#{attribute}="), "Unexpected :#{attribute} attribute returned"
|
||||
end
|
||||
end
|
||||
|
||||
test '#authenticate with an invalid LDAP user should return nil' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert_nil auth.authenticate('nouser','123456')
|
||||
end
|
||||
|
||||
test '#authenticate without a login should return nil' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert_nil auth.authenticate('','123456')
|
||||
end
|
||||
|
||||
test '#authenticate without a password should return nil' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert_nil auth.authenticate('edavis','')
|
||||
end
|
||||
|
||||
test '#authenticate without filter should return any user' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert auth.authenticate('example1','123456')
|
||||
assert auth.authenticate('edavis', '123456')
|
||||
end
|
||||
|
||||
test '#authenticate with filter should return user who matches the filter only' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
auth.filter = "(mail=*@redmine.org)"
|
||||
|
||||
assert auth.authenticate('example1','123456')
|
||||
assert_nil auth.authenticate('edavis', '123456')
|
||||
end
|
||||
|
||||
def test_authenticate_should_timeout
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.timeout = 1
|
||||
def auth_source.initialize_ldap_con(*args); sleep(5); end
|
||||
|
||||
assert_raise AuthSourceTimeoutException do
|
||||
auth_source.authenticate 'example1', '123456'
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_should_return_matching_entries
|
||||
results = AuthSource.search("exa")
|
||||
assert_equal 1, results.size
|
||||
result = results.first
|
||||
assert_kind_of Hash, result
|
||||
assert_equal "example1", result[:login]
|
||||
assert_equal "Example", result[:firstname]
|
||||
assert_equal "One", result[:lastname]
|
||||
assert_equal "example1@redmine.org", result[:mail]
|
||||
assert_equal 1, result[:auth_source_id]
|
||||
end
|
||||
|
||||
def test_search_with_no_match_should_return_an_empty_array
|
||||
results = AuthSource.search("wro")
|
||||
assert_equal [], results
|
||||
end
|
||||
|
||||
def test_search_with_exception_should_return_an_empty_array
|
||||
Net::LDAP.stubs(:new).raises(Net::LDAP::LdapError, 'Cannot connect')
|
||||
|
||||
results = AuthSource.search("exa")
|
||||
assert_equal [], results
|
||||
end
|
||||
|
||||
def test_test_connection_with_correct_host_and_port
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
|
||||
assert_nothing_raised Net::LDAP::Error do
|
||||
auth_source.test_connection
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_connection_with_incorrect_host
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.host = "badhost"
|
||||
auth_source.save!
|
||||
|
||||
assert_raise Net::LDAP::Error do
|
||||
auth_source.test_connection
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_connection_with_incorrect_port
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.port = 1234
|
||||
auth_source.save!
|
||||
|
||||
assert_raise Net::LDAP::Error do
|
||||
auth_source.test_connection
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_connection_bind_with_account_and_password
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.account = "cn=admin,dc=redmine,dc=org"
|
||||
auth_source.account_password = "secret"
|
||||
auth_source.save!
|
||||
|
||||
assert_equal "cn=admin,dc=redmine,dc=org", auth_source.account
|
||||
assert_equal "secret", auth_source.account_password
|
||||
assert_nil auth_source.test_connection
|
||||
end
|
||||
|
||||
def test_test_connection_bind_without_account_and_password
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
|
||||
assert_nil auth_source.account
|
||||
assert_equal "", auth_source.account_password
|
||||
assert_nil auth_source.test_connection
|
||||
end
|
||||
|
||||
def test_test_connection_bind_with_incorrect_account
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.account = "cn=baduser,dc=redmine,dc=org"
|
||||
auth_source.account_password = "secret"
|
||||
auth_source.save!
|
||||
|
||||
assert_equal "cn=baduser,dc=redmine,dc=org", auth_source.account
|
||||
assert_equal "secret", auth_source.account_password
|
||||
assert_raise AuthSourceException do
|
||||
auth_source.test_connection
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_connection_bind_with_incorrect_password
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.account = "cn=admin,dc=redmine,dc=org"
|
||||
auth_source.account_password = "badpassword"
|
||||
auth_source.save!
|
||||
|
||||
assert_equal "cn=admin,dc=redmine,dc=org", auth_source.account
|
||||
assert_equal "badpassword", auth_source.account_password
|
||||
assert_raise AuthSourceException do
|
||||
auth_source.test_connection
|
||||
end
|
||||
end
|
||||
else
|
||||
puts '(Test LDAP server not configured)'
|
||||
end
|
||||
end
|
||||
125
test/unit/board_test.rb
Normal file
125
test/unit/board_test.rb
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
# 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__)
|
||||
|
||||
class BoardTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :boards, :messages, :attachments, :watchers
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def setup
|
||||
@project = Project.find(1)
|
||||
end
|
||||
|
||||
def test_create
|
||||
board = Board.new(:project => @project, :name => 'Test board', :description => 'Test board description')
|
||||
assert board.save
|
||||
board.reload
|
||||
assert_equal 'Test board', board.name
|
||||
assert_equal 'Test board description', board.description
|
||||
assert_equal @project, board.project
|
||||
assert_equal 0, board.topics_count
|
||||
assert_equal 0, board.messages_count
|
||||
assert_nil board.last_message
|
||||
# last position
|
||||
assert_equal @project.boards.size, board.position
|
||||
end
|
||||
|
||||
def test_parent_should_be_in_same_project
|
||||
set_language_if_valid 'en'
|
||||
board = Board.new(:project_id => 3, :name => 'Test', :description => 'Test', :parent_id => 1)
|
||||
assert !board.save
|
||||
assert_include "Parent forum is invalid", board.errors.full_messages
|
||||
end
|
||||
|
||||
def test_valid_parents_should_not_include_self_nor_a_descendant
|
||||
board1 = Board.generate!(:project_id => 3)
|
||||
board2 = Board.generate!(:project_id => 3, :parent => board1)
|
||||
board3 = Board.generate!(:project_id => 3, :parent => board2)
|
||||
board4 = Board.generate!(:project_id => 3)
|
||||
|
||||
assert_equal [board4], board1.reload.valid_parents.sort_by(&:id)
|
||||
assert_equal [board1, board4], board2.reload.valid_parents.sort_by(&:id)
|
||||
assert_equal [board1, board2, board4], board3.reload.valid_parents.sort_by(&:id)
|
||||
assert_equal [board1, board2, board3], board4.reload.valid_parents.sort_by(&:id)
|
||||
end
|
||||
|
||||
def test_position_should_be_assigned_with_parent_scope
|
||||
parent1 = Board.generate!(:project_id => 3)
|
||||
parent2 = Board.generate!(:project_id => 3)
|
||||
child1 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
child2 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
|
||||
assert_equal 1, parent1.reload.position
|
||||
assert_equal 1, child1.reload.position
|
||||
assert_equal 2, child2.reload.position
|
||||
assert_equal 2, parent2.reload.position
|
||||
end
|
||||
|
||||
def test_board_tree_should_yield_boards_with_level
|
||||
parent1 = Board.generate!(:project_id => 3)
|
||||
parent2 = Board.generate!(:project_id => 3)
|
||||
child1 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
child2 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
child3 = Board.generate!(:project_id => 3, :parent => child1)
|
||||
|
||||
tree = Board.board_tree(Project.find(3).boards)
|
||||
|
||||
assert_equal [
|
||||
[parent1, 0],
|
||||
[child1, 1],
|
||||
[child3, 2],
|
||||
[child2, 1],
|
||||
[parent2, 0]
|
||||
], tree
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
board = Board.find(1)
|
||||
assert_difference 'Message.count', -6 do
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
assert_difference 'Watcher.count', -1 do
|
||||
assert board.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_equal 0, Message.where(:board_id => 1).count
|
||||
end
|
||||
|
||||
def test_destroy_should_nullify_children
|
||||
parent = Board.generate!(:project => @project)
|
||||
child = Board.generate!(:project => @project, :parent => parent)
|
||||
assert_equal parent, child.parent
|
||||
|
||||
assert parent.destroy
|
||||
child.reload
|
||||
assert_nil child.parent
|
||||
assert_nil child.parent_id
|
||||
end
|
||||
|
||||
def test_reset_counters_should_update_attributes
|
||||
Board.where(:id => 1).update_all(:topics_count => 0, :messages_count => 0, :last_message_id => 0)
|
||||
Board.reset_counters!(1)
|
||||
board = Board.find(1)
|
||||
assert_equal board.topics.count, board.topics_count
|
||||
assert_equal board.messages.count, board.messages_count
|
||||
assert_equal board.messages.order("id DESC").first.id, board.last_message_id
|
||||
end
|
||||
end
|
||||
608
test/unit/changeset_test.rb
Normal file
608
test/unit/changeset_test.rb
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
# 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__)
|
||||
|
||||
class ChangesetTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :repositories,
|
||||
:issues, :issue_statuses, :issue_categories,
|
||||
:journals, :journal_details,
|
||||
:workflows,
|
||||
:changesets, :changes,
|
||||
:enumerations,
|
||||
:custom_fields, :custom_values,
|
||||
:users, :members, :member_roles,
|
||||
:email_addresses,
|
||||
:trackers, :projects_trackers,
|
||||
:enabled_modules, :roles
|
||||
|
||||
def test_ref_keywords_any
|
||||
ActionMailer::Base.deliveries.clear
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_update_keywords = [{'keywords' => 'fixes , closes', 'status_id' => '5', 'done_ratio' => '90'}]
|
||||
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'New commit (#2). Fixes #1',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
fixed = Issue.find(1)
|
||||
assert fixed.closed?
|
||||
assert_equal 90, fixed.done_ratio
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_ref_keywords
|
||||
Setting.commit_ref_keywords = 'refs'
|
||||
Setting.commit_update_keywords = ''
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'Ignores #2. Refs #1',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_any_only
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_update_keywords = ''
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'Ignores #2. Refs #1',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_any_with_timelog
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_logtime_enabled = '1'
|
||||
|
||||
{
|
||||
'2' => 2.0,
|
||||
'2h' => 2.0,
|
||||
'2hours' => 2.0,
|
||||
'15m' => 0.25,
|
||||
'15min' => 0.25,
|
||||
'3h15' => 3.25,
|
||||
'3h15m' => 3.25,
|
||||
'3h15min' => 3.25,
|
||||
'3:15' => 3.25,
|
||||
'3.25' => 3.25,
|
||||
'3.25h' => 3.25,
|
||||
'3,25' => 3.25,
|
||||
'3,25h' => 3.25,
|
||||
}.each do |syntax, expected_hours|
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => 24.hours.ago,
|
||||
:comments => "Worked on this issue #1 @#{syntax}",
|
||||
:revision => '520',
|
||||
:user => User.find(2))
|
||||
assert_difference 'TimeEntry.count' do
|
||||
c.scan_comment_for_issue_ids
|
||||
end
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
|
||||
time = TimeEntry.order('id desc').first
|
||||
assert_equal 1, time.issue_id
|
||||
assert_equal 1, time.project_id
|
||||
assert_equal 2, time.user_id
|
||||
assert_equal expected_hours, time.hours,
|
||||
"@#{syntax} should be logged as #{expected_hours} hours but was #{time.hours}"
|
||||
assert_equal Date.yesterday, time.spent_on
|
||||
assert time.activity.is_default?
|
||||
assert time.comments.include?('r520'),
|
||||
"r520 was expected in time_entry comments: #{time.comments}"
|
||||
end
|
||||
end
|
||||
|
||||
def test_ref_keywords_closing_with_timelog
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_update_keywords = [{'keywords' => 'fixes , closes',
|
||||
'status_id' => IssueStatus.where(:is_closed => true).first.id.to_s}]
|
||||
Setting.commit_logtime_enabled = '1'
|
||||
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'This is a comment. Fixes #1 @4.5, #2 @1',
|
||||
:user => User.find(2))
|
||||
assert_difference 'TimeEntry.count', 2 do
|
||||
c.scan_comment_for_issue_ids
|
||||
end
|
||||
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
assert Issue.find(1).closed?
|
||||
assert Issue.find(2).closed?
|
||||
|
||||
times = TimeEntry.order('id desc').limit(2)
|
||||
assert_equal [1, 2], times.collect(&:issue_id).sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_any_line_start
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => '#1 is the reason of this commit',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_allow_brackets_around_a_issue_number
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => '[#1] Worked on this issue',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_allow_brackets_around_multiple_issue_numbers
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => '[#1 #2, #3] Worked on these',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1,2,3], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_with_large_number_should_not_error
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'Out of range #2010021810000121',
|
||||
:revision => '12345')
|
||||
assert_nothing_raised do
|
||||
assert c.save
|
||||
end
|
||||
assert_equal [], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_update_keywords_with_changes_should_create_journal
|
||||
issue = Issue.generate!(:project_id => 1, :status_id => 1)
|
||||
|
||||
with_settings :commit_update_keywords => [{'keywords' => 'fixes', 'status_id' => '3'}] do
|
||||
assert_difference 'Journal.count' do
|
||||
c = Changeset.generate!(:repository => Project.find(1).repository,:comments => "Fixes ##{issue.id}")
|
||||
assert_include c.id, issue.reload.changeset_ids
|
||||
journal = Journal.order('id DESC').first
|
||||
assert_equal 1, journal.details.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_keywords_without_change_should_not_create_journal
|
||||
issue = Issue.generate!(:project_id => 1, :status_id => 3)
|
||||
|
||||
with_settings :commit_update_keywords => [{'keywords' => 'fixes', 'status_id' => '3'}] do
|
||||
assert_no_difference 'Journal.count' do
|
||||
c = Changeset.generate!(:repository => Project.find(1).repository,:comments => "Fixes ##{issue.id}")
|
||||
assert_include c.id, issue.reload.changeset_ids
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_keywords_with_multiple_rules
|
||||
with_settings :commit_update_keywords => [
|
||||
{'keywords' => 'fixes, closes', 'status_id' => '5'},
|
||||
{'keywords' => 'resolves', 'status_id' => '3'}
|
||||
] do
|
||||
|
||||
issue1 = Issue.generate!
|
||||
issue2 = Issue.generate!
|
||||
Changeset.generate!(:comments => "Closes ##{issue1.id}\nResolves ##{issue2.id}")
|
||||
assert_equal 5, issue1.reload.status_id
|
||||
assert_equal 3, issue2.reload.status_id
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_keywords_with_multiple_rules_for_the_same_keyword_should_match_tracker
|
||||
with_settings :commit_update_keywords => [
|
||||
{'keywords' => 'fixes', 'status_id' => '5', 'if_tracker_id' => '2'},
|
||||
{'keywords' => 'fixes', 'status_id' => '3', 'if_tracker_id' => ''}
|
||||
] do
|
||||
|
||||
issue1 = Issue.generate!(:tracker_id => 2)
|
||||
issue2 = Issue.generate!
|
||||
Changeset.generate!(:comments => "Fixes ##{issue1.id}, ##{issue2.id}")
|
||||
assert_equal 5, issue1.reload.status_id
|
||||
assert_equal 3, issue2.reload.status_id
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_keywords_with_multiple_rules_for_the_same_tracker_should_match_keyword
|
||||
with_settings :commit_update_keywords => [
|
||||
{'keywords' => 'Fixes, Closes', 'status_id' => '5', 'done_ratio' => '100', 'if_tracker_id' => '2'},
|
||||
{'keywords' => 'Testing', 'status_id' => '3', 'done_ratio' => '90', 'if_tracker_id' => '2'}
|
||||
] do
|
||||
|
||||
issue1 = Issue.generate!(:tracker_id => 2)
|
||||
issue2 = Issue.generate!(:tracker_id => 2)
|
||||
Changeset.generate!(:comments => "Testing ##{issue1.id}, Fixes ##{issue2.id}")
|
||||
issue1.reload
|
||||
assert_equal 3, issue1.status_id
|
||||
assert_equal 90, issue1.done_ratio
|
||||
issue2.reload
|
||||
assert_equal 5, issue2.status_id
|
||||
assert_equal 100, issue2.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_keywords_with_multiple_rules_and_no_match
|
||||
with_settings :commit_update_keywords => [
|
||||
{'keywords' => 'fixes', 'status_id' => '5', 'if_tracker_id' => '2'},
|
||||
{'keywords' => 'fixes', 'status_id' => '3', 'if_tracker_id' => '3'}
|
||||
] do
|
||||
|
||||
issue1 = Issue.generate!(:tracker_id => 2)
|
||||
issue2 = Issue.generate!
|
||||
Changeset.generate!(:comments => "Fixes ##{issue1.id}, ##{issue2.id}")
|
||||
assert_equal 5, issue1.reload.status_id
|
||||
assert_equal 1, issue2.reload.status_id # no updates
|
||||
end
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_subproject_issue
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #5, a subproject issue',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [5], c.issue_ids.sort
|
||||
assert c.issues.first.project != c.project
|
||||
end
|
||||
|
||||
def test_commit_closing_a_subproject_issue
|
||||
with_settings :commit_update_keywords => [{'keywords' => 'closes', 'status_id' => '5'}],
|
||||
:default_language => 'en' do
|
||||
issue = Issue.find(5)
|
||||
assert !issue.closed?
|
||||
assert_difference 'Journal.count' do
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'closes #5, a subproject issue',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
end
|
||||
assert issue.reload.closed?
|
||||
journal = Journal.order('id DESC').first
|
||||
assert_equal issue, journal.issue
|
||||
assert_include "Applied in changeset ecookbook:r12345.", journal.notes
|
||||
end
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_parent_project_issue
|
||||
# repository of child project
|
||||
r = Repository::Subversion.create!(
|
||||
:project => Project.find(3),
|
||||
:url => 'svn://localhost/test')
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #2, an issue of a parent project',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [2], c.issue_ids.sort
|
||||
assert c.issues.first.project != c.project
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_project_with_commit_cross_project_ref_disabled
|
||||
r = Repository::Subversion.create!(
|
||||
:project => Project.find(3),
|
||||
:url => 'svn://localhost/test')
|
||||
with_settings :commit_cross_project_ref => '0' do
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #4, an issue of a different project',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [], c.issue_ids
|
||||
end
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_project_with_commit_cross_project_ref_enabled
|
||||
r = Repository::Subversion.create!(
|
||||
:project => Project.find(3),
|
||||
:url => 'svn://localhost/test')
|
||||
with_settings :commit_cross_project_ref => '1' do
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #4, an issue of a different project',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [4], c.issue_ids
|
||||
end
|
||||
end
|
||||
|
||||
def test_old_commits_should_not_update_issues_nor_log_time
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_update_keywords = {'fixes , closes' => {'status_id' => '5', 'done_ratio' => '90'}}
|
||||
Setting.commit_logtime_enabled = '1'
|
||||
|
||||
repository = Project.find(1).repository
|
||||
repository.created_on = Time.now
|
||||
repository.save!
|
||||
|
||||
c = Changeset.new(:repository => repository,
|
||||
:committed_on => 1.month.ago,
|
||||
:comments => 'New commit (#2). Fixes #1 @1h',
|
||||
:revision => '12345')
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
assert c.save
|
||||
end
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
issue = Issue.find(1)
|
||||
assert_equal 1, issue.status_id
|
||||
assert_equal 0, issue.done_ratio
|
||||
end
|
||||
|
||||
def test_2_repositories_with_same_backend_should_not_link_issue_multiple_times
|
||||
Setting.commit_ref_keywords = '*'
|
||||
r1 = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///svn1')
|
||||
r2 = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn2', :url => 'file:///svn1')
|
||||
now = Time.now
|
||||
assert_difference 'Issue.find(1).changesets.count' do
|
||||
c1 = Changeset.create!(:repository => r1, :committed_on => now, :comments => 'Fixes #1', :revision => '12345')
|
||||
c1 = Changeset.create!(:repository => r2, :committed_on => now, :comments => 'Fixes #1', :revision => '12345')
|
||||
end
|
||||
end
|
||||
|
||||
def test_text_tag_revision
|
||||
c = Changeset.new(:revision => '520')
|
||||
assert_equal 'r520', c.text_tag
|
||||
end
|
||||
|
||||
def test_text_tag_revision_with_same_project
|
||||
c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
|
||||
assert_equal 'r520', c.text_tag(Project.find(1))
|
||||
end
|
||||
|
||||
def test_text_tag_revision_with_different_project
|
||||
c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
|
||||
assert_equal 'ecookbook:r520', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_text_tag_revision_with_repository_identifier
|
||||
r = Repository::Subversion.create!(
|
||||
:project_id => 1,
|
||||
:url => 'svn://localhost/test',
|
||||
:identifier => 'documents')
|
||||
c = Changeset.new(:revision => '520', :repository => r)
|
||||
assert_equal 'documents|r520', c.text_tag
|
||||
assert_equal 'ecookbook:documents|r520', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_text_tag_hash
|
||||
c = Changeset.new(
|
||||
:scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518',
|
||||
:revision => '7234cb2750b63f47bff735edc50a1c0a433c2518')
|
||||
assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
|
||||
end
|
||||
|
||||
def test_text_tag_hash_with_same_project
|
||||
c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
|
||||
assert_equal 'commit:7234cb27', c.text_tag(Project.find(1))
|
||||
end
|
||||
|
||||
def test_text_tag_hash_with_different_project
|
||||
c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
|
||||
assert_equal 'ecookbook:commit:7234cb27', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_text_tag_hash_all_number
|
||||
c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
|
||||
assert_equal 'commit:0123456789', c.text_tag
|
||||
end
|
||||
|
||||
def test_text_tag_hash_with_repository_identifier
|
||||
r = Repository::Subversion.new(
|
||||
:project_id => 1,
|
||||
:url => 'svn://localhost/test',
|
||||
:identifier => 'documents')
|
||||
c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => r)
|
||||
assert_equal 'commit:documents|7234cb27', c.text_tag
|
||||
assert_equal 'ecookbook:commit:documents|7234cb27', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_previous
|
||||
changeset = Changeset.find_by_revision('3')
|
||||
assert_equal Changeset.find_by_revision('2'), changeset.previous
|
||||
end
|
||||
|
||||
def test_previous_nil
|
||||
changeset = Changeset.find_by_revision('1')
|
||||
assert_nil changeset.previous
|
||||
end
|
||||
|
||||
def test_next
|
||||
changeset = Changeset.find_by_revision('2')
|
||||
assert_equal Changeset.find_by_revision('3'), changeset.next
|
||||
end
|
||||
|
||||
def test_next_nil
|
||||
changeset = Changeset.find_by_revision('10')
|
||||
assert_nil changeset.next
|
||||
end
|
||||
|
||||
def test_comments_should_be_converted_to_utf8
|
||||
proj = Project.find(3)
|
||||
# str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
|
||||
str = "Texte encod\xe9 en ISO-8859-1.".force_encoding("ASCII-8BIT")
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => str)
|
||||
assert( c.save )
|
||||
str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1.".force_encoding("UTF-8")
|
||||
assert_equal str_utf8, c.comments
|
||||
end
|
||||
|
||||
def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
|
||||
proj = Project.find(3)
|
||||
# str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
|
||||
str1 = "Texte encod\xe9 en ISO-8859-1.".force_encoding("UTF-8")
|
||||
str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'UTF-8' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => str1,
|
||||
:committer => str2)
|
||||
assert( c.save )
|
||||
assert_equal "Texte encod? en ISO-8859-1.", c.comments
|
||||
assert_equal "?a?b?c?d?e test", c.committer
|
||||
end
|
||||
|
||||
def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
|
||||
proj = Project.find(3)
|
||||
str = "test\xb5\xfetest\xb5\xfe".force_encoding('ASCII-8BIT')
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-2022-JP' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => str)
|
||||
assert( c.save )
|
||||
assert_equal "test??test??", c.comments
|
||||
end
|
||||
|
||||
def test_comments_should_be_converted_all_latin1_to_utf8
|
||||
s1 = "\xC2\x80"
|
||||
s2 = "\xc3\x82\xc2\x80"
|
||||
s4 = s2.dup
|
||||
s3 = s1.dup
|
||||
s1.force_encoding('ASCII-8BIT')
|
||||
s2.force_encoding('ASCII-8BIT')
|
||||
s3.force_encoding('ISO-8859-1')
|
||||
s4.force_encoding('UTF-8')
|
||||
assert_equal s3.encode('UTF-8'), s4
|
||||
proj = Project.find(3)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => s1)
|
||||
assert( c.save )
|
||||
assert_equal s4, c.comments
|
||||
end
|
||||
|
||||
def test_invalid_utf8_sequences_in_paths_should_be_replaced
|
||||
proj = Project.find(3)
|
||||
str1 = "Texte encod\xe9 en ISO-8859-1".force_encoding("UTF-8")
|
||||
str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test".force_encoding("ASCII-8BIT")
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'UTF-8' )
|
||||
assert r
|
||||
cs = Changeset.new(
|
||||
:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => "test")
|
||||
assert(cs.save)
|
||||
ch = Change.new(
|
||||
:changeset => cs,
|
||||
:action => "A",
|
||||
:path => str1,
|
||||
:from_path => str2,
|
||||
:from_revision => "345")
|
||||
assert(ch.save)
|
||||
assert_equal "Texte encod? en ISO-8859-1", ch.path
|
||||
assert_equal "?a?b?c?d?e test", ch.from_path
|
||||
end
|
||||
|
||||
def test_comments_nil
|
||||
proj = Project.find(3)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => nil,
|
||||
:committer => nil)
|
||||
assert( c.save )
|
||||
assert_equal "", c.comments
|
||||
assert_nil c.committer
|
||||
assert_equal "UTF-8", c.comments.encoding.to_s
|
||||
end
|
||||
|
||||
def test_comments_empty
|
||||
proj = Project.find(3)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => "",
|
||||
:committer => "")
|
||||
assert( c.save )
|
||||
assert_equal "", c.comments
|
||||
assert_equal "", c.committer
|
||||
assert_equal "UTF-8", c.comments.encoding.to_s
|
||||
assert_equal "UTF-8", c.committer.encoding.to_s
|
||||
end
|
||||
|
||||
def test_comments_should_accept_more_than_64k
|
||||
c = Changeset.new(:repository => Repository.first,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => "a" * 500.kilobyte)
|
||||
assert c.save
|
||||
c.reload
|
||||
assert_equal 500.kilobyte, c.comments.size
|
||||
end
|
||||
|
||||
def test_identifier
|
||||
c = Changeset.find_by_revision('1')
|
||||
assert_equal c.revision, c.identifier
|
||||
end
|
||||
end
|
||||
57
test/unit/comment_test.rb
Normal file
57
test/unit/comment_test.rb
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# 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 CommentTest < ActiveSupport::TestCase
|
||||
fixtures :users, :email_addresses, :news, :comments, :projects, :enabled_modules
|
||||
|
||||
def setup
|
||||
@jsmith = User.find(2)
|
||||
@news = News.find(1)
|
||||
end
|
||||
|
||||
def test_create
|
||||
comment = Comment.new(:commented => @news, :author => @jsmith, :comments => "my comment")
|
||||
assert comment.save
|
||||
@news.reload
|
||||
assert_equal 2, @news.comments_count
|
||||
end
|
||||
|
||||
def test_create_should_send_notification
|
||||
Watcher.create!(:watchable => @news, :user => @jsmith)
|
||||
|
||||
with_settings :notified_events => %w(news_comment_added) do
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate
|
||||
comment = Comment.new(:commented => @news)
|
||||
assert !comment.save
|
||||
assert_equal 2, comment.errors.count
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
comment = Comment.find(1)
|
||||
assert comment.destroy
|
||||
@news.reload
|
||||
assert_equal 0, @news.comments_count
|
||||
end
|
||||
end
|
||||
343
test/unit/custom_field_test.rb
Normal file
343
test/unit/custom_field_test.rb
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
# 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 CustomFieldTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :roles, :projects,
|
||||
:trackers, :issue_statuses,
|
||||
:issues
|
||||
|
||||
def test_create
|
||||
field = UserCustomField.new(:name => 'Money money money', :field_format => 'float')
|
||||
assert field.save
|
||||
end
|
||||
|
||||
def test_before_validation
|
||||
field = CustomField.new(:name => 'test_before_validation', :field_format => 'int')
|
||||
field.searchable = true
|
||||
assert field.save
|
||||
assert_equal false, field.searchable
|
||||
field.searchable = true
|
||||
assert field.save
|
||||
assert_equal false, field.searchable
|
||||
end
|
||||
|
||||
def test_regexp_validation
|
||||
field = IssueCustomField.new(:name => 'regexp', :field_format => 'text', :regexp => '[a-z0-9')
|
||||
assert !field.save
|
||||
assert_include I18n.t('activerecord.errors.messages.invalid'),
|
||||
field.errors[:regexp]
|
||||
field.regexp = '[a-z0-9]'
|
||||
assert field.save
|
||||
end
|
||||
|
||||
def test_default_value_should_be_validated
|
||||
field = CustomField.new(:name => 'Test', :field_format => 'int')
|
||||
field.default_value = 'abc'
|
||||
assert !field.valid?
|
||||
field.default_value = '6'
|
||||
assert field.valid?
|
||||
end
|
||||
|
||||
def test_default_value_should_not_be_validated_when_blank
|
||||
field = CustomField.new(:name => 'Test', :field_format => 'list',
|
||||
:possible_values => ['a', 'b'], :is_required => true,
|
||||
:default_value => '')
|
||||
assert field.valid?
|
||||
end
|
||||
|
||||
def test_field_format_should_be_validated
|
||||
field = CustomField.new(:name => 'Test', :field_format => 'foo')
|
||||
assert !field.valid?
|
||||
end
|
||||
|
||||
def test_field_format_validation_should_accept_formats_added_at_runtime
|
||||
Redmine::FieldFormat.add 'foobar', Class.new(Redmine::FieldFormat::Base)
|
||||
|
||||
field = CustomField.new(:name => 'Some Custom Field', :field_format => 'foobar')
|
||||
assert field.valid?, 'field should be valid'
|
||||
ensure
|
||||
Redmine::FieldFormat.delete 'foobar'
|
||||
end
|
||||
|
||||
def test_should_not_change_field_format_of_existing_custom_field
|
||||
field = CustomField.find(1)
|
||||
field.field_format = 'int'
|
||||
assert_equal 'list', field.field_format
|
||||
end
|
||||
|
||||
def test_possible_values_should_accept_an_array
|
||||
field = CustomField.new
|
||||
field.possible_values = ["One value", ""]
|
||||
assert_equal ["One value"], field.possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_should_stringify_values
|
||||
field = CustomField.new
|
||||
field.possible_values = [1, 2]
|
||||
assert_equal ["1", "2"], field.possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_should_accept_a_string
|
||||
field = CustomField.new
|
||||
field.possible_values = "One value"
|
||||
assert_equal ["One value"], field.possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_should_return_utf8_encoded_strings
|
||||
field = CustomField.new
|
||||
s = "Value".force_encoding('BINARY')
|
||||
field.possible_values = s
|
||||
assert_equal [s], field.possible_values
|
||||
assert_equal 'UTF-8', field.possible_values.first.encoding.name
|
||||
end
|
||||
|
||||
def test_possible_values_should_accept_a_multiline_string
|
||||
field = CustomField.new
|
||||
field.possible_values = "One value\nAnd another one \r\n \n"
|
||||
assert_equal ["One value", "And another one"], field.possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_stored_as_binary_should_be_utf8_encoded
|
||||
field = CustomField.find(11)
|
||||
assert_kind_of Array, field.possible_values
|
||||
assert field.possible_values.size > 0
|
||||
field.possible_values.each do |value|
|
||||
assert_equal "UTF-8", value.encoding.name
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
field = CustomField.find(1)
|
||||
assert field.destroy
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_should_return_an_instance
|
||||
f = CustomField.new_subclass_instance('IssueCustomField')
|
||||
assert_kind_of IssueCustomField, f
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_should_set_attributes
|
||||
f = CustomField.new_subclass_instance('IssueCustomField', :name => 'Test')
|
||||
assert_kind_of IssueCustomField, f
|
||||
assert_equal 'Test', f.name
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_with_invalid_class_name_should_return_nil
|
||||
assert_nil CustomField.new_subclass_instance('WrongClassName')
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_with_non_subclass_name_should_return_nil
|
||||
assert_nil CustomField.new_subclass_instance('Project')
|
||||
end
|
||||
|
||||
def test_string_field_validation_with_blank_value
|
||||
f = CustomField.new(:field_format => 'string')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
|
||||
f.is_required = true
|
||||
assert !f.valid_field_value?(nil)
|
||||
assert !f.valid_field_value?('')
|
||||
end
|
||||
|
||||
def test_string_field_validation_with_min_and_max_lengths
|
||||
f = CustomField.new(:field_format => 'string', :min_length => 2, :max_length => 5)
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?('a' * 2)
|
||||
assert !f.valid_field_value?('a')
|
||||
assert !f.valid_field_value?('a' * 6)
|
||||
end
|
||||
|
||||
def test_string_field_validation_with_regexp
|
||||
f = CustomField.new(:field_format => 'string', :regexp => '^[A-Z0-9]*$')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?('ABC')
|
||||
assert !f.valid_field_value?('abc')
|
||||
end
|
||||
|
||||
def test_date_field_validation
|
||||
f = CustomField.new(:field_format => 'date')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?('1975-07-14')
|
||||
assert !f.valid_field_value?('1975-07-33')
|
||||
assert !f.valid_field_value?('abc')
|
||||
end
|
||||
|
||||
def test_list_field_validation
|
||||
f = CustomField.new(:field_format => 'list', :possible_values => ['value1', 'value2'])
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?('value2')
|
||||
assert !f.valid_field_value?('abc')
|
||||
end
|
||||
|
||||
def test_int_field_validation
|
||||
f = CustomField.new(:field_format => 'int')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?('123')
|
||||
assert f.valid_field_value?('+123')
|
||||
assert f.valid_field_value?('-123')
|
||||
assert !f.valid_field_value?('6abc')
|
||||
assert f.valid_field_value?(123)
|
||||
end
|
||||
|
||||
def test_float_field_validation
|
||||
f = CustomField.new(:field_format => 'float')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?('11.2')
|
||||
assert f.valid_field_value?('-6.250')
|
||||
assert f.valid_field_value?('5')
|
||||
assert !f.valid_field_value?('6abc')
|
||||
assert f.valid_field_value?(11.2)
|
||||
end
|
||||
|
||||
def test_multi_field_validation
|
||||
f = CustomField.new(:field_format => 'list', :multiple => 'true', :possible_values => ['value1', 'value2'])
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert !f.valid_field_value?(' ')
|
||||
assert f.valid_field_value?([])
|
||||
assert f.valid_field_value?([nil])
|
||||
assert f.valid_field_value?([''])
|
||||
assert !f.valid_field_value?([' '])
|
||||
|
||||
assert f.valid_field_value?('value2')
|
||||
assert !f.valid_field_value?('abc')
|
||||
|
||||
assert f.valid_field_value?(['value2'])
|
||||
assert !f.valid_field_value?(['abc'])
|
||||
|
||||
assert f.valid_field_value?(['', 'value2'])
|
||||
assert !f.valid_field_value?(['', 'abc'])
|
||||
|
||||
assert f.valid_field_value?(['value1', 'value2'])
|
||||
assert !f.valid_field_value?(['value1', 'abc'])
|
||||
end
|
||||
|
||||
def test_changing_multiple_to_false_should_delete_multiple_values
|
||||
field = ProjectCustomField.create!(:name => 'field', :field_format => 'list',
|
||||
:multiple => 'true',
|
||||
:possible_values => ['field1', 'field2'])
|
||||
other = ProjectCustomField.create!(:name => 'other', :field_format => 'list',
|
||||
:multiple => 'true',
|
||||
:possible_values => ['other1', 'other2'])
|
||||
item_with_multiple_values = Project.generate!(:custom_field_values =>
|
||||
{field.id => ['field1', 'field2'],
|
||||
other.id => ['other1', 'other2']})
|
||||
item_with_single_values = Project.generate!(:custom_field_values =>
|
||||
{field.id => ['field1'],
|
||||
other.id => ['other2']})
|
||||
assert_difference 'CustomValue.count', -1 do
|
||||
field.multiple = false
|
||||
field.save!
|
||||
end
|
||||
|
||||
item_with_multiple_values = Project.find(item_with_multiple_values.id)
|
||||
assert_kind_of String, item_with_multiple_values.custom_field_value(field)
|
||||
assert_kind_of Array, item_with_multiple_values.custom_field_value(other)
|
||||
assert_equal 2, item_with_multiple_values.custom_field_value(other).size
|
||||
end
|
||||
|
||||
def test_value_class_should_return_the_class_used_for_fields_values
|
||||
assert_equal User, CustomField.new(:field_format => 'user').value_class
|
||||
assert_equal Version, CustomField.new(:field_format => 'version').value_class
|
||||
end
|
||||
|
||||
def test_value_class_should_return_nil_for_other_fields
|
||||
assert_nil CustomField.new(:field_format => 'text').value_class
|
||||
assert_nil CustomField.new.value_class
|
||||
end
|
||||
|
||||
def test_value_from_keyword_for_list_custom_field
|
||||
field = CustomField.find(1)
|
||||
assert_equal 'PostgreSQL', field.value_from_keyword('postgresql', Issue.find(1))
|
||||
end
|
||||
|
||||
def test_visibile_scope_with_admin_should_return_all_custom_fields
|
||||
admin = User.generate! {|user| user.admin = true}
|
||||
CustomField.delete_all
|
||||
fields = [
|
||||
CustomField.generate!(:visible => true),
|
||||
CustomField.generate!(:visible => false),
|
||||
CustomField.generate!(:visible => false, :role_ids => [1, 3]),
|
||||
CustomField.generate!(:visible => false, :role_ids => [1, 2]),
|
||||
]
|
||||
|
||||
assert_equal 4, CustomField.visible(admin).count
|
||||
end
|
||||
|
||||
def test_visibile_scope_with_non_admin_user_should_return_visible_custom_fields
|
||||
CustomField.delete_all
|
||||
fields = [
|
||||
CustomField.generate!(:visible => true),
|
||||
CustomField.generate!(:visible => false),
|
||||
CustomField.generate!(:visible => false, :role_ids => [1, 3]),
|
||||
CustomField.generate!(:visible => false, :role_ids => [1, 2]),
|
||||
]
|
||||
user = User.generate!
|
||||
User.add_to_project(user, Project.first, Role.find(3))
|
||||
|
||||
assert_equal [fields[0], fields[2]], CustomField.visible(user).order("id").to_a
|
||||
end
|
||||
|
||||
def test_visibile_scope_with_anonymous_user_should_return_visible_custom_fields
|
||||
CustomField.delete_all
|
||||
fields = [
|
||||
CustomField.generate!(:visible => true),
|
||||
CustomField.generate!(:visible => false),
|
||||
CustomField.generate!(:visible => false, :role_ids => [1, 3]),
|
||||
CustomField.generate!(:visible => false, :role_ids => [1, 2]),
|
||||
]
|
||||
|
||||
assert_equal [fields[0]], CustomField.visible(User.anonymous).order("id").to_a
|
||||
end
|
||||
|
||||
def test_float_cast_blank_value_should_return_nil
|
||||
field = CustomField.new(:field_format => 'float')
|
||||
assert_nil field.cast_value(nil)
|
||||
assert_nil field.cast_value('')
|
||||
end
|
||||
|
||||
def test_float_cast_valid_value_should_return_float
|
||||
field = CustomField.new(:field_format => 'float')
|
||||
assert_equal 12.0, field.cast_value('12')
|
||||
assert_equal 12.5, field.cast_value('12.5')
|
||||
assert_equal 12.5, field.cast_value('+12.5')
|
||||
assert_equal -12.5, field.cast_value('-12.5')
|
||||
end
|
||||
end
|
||||
78
test/unit/custom_field_user_format_test.rb
Normal file
78
test/unit/custom_field_user_format_test.rb
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# 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 CustomFieldUserFormatTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues
|
||||
|
||||
def setup
|
||||
@field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user')
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_no_arguments
|
||||
assert_equal [], @field.possible_values_options
|
||||
assert_equal [], @field.possible_values_options(nil)
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_project_resource
|
||||
project = Project.find(1)
|
||||
possible_values_options = @field.possible_values_options(project.issues.first)
|
||||
assert possible_values_options.any?
|
||||
assert_equal project.users.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_array
|
||||
projects = Project.find([1, 2])
|
||||
possible_values_options = @field.possible_values_options(projects)
|
||||
assert possible_values_options.any?
|
||||
assert_equal (projects.first.users & projects.last.users).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_possible_custom_value_options_should_not_include_locked_users
|
||||
custom_value = CustomValue.new(:customized => Issue.find(1), :custom_field => @field)
|
||||
assert_include '2', @field.possible_custom_value_options(custom_value).map(&:last)
|
||||
|
||||
assert User.find(2).lock!
|
||||
assert_not_include '2', @field.possible_custom_value_options(custom_value).map(&:last)
|
||||
end
|
||||
|
||||
def test_possible_custom_value_options_should_include_user_that_was_assigned_to_the_custom_value
|
||||
user = User.generate!
|
||||
custom_value = CustomValue.new(:customized => Issue.find(1), :custom_field => @field)
|
||||
assert_not_include user.id.to_s, @field.possible_custom_value_options(custom_value).map(&:last)
|
||||
|
||||
custom_value.value = user.id
|
||||
custom_value.save!
|
||||
assert_include user.id.to_s, @field.possible_custom_value_options(custom_value).map(&:last)
|
||||
end
|
||||
|
||||
def test_cast_blank_value
|
||||
assert_nil @field.cast_value(nil)
|
||||
assert_nil @field.cast_value("")
|
||||
end
|
||||
|
||||
def test_cast_valid_value
|
||||
user = @field.cast_value("2")
|
||||
assert_kind_of User, user
|
||||
assert_equal User.find(2), user
|
||||
end
|
||||
|
||||
def test_cast_invalid_value
|
||||
assert_nil @field.cast_value("187")
|
||||
end
|
||||
end
|
||||
61
test/unit/custom_field_version_format_test.rb
Normal file
61
test/unit/custom_field_version_format_test.rb
Normal 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 CustomFieldVersionFormatTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues, :versions
|
||||
|
||||
def setup
|
||||
@field = IssueCustomField.create!(:name => 'Tester', :field_format => 'version')
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_no_arguments
|
||||
Version.delete_all
|
||||
assert_equal [], @field.possible_values_options
|
||||
assert_equal [], @field.possible_values_options(nil)
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_project_resource
|
||||
project = Project.find(1)
|
||||
possible_values_options = @field.possible_values_options(project.issues.first)
|
||||
assert possible_values_options.any?
|
||||
assert_equal project.shared_versions.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_array
|
||||
projects = Project.find([1, 2])
|
||||
possible_values_options = @field.possible_values_options(projects)
|
||||
assert possible_values_options.any?
|
||||
assert_equal (projects.first.shared_versions & projects.last.shared_versions).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_cast_blank_value
|
||||
assert_nil @field.cast_value(nil)
|
||||
assert_nil @field.cast_value("")
|
||||
end
|
||||
|
||||
def test_cast_valid_value
|
||||
version = @field.cast_value("2")
|
||||
assert_kind_of Version, version
|
||||
assert_equal Version.find(2), version
|
||||
end
|
||||
|
||||
def test_cast_invalid_value
|
||||
assert_nil @field.cast_value("187")
|
||||
end
|
||||
end
|
||||
49
test/unit/custom_value_test.rb
Normal file
49
test/unit/custom_value_test.rb
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# 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 CustomValueTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :custom_values, :users
|
||||
|
||||
def test_new_without_value_should_set_default_value
|
||||
field = CustomField.generate!(:default_value => 'Default string')
|
||||
|
||||
v = CustomValue.new(:custom_field => field)
|
||||
assert_equal 'Default string', v.value
|
||||
end
|
||||
|
||||
def test_new_with_value_should_not_set_default_value
|
||||
field = CustomField.generate!(:default_value => 'Default string')
|
||||
|
||||
v = CustomValue.new(:custom_field => field, :value => 'String')
|
||||
assert_equal 'String', v.value
|
||||
end
|
||||
|
||||
def test_new_with_nil_value_should_not_set_default_value
|
||||
field = CustomField.generate!(:default_value => 'Default string')
|
||||
|
||||
v = CustomValue.new(:custom_field => field, :value => nil)
|
||||
assert_nil v.value
|
||||
end
|
||||
|
||||
def test_sti_polymorphic_association
|
||||
# Rails uses top level sti class for polymorphic association. See #3978.
|
||||
assert !User.find(4).custom_values.empty?
|
||||
assert !CustomValue.find(2).customized.nil?
|
||||
end
|
||||
end
|
||||
60
test/unit/default_data_test.rb
Normal file
60
test/unit/default_data_test.rb
Normal 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 DefaultDataTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
fixtures :roles
|
||||
|
||||
def test_no_data
|
||||
assert !Redmine::DefaultData::Loader::no_data?
|
||||
clear_data
|
||||
assert Redmine::DefaultData::Loader::no_data?
|
||||
end
|
||||
|
||||
def test_load
|
||||
clear_data
|
||||
assert Redmine::DefaultData::Loader::load('en')
|
||||
assert_not_nil DocumentCategory.first
|
||||
assert_not_nil IssuePriority.first
|
||||
assert_not_nil TimeEntryActivity.first
|
||||
assert_not_nil WorkflowTransition.first
|
||||
end
|
||||
|
||||
def test_load_for_all_language
|
||||
valid_languages.each do |lang|
|
||||
clear_data
|
||||
begin
|
||||
assert Redmine::DefaultData::Loader::load(lang, :workflow => false)
|
||||
assert_not_nil DocumentCategory.first
|
||||
assert_not_nil IssuePriority.first
|
||||
assert_not_nil TimeEntryActivity.first
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
assert false, ":#{lang} default data is invalid (#{e.message})."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def clear_data
|
||||
Role.where("builtin = 0").delete_all
|
||||
Tracker.delete_all
|
||||
IssueStatus.delete_all
|
||||
Enumeration.delete_all
|
||||
WorkflowRule.delete_all
|
||||
end
|
||||
end
|
||||
47
test/unit/document_category_test.rb
Normal file
47
test/unit/document_category_test.rb
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# 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 DocumentCategoryTest < ActiveSupport::TestCase
|
||||
fixtures :enumerations, :documents, :issues
|
||||
|
||||
def test_should_be_an_enumeration
|
||||
assert DocumentCategory.ancestors.include?(Enumeration)
|
||||
end
|
||||
|
||||
def test_objects_count
|
||||
assert_equal 2, DocumentCategory.find_by_name("Uncategorized").objects_count
|
||||
assert_equal 0, DocumentCategory.find_by_name("User documentation").objects_count
|
||||
end
|
||||
|
||||
def test_option_name
|
||||
assert_equal :enumeration_doc_categories, DocumentCategory.new.option_name
|
||||
end
|
||||
|
||||
def test_default
|
||||
assert_nil DocumentCategory.where(:is_default => true).first
|
||||
e = Enumeration.find_by_name('Technical documentation')
|
||||
e.update_attributes(:is_default => true)
|
||||
assert_equal 3, DocumentCategory.default.id
|
||||
end
|
||||
|
||||
def test_force_default
|
||||
assert_nil DocumentCategory.where(:is_default => true).first
|
||||
assert_equal 1, DocumentCategory.default.id
|
||||
end
|
||||
end
|
||||
68
test/unit/document_test.rb
Normal file
68
test/unit/document_test.rb
Normal 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 DocumentTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :enumerations, :documents, :attachments,
|
||||
:enabled_modules,
|
||||
:users, :email_addresses, :members, :member_roles, :roles,
|
||||
:groups_users
|
||||
|
||||
def test_create
|
||||
doc = Document.new(:project => Project.find(1), :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
|
||||
assert doc.save
|
||||
end
|
||||
|
||||
def test_create_with_long_title
|
||||
title = 'x'*255
|
||||
doc = Document.new(:project => Project.find(1), :title => title, :category => DocumentCategory.first)
|
||||
assert_save doc
|
||||
assert_equal title, doc.reload.title
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
with_settings :notified_events => %w(document_added) do
|
||||
doc = Document.new(:project => Project.find(1), :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
|
||||
assert doc.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_with_default_category
|
||||
# Sets a default category
|
||||
e = Enumeration.find_by_name('Technical documentation')
|
||||
e.update_attributes(:is_default => true)
|
||||
|
||||
doc = Document.new(:project => Project.find(1), :title => 'New document')
|
||||
assert_equal e, doc.category
|
||||
assert doc.save
|
||||
end
|
||||
|
||||
def test_updated_on_with_attachments
|
||||
d = Document.find(1)
|
||||
assert d.attachments.any?
|
||||
assert_equal d.attachments.map(&:created_on).max, d.updated_on
|
||||
end
|
||||
|
||||
def test_updated_on_without_attachments
|
||||
d = Document.find(2)
|
||||
assert d.attachments.empty?
|
||||
assert_equal d.created_on, d.updated_on
|
||||
end
|
||||
end
|
||||
43
test/unit/enabled_module_test.rb
Normal file
43
test/unit/enabled_module_test.rb
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 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 EnabledModuleTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :trackers, :issue_statuses, :wikis
|
||||
|
||||
def test_enabling_wiki_should_create_a_wiki
|
||||
CustomField.delete_all
|
||||
project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject', :enabled_module_names => [])
|
||||
assert_nil project.wiki
|
||||
project.enabled_module_names = ['wiki']
|
||||
project.reload
|
||||
assert_not_nil project.wiki
|
||||
assert_equal 'Wiki', project.wiki.start_page
|
||||
end
|
||||
|
||||
def test_reenabling_wiki_should_not_create_another_wiki
|
||||
project = Project.find(1)
|
||||
assert_not_nil project.wiki
|
||||
project.enabled_module_names = []
|
||||
project.reload
|
||||
assert_no_difference 'Wiki.count' do
|
||||
project.enabled_module_names = ['wiki']
|
||||
end
|
||||
assert_not_nil project.wiki
|
||||
end
|
||||
end
|
||||
175
test/unit/enumeration_test.rb
Normal file
175
test/unit/enumeration_test.rb
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
# 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 EnumerationTest < ActiveSupport::TestCase
|
||||
fixtures :enumerations, :issues, :custom_fields, :custom_values
|
||||
|
||||
def test_objects_count
|
||||
# low priority
|
||||
assert_equal 6, Enumeration.find(4).objects_count
|
||||
# urgent
|
||||
assert_equal 0, Enumeration.find(7).objects_count
|
||||
end
|
||||
|
||||
def test_in_use
|
||||
# low priority
|
||||
assert Enumeration.find(4).in_use?
|
||||
# urgent
|
||||
assert !Enumeration.find(7).in_use?
|
||||
end
|
||||
|
||||
def test_default
|
||||
e = Enumeration.default
|
||||
assert e.is_a?(Enumeration)
|
||||
assert e.is_default?
|
||||
assert e.active?
|
||||
assert_equal 'Default Enumeration', e.name
|
||||
end
|
||||
|
||||
def test_default_non_active
|
||||
e = Enumeration.find(12)
|
||||
assert e.is_a?(Enumeration)
|
||||
assert e.is_default?
|
||||
assert e.active?
|
||||
e.update_attributes(:active => false)
|
||||
assert e.is_default?
|
||||
assert !e.active?
|
||||
end
|
||||
|
||||
def test_create
|
||||
e = Enumeration.new(:name => 'Not default', :is_default => false)
|
||||
e.type = 'Enumeration'
|
||||
assert e.save
|
||||
assert_equal 'Default Enumeration', Enumeration.default.name
|
||||
end
|
||||
|
||||
def test_create_as_default
|
||||
e = Enumeration.new(:name => 'Very urgent', :is_default => true)
|
||||
e.type = 'Enumeration'
|
||||
assert e.save
|
||||
assert_equal e, Enumeration.default
|
||||
end
|
||||
|
||||
def test_update_default
|
||||
e = Enumeration.default
|
||||
e.update_attributes(:name => 'Changed', :is_default => true)
|
||||
assert_equal e, Enumeration.default
|
||||
end
|
||||
|
||||
def test_update_default_to_non_default
|
||||
e = Enumeration.default
|
||||
e.update_attributes(:name => 'Changed', :is_default => false)
|
||||
assert_nil Enumeration.default
|
||||
end
|
||||
|
||||
def test_change_default
|
||||
e = Enumeration.find_by_name('Default Enumeration')
|
||||
e.update_attributes(:name => 'Changed Enumeration', :is_default => true)
|
||||
assert_equal e, Enumeration.default
|
||||
end
|
||||
|
||||
def test_destroy_with_reassign
|
||||
Enumeration.find(4).destroy(Enumeration.find(6))
|
||||
assert_nil Issue.where(:priority_id => 4).first
|
||||
assert_equal 6, Enumeration.find(6).objects_count
|
||||
end
|
||||
|
||||
def test_should_be_customizable
|
||||
assert Enumeration.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
|
||||
end
|
||||
|
||||
def test_should_belong_to_a_project
|
||||
association = Enumeration.reflect_on_association(:project)
|
||||
assert association, "No Project association found"
|
||||
assert_equal :belongs_to, association.macro
|
||||
end
|
||||
|
||||
def test_should_act_as_tree
|
||||
enumeration = Enumeration.find(4)
|
||||
|
||||
assert enumeration.respond_to?(:parent)
|
||||
assert enumeration.respond_to?(:children)
|
||||
end
|
||||
|
||||
def test_is_override
|
||||
# Defaults to off
|
||||
enumeration = Enumeration.find(4)
|
||||
assert !enumeration.is_override?
|
||||
|
||||
# Setup as an override
|
||||
enumeration.parent = Enumeration.find(5)
|
||||
assert enumeration.is_override?
|
||||
end
|
||||
|
||||
def test_get_subclasses
|
||||
classes = Enumeration.get_subclasses
|
||||
assert_include IssuePriority, classes
|
||||
assert_include DocumentCategory, classes
|
||||
assert_include TimeEntryActivity, classes
|
||||
|
||||
classes.each do |klass|
|
||||
assert_equal Enumeration, klass.superclass
|
||||
end
|
||||
end
|
||||
|
||||
def test_list_should_be_scoped_for_each_type
|
||||
Enumeration.delete_all
|
||||
|
||||
a = IssuePriority.create!(:name => 'A')
|
||||
b = IssuePriority.create!(:name => 'B')
|
||||
c = DocumentCategory.create!(:name => 'C')
|
||||
|
||||
assert_equal [1, 2, 1], [a, b, c].map(&:reload).map(&:position)
|
||||
end
|
||||
|
||||
def test_override_should_be_created_with_same_position_as_parent
|
||||
Enumeration.delete_all
|
||||
|
||||
a = IssuePriority.create!(:name => 'A')
|
||||
b = IssuePriority.create!(:name => 'B')
|
||||
override = IssuePriority.create!(:name => 'BB', :parent_id => b.id)
|
||||
|
||||
assert_equal [1, 2, 2], [a, b, override].map(&:reload).map(&:position)
|
||||
end
|
||||
|
||||
def test_override_position_should_be_updated_with_parent_position
|
||||
Enumeration.delete_all
|
||||
|
||||
a = IssuePriority.create!(:name => 'A')
|
||||
b = IssuePriority.create!(:name => 'B')
|
||||
override = IssuePriority.create!(:name => 'BB', :parent_id => b.id)
|
||||
b.position -= 1
|
||||
b.save!
|
||||
|
||||
assert_equal [2, 1, 1], [a, b, override].map(&:reload).map(&:position)
|
||||
end
|
||||
|
||||
def test_destroying_override_should_not_update_positions
|
||||
Enumeration.delete_all
|
||||
|
||||
a = IssuePriority.create!(:name => 'A')
|
||||
b = IssuePriority.create!(:name => 'B')
|
||||
c = IssuePriority.create!(:name => 'C')
|
||||
override = IssuePriority.create!(:name => 'BB', :parent_id => b.id)
|
||||
assert_equal [1, 2, 3, 2], [a, b, c, override].map(&:reload).map(&:position)
|
||||
|
||||
override.destroy
|
||||
assert_equal [1, 2, 3], [a, b, c].map(&:reload).map(&:position)
|
||||
end
|
||||
end
|
||||
169
test/unit/group_test.rb
Normal file
169
test/unit/group_test.rb
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
# 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 GroupTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:groups_users
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def test_create
|
||||
g = Group.new(:name => 'New group')
|
||||
assert g.save
|
||||
g.reload
|
||||
assert_equal 'New group', g.name
|
||||
end
|
||||
|
||||
def test_name_should_accept_255_characters
|
||||
name = 'a' * 255
|
||||
g = Group.new(:name => name)
|
||||
assert g.save
|
||||
g.reload
|
||||
assert_equal name, g.name
|
||||
end
|
||||
|
||||
def test_blank_name_error_message
|
||||
set_language_if_valid 'en'
|
||||
g = Group.new
|
||||
assert !g.save
|
||||
assert_include "Name cannot be blank", g.errors.full_messages
|
||||
end
|
||||
|
||||
def test_blank_name_error_message_fr
|
||||
set_language_if_valid 'fr'
|
||||
str = "Nom doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8')
|
||||
g = Group.new
|
||||
assert !g.save
|
||||
assert_include str, g.errors.full_messages
|
||||
end
|
||||
|
||||
def test_group_roles_should_be_given_to_added_user
|
||||
group = Group.find(11)
|
||||
user = User.find(9)
|
||||
project = Project.first
|
||||
|
||||
Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
|
||||
group.users << user
|
||||
assert user.member_of?(project)
|
||||
end
|
||||
|
||||
def test_new_roles_should_be_given_to_existing_user
|
||||
group = Group.find(11)
|
||||
user = User.find(9)
|
||||
project = Project.first
|
||||
|
||||
group.users << user
|
||||
m = Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
|
||||
assert user.member_of?(project)
|
||||
end
|
||||
|
||||
def test_user_roles_should_updated_when_updating_user_ids
|
||||
group = Group.find(11)
|
||||
user = User.find(9)
|
||||
project = Project.first
|
||||
|
||||
Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
|
||||
group.user_ids = [user.id]
|
||||
group.save!
|
||||
assert User.find(9).member_of?(project)
|
||||
|
||||
group.user_ids = [1]
|
||||
group.save!
|
||||
assert !User.find(9).member_of?(project)
|
||||
end
|
||||
|
||||
def test_user_roles_should_updated_when_updating_group_roles
|
||||
group = Group.find(11)
|
||||
user = User.find(9)
|
||||
project = Project.first
|
||||
group.users << user
|
||||
m = Member.create!(:principal => group, :project => project, :role_ids => [1])
|
||||
assert_equal [1], user.reload.roles_for_project(project).collect(&:id).sort
|
||||
|
||||
m.role_ids = [1, 2]
|
||||
assert_equal [1, 2], user.reload.roles_for_project(project).collect(&:id).sort
|
||||
|
||||
m.role_ids = [2]
|
||||
assert_equal [2], user.reload.roles_for_project(project).collect(&:id).sort
|
||||
|
||||
m.role_ids = [1]
|
||||
assert_equal [1], user.reload.roles_for_project(project).collect(&:id).sort
|
||||
end
|
||||
|
||||
def test_user_memberships_should_be_removed_when_removing_group_membership
|
||||
assert User.find(8).member_of?(Project.find(5))
|
||||
Member.find_by_project_id_and_user_id(5, 10).destroy
|
||||
assert !User.find(8).member_of?(Project.find(5))
|
||||
end
|
||||
|
||||
def test_user_roles_should_be_removed_when_removing_user_from_group
|
||||
assert User.find(8).member_of?(Project.find(5))
|
||||
User.find(8).groups = []
|
||||
assert !User.find(8).member_of?(Project.find(5))
|
||||
end
|
||||
|
||||
def test_destroy_should_unassign_issues
|
||||
group = Group.find(10)
|
||||
Issue.where(:id => 1).update_all(["assigned_to_id = ?", group.id])
|
||||
|
||||
assert group.destroy
|
||||
assert group.destroyed?
|
||||
|
||||
assert_nil Issue.find(1).assigned_to_id
|
||||
end
|
||||
|
||||
def test_builtin_groups_should_be_created_if_missing
|
||||
Group.delete_all
|
||||
|
||||
assert_difference 'Group.count', 2 do
|
||||
group = Group.anonymous
|
||||
assert_equal GroupAnonymous, group.class
|
||||
|
||||
group = Group.non_member
|
||||
assert_equal GroupNonMember, group.class
|
||||
end
|
||||
end
|
||||
|
||||
def test_builtin_in_group_should_be_uniq
|
||||
group = GroupAnonymous.new
|
||||
group.name = 'Foo'
|
||||
assert !group.save
|
||||
end
|
||||
|
||||
def test_builtin_in_group_should_not_accept_users
|
||||
group = Group.anonymous
|
||||
assert_raise RuntimeError do
|
||||
group.users << User.find(1)
|
||||
end
|
||||
assert_equal 0, group.reload.users.count
|
||||
end
|
||||
|
||||
def test_sorted_scope_should_sort_groups_alphabetically
|
||||
Group.delete_all
|
||||
b = Group.generate!(:name => 'B')
|
||||
a = Group.generate!(:name => 'A')
|
||||
|
||||
assert_equal %w(A B), Group.sorted.to_a.map(&:name)
|
||||
end
|
||||
end
|
||||
102
test/unit/helpers/activities_helper_test.rb
Normal file
102
test/unit/helpers/activities_helper_test.rb
Normal 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 ActivitiesHelperTest < Redmine::HelperTest
|
||||
include ActivitiesHelper
|
||||
|
||||
class MockEvent
|
||||
attr_reader :event_datetime, :event_group, :name
|
||||
|
||||
def initialize(group=nil)
|
||||
@@count ||= 0
|
||||
@name = "e#{@@count}"
|
||||
@event_datetime = Time.now + @@count.hours
|
||||
@event_group = group || self
|
||||
@@count += 1
|
||||
end
|
||||
|
||||
def self.clear
|
||||
@@count = 0
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
super
|
||||
MockEvent.clear
|
||||
end
|
||||
|
||||
def test_sort_activity_events_should_sort_by_datetime
|
||||
events = []
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new
|
||||
|
||||
assert_equal [
|
||||
['e2', false],
|
||||
['e1', false],
|
||||
['e0', false]
|
||||
], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
|
||||
end
|
||||
|
||||
def test_sort_activity_events_should_group_events
|
||||
events = []
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new(events[0])
|
||||
events << MockEvent.new(events[0])
|
||||
|
||||
assert_equal [
|
||||
['e2', false],
|
||||
['e1', true],
|
||||
['e0', true]
|
||||
], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
|
||||
end
|
||||
|
||||
def test_sort_activity_events_with_group_not_in_set_should_group_events
|
||||
e = MockEvent.new
|
||||
events = []
|
||||
events << MockEvent.new(e)
|
||||
events << MockEvent.new(e)
|
||||
|
||||
assert_equal [
|
||||
['e2', false],
|
||||
['e1', true]
|
||||
], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
|
||||
end
|
||||
|
||||
def test_sort_activity_events_should_sort_by_datetime_and_group
|
||||
events = []
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new(events[1])
|
||||
events << MockEvent.new(events[2])
|
||||
events << MockEvent.new
|
||||
events << MockEvent.new(events[2])
|
||||
|
||||
assert_equal [
|
||||
['e6', false],
|
||||
['e4', true],
|
||||
['e2', true],
|
||||
['e5', false],
|
||||
['e3', false],
|
||||
['e1', true],
|
||||
['e0', false]
|
||||
], sort_activity_events(events).map {|event, grouped| [event.name, grouped]}
|
||||
end
|
||||
end
|
||||
1611
test/unit/helpers/application_helper_test.rb
Normal file
1611
test/unit/helpers/application_helper_test.rb
Normal file
File diff suppressed because it is too large
Load diff
89
test/unit/helpers/custom_fields_helper_test.rb
Normal file
89
test/unit/helpers/custom_fields_helper_test.rb
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# 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 CustomFieldsHelperTest < Redmine::HelperTest
|
||||
include ApplicationHelper
|
||||
include CustomFieldsHelper
|
||||
include ERB::Util
|
||||
|
||||
def test_format_boolean_value
|
||||
I18n.locale = 'en'
|
||||
assert_equal 'Yes', format_value('1', CustomField.new(:field_format => 'bool'))
|
||||
assert_equal 'No', format_value('0', CustomField.new(:field_format => 'bool'))
|
||||
end
|
||||
|
||||
def test_label_tag_should_include_description_as_span_title_if_present
|
||||
field = CustomField.new(:field_format => 'string', :description => 'This is the description')
|
||||
tag = custom_field_label_tag('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in tag, 'label span[title=?]', 'This is the description'
|
||||
end
|
||||
|
||||
def test_label_tag_should_not_include_title_if_description_is_blank
|
||||
field = CustomField.new(:field_format => 'string')
|
||||
tag = custom_field_label_tag('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in tag, 'label span[title]', 0
|
||||
end
|
||||
|
||||
def test_label_tag_should_include_for_attribute_for_select_tag
|
||||
field = CustomField.new(:name => 'Foo', :field_format => 'list')
|
||||
s = custom_field_tag_with_label('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in s, 'label[for]'
|
||||
end
|
||||
|
||||
def test_label_tag_should_not_include_for_attribute_for_checkboxes
|
||||
field = CustomField.new(:name => 'Foo', :field_format => 'list', :edit_tag_style => 'check_box')
|
||||
s = custom_field_tag_with_label('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in s, 'label:not([for])'
|
||||
end
|
||||
|
||||
def test_label_tag_should_include_for_attribute_for_bool_as_select_tag
|
||||
field = CustomField.new(:name => 'Foo', :field_format => 'bool')
|
||||
s = custom_field_tag_with_label('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in s, 'label[for]'
|
||||
end
|
||||
|
||||
def test_label_tag_should_include_for_attribute_for_bool_as_checkbox
|
||||
field = CustomField.new(:name => 'Foo', :field_format => 'bool', :edit_tag_style => 'check_box')
|
||||
s = custom_field_tag_with_label('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in s, 'label[for]'
|
||||
end
|
||||
|
||||
def test_label_tag_should_not_include_for_attribute_for_bool_as_radio
|
||||
field = CustomField.new(:name => 'Foo', :field_format => 'bool', :edit_tag_style => 'radio')
|
||||
s = custom_field_tag_with_label('foo', CustomValue.new(:custom_field => field))
|
||||
assert_select_in s, 'label:not([for])'
|
||||
end
|
||||
|
||||
def test_unknow_field_format_should_be_edited_as_string
|
||||
field = CustomField.new(:field_format => 'foo')
|
||||
value = CustomValue.new(:value => 'bar', :custom_field => field)
|
||||
field.id = 52
|
||||
|
||||
assert_select_in custom_field_tag('object', value),
|
||||
'input[type=text][value=bar][name=?]', 'object[custom_field_values][52]'
|
||||
end
|
||||
|
||||
def test_unknow_field_format_should_be_bulk_edited_as_string
|
||||
field = CustomField.new(:field_format => 'foo')
|
||||
field.id = 52
|
||||
|
||||
assert_select_in custom_field_tag_for_bulk_edit('object', field),
|
||||
'input[type=text][value=""][name=?]', 'object[custom_field_values][52]'
|
||||
end
|
||||
end
|
||||
42
test/unit/helpers/groups_helper_test.rb
Normal file
42
test/unit/helpers/groups_helper_test.rb
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# 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 GroupsHelperTest < Redmine::HelperTest
|
||||
include ERB::Util
|
||||
include GroupsHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :users
|
||||
|
||||
def test_render_principals_for_new_group_users
|
||||
group = Group.generate!
|
||||
|
||||
result = render_principals_for_new_group_users(group)
|
||||
assert_select_in result, 'input[name=?][value="2"]', 'user_ids[]'
|
||||
end
|
||||
|
||||
def test_render_principals_for_new_group_users_with_limited_results_should_paginate
|
||||
group = Group.generate!
|
||||
|
||||
result = render_principals_for_new_group_users(group, 3)
|
||||
assert_select_in result, 'span.pagination'
|
||||
assert_select_in result, 'span.pagination li.current span', :text => '1'
|
||||
assert_select_in result, 'a[href=?]', "/groups/#{group.id}/autocomplete_for_user.js?page=2", :text => '2'
|
||||
end
|
||||
end
|
||||
332
test/unit/helpers/issues_helper_test.rb
Normal file
332
test/unit/helpers/issues_helper_test.rb
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
# 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 IssuesHelperTest < Redmine::HelperTest
|
||||
include IssuesHelper
|
||||
include CustomFieldsHelper
|
||||
include ERB::Util
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:custom_fields,
|
||||
:attachments,
|
||||
:versions
|
||||
|
||||
def test_issue_heading
|
||||
assert_equal "Bug #1", issue_heading(Issue.find(1))
|
||||
end
|
||||
|
||||
def test_issues_destroy_confirmation_message_with_one_root_issue
|
||||
assert_equal l(:text_issues_destroy_confirmation),
|
||||
issues_destroy_confirmation_message(Issue.find(1))
|
||||
end
|
||||
|
||||
def test_issues_destroy_confirmation_message_with_an_arrayt_of_root_issues
|
||||
assert_equal l(:text_issues_destroy_confirmation),
|
||||
issues_destroy_confirmation_message(Issue.find([1, 2]))
|
||||
end
|
||||
|
||||
def test_issues_destroy_confirmation_message_with_one_parent_issue
|
||||
Issue.find(2).update! :parent_issue_id => 1
|
||||
assert_equal l(:text_issues_destroy_confirmation) + "\n" +
|
||||
l(:text_issues_destroy_descendants_confirmation, :count => 1),
|
||||
issues_destroy_confirmation_message(Issue.find(1))
|
||||
end
|
||||
|
||||
def test_issues_destroy_confirmation_message_with_one_parent_issue_and_its_child
|
||||
Issue.find(2).update! :parent_issue_id => 1
|
||||
assert_equal l(:text_issues_destroy_confirmation),
|
||||
issues_destroy_confirmation_message(Issue.find([1, 2]))
|
||||
end
|
||||
|
||||
def test_issues_destroy_confirmation_message_with_issues_that_share_descendants
|
||||
root = Issue.generate!
|
||||
child = Issue.generate!(:parent_issue_id => root.id)
|
||||
Issue.generate!(:parent_issue_id => child.id)
|
||||
|
||||
assert_equal l(:text_issues_destroy_confirmation) + "\n" +
|
||||
l(:text_issues_destroy_descendants_confirmation, :count => 1),
|
||||
issues_destroy_confirmation_message([root.reload, child.reload])
|
||||
end
|
||||
|
||||
test 'show_detail with no_html should show a changing attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :old_value => '40',
|
||||
:value => '100', :prop_key => 'done_ratio')
|
||||
assert_equal "% Done changed from 40 to 100", show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail with no_html should show a new attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :old_value => nil,
|
||||
:value => '100', :prop_key => 'done_ratio')
|
||||
assert_equal "% Done set to 100", show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail with no_html should show a deleted attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :old_value => '50',
|
||||
:value => nil, :prop_key => 'done_ratio')
|
||||
assert_equal "% Done deleted (50)", show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail with html should show a changing attribute with HTML highlights' do
|
||||
detail = JournalDetail.new(:property => 'attr', :old_value => '40',
|
||||
:value => '100', :prop_key => 'done_ratio')
|
||||
html = show_detail(detail, false)
|
||||
assert_include '<strong>% Done</strong>', html
|
||||
assert_include '<i>40</i>', html
|
||||
assert_include '<i>100</i>', html
|
||||
end
|
||||
|
||||
test 'show_detail with html should show a new attribute with HTML highlights' do
|
||||
detail = JournalDetail.new(:property => 'attr', :old_value => nil,
|
||||
:value => '100', :prop_key => 'done_ratio')
|
||||
html = show_detail(detail, false)
|
||||
assert_include '<strong>% Done</strong>', html
|
||||
assert_include '<i>100</i>', html
|
||||
end
|
||||
|
||||
test 'show_detail with html should show a deleted attribute with HTML highlights' do
|
||||
detail = JournalDetail.new(:property => 'attr', :old_value => '50',
|
||||
:value => nil, :prop_key => 'done_ratio')
|
||||
html = show_detail(detail, false)
|
||||
assert_include '<strong>% Done</strong>', html
|
||||
assert_include '<del><i>50</i></del>', html
|
||||
end
|
||||
|
||||
test 'show_detail with a start_date attribute should format the dates' do
|
||||
detail = JournalDetail.new(
|
||||
:property => 'attr',
|
||||
:old_value => '2010-01-01',
|
||||
:value => '2010-01-31',
|
||||
:prop_key => 'start_date'
|
||||
)
|
||||
with_settings :date_format => '%m/%d/%Y' do
|
||||
assert_match "01/31/2010", show_detail(detail, true)
|
||||
assert_match "01/01/2010", show_detail(detail, true)
|
||||
end
|
||||
end
|
||||
|
||||
test 'show_detail with a due_date attribute should format the dates' do
|
||||
detail = JournalDetail.new(
|
||||
:property => 'attr',
|
||||
:old_value => '2010-01-01',
|
||||
:value => '2010-01-31',
|
||||
:prop_key => 'due_date'
|
||||
)
|
||||
with_settings :date_format => '%m/%d/%Y' do
|
||||
assert_match "01/31/2010", show_detail(detail, true)
|
||||
assert_match "01/01/2010", show_detail(detail, true)
|
||||
end
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a project attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'project_id',
|
||||
:old_value => 1, :value => 2)
|
||||
assert_match 'eCookbook', show_detail(detail, true)
|
||||
assert_match 'OnlineStore', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a issue status attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'status_id',
|
||||
:old_value => 1, :value => 2)
|
||||
assert_match 'New', show_detail(detail, true)
|
||||
assert_match 'Assigned', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a tracker attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'tracker_id',
|
||||
:old_value => 1, :value => 2)
|
||||
assert_match 'Bug', show_detail(detail, true)
|
||||
assert_match 'Feature request', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a assigned to attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'assigned_to_id',
|
||||
:old_value => 1, :value => 2)
|
||||
assert_match 'Redmine Admin', show_detail(detail, true)
|
||||
assert_match 'John Smith', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a priority attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'priority_id',
|
||||
:old_value => 4, :value => 5)
|
||||
assert_match 'Low', show_detail(detail, true)
|
||||
assert_match 'Normal', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a category attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'category_id',
|
||||
:old_value => 1, :value => 2)
|
||||
assert_match 'Printing', show_detail(detail, true)
|
||||
assert_match 'Recipes', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a fixed version attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'fixed_version_id',
|
||||
:old_value => 1, :value => 2)
|
||||
assert_match '0.1', show_detail(detail, true)
|
||||
assert_match '1.0', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a estimated hours attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'estimated_hours',
|
||||
:old_value => '5', :value => '6.3')
|
||||
assert_match '5.00', show_detail(detail, true)
|
||||
assert_match '6.30', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should not show values with a description attribute' do
|
||||
detail = JournalDetail.new(:property => 'attr', :prop_key => 'description',
|
||||
:old_value => 'Foo', :value => 'Bar')
|
||||
assert_equal 'Description updated', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show old and new values with a custom field' do
|
||||
detail = JournalDetail.new(:property => 'cf', :prop_key => '1',
|
||||
:old_value => 'MySQL', :value => 'PostgreSQL')
|
||||
assert_equal 'Database changed from MySQL to PostgreSQL', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should not show values with a long text custom field' do
|
||||
field = IssueCustomField.create!(:name => "Long field", :field_format => 'text')
|
||||
detail = JournalDetail.new(:property => 'cf', :prop_key => field.id,
|
||||
:old_value => 'Foo', :value => 'Bar')
|
||||
assert_equal 'Long field updated', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show added file' do
|
||||
detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
|
||||
:old_value => nil, :value => 'error281.txt')
|
||||
assert_match 'error281.txt', show_detail(detail, true)
|
||||
end
|
||||
|
||||
test 'show_detail should show removed file' do
|
||||
detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
|
||||
:old_value => 'error281.txt', :value => nil)
|
||||
assert_match 'error281.txt', show_detail(detail, true)
|
||||
end
|
||||
|
||||
def test_show_detail_relation_added
|
||||
detail = JournalDetail.new(:property => 'relation',
|
||||
:prop_key => 'precedes',
|
||||
:value => 1)
|
||||
assert_equal "Precedes Bug #1: Cannot print recipes added", show_detail(detail, true)
|
||||
str = link_to("Bug #1", "/issues/1", :class => Issue.find(1).css_classes)
|
||||
assert_equal "<strong>Precedes</strong> <i>#{str}: Cannot print recipes</i> added",
|
||||
show_detail(detail, false)
|
||||
end
|
||||
|
||||
def test_show_detail_relation_added_with_inexistant_issue
|
||||
inexistant_issue_number = 9999
|
||||
assert_nil Issue.find_by_id(inexistant_issue_number)
|
||||
detail = JournalDetail.new(:property => 'relation',
|
||||
:prop_key => 'precedes',
|
||||
:value => inexistant_issue_number)
|
||||
assert_equal "Precedes Issue ##{inexistant_issue_number} added", show_detail(detail, true)
|
||||
assert_equal "<strong>Precedes</strong> <i>Issue ##{inexistant_issue_number}</i> added", show_detail(detail, false)
|
||||
end
|
||||
|
||||
def test_show_detail_relation_added_should_not_disclose_issue_that_is_not_visible
|
||||
issue = Issue.generate!(:is_private => true)
|
||||
detail = JournalDetail.new(:property => 'relation',
|
||||
:prop_key => 'precedes',
|
||||
:value => issue.id)
|
||||
|
||||
assert_equal "Precedes Issue ##{issue.id} added", show_detail(detail, true)
|
||||
assert_equal "<strong>Precedes</strong> <i>Issue ##{issue.id}</i> added", show_detail(detail, false)
|
||||
end
|
||||
|
||||
def test_show_detail_relation_deleted
|
||||
detail = JournalDetail.new(:property => 'relation',
|
||||
:prop_key => 'precedes',
|
||||
:old_value => 1)
|
||||
assert_equal "Precedes deleted (Bug #1: Cannot print recipes)", show_detail(detail, true)
|
||||
str = link_to("Bug #1",
|
||||
"/issues/1",
|
||||
:class => Issue.find(1).css_classes)
|
||||
assert_equal "<strong>Precedes</strong> deleted (<i>#{str}: Cannot print recipes</i>)",
|
||||
show_detail(detail, false)
|
||||
end
|
||||
|
||||
def test_show_detail_relation_deleted_with_inexistant_issue
|
||||
inexistant_issue_number = 9999
|
||||
assert_nil Issue.find_by_id(inexistant_issue_number)
|
||||
detail = JournalDetail.new(:property => 'relation',
|
||||
:prop_key => 'precedes',
|
||||
:old_value => inexistant_issue_number)
|
||||
assert_equal "Precedes deleted (Issue #9999)", show_detail(detail, true)
|
||||
assert_equal "<strong>Precedes</strong> deleted (<i>Issue #9999</i>)", show_detail(detail, false)
|
||||
end
|
||||
|
||||
def test_show_detail_relation_deleted_should_not_disclose_issue_that_is_not_visible
|
||||
issue = Issue.generate!(:is_private => true)
|
||||
detail = JournalDetail.new(:property => 'relation',
|
||||
:prop_key => 'precedes',
|
||||
:old_value => issue.id)
|
||||
|
||||
assert_equal "Precedes deleted (Issue ##{issue.id})", show_detail(detail, true)
|
||||
assert_equal "<strong>Precedes</strong> deleted (<i>Issue ##{issue.id}</i>)", show_detail(detail, false)
|
||||
end
|
||||
|
||||
def test_details_to_strings_with_multiple_values_removed_from_custom_field
|
||||
field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
|
||||
details = []
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '1', :value => nil)
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '3', :value => nil)
|
||||
|
||||
assert_equal ["User deleted (Dave Lopper, Redmine Admin)"], details_to_strings(details, true)
|
||||
assert_equal ["<strong>User</strong> deleted (<del><i>Dave Lopper, Redmine Admin</i></del>)"], details_to_strings(details, false)
|
||||
end
|
||||
|
||||
def test_details_to_strings_with_multiple_values_added_to_custom_field
|
||||
field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
|
||||
details = []
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '1')
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '3')
|
||||
|
||||
assert_equal ["User Dave Lopper, Redmine Admin added"], details_to_strings(details, true)
|
||||
assert_equal ["<strong>User</strong> <i>Dave Lopper, Redmine Admin</i> added"], details_to_strings(details, false)
|
||||
end
|
||||
|
||||
def test_details_to_strings_with_multiple_values_added_and_removed_from_custom_field
|
||||
field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
|
||||
details = []
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '1')
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '2', :value => nil)
|
||||
details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '3', :value => nil)
|
||||
|
||||
assert_equal [
|
||||
"User Redmine Admin added",
|
||||
"User deleted (Dave Lopper, John Smith)"
|
||||
], details_to_strings(details, true)
|
||||
assert_equal [
|
||||
"<strong>User</strong> <i>Redmine Admin</i> added",
|
||||
"<strong>User</strong> deleted (<del><i>Dave Lopper, John Smith</i></del>)"
|
||||
], details_to_strings(details, false)
|
||||
end
|
||||
|
||||
def test_find_name_by_reflection_should_return_nil_for_missing_record
|
||||
assert_nil find_name_by_reflection('status', 99)
|
||||
end
|
||||
end
|
||||
48
test/unit/helpers/journals_helper_test.rb
Normal file
48
test/unit/helpers/journals_helper_test.rb
Normal 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 JournalsHelperTest < Redmine::HelperTest
|
||||
include JournalsHelper
|
||||
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :issue_categories,
|
||||
:projects_trackers,
|
||||
:users, :roles, :member_roles, :members,
|
||||
:enabled_modules,
|
||||
:custom_fields,
|
||||
:attachments,
|
||||
:versions
|
||||
|
||||
def test_journal_thumbnail_attachments_should_return_thumbnailable_attachments
|
||||
issue = Issue.generate!
|
||||
|
||||
journal = new_record(Journal) do
|
||||
issue.init_journal(User.find(1))
|
||||
issue.attachments << Attachment.new(:file => mock_file_with_options(:original_filename => 'image.png'), :author => User.find(1))
|
||||
issue.attachments << Attachment.new(:file => mock_file_with_options(:original_filename => 'foo'), :author => User.find(1))
|
||||
issue.save
|
||||
end
|
||||
assert_equal 2, journal.details.count
|
||||
|
||||
thumbnails = journal_thumbnail_attachments(journal)
|
||||
assert_equal 1, thumbnails.count
|
||||
assert_kind_of Attachment, thumbnails.first
|
||||
assert_equal 'image.png', thumbnails.first.filename
|
||||
end
|
||||
end
|
||||
43
test/unit/helpers/members_helper_test.rb
Normal file
43
test/unit/helpers/members_helper_test.rb
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 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 MembersHelperTest < Redmine::HelperTest
|
||||
include ERB::Util
|
||||
include MembersHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :projects, :users, :members, :member_roles,
|
||||
:trackers, :issue_statuses
|
||||
|
||||
def test_render_principals_for_new_members
|
||||
project = Project.generate!
|
||||
|
||||
result = render_principals_for_new_members(project)
|
||||
assert_select_in result, 'input[name=?][value="2"]', 'membership[user_ids][]'
|
||||
end
|
||||
|
||||
def test_render_principals_for_new_members_with_limited_results_should_paginate
|
||||
project = Project.generate!
|
||||
|
||||
result = render_principals_for_new_members(project, 3)
|
||||
assert_select_in result, 'span.pagination'
|
||||
assert_select_in result, 'span.pagination li.current span', :text => '1'
|
||||
assert_select_in result, 'a[href=?]', "/projects/#{project.identifier}/memberships/autocomplete.js?page=2", :text => '2'
|
||||
end
|
||||
end
|
||||
78
test/unit/helpers/projects_helper_test.rb
Normal file
78
test/unit/helpers/projects_helper_test.rb
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# 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 ProjectsHelperTest < Redmine::HelperTest
|
||||
include ApplicationHelper
|
||||
include ProjectsHelper
|
||||
include ERB::Util
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:versions,
|
||||
:projects_trackers,
|
||||
:member_roles,
|
||||
:members,
|
||||
:groups_users,
|
||||
:enabled_modules
|
||||
|
||||
def test_link_to_version_within_project
|
||||
@project = Project.find(2)
|
||||
User.current = User.find(1)
|
||||
assert_equal '<a title="07/01/2006" href="/versions/5">Alpha</a>', link_to_version(Version.find(5))
|
||||
end
|
||||
|
||||
def test_link_to_version
|
||||
User.current = User.find(1)
|
||||
assert_equal '<a title="07/01/2006" href="/versions/5">OnlineStore - Alpha</a>', link_to_version(Version.find(5))
|
||||
end
|
||||
|
||||
def test_link_to_version_without_effective_date
|
||||
User.current = User.find(1)
|
||||
version = Version.find(5)
|
||||
version.effective_date = nil
|
||||
assert_equal '<a href="/versions/5">OnlineStore - Alpha</a>', link_to_version(version)
|
||||
end
|
||||
|
||||
def test_link_to_private_version
|
||||
assert_equal 'OnlineStore - Alpha', link_to_version(Version.find(5))
|
||||
end
|
||||
|
||||
def test_link_to_version_invalid_version
|
||||
assert_equal '', link_to_version(Object)
|
||||
end
|
||||
|
||||
def test_format_version_name_within_project
|
||||
@project = Project.find(1)
|
||||
assert_equal "0.1", format_version_name(Version.find(1))
|
||||
end
|
||||
|
||||
def test_format_version_name
|
||||
assert_equal "eCookbook - 0.1", format_version_name(Version.find(1))
|
||||
end
|
||||
|
||||
def test_format_version_name_for_system_version
|
||||
assert_equal "OnlineStore - Systemwide visible version", format_version_name(Version.find(7))
|
||||
end
|
||||
|
||||
def test_version_options_for_select_with_no_versions
|
||||
assert_equal '', version_options_for_select([])
|
||||
assert_equal '', version_options_for_select([], Version.find(1))
|
||||
end
|
||||
end
|
||||
96
test/unit/helpers/queries_helper_test.rb
Normal file
96
test/unit/helpers/queries_helper_test.rb
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# 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 QueriesHelperTest < Redmine::HelperTest
|
||||
include QueriesHelper
|
||||
|
||||
fixtures :projects, :enabled_modules, :users, :members,
|
||||
:member_roles, :roles, :trackers, :issue_statuses,
|
||||
:issue_categories, :enumerations, :issues,
|
||||
:watchers, :custom_fields, :custom_values, :versions,
|
||||
:queries,
|
||||
:projects_trackers,
|
||||
:custom_fields_trackers
|
||||
|
||||
def test_filters_options_for_select_should_have_a_blank_option
|
||||
options = filters_options_for_select(IssueQuery.new)
|
||||
assert_select_in options, 'option[value=""]'
|
||||
end
|
||||
|
||||
def test_filters_options_for_select_should_not_group_regular_filters
|
||||
with_locale 'en' do
|
||||
options = filters_options_for_select(IssueQuery.new)
|
||||
assert_select_in options, 'optgroup option[value=status_id]', 0
|
||||
assert_select_in options, 'option[value=status_id]', :text => 'Status'
|
||||
end
|
||||
end
|
||||
|
||||
def test_filters_options_for_select_should_group_date_filters
|
||||
with_locale 'en' do
|
||||
options = filters_options_for_select(IssueQuery.new)
|
||||
assert_select_in options, 'optgroup[label=?]', 'Date', 1
|
||||
assert_select_in options, 'optgroup > option[value=due_date]', :text => 'Due date'
|
||||
end
|
||||
end
|
||||
|
||||
def test_filters_options_for_select_should_not_group_only_one_date_filter
|
||||
with_locale 'en' do
|
||||
options = filters_options_for_select(TimeEntryQuery.new)
|
||||
assert_select_in options, 'option[value=spent_on]'
|
||||
assert_select_in options, 'optgroup[label=?]', 'Date', 0
|
||||
assert_select_in options, 'optgroup option[value=spent_on]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_filters_options_for_select_should_group_relations_filters
|
||||
with_locale 'en' do
|
||||
options = filters_options_for_select(IssueQuery.new)
|
||||
assert_select_in options, 'optgroup[label=?]', 'Relations', 1
|
||||
assert_select_in options, 'optgroup[label=?] > option', 'Relations', 11
|
||||
assert_select_in options, 'optgroup > option[value=relates]', :text => 'Related to'
|
||||
end
|
||||
end
|
||||
|
||||
def test_filters_options_for_select_should_group_associations_filters
|
||||
CustomField.delete_all
|
||||
cf1 = ProjectCustomField.create!(:name => 'Foo', :field_format => 'string', :is_filter => true)
|
||||
cf2 = ProjectCustomField.create!(:name => 'Bar', :field_format => 'string', :is_filter => true)
|
||||
|
||||
with_locale 'en' do
|
||||
options = filters_options_for_select(IssueQuery.new)
|
||||
assert_select_in options, 'optgroup[label=?]', 'Project', 1
|
||||
assert_select_in options, 'optgroup[label=?] > option', 'Project', 2
|
||||
assert_select_in options, 'optgroup > option[value=?]', "project.cf_#{cf1.id}", :text => "Project's Foo"
|
||||
end
|
||||
end
|
||||
|
||||
def test_query_to_csv_should_translate_boolean_custom_field_values
|
||||
f = IssueCustomField.generate!(:field_format => 'bool', :name => 'Boolean', :is_for_all => true, :trackers => Tracker.all)
|
||||
issues = [
|
||||
Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {f.id.to_s => '0'}),
|
||||
Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {f.id.to_s => '1'})
|
||||
]
|
||||
|
||||
with_locale 'fr' do
|
||||
csv = query_to_csv(issues, IssueQuery.new(:column_names => ['id', "cf_#{f.id}"]))
|
||||
assert_include "Oui", csv
|
||||
assert_include "Non", csv
|
||||
end
|
||||
end
|
||||
end
|
||||
43
test/unit/helpers/routes_helper_test.rb
Normal file
43
test/unit/helpers/routes_helper_test.rb
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 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__)
|
||||
|
||||
class RoutesHelperTest < Redmine::HelperTest
|
||||
fixtures :projects, :issues
|
||||
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
def test_time_entries_path
|
||||
assert_equal '/projects/ecookbook/time_entries', _time_entries_path(Project.find(1), nil)
|
||||
assert_equal '/time_entries', _time_entries_path(nil, nil)
|
||||
end
|
||||
|
||||
def test_report_time_entries_path
|
||||
assert_equal '/projects/ecookbook/time_entries/report', _report_time_entries_path(Project.find(1), nil)
|
||||
assert_equal '/time_entries/report', _report_time_entries_path(nil, nil)
|
||||
end
|
||||
|
||||
def test_new_time_entry_path
|
||||
assert_equal '/projects/ecookbook/time_entries/new', _new_time_entry_path(Project.find(1), nil)
|
||||
assert_equal '/issues/1/time_entries/new', _new_time_entry_path(Project.find(1), Issue.find(1))
|
||||
assert_equal '/issues/1/time_entries/new', _new_time_entry_path(nil, Issue.find(1))
|
||||
assert_equal '/time_entries/new', _new_time_entry_path(nil, nil)
|
||||
end
|
||||
end
|
||||
48
test/unit/helpers/search_helper_test.rb
Normal file
48
test/unit/helpers/search_helper_test.rb
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# 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__)
|
||||
|
||||
class SearchHelperTest < Redmine::HelperTest
|
||||
include SearchHelper
|
||||
include ERB::Util
|
||||
|
||||
def test_highlight_single_token
|
||||
assert_equal 'This is a <span class="highlight token-0">token</span>.',
|
||||
highlight_tokens('This is a token.', %w(token))
|
||||
end
|
||||
|
||||
def test_highlight_multiple_tokens
|
||||
assert_equal 'This is a <span class="highlight token-0">token</span> and <span class="highlight token-1">another</span> <span class="highlight token-0">token</span>.',
|
||||
highlight_tokens('This is a token and another token.', %w(token another))
|
||||
end
|
||||
|
||||
def test_highlight_should_not_exceed_maximum_length
|
||||
s = (('1234567890' * 100) + ' token ') * 100
|
||||
r = highlight_tokens(s, %w(token))
|
||||
assert r.include?('<span class="highlight token-0">token</span>')
|
||||
assert r.length <= 1300
|
||||
end
|
||||
|
||||
def test_highlight_multibyte
|
||||
s = ('й' * 200) + ' token ' + ('й' * 200)
|
||||
r = highlight_tokens(s, %w(token))
|
||||
assert_equal ('й' * 45) + ' ... ' + ('й' * 44) + ' <span class="highlight token-0">token</span> ' + ('й' * 44) + ' ... ' + ('й' * 45), r
|
||||
end
|
||||
end
|
||||
30
test/unit/helpers/settings_helper_test.rb
Normal file
30
test/unit/helpers/settings_helper_test.rb
Normal 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 SettingsHelperTest < Redmine::HelperTest
|
||||
include SettingsHelper
|
||||
include ERB::Util
|
||||
|
||||
def test_date_format_setting_options_should_include_human_readable_format
|
||||
Date.stubs(:today).returns(Date.parse("2015-07-14"))
|
||||
|
||||
options = date_format_setting_options('en')
|
||||
assert_include ["2015-07-14 (yyyy-mm-dd)", "%Y-%m-%d"], options
|
||||
end
|
||||
end
|
||||
109
test/unit/helpers/sort_helper_test.rb
Normal file
109
test/unit/helpers/sort_helper_test.rb
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# 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 SortHelperTest < Redmine::HelperTest
|
||||
include SortHelper
|
||||
include ERB::Util
|
||||
|
||||
def setup
|
||||
super
|
||||
@session = nil
|
||||
@sort_param = nil
|
||||
end
|
||||
|
||||
def test_default_sort_clause_with_array
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update(['attr1', 'attr2'])
|
||||
|
||||
assert_equal ['attr1 DESC'], sort_clause
|
||||
end
|
||||
|
||||
def test_default_sort_clause_with_hash
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
|
||||
|
||||
assert_equal ['table1.attr1 DESC'], sort_clause
|
||||
end
|
||||
|
||||
def test_default_sort_clause_with_multiple_columns
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update({'attr1' => ['table1.attr1', 'table1.attr2'], 'attr2' => 'table2.attr2'})
|
||||
|
||||
assert_equal ['table1.attr1 DESC', 'table1.attr2 DESC'], sort_clause
|
||||
end
|
||||
|
||||
def test_params_sort
|
||||
@sort_param = 'attr1,attr2:desc'
|
||||
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
|
||||
|
||||
assert_equal ['table1.attr1 ASC', 'table2.attr2 DESC'], sort_clause
|
||||
assert_equal 'attr1,attr2:desc', @session['foo_bar_sort']
|
||||
end
|
||||
|
||||
def test_invalid_params_sort
|
||||
@sort_param = 'invalid_key'
|
||||
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
|
||||
|
||||
assert_nil sort_clause
|
||||
assert_equal 'invalid_key', @session['foo_bar_sort']
|
||||
end
|
||||
|
||||
def test_invalid_order_params_sort
|
||||
@sort_param = 'attr1:foo:bar,attr2'
|
||||
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update({'attr1' => 'table1.attr1', 'attr2' => 'table2.attr2'})
|
||||
|
||||
assert_equal ['table1.attr1 ASC', 'table2.attr2 ASC'], sort_clause
|
||||
assert_equal 'attr1,attr2', @session['foo_bar_sort']
|
||||
end
|
||||
|
||||
def test_sort_css_without_params_should_use_default_sort
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update(['attr1', 'attr2'])
|
||||
|
||||
assert_equal 'sort-by-attr1 sort-desc', sort_css_classes
|
||||
end
|
||||
|
||||
def test_sort_css_should_use_params
|
||||
@sort_param = 'attr2,attr1'
|
||||
sort_init 'attr1', 'desc'
|
||||
sort_update(['attr1', 'attr2'])
|
||||
|
||||
assert_equal 'sort-by-attr2 sort-asc', sort_css_classes
|
||||
end
|
||||
|
||||
def test_sort_css_should_dasherize_sort_name
|
||||
sort_init 'foo_bar'
|
||||
sort_update(['foo_bar'])
|
||||
|
||||
assert_equal 'sort-by-foo-bar sort-asc', sort_css_classes
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def controller_name; 'foo'; end
|
||||
def action_name; 'bar'; end
|
||||
def params; {:sort => @sort_param}; end
|
||||
def session; @session ||= {}; end
|
||||
end
|
||||
53
test/unit/helpers/timelog_helper_test.rb
Normal file
53
test/unit/helpers/timelog_helper_test.rb
Normal 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 TimelogHelperTest < Redmine::HelperTest
|
||||
include TimelogHelper
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Helpers::DateHelper
|
||||
include ERB::Util
|
||||
|
||||
fixtures :projects, :roles, :enabled_modules, :users,
|
||||
:repositories, :changesets,
|
||||
:trackers, :issue_statuses, :issues, :versions, :documents,
|
||||
:wikis, :wiki_pages, :wiki_contents,
|
||||
:boards, :messages,
|
||||
:attachments,
|
||||
:enumerations
|
||||
|
||||
def test_activities_collection_for_select_options_should_return_array_of_activity_names_and_ids
|
||||
activities = activity_collection_for_select_options
|
||||
assert activities.include?(["Design", 9])
|
||||
assert activities.include?(["Development", 10])
|
||||
end
|
||||
|
||||
def test_activities_collection_for_select_options_should_not_include_inactive_activities
|
||||
activities = activity_collection_for_select_options
|
||||
assert !activities.include?(["Inactive Activity", 14])
|
||||
end
|
||||
|
||||
def test_activities_collection_for_select_options_should_use_the_projects_override
|
||||
project = Project.find(1)
|
||||
override_activity = TimeEntryActivity.create!({:name => "Design override", :parent => TimeEntryActivity.find_by_name("Design"), :project => project})
|
||||
|
||||
activities = activity_collection_for_select_options(nil, project)
|
||||
assert !activities.include?(["Design", 9]), "System activity found in: " + activities.inspect
|
||||
assert activities.include?(["Design override", override_activity.id]), "Override activity not found in: " + activities.inspect
|
||||
end
|
||||
end
|
||||
54
test/unit/helpers/version_helper_test.rb
Normal file
54
test/unit/helpers/version_helper_test.rb
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# 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 VersionsHelperTest < Redmine::HelperTest
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :projects, :versions
|
||||
|
||||
def test_version_filtered_issues_path_sharing_none
|
||||
version = Version.new(:name => 'test', :sharing => 'none')
|
||||
version.project = Project.find(5)
|
||||
assert_match '/projects/private-child/issues?', version_filtered_issues_path(version)
|
||||
end
|
||||
|
||||
def test_version_filtered_issues_path_sharing_descendants
|
||||
version = Version.new(:name => 'test', :sharing => 'descendants')
|
||||
version.project = Project.find(5)
|
||||
assert_match '/projects/private-child/issues?', version_filtered_issues_path(version)
|
||||
end
|
||||
|
||||
def test_version_filtered_issues_path_sharing_hierarchy
|
||||
version = Version.new(:name => 'test', :sharing => 'hierarchy')
|
||||
version.project = Project.find(5)
|
||||
assert_match '/projects/ecookbook/issues?', version_filtered_issues_path(version)
|
||||
end
|
||||
|
||||
def test_version_filtered_issues_path_sharing_tree
|
||||
version = Version.new(:name => 'test', :sharing => 'tree')
|
||||
version.project = Project.find(5)
|
||||
assert_match '/projects/ecookbook/issues?', version_filtered_issues_path(version)
|
||||
end
|
||||
|
||||
def test_version_filtered_issues_path_sharing_system
|
||||
version = Version.new(:name => 'test', :sharing => 'system')
|
||||
version.project = Project.find(5)
|
||||
assert_match /^\/issues\?/, version_filtered_issues_path(version)
|
||||
end
|
||||
end
|
||||
67
test/unit/helpers/watchers_helper_test.rb
Normal file
67
test/unit/helpers/watchers_helper_test.rb
Normal 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 WatchersHelperTest < Redmine::HelperTest
|
||||
include WatchersHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :users, :issues
|
||||
|
||||
test '#watcher_link with a non-watched object' do
|
||||
expected = link_to(
|
||||
"Watch",
|
||||
"/watchers/watch?object_id=1&object_type=issue",
|
||||
:remote => true, :method => 'post', :class => "issue-1-watcher icon icon-fav-off"
|
||||
)
|
||||
assert_equal expected, watcher_link(Issue.find(1), User.find(1))
|
||||
end
|
||||
|
||||
test '#watcher_link with a single objet array' do
|
||||
expected = link_to(
|
||||
"Watch",
|
||||
"/watchers/watch?object_id=1&object_type=issue",
|
||||
:remote => true, :method => 'post', :class => "issue-1-watcher icon icon-fav-off"
|
||||
)
|
||||
assert_equal expected, watcher_link([Issue.find(1)], User.find(1))
|
||||
end
|
||||
|
||||
test '#watcher_link with a multiple objets array' do
|
||||
expected = link_to(
|
||||
"Watch",
|
||||
"/watchers/watch?object_id%5B%5D=1&object_id%5B%5D=3&object_type=issue",
|
||||
:remote => true, :method => 'post', :class => "issue-bulk-watcher icon icon-fav-off"
|
||||
)
|
||||
assert_equal expected, watcher_link([Issue.find(1), Issue.find(3)], User.find(1))
|
||||
end
|
||||
|
||||
def test_watcher_link_with_nil_should_return_empty_string
|
||||
assert_equal '', watcher_link(nil, User.find(1))
|
||||
end
|
||||
|
||||
test '#watcher_link with a watched object' do
|
||||
Watcher.create!(:watchable => Issue.find(1), :user => User.find(1))
|
||||
|
||||
expected = link_to(
|
||||
"Unwatch",
|
||||
"/watchers/watch?object_id=1&object_type=issue",
|
||||
:remote => true, :method => 'delete', :class => "issue-1-watcher icon icon-fav"
|
||||
)
|
||||
assert_equal expected, watcher_link(Issue.find(1), User.find(1))
|
||||
end
|
||||
end
|
||||
45
test/unit/helpers/wiki_helper_test.rb
Normal file
45
test/unit/helpers/wiki_helper_test.rb
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# 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 WikiHelperTest < Redmine::HelperTest
|
||||
include WikiHelper
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
fixtures :projects, :users,
|
||||
:roles, :member_roles, :members,
|
||||
:enabled_modules, :wikis, :wiki_pages
|
||||
|
||||
def test_wiki_page_edit_cancel_path_for_new_page_without_parent_should_be_wiki_index
|
||||
wiki = Wiki.find(1)
|
||||
page = WikiPage.new(:wiki => wiki)
|
||||
assert_equal '/projects/ecookbook/wiki/index', wiki_page_edit_cancel_path(page)
|
||||
end
|
||||
|
||||
def test_wiki_page_edit_cancel_path_for_new_page_with_parent_should_be_parent
|
||||
wiki = Wiki.find(1)
|
||||
page = WikiPage.new(:wiki => wiki, :parent => wiki.find_page('Another_page'))
|
||||
assert_equal '/projects/ecookbook/wiki/Another_page', wiki_page_edit_cancel_path(page)
|
||||
end
|
||||
|
||||
def test_wiki_page_edit_cancel_path_for_existing_page_should_be_the_page
|
||||
wiki = Wiki.find(1)
|
||||
page = wiki.find_page('Child_1')
|
||||
assert_equal '/projects/ecookbook/wiki/Child_1', wiki_page_edit_cancel_path(page)
|
||||
end
|
||||
end
|
||||
95
test/unit/initializers/patches_test.rb
Normal file
95
test/unit/initializers/patches_test.rb
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# 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 PatchesTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
|
||||
def setup
|
||||
Setting.default_language = 'en'
|
||||
@symbols = { :a => 1, :b => 2 }
|
||||
@keys = %w( blue green red pink orange )
|
||||
@values = %w( 000099 009900 aa0000 cc0066 cc6633 )
|
||||
@hash = Hash.new
|
||||
@ordered_hash = ActiveSupport::OrderedHash.new
|
||||
|
||||
@keys.each_with_index do |key, index|
|
||||
@hash[key] = @values[index]
|
||||
@ordered_hash[key] = @values[index]
|
||||
end
|
||||
end
|
||||
|
||||
test "ActiveRecord::Base.human_attribute_name should transform name to field_name" do
|
||||
assert_equal l('field_last_login_on'), ActiveRecord::Base.human_attribute_name('last_login_on')
|
||||
end
|
||||
|
||||
test "ActiveRecord::Base.human_attribute_name should cut extra _id suffix for better validation" do
|
||||
assert_equal l('field_last_login_on'), ActiveRecord::Base.human_attribute_name('last_login_on_id')
|
||||
end
|
||||
|
||||
test "ActiveRecord::Base.human_attribute_name should default to humanized value if no translation has been found (useful for custom fields)" do
|
||||
assert_equal 'Patch name', ActiveRecord::Base.human_attribute_name('Patch name')
|
||||
end
|
||||
|
||||
# https://github.com/rails/rails/pull/14198/files
|
||||
def test_indifferent_select
|
||||
hash = ActiveSupport::HashWithIndifferentAccess.new(@symbols).select { |_ ,v| v == 1 }
|
||||
assert_equal({ 'a' => 1 }, hash)
|
||||
assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ?
|
||||
Hash : ActiveSupport::HashWithIndifferentAccess),
|
||||
hash
|
||||
end
|
||||
|
||||
def test_indifferent_select_bang
|
||||
indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@symbols)
|
||||
indifferent_strings.select! { |_, v| v == 1 }
|
||||
assert_equal({ 'a' => 1 }, indifferent_strings)
|
||||
assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings
|
||||
end
|
||||
|
||||
def test_indifferent_reject
|
||||
hash = ActiveSupport::HashWithIndifferentAccess.new(@symbols).reject { |_, v| v != 1 }
|
||||
assert_equal({ 'a' => 1 }, hash)
|
||||
assert_instance_of ActiveSupport::HashWithIndifferentAccess, hash
|
||||
end
|
||||
|
||||
def test_indifferent_reject_bang
|
||||
indifferent_strings = ActiveSupport::HashWithIndifferentAccess.new(@symbols)
|
||||
indifferent_strings.reject! { |_, v| v != 1 }
|
||||
assert_equal({ 'a' => 1 }, indifferent_strings)
|
||||
assert_instance_of ActiveSupport::HashWithIndifferentAccess, indifferent_strings
|
||||
end
|
||||
|
||||
def test_select
|
||||
assert_equal @keys, @ordered_hash.select { true }.map(&:first)
|
||||
new_ordered_hash = @ordered_hash.select { true }
|
||||
assert_equal @keys, new_ordered_hash.map(&:first)
|
||||
assert_instance_of ((Rails::VERSION::MAJOR < 4 && RUBY_VERSION < "2.1") ?
|
||||
Hash : ActiveSupport::OrderedHash),
|
||||
new_ordered_hash
|
||||
end
|
||||
|
||||
def test_reject
|
||||
copy = @ordered_hash.dup
|
||||
new_ordered_hash = @ordered_hash.reject { |k, _| k == 'pink' }
|
||||
assert_equal copy, @ordered_hash
|
||||
assert !new_ordered_hash.keys.include?('pink')
|
||||
assert @ordered_hash.keys.include?('pink')
|
||||
assert_instance_of ActiveSupport::OrderedHash, new_ordered_hash
|
||||
end
|
||||
end
|
||||
54
test/unit/issue_category_test.rb
Normal file
54
test/unit/issue_category_test.rb
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# 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 IssueCategoryTest < ActiveSupport::TestCase
|
||||
fixtures :issue_categories, :issues, :users, :groups_users
|
||||
|
||||
def setup
|
||||
@category = IssueCategory.find(1)
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert IssueCategory.new(:project_id => 2, :name => 'New category').save
|
||||
category = IssueCategory.order('id DESC').first
|
||||
assert_equal 'New category', category.name
|
||||
end
|
||||
|
||||
def test_create_with_group_assignment
|
||||
assert IssueCategory.new(:project_id => 2, :name => 'Group assignment', :assigned_to_id => 11).save
|
||||
category = IssueCategory.order('id DESC').first
|
||||
assert_kind_of Group, category.assigned_to
|
||||
assert_equal Group.find(11), category.assigned_to
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
issue = @category.issues.first
|
||||
@category.destroy
|
||||
# Make sure the category was nullified on the issue
|
||||
assert_nil issue.reload.category
|
||||
end
|
||||
|
||||
def test_destroy_with_reassign
|
||||
issue = @category.issues.first
|
||||
reassign_to = IssueCategory.find(2)
|
||||
@category.destroy(reassign_to)
|
||||
# Make sure the issue was reassigned
|
||||
assert_equal reassign_to, issue.reload.category
|
||||
end
|
||||
end
|
||||
42
test/unit/issue_custom_field_test.rb
Normal file
42
test/unit/issue_custom_field_test.rb
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# 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 IssueCustomFieldTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
|
||||
fixtures :roles
|
||||
|
||||
def test_custom_field_with_visible_set_to_false_should_validate_roles
|
||||
set_language_if_valid 'en'
|
||||
field = IssueCustomField.new(:name => 'Field', :field_format => 'string', :visible => false)
|
||||
assert !field.save
|
||||
assert_include "Roles cannot be blank", field.errors.full_messages
|
||||
field.role_ids = [1, 2]
|
||||
assert field.save
|
||||
end
|
||||
|
||||
def test_changing_visible_to_true_should_clear_roles
|
||||
field = IssueCustomField.create!(:name => 'Field', :field_format => 'string', :visible => false, :role_ids => [1, 2])
|
||||
assert_equal 2, field.roles.count
|
||||
|
||||
field.visible = true
|
||||
field.save!
|
||||
assert_equal 0, field.roles.count
|
||||
end
|
||||
end
|
||||
191
test/unit/issue_import_test.rb
Normal file
191
test/unit/issue_import_test.rb
Normal 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 IssueImportTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :enabled_modules,
|
||||
:users, :email_addresses,
|
||||
:roles, :members, :member_roles,
|
||||
:issues, :issue_statuses,
|
||||
:trackers, :projects_trackers,
|
||||
:versions,
|
||||
:issue_categories,
|
||||
:enumerations,
|
||||
:workflows,
|
||||
:custom_fields,
|
||||
:custom_values,
|
||||
:custom_fields_projects,
|
||||
:custom_fields_trackers
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def setup
|
||||
set_language_if_valid 'en'
|
||||
end
|
||||
|
||||
def test_create_versions_should_create_missing_versions
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('fixed_version' => '9', 'create_versions' => '1')
|
||||
import.save!
|
||||
|
||||
version = new_record(Version) do
|
||||
assert_difference 'Issue.count', 3 do
|
||||
import.run
|
||||
end
|
||||
end
|
||||
assert_equal '2.1', version.name
|
||||
end
|
||||
|
||||
def test_create_categories_should_create_missing_categories
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('category' => '10', 'create_categories' => '1')
|
||||
import.save!
|
||||
|
||||
category = new_record(IssueCategory) do
|
||||
assert_difference 'Issue.count', 3 do
|
||||
import.run
|
||||
end
|
||||
end
|
||||
assert_equal 'New category', category.name
|
||||
end
|
||||
|
||||
def test_mapping_with_fixed_tracker
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('tracker' => 'value:2')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_equal [2], issues.map(&:tracker_id).uniq
|
||||
end
|
||||
|
||||
def test_mapping_with_mapped_tracker
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('tracker' => '13')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_equal [1, 2, 1], issues.map(&:tracker_id)
|
||||
end
|
||||
|
||||
def test_should_not_import_with_default_tracker_when_tracker_is_invalid
|
||||
Tracker.find_by_name('Feature request').update!(:name => 'Feature')
|
||||
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('tracker' => '13')
|
||||
import.save!
|
||||
import.run
|
||||
|
||||
assert_equal 1, import.unsaved_items.count
|
||||
item = import.unsaved_items.first
|
||||
assert_include "Tracker cannot be blank", item.message
|
||||
end
|
||||
|
||||
def test_status_should_be_set
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('status' => '14')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_equal ['New', 'New', 'Assigned'], issues.map(&:status).map(&:name)
|
||||
end
|
||||
|
||||
def test_parent_should_be_set
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('parent_issue_id' => '5')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_nil issues[0].parent
|
||||
assert_equal issues[0].id, issues[1].parent_id
|
||||
assert_equal 2, issues[2].parent_id
|
||||
end
|
||||
|
||||
def test_backward_and_forward_reference_to_parent_should_work
|
||||
import = generate_import('import_subtasks.csv')
|
||||
import.settings = {
|
||||
'separator' => ";", 'wrapper' => '"', 'encoding' => "UTF-8",
|
||||
'mapping' => {'project_id' => '1', 'tracker' => '1', 'subject' => '2', 'parent_issue_id' => '3'}
|
||||
}
|
||||
import.save!
|
||||
|
||||
root, child1, grandchild, child2 = new_records(Issue, 4) { import.run }
|
||||
assert_equal root, child1.parent
|
||||
assert_equal child2, grandchild.parent
|
||||
end
|
||||
|
||||
def test_assignee_should_be_set
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('assigned_to' => '11')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_equal [User.find(3), nil, nil], issues.map(&:assigned_to)
|
||||
end
|
||||
|
||||
def test_user_custom_field_should_be_set
|
||||
field = IssueCustomField.generate!(:field_format => 'user', :is_for_all => true, :trackers => Tracker.all)
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!("cf_#{field.id}" => '11')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_equal '3', issues.first.custom_field_value(field)
|
||||
end
|
||||
|
||||
def test_is_private_should_be_set_based_on_user_locale
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge!('is_private' => '6')
|
||||
import.save!
|
||||
|
||||
issues = new_records(Issue, 3) { import.run }
|
||||
assert_equal [false, true, false], issues.map(&:is_private)
|
||||
end
|
||||
|
||||
def test_dates_should_be_parsed_using_date_format_setting
|
||||
field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
|
||||
import = generate_import_with_mapping('import_dates.csv')
|
||||
import.settings.merge!('date_format' => Import::DATE_FORMATS[1])
|
||||
import.mapping.merge!('tracker' => 'value:1', 'subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
|
||||
import.save!
|
||||
|
||||
issue = new_record(Issue) { import.run } # only 1 valid issue
|
||||
assert_equal "Valid dates", issue.subject
|
||||
assert_equal Date.parse('2015-07-10'), issue.start_date
|
||||
assert_equal Date.parse('2015-08-12'), issue.due_date
|
||||
assert_equal '2015-07-14', issue.custom_field_value(field)
|
||||
end
|
||||
|
||||
def test_date_format_should_default_to_user_language
|
||||
user = User.generate!(:language => 'fr')
|
||||
import = Import.new
|
||||
import.user = user
|
||||
assert_nil import.settings['date_format']
|
||||
|
||||
import.set_default_settings
|
||||
assert_equal '%d/%m/%Y', import.settings['date_format']
|
||||
end
|
||||
|
||||
def test_run_should_remove_the_file
|
||||
import = generate_import_with_mapping
|
||||
file_path = import.filepath
|
||||
assert File.exists?(file_path)
|
||||
|
||||
import.run
|
||||
assert !File.exists?(file_path)
|
||||
end
|
||||
end
|
||||
96
test/unit/issue_nested_set_concurrency_test.rb
Normal file
96
test/unit/issue_nested_set_concurrency_test.rb
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# 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 IssueNestedSetConcurrencyTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :users,
|
||||
:trackers, :projects_trackers,
|
||||
:enabled_modules,
|
||||
:issue_statuses,
|
||||
:enumerations
|
||||
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
skip if sqlite? || mysql?
|
||||
CustomField.delete_all
|
||||
end
|
||||
|
||||
def teardown
|
||||
Issue.delete_all
|
||||
end
|
||||
|
||||
def test_concurrency
|
||||
# Generates an issue and destroys it in order
|
||||
# to load all needed classes before starting threads
|
||||
i = Issue.generate!
|
||||
i.destroy
|
||||
|
||||
root = Issue.generate!
|
||||
assert_difference 'Issue.count', 60 do
|
||||
threaded(3) do
|
||||
10.times do
|
||||
i = Issue.generate! :parent_issue_id => root.id
|
||||
c1 = Issue.generate! :parent_issue_id => i.id
|
||||
c2 = Issue.generate! :parent_issue_id => i.id
|
||||
c3 = Issue.generate! :parent_issue_id => i.id
|
||||
c2.reload.destroy
|
||||
c1.reload.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_concurrent_subtasks_creation
|
||||
root = Issue.generate!
|
||||
assert_difference 'Issue.count', 30 do
|
||||
threaded(3) do
|
||||
10.times do
|
||||
Issue.generate! :parent_issue_id => root.id
|
||||
end
|
||||
end
|
||||
end
|
||||
root.reload
|
||||
assert_equal [1, 62], [root.lft, root.rgt]
|
||||
children_bounds = root.children.sort_by(&:lft).map {|c| [c.lft, c.rgt]}.flatten
|
||||
assert_equal (2..61).to_a, children_bounds
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def threaded(count, &block)
|
||||
with_settings :notified_events => [] do
|
||||
threads = []
|
||||
count.times do |i|
|
||||
threads << Thread.new(i) do
|
||||
ActiveRecord::Base.connection_pool.with_connection do
|
||||
begin
|
||||
yield
|
||||
rescue Exception => e
|
||||
Thread.current[:exception] = e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
threads.each do |thread|
|
||||
thread.join
|
||||
assert_nil thread[:exception]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
328
test/unit/issue_nested_set_test.rb
Normal file
328
test/unit/issue_nested_set_test.rb
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
# 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 IssueNestedSetTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :users, :roles,
|
||||
:trackers, :projects_trackers,
|
||||
:issue_statuses, :issue_categories, :issue_relations,
|
||||
:enumerations,
|
||||
:issues
|
||||
|
||||
def test_new_record_is_leaf
|
||||
i = Issue.new
|
||||
assert i.leaf?
|
||||
end
|
||||
|
||||
def test_create_root_issue
|
||||
lft1 = new_issue_lft
|
||||
issue1 = Issue.generate!
|
||||
lft2 = new_issue_lft
|
||||
issue2 = Issue.generate!
|
||||
issue1.reload
|
||||
issue2.reload
|
||||
assert_equal [issue1.id, nil, lft1, lft1 + 1], [issue1.root_id, issue1.parent_id, issue1.lft, issue1.rgt]
|
||||
assert_equal [issue2.id, nil, lft2, lft2 + 1], [issue2.root_id, issue2.parent_id, issue2.lft, issue2.rgt]
|
||||
end
|
||||
|
||||
def test_create_child_issue
|
||||
lft = new_issue_lft
|
||||
parent = Issue.generate!
|
||||
child = parent.generate_child!
|
||||
parent.reload
|
||||
child.reload
|
||||
assert_equal [parent.id, nil, lft, lft + 3], [parent.root_id, parent.parent_id, parent.lft, parent.rgt]
|
||||
assert_equal [parent.id, parent.id, lft + 1, lft + 2], [child.root_id, child.parent_id, child.lft, child.rgt]
|
||||
end
|
||||
|
||||
def test_creating_a_child_in_a_subproject_should_validate
|
||||
issue = Issue.generate!
|
||||
child = Issue.new(:project_id => 3, :tracker_id => 2, :author_id => 1,
|
||||
:subject => 'child', :parent_issue_id => issue.id)
|
||||
assert_save child
|
||||
assert_equal issue, child.reload.parent
|
||||
end
|
||||
|
||||
def test_creating_a_child_in_an_invalid_project_should_not_validate
|
||||
issue = Issue.generate!
|
||||
child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
|
||||
:subject => 'child', :parent_issue_id => issue.id)
|
||||
assert !child.save
|
||||
assert_not_equal [], child.errors[:parent_issue_id]
|
||||
end
|
||||
|
||||
def test_move_a_root_to_child
|
||||
lft = new_issue_lft
|
||||
parent1 = Issue.generate!
|
||||
parent2 = Issue.generate!
|
||||
child = parent1.generate_child!
|
||||
parent2.parent_issue_id = parent1.id
|
||||
parent2.save!
|
||||
child.reload
|
||||
parent1.reload
|
||||
parent2.reload
|
||||
assert_equal [parent1.id, lft, lft + 5], [parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [parent1.id, lft + 1, lft + 2], [parent2.root_id, parent2.lft, parent2.rgt]
|
||||
assert_equal [parent1.id, lft + 3, lft + 4], [child.root_id, child.lft, child.rgt]
|
||||
end
|
||||
|
||||
def test_move_a_child_to_root
|
||||
lft1 = new_issue_lft
|
||||
parent1 = Issue.generate!
|
||||
lft2 = new_issue_lft
|
||||
parent2 = Issue.generate!
|
||||
lft3 = new_issue_lft
|
||||
child = parent1.generate_child!
|
||||
child.parent_issue_id = nil
|
||||
child.save!
|
||||
child.reload
|
||||
parent1.reload
|
||||
parent2.reload
|
||||
assert_equal [parent1.id, lft1, lft1 + 1], [parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [parent2.id, lft2, lft2 + 1], [parent2.root_id, parent2.lft, parent2.rgt]
|
||||
assert_equal [child.id, lft3, lft3 + 1], [child.root_id, child.lft, child.rgt]
|
||||
end
|
||||
|
||||
def test_move_a_child_to_another_issue
|
||||
lft1 = new_issue_lft
|
||||
parent1 = Issue.generate!
|
||||
lft2 = new_issue_lft
|
||||
parent2 = Issue.generate!
|
||||
child = parent1.generate_child!
|
||||
child.parent_issue_id = parent2.id
|
||||
child.save!
|
||||
child.reload
|
||||
parent1.reload
|
||||
parent2.reload
|
||||
assert_equal [parent1.id, lft1, lft1 + 1], [parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [parent2.id, lft2, lft2 + 3], [parent2.root_id, parent2.lft, parent2.rgt]
|
||||
assert_equal [parent2.id, lft2 + 1, lft2 + 2], [child.root_id, child.lft, child.rgt]
|
||||
end
|
||||
|
||||
def test_move_a_child_with_descendants_to_another_issue
|
||||
lft1 = new_issue_lft
|
||||
parent1 = Issue.generate!
|
||||
lft2 = new_issue_lft
|
||||
parent2 = Issue.generate!
|
||||
child = parent1.generate_child!
|
||||
grandchild = child.generate_child!
|
||||
parent1.reload
|
||||
parent2.reload
|
||||
child.reload
|
||||
grandchild.reload
|
||||
assert_equal [parent1.id, lft1, lft1 + 5], [parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [parent2.id, lft2, lft2 + 1], [parent2.root_id, parent2.lft, parent2.rgt]
|
||||
assert_equal [parent1.id, lft1 + 1, lft1 + 4], [child.root_id, child.lft, child.rgt]
|
||||
assert_equal [parent1.id, lft1 + 2, lft1 + 3], [grandchild.root_id, grandchild.lft, grandchild.rgt]
|
||||
child.reload.parent_issue_id = parent2.id
|
||||
child.save!
|
||||
child.reload
|
||||
grandchild.reload
|
||||
parent1.reload
|
||||
parent2.reload
|
||||
assert_equal [parent1.id, lft1, lft1 + 1], [parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [parent2.id, lft2, lft2 + 5], [parent2.root_id, parent2.lft, parent2.rgt]
|
||||
assert_equal [parent2.id, lft2 + 1, lft2 + 4], [child.root_id, child.lft, child.rgt]
|
||||
assert_equal [parent2.id, lft2 + 2, lft2 + 3], [grandchild.root_id, grandchild.lft, grandchild.rgt]
|
||||
end
|
||||
|
||||
def test_move_a_child_with_descendants_to_another_project
|
||||
lft1 = new_issue_lft
|
||||
parent1 = Issue.generate!
|
||||
child = parent1.generate_child!
|
||||
grandchild = child.generate_child!
|
||||
lft4 = new_issue_lft
|
||||
child.reload
|
||||
child.project = Project.find(2)
|
||||
assert child.save
|
||||
child.reload
|
||||
grandchild.reload
|
||||
parent1.reload
|
||||
assert_equal [1, parent1.id, lft1, lft1 + 1], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [2, child.id, lft4, lft4 + 3],
|
||||
[child.project_id, child.root_id, child.lft, child.rgt]
|
||||
assert_equal [2, child.id, lft4 + 1, lft4 + 2],
|
||||
[grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
|
||||
end
|
||||
|
||||
def test_moving_an_issue_to_a_descendant_should_not_validate
|
||||
parent1 = Issue.generate!
|
||||
parent2 = Issue.generate!
|
||||
child = parent1.generate_child!
|
||||
grandchild = child.generate_child!
|
||||
|
||||
child.reload
|
||||
child.parent_issue_id = grandchild.id
|
||||
assert !child.save
|
||||
assert_not_equal [], child.errors[:parent_issue_id]
|
||||
end
|
||||
|
||||
def test_updating_a_root_issue_should_not_trigger_update_nested_set_attributes_on_parent_change
|
||||
issue = Issue.find(Issue.generate!.id)
|
||||
issue.parent_issue_id = ""
|
||||
issue.expects(:update_nested_set_attributes_on_parent_change).never
|
||||
issue.save!
|
||||
end
|
||||
|
||||
def test_updating_a_child_issue_should_not_trigger_update_nested_set_attributes_on_parent_change
|
||||
issue = Issue.find(Issue.generate!(:parent_issue_id => 1).id)
|
||||
issue.parent_issue_id = "1"
|
||||
issue.expects(:update_nested_set_attributes_on_parent_change).never
|
||||
issue.save!
|
||||
end
|
||||
|
||||
def test_moving_a_root_issue_should_trigger_update_nested_set_attributes_on_parent_change
|
||||
issue = Issue.find(Issue.generate!.id)
|
||||
issue.parent_issue_id = "1"
|
||||
issue.expects(:update_nested_set_attributes_on_parent_change).once
|
||||
issue.save!
|
||||
end
|
||||
|
||||
def test_moving_a_child_issue_to_another_parent_should_trigger_update_nested_set_attributes_on_parent_change
|
||||
issue = Issue.find(Issue.generate!(:parent_issue_id => 1).id)
|
||||
issue.parent_issue_id = "2"
|
||||
issue.expects(:update_nested_set_attributes_on_parent_change).once
|
||||
issue.save!
|
||||
end
|
||||
|
||||
def test_moving_a_child_issue_to_root_should_trigger_update_nested_set_attributes_on_parent_change
|
||||
issue = Issue.find(Issue.generate!(:parent_issue_id => 1).id)
|
||||
issue.parent_issue_id = ""
|
||||
issue.expects(:update_nested_set_attributes_on_parent_change).once
|
||||
issue.save!
|
||||
end
|
||||
|
||||
def test_destroy_should_destroy_children
|
||||
lft1 = new_issue_lft
|
||||
issue1 = Issue.generate!
|
||||
issue2 = Issue.generate!
|
||||
issue3 = issue2.generate_child!
|
||||
issue4 = issue1.generate_child!
|
||||
issue3.init_journal(User.find(2))
|
||||
issue3.subject = 'child with journal'
|
||||
issue3.save!
|
||||
assert_difference 'Issue.count', -2 do
|
||||
assert_difference 'Journal.count', -1 do
|
||||
assert_difference 'JournalDetail.count', -1 do
|
||||
Issue.find(issue2.id).destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
issue1.reload
|
||||
issue4.reload
|
||||
assert !Issue.exists?(issue2.id)
|
||||
assert !Issue.exists?(issue3.id)
|
||||
assert_equal [issue1.id, lft1, lft1 + 3], [issue1.root_id, issue1.lft, issue1.rgt]
|
||||
assert_equal [issue1.id, lft1 + 1, lft1 + 2], [issue4.root_id, issue4.lft, issue4.rgt]
|
||||
end
|
||||
|
||||
def test_destroy_child_should_update_parent
|
||||
lft1 = new_issue_lft
|
||||
issue = Issue.generate!
|
||||
child1 = issue.generate_child!
|
||||
child2 = issue.generate_child!
|
||||
issue.reload
|
||||
assert_equal [issue.id, lft1, lft1 + 5], [issue.root_id, issue.lft, issue.rgt]
|
||||
child2.reload.destroy
|
||||
issue.reload
|
||||
assert_equal [issue.id, lft1, lft1 + 3], [issue.root_id, issue.lft, issue.rgt]
|
||||
end
|
||||
|
||||
def test_destroy_parent_issue_updated_during_children_destroy
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:start_date => Date.today)
|
||||
parent.generate_child!(:start_date => 2.days.from_now)
|
||||
|
||||
assert_difference 'Issue.count', -3 do
|
||||
Issue.find(parent.id).destroy
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_child_issue_with_children
|
||||
root = Issue.generate!
|
||||
child = root.generate_child!
|
||||
leaf = child.generate_child!
|
||||
leaf.init_journal(User.find(2))
|
||||
leaf.subject = 'leaf with journal'
|
||||
leaf.save!
|
||||
|
||||
assert_difference 'Issue.count', -2 do
|
||||
assert_difference 'Journal.count', -1 do
|
||||
assert_difference 'JournalDetail.count', -1 do
|
||||
Issue.find(child.id).destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
root = Issue.find(root.id)
|
||||
assert root.leaf?, "Root issue is not a leaf (lft: #{root.lft}, rgt: #{root.rgt})"
|
||||
end
|
||||
|
||||
def test_destroy_issue_with_grand_child
|
||||
lft1 = new_issue_lft
|
||||
parent = Issue.generate!
|
||||
issue = parent.generate_child!
|
||||
child = issue.generate_child!
|
||||
grandchild1 = child.generate_child!
|
||||
grandchild2 = child.generate_child!
|
||||
assert_difference 'Issue.count', -4 do
|
||||
Issue.find(issue.id).destroy
|
||||
parent.reload
|
||||
assert_equal [lft1, lft1 + 1], [parent.lft, parent.rgt]
|
||||
end
|
||||
end
|
||||
|
||||
def test_project_copy_should_copy_issue_tree
|
||||
p = Project.create!(:name => 'Tree copy', :identifier => 'tree-copy', :tracker_ids => [1, 2])
|
||||
i1 = Issue.generate!(:project => p, :subject => 'i1')
|
||||
i2 = i1.generate_child!(:project => p, :subject => 'i2')
|
||||
i3 = i1.generate_child!(:project => p, :subject => 'i3')
|
||||
i4 = i2.generate_child!(:project => p, :subject => 'i4')
|
||||
i5 = Issue.generate!(:project => p, :subject => 'i5')
|
||||
c = Project.new(:name => 'Copy', :identifier => 'copy', :tracker_ids => [1, 2])
|
||||
c.copy(p, :only => 'issues')
|
||||
c.reload
|
||||
|
||||
assert_equal 5, c.issues.count
|
||||
ic1, ic2, ic3, ic4, ic5 = c.issues.order('subject').to_a
|
||||
assert ic1.root?
|
||||
assert_equal ic1, ic2.parent
|
||||
assert_equal ic1, ic3.parent
|
||||
assert_equal ic2, ic4.parent
|
||||
assert ic5.root?
|
||||
end
|
||||
|
||||
def test_rebuild_single_tree
|
||||
i1 = Issue.generate!
|
||||
i2 = i1.generate_child!
|
||||
i3 = i1.generate_child!
|
||||
Issue.update_all(:lft => 7, :rgt => 7)
|
||||
|
||||
Issue.rebuild_single_tree!(i1.id)
|
||||
|
||||
i1.reload
|
||||
assert_equal [1, 6], [i1.lft, i1.rgt]
|
||||
i2.reload
|
||||
assert_equal [2, 3], [i2.lft, i2.rgt]
|
||||
i3.reload
|
||||
assert_equal [4, 5], [i3.lft, i3.rgt]
|
||||
|
||||
other = Issue.find(1)
|
||||
assert_equal [7, 7], [other.lft, other.rgt]
|
||||
end
|
||||
end
|
||||
102
test/unit/issue_priority_test.rb
Normal file
102
test/unit/issue_priority_test.rb
Normal 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 IssuePriorityTest < ActiveSupport::TestCase
|
||||
fixtures :enumerations, :issues
|
||||
|
||||
def test_named_scope
|
||||
assert_equal Enumeration.find_by_name('Normal'), Enumeration.named('normal').first
|
||||
end
|
||||
|
||||
def test_default_should_return_the_default_priority
|
||||
assert_equal Enumeration.find_by_name('Normal'), IssuePriority.default
|
||||
end
|
||||
|
||||
def test_default_should_return_nil_when_no_default_priority
|
||||
IssuePriority.update_all :is_default => false
|
||||
assert_nil IssuePriority.default
|
||||
end
|
||||
|
||||
def test_should_be_an_enumeration
|
||||
assert IssuePriority.ancestors.include?(Enumeration)
|
||||
end
|
||||
|
||||
def test_objects_count
|
||||
# low priority
|
||||
assert_equal 6, IssuePriority.find(4).objects_count
|
||||
# urgent
|
||||
assert_equal 0, IssuePriority.find(7).objects_count
|
||||
end
|
||||
|
||||
def test_option_name
|
||||
assert_equal :enumeration_issue_priorities, IssuePriority.new.option_name
|
||||
end
|
||||
|
||||
def test_should_be_created_at_last_position
|
||||
IssuePriority.delete_all
|
||||
|
||||
priorities = [1, 2, 3].map {|i| IssuePriority.create!(:name => "P#{i}")}
|
||||
assert_equal [1, 2, 3], priorities.map(&:position)
|
||||
end
|
||||
|
||||
def test_clear_position_names_should_set_position_names_to_nil
|
||||
IssuePriority.clear_position_names
|
||||
assert IssuePriority.all.all? {|priority| priority.position_name.nil?}
|
||||
end
|
||||
|
||||
def test_compute_position_names_with_default_priority
|
||||
IssuePriority.clear_position_names
|
||||
|
||||
IssuePriority.compute_position_names
|
||||
assert_equal %w(lowest default high3 high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
|
||||
end
|
||||
|
||||
def test_compute_position_names_without_default_priority_should_split_priorities
|
||||
IssuePriority.clear_position_names
|
||||
IssuePriority.update_all :is_default => false
|
||||
|
||||
IssuePriority.compute_position_names
|
||||
assert_equal %w(lowest low2 default high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
|
||||
end
|
||||
|
||||
def test_adding_a_priority_should_update_position_names
|
||||
priority = IssuePriority.create!(:name => 'New')
|
||||
assert_equal %w(lowest default high4 high3 high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
|
||||
end
|
||||
|
||||
def test_moving_a_priority_should_update_position_names
|
||||
prio = IssuePriority.first
|
||||
prio.position = IssuePriority.count
|
||||
prio.save!
|
||||
prio.reload
|
||||
assert_equal 'highest', prio.position_name
|
||||
end
|
||||
|
||||
def test_deactivating_a_priority_should_update_position_names
|
||||
prio = IssuePriority.active.order(:position).last
|
||||
prio.active = false
|
||||
prio.save
|
||||
assert_equal 'highest', IssuePriority.active.order(:position).last.position_name
|
||||
end
|
||||
|
||||
def test_destroying_a_priority_should_update_position_names
|
||||
IssuePriority.find_by_position_name('highest').destroy
|
||||
assert_equal %w(lowest default high2 highest), IssuePriority.active.to_a.sort.map(&:position_name)
|
||||
end
|
||||
end
|
||||
250
test/unit/issue_relation_test.rb
Normal file
250
test/unit/issue_relation_test.rb
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
# 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 IssueRelationTest < ActiveSupport::TestCase
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issues,
|
||||
:issue_statuses,
|
||||
:issue_relations,
|
||||
:enabled_modules,
|
||||
:enumerations,
|
||||
:trackers,
|
||||
:projects_trackers
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def test_create
|
||||
from = Issue.find(1)
|
||||
to = Issue.find(2)
|
||||
|
||||
relation = IssueRelation.new :issue_from => from, :issue_to => to,
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
assert relation.save
|
||||
relation.reload
|
||||
assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type
|
||||
assert_equal from, relation.issue_from
|
||||
assert_equal to, relation.issue_to
|
||||
end
|
||||
|
||||
def test_create_minimum
|
||||
relation = IssueRelation.new :issue_from => Issue.find(1), :issue_to => Issue.find(2)
|
||||
assert relation.save
|
||||
assert_equal IssueRelation::TYPE_RELATES, relation.relation_type
|
||||
end
|
||||
|
||||
def test_follows_relation_should_be_reversed
|
||||
from = Issue.find(1)
|
||||
to = Issue.find(2)
|
||||
|
||||
relation = IssueRelation.new :issue_from => from, :issue_to => to,
|
||||
:relation_type => IssueRelation::TYPE_FOLLOWS
|
||||
assert relation.save
|
||||
relation.reload
|
||||
assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type
|
||||
assert_equal to, relation.issue_from
|
||||
assert_equal from, relation.issue_to
|
||||
end
|
||||
|
||||
def test_cannot_create_inverse_relates_relations
|
||||
from = Issue.find(1)
|
||||
to = Issue.find(2)
|
||||
|
||||
relation1 = IssueRelation.new :issue_from => from, :issue_to => to,
|
||||
:relation_type => IssueRelation::TYPE_RELATES
|
||||
assert relation1.save
|
||||
|
||||
relation2 = IssueRelation.new :issue_from => to, :issue_to => from,
|
||||
:relation_type => IssueRelation::TYPE_RELATES
|
||||
assert !relation2.save
|
||||
assert_not_equal [], relation2.errors[:base]
|
||||
end
|
||||
|
||||
def test_follows_relation_should_not_be_reversed_if_validation_fails
|
||||
from = Issue.find(1)
|
||||
to = Issue.find(2)
|
||||
|
||||
relation = IssueRelation.new :issue_from => from, :issue_to => to,
|
||||
:relation_type => IssueRelation::TYPE_FOLLOWS,
|
||||
:delay => 'xx'
|
||||
assert !relation.save
|
||||
assert_equal IssueRelation::TYPE_FOLLOWS, relation.relation_type
|
||||
assert_equal from, relation.issue_from
|
||||
assert_equal to, relation.issue_to
|
||||
end
|
||||
|
||||
def test_relation_type_for
|
||||
from = Issue.find(1)
|
||||
to = Issue.find(2)
|
||||
|
||||
relation = IssueRelation.new :issue_from => from, :issue_to => to,
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
assert_equal IssueRelation::TYPE_PRECEDES, relation.relation_type_for(from)
|
||||
assert_equal IssueRelation::TYPE_FOLLOWS, relation.relation_type_for(to)
|
||||
end
|
||||
|
||||
def test_set_issue_to_dates_without_issue_to
|
||||
r = IssueRelation.new(:issue_from => Issue.new(:start_date => Date.today),
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES,
|
||||
:delay => 1)
|
||||
assert_nil r.set_issue_to_dates
|
||||
end
|
||||
|
||||
def test_set_issue_to_dates_without_issues
|
||||
r = IssueRelation.new(:relation_type => IssueRelation::TYPE_PRECEDES, :delay => 1)
|
||||
assert_nil r.set_issue_to_dates
|
||||
end
|
||||
|
||||
def test_validates_circular_dependency
|
||||
IssueRelation.delete_all
|
||||
assert IssueRelation.create!(
|
||||
:issue_from => Issue.find(1), :issue_to => Issue.find(2),
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
)
|
||||
assert IssueRelation.create!(
|
||||
:issue_from => Issue.find(2), :issue_to => Issue.find(3),
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
)
|
||||
r = IssueRelation.new(
|
||||
:issue_from => Issue.find(3), :issue_to => Issue.find(1),
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
)
|
||||
assert !r.save
|
||||
assert_not_equal [], r.errors[:base]
|
||||
end
|
||||
|
||||
def test_validates_circular_dependency_of_subtask
|
||||
set_language_if_valid 'en'
|
||||
issue1 = Issue.generate!
|
||||
issue2 = Issue.generate!
|
||||
IssueRelation.create!(
|
||||
:issue_from => issue1, :issue_to => issue2,
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
)
|
||||
child = Issue.generate!(:parent_issue_id => issue2.id)
|
||||
issue1.reload
|
||||
child.reload
|
||||
|
||||
r = IssueRelation.new(
|
||||
:issue_from => child, :issue_to => issue1,
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
)
|
||||
assert !r.save
|
||||
assert_include 'This relation would create a circular dependency', r.errors.full_messages
|
||||
end
|
||||
|
||||
def test_subtasks_should_allow_precedes_relation
|
||||
parent = Issue.generate!
|
||||
child1 = Issue.generate!(:parent_issue_id => parent.id)
|
||||
child2 = Issue.generate!(:parent_issue_id => parent.id)
|
||||
|
||||
r = IssueRelation.new(
|
||||
:issue_from => child1, :issue_to => child2,
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||
)
|
||||
assert r.valid?
|
||||
assert r.save
|
||||
end
|
||||
|
||||
def test_validates_circular_dependency_on_reverse_relations
|
||||
IssueRelation.delete_all
|
||||
assert IssueRelation.create!(
|
||||
:issue_from => Issue.find(1), :issue_to => Issue.find(3),
|
||||
:relation_type => IssueRelation::TYPE_BLOCKS
|
||||
)
|
||||
assert IssueRelation.create!(
|
||||
:issue_from => Issue.find(1), :issue_to => Issue.find(2),
|
||||
:relation_type => IssueRelation::TYPE_BLOCKED
|
||||
)
|
||||
r = IssueRelation.new(
|
||||
:issue_from => Issue.find(2), :issue_to => Issue.find(1),
|
||||
:relation_type => IssueRelation::TYPE_BLOCKED
|
||||
)
|
||||
assert !r.save
|
||||
assert_not_equal [], r.errors[:base]
|
||||
end
|
||||
|
||||
def test_create_with_initialized_journals_should_create_journals
|
||||
from = Issue.find(1)
|
||||
to = Issue.find(2)
|
||||
from_journals = from.journals.size
|
||||
to_journals = to.journals.size
|
||||
relation = IssueRelation.new(:issue_from => from, :issue_to => to,
|
||||
:relation_type => IssueRelation::TYPE_PRECEDES)
|
||||
relation.init_journals User.find(1)
|
||||
assert relation.save
|
||||
from.reload
|
||||
to.reload
|
||||
relation.reload
|
||||
assert_equal from.journals.size, (from_journals + 1)
|
||||
assert_equal to.journals.size, (to_journals + 1)
|
||||
assert_equal 'relation', from.journals.last.details.last.property
|
||||
assert_equal 'precedes', from.journals.last.details.last.prop_key
|
||||
assert_equal '2', from.journals.last.details.last.value
|
||||
assert_nil from.journals.last.details.last.old_value
|
||||
assert_equal 'relation', to.journals.last.details.last.property
|
||||
assert_equal 'follows', to.journals.last.details.last.prop_key
|
||||
assert_equal '1', to.journals.last.details.last.value
|
||||
assert_nil to.journals.last.details.last.old_value
|
||||
end
|
||||
|
||||
def test_destroy_with_initialized_journals_should_create_journals
|
||||
relation = IssueRelation.find(1)
|
||||
from = relation.issue_from
|
||||
to = relation.issue_to
|
||||
from_journals = from.journals.size
|
||||
to_journals = to.journals.size
|
||||
relation.init_journals User.find(1)
|
||||
assert relation.destroy
|
||||
from.reload
|
||||
to.reload
|
||||
assert_equal from.journals.size, (from_journals + 1)
|
||||
assert_equal to.journals.size, (to_journals + 1)
|
||||
assert_equal 'relation', from.journals.last.details.last.property
|
||||
assert_equal 'blocks', from.journals.last.details.last.prop_key
|
||||
assert_equal '9', from.journals.last.details.last.old_value
|
||||
assert_nil from.journals.last.details.last.value
|
||||
assert_equal 'relation', to.journals.last.details.last.property
|
||||
assert_equal 'blocked', to.journals.last.details.last.prop_key
|
||||
assert_equal '10', to.journals.last.details.last.old_value
|
||||
assert_nil to.journals.last.details.last.value
|
||||
end
|
||||
|
||||
def test_to_s_should_return_the_relation_string
|
||||
set_language_if_valid 'en'
|
||||
relation = IssueRelation.find(1)
|
||||
assert_equal "Blocks #9", relation.to_s(relation.issue_from)
|
||||
assert_equal "Blocked by #10", relation.to_s(relation.issue_to)
|
||||
end
|
||||
|
||||
def test_to_s_without_argument_should_return_the_relation_string_for_issue_from
|
||||
set_language_if_valid 'en'
|
||||
relation = IssueRelation.find(1)
|
||||
assert_equal "Blocks #9", relation.to_s
|
||||
end
|
||||
|
||||
def test_to_s_should_accept_a_block_as_custom_issue_formatting
|
||||
set_language_if_valid 'en'
|
||||
relation = IssueRelation.find(1)
|
||||
assert_equal "Blocks Bug #9", relation.to_s {|issue| "#{issue.tracker} ##{issue.id}"}
|
||||
end
|
||||
end
|
||||
69
test/unit/issue_scopes_test.rb
Normal file
69
test/unit/issue_scopes_test.rb
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# 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 IssueScopesTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles,
|
||||
:groups_users,
|
||||
:trackers, :projects_trackers,
|
||||
:enabled_modules,
|
||||
:versions, :issue_statuses, :issue_categories, :enumerations,
|
||||
:issues,
|
||||
:custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values
|
||||
|
||||
def test_cross_project_scope_without_project_should_return_all_issues
|
||||
ids = Issue.cross_project_scope(nil).pluck(:id).sort
|
||||
assert_equal Issue.pluck(:id).sort, ids
|
||||
end
|
||||
|
||||
def test_cross_project_scope_with_project_should_return_project_issues
|
||||
project = Project.find(1)
|
||||
ids = Issue.cross_project_scope(project).pluck(:id).sort
|
||||
assert_equal project.issues.pluck(:id).sort, ids
|
||||
end
|
||||
|
||||
def test_cross_project_scope_with_all_scope_should_return_all_issues
|
||||
project = Project.find(1)
|
||||
ids = Issue.cross_project_scope(project, 'all').pluck(:id).sort
|
||||
assert_equal Issue.pluck(:id).sort, ids
|
||||
end
|
||||
|
||||
def test_cross_project_scope_with_system_scope_should_return_all_issues
|
||||
project = Project.find(1)
|
||||
ids = Issue.cross_project_scope(project, 'system').pluck(:id).sort
|
||||
assert_equal Issue.pluck(:id).sort, ids
|
||||
end
|
||||
|
||||
def test_cross_project_scope_with_tree_scope_should_return_tree_issues
|
||||
project = Project.find(5)
|
||||
ids = Issue.cross_project_scope(project, 'tree').pluck(:id).sort
|
||||
assert_equal project.root.self_and_descendants.map{|p| p.issues.pluck(:id)}.flatten.sort, ids
|
||||
end
|
||||
|
||||
def test_cross_project_scope_with_hierarchy_scope_should_return_hierarchy_issues
|
||||
project = Project.find(5)
|
||||
ids = Issue.cross_project_scope(project, 'hierarchy').pluck(:id).sort
|
||||
assert_equal (project.self_and_descendants + project.ancestors).map{|p| p.issues.pluck(:id)}.flatten.sort, ids
|
||||
end
|
||||
|
||||
def test_cross_project_scope_with_descendants_scope_should_return_descendants_issues
|
||||
project = Project.find(5)
|
||||
ids = Issue.cross_project_scope(project, 'descendants').pluck(:id).sort
|
||||
assert_equal project.self_and_descendants.map{|p| p.issues.pluck(:id)}.flatten.sort, ids
|
||||
end
|
||||
end
|
||||
141
test/unit/issue_status_test.rb
Normal file
141
test/unit/issue_status_test.rb
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
# 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 IssueStatusTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles,
|
||||
:groups_users,
|
||||
:trackers, :projects_trackers,
|
||||
:enabled_modules,
|
||||
:versions,
|
||||
:issue_statuses, :issue_categories, :issue_relations, :workflows,
|
||||
:enumerations,
|
||||
:issues, :journals, :journal_details,
|
||||
:custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values
|
||||
|
||||
def test_create
|
||||
status = IssueStatus.new :name => "Assigned"
|
||||
assert !status.save
|
||||
# status name uniqueness
|
||||
assert_equal 1, status.errors.count
|
||||
|
||||
status.name = "Test Status"
|
||||
assert status.save
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
status = IssueStatus.find(3)
|
||||
assert_difference 'IssueStatus.count', -1 do
|
||||
assert status.destroy
|
||||
end
|
||||
assert_nil WorkflowTransition.where(:old_status_id => status.id).first
|
||||
assert_nil WorkflowTransition.where(:new_status_id => status.id).first
|
||||
end
|
||||
|
||||
def test_destroy_status_in_use
|
||||
# Status assigned to an Issue
|
||||
status = Issue.find(1).status
|
||||
assert_raise(RuntimeError, "Cannot delete status") { status.destroy }
|
||||
end
|
||||
|
||||
def test_new_statuses_allowed_to
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
|
||||
status = IssueStatus.find(1)
|
||||
role = Role.find(1)
|
||||
tracker = Tracker.find(1)
|
||||
|
||||
assert_equal [2], status.new_statuses_allowed_to([role], tracker, false, false).map(&:id)
|
||||
assert_equal [2], status.find_new_statuses_allowed_to([role], tracker, false, false).map(&:id)
|
||||
|
||||
assert_equal [2, 3, 5], status.new_statuses_allowed_to([role], tracker, true, false).map(&:id)
|
||||
assert_equal [2, 3, 5], status.find_new_statuses_allowed_to([role], tracker, true, false).map(&:id)
|
||||
|
||||
assert_equal [2, 4, 5], status.new_statuses_allowed_to([role], tracker, false, true).map(&:id)
|
||||
assert_equal [2, 4, 5], status.find_new_statuses_allowed_to([role], tracker, false, true).map(&:id)
|
||||
|
||||
assert_equal [2, 3, 4, 5], status.new_statuses_allowed_to([role], tracker, true, true).map(&:id)
|
||||
assert_equal [2, 3, 4, 5], status.find_new_statuses_allowed_to([role], tracker, true, true).map(&:id)
|
||||
end
|
||||
|
||||
def test_update_done_ratios_with_issue_done_ratio_set_to_issue_field_should_change_nothing
|
||||
IssueStatus.find(1).update_attribute(:default_done_ratio, 50)
|
||||
|
||||
with_settings :issue_done_ratio => 'issue_field' do
|
||||
IssueStatus.update_issue_done_ratios
|
||||
assert_equal 0, Issue.where(:done_ratio => 50).count
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_done_ratios_with_issue_done_ratio_set_to_issue_status_should_update_issues
|
||||
IssueStatus.find(1).update_attribute(:default_done_ratio, 50)
|
||||
with_settings :issue_done_ratio => 'issue_status' do
|
||||
IssueStatus.update_issue_done_ratios
|
||||
issues = Issue.where(:status_id => 1)
|
||||
assert_equal [50], issues.map {|issue| issue.read_attribute(:done_ratio)}.uniq
|
||||
end
|
||||
end
|
||||
|
||||
def test_sorted_scope
|
||||
assert_equal IssueStatus.all.sort, IssueStatus.sorted.to_a
|
||||
end
|
||||
|
||||
def test_named_scope
|
||||
status = IssueStatus.named("resolved").first
|
||||
assert_not_nil status
|
||||
assert_equal "Resolved", status.name
|
||||
end
|
||||
|
||||
def test_setting_status_as_closed_should_set_closed_on_for_issues_without_status_journal
|
||||
issue = Issue.generate!(:status_id => 1, :created_on => 2.days.ago)
|
||||
assert_nil issue.closed_on
|
||||
|
||||
issue.status.update! :is_closed => true
|
||||
|
||||
issue.reload
|
||||
assert issue.closed?
|
||||
assert_equal issue.created_on, issue.closed_on
|
||||
end
|
||||
|
||||
def test_setting_status_as_closed_should_set_closed_on_for_issues_with_status_journal
|
||||
issue = Issue.generate!(:status_id => 1, :created_on => 2.days.ago)
|
||||
issue.init_journal(User.find(1))
|
||||
issue.status_id = 2
|
||||
issue.save!
|
||||
|
||||
issue.status.update! :is_closed => true
|
||||
|
||||
issue.reload
|
||||
assert issue.closed?
|
||||
assert_equal issue.journals.first.created_on, issue.closed_on
|
||||
end
|
||||
|
||||
def test_setting_status_as_closed_should_not_set_closed_on_for_issues_with_other_status
|
||||
issue = Issue.generate!(:status_id => 2)
|
||||
|
||||
IssueStatus.find(1).update! :is_closed => true
|
||||
|
||||
issue.reload
|
||||
assert !issue.closed?
|
||||
assert_nil issue.closed_on
|
||||
end
|
||||
end
|
||||
342
test/unit/issue_subtasking_test.rb
Normal file
342
test/unit/issue_subtasking_test.rb
Normal 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 IssueSubtaskingTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :users, :roles, :members, :member_roles,
|
||||
:trackers, :projects_trackers,
|
||||
:issue_statuses, :issue_categories, :enumerations,
|
||||
:issues,
|
||||
:enabled_modules,
|
||||
:workflows
|
||||
|
||||
def test_leaf_planning_fields_should_be_editable
|
||||
issue = Issue.generate!
|
||||
user = User.find(1)
|
||||
%w(priority_id done_ratio start_date due_date estimated_hours).each do |attribute|
|
||||
assert issue.safe_attribute?(attribute, user)
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_dates_should_be_read_only_with_parent_issue_dates_set_to_derived
|
||||
with_settings :parent_issue_dates => 'derived' do
|
||||
issue = Issue.generate_with_child!
|
||||
user = User.find(1)
|
||||
%w(start_date due_date).each do |attribute|
|
||||
assert !issue.safe_attribute?(attribute, user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_dates_should_be_lowest_start_and_highest_due_dates_with_parent_issue_dates_set_to_derived
|
||||
with_settings :parent_issue_dates => 'derived' do
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:start_date => '2010-01-25', :due_date => '2010-02-15')
|
||||
parent.generate_child!( :due_date => '2010-02-13')
|
||||
parent.generate_child!(:start_date => '2010-02-01', :due_date => '2010-02-22')
|
||||
parent.reload
|
||||
assert_equal Date.parse('2010-01-25'), parent.start_date
|
||||
assert_equal Date.parse('2010-02-22'), parent.due_date
|
||||
end
|
||||
end
|
||||
|
||||
def test_reschuling_a_parent_should_reschedule_subtasks_with_parent_issue_dates_set_to_derived
|
||||
with_settings :parent_issue_dates => 'derived' do
|
||||
parent = Issue.generate!
|
||||
c1 = parent.generate_child!(:start_date => '2010-05-12', :due_date => '2010-05-18')
|
||||
c2 = parent.generate_child!(:start_date => '2010-06-03', :due_date => '2010-06-10')
|
||||
parent.reload.reschedule_on!(Date.parse('2010-06-02'))
|
||||
c1.reload
|
||||
assert_equal [Date.parse('2010-06-02'), Date.parse('2010-06-08')], [c1.start_date, c1.due_date]
|
||||
c2.reload
|
||||
assert_equal [Date.parse('2010-06-03'), Date.parse('2010-06-10')], [c2.start_date, c2.due_date] # no change
|
||||
parent.reload
|
||||
assert_equal [Date.parse('2010-06-02'), Date.parse('2010-06-10')], [parent.start_date, parent.due_date]
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_priority_should_be_read_only_with_parent_issue_priority_set_to_derived
|
||||
with_settings :parent_issue_priority => 'derived' do
|
||||
issue = Issue.generate_with_child!
|
||||
user = User.find(1)
|
||||
assert !issue.safe_attribute?('priority_id', user)
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_priority_should_be_the_highest_open_child_priority
|
||||
with_settings :parent_issue_priority => 'derived' do
|
||||
parent = Issue.generate!(:priority => IssuePriority.find_by_name('Normal'))
|
||||
# Create children
|
||||
child1 = parent.generate_child!(:priority => IssuePriority.find_by_name('High'))
|
||||
assert_equal 'High', parent.reload.priority.name
|
||||
child2 = child1.generate_child!(:priority => IssuePriority.find_by_name('Immediate'))
|
||||
assert_equal 'Immediate', child1.reload.priority.name
|
||||
assert_equal 'Immediate', parent.reload.priority.name
|
||||
child3 = parent.generate_child!(:priority => IssuePriority.find_by_name('Low'))
|
||||
child4 = parent.generate_child!(:priority => IssuePriority.find_by_name('Urgent'))
|
||||
assert_equal 'Immediate', parent.reload.priority.name
|
||||
# Destroy a child
|
||||
child1.destroy
|
||||
assert_equal 'Urgent', parent.reload.priority.name
|
||||
# Close a child
|
||||
child4.status = IssueStatus.where(:is_closed => true).first
|
||||
child4.save!
|
||||
assert_equal 'Low', parent.reload.priority.name
|
||||
# Update a child
|
||||
child3.reload.priority = IssuePriority.find_by_name('Normal')
|
||||
child3.save!
|
||||
assert_equal 'Normal', parent.reload.priority.name
|
||||
# Reopen a child
|
||||
child4.status = IssueStatus.where(:is_closed => false).first
|
||||
child4.save!
|
||||
assert_equal 'Urgent', parent.reload.priority.name
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_priority_should_be_set_to_default_when_all_children_are_closed
|
||||
with_settings :parent_issue_priority => 'derived' do
|
||||
parent = Issue.generate!
|
||||
child = parent.generate_child!(:priority => IssuePriority.find_by_name('High'))
|
||||
assert_equal 'High', parent.reload.priority.name
|
||||
child.status = IssueStatus.where(:is_closed => true).first
|
||||
child.save!
|
||||
assert_equal 'Normal', parent.reload.priority.name
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_priority_should_be_left_unchanged_when_all_children_are_closed_and_no_default_priority
|
||||
IssuePriority.update_all :is_default => false
|
||||
|
||||
with_settings :parent_issue_priority => 'derived' do
|
||||
parent = Issue.generate!(:priority => IssuePriority.find_by_name('Normal'))
|
||||
child = parent.generate_child!(:priority => IssuePriority.find_by_name('High'))
|
||||
assert_equal 'High', parent.reload.priority.name
|
||||
child.status = IssueStatus.where(:is_closed => true).first
|
||||
child.save!
|
||||
assert_equal 'High', parent.reload.priority.name
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_should_be_read_only_with_parent_issue_done_ratio_set_to_derived
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
issue = Issue.generate_with_child!
|
||||
user = User.find(1)
|
||||
assert !issue.safe_attribute?('done_ratio', user)
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_should_be_average_done_ratio_of_leaves
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:done_ratio => 20)
|
||||
assert_equal 20, parent.reload.done_ratio
|
||||
parent.generate_child!(:done_ratio => 70)
|
||||
assert_equal 45, parent.reload.done_ratio
|
||||
|
||||
child = parent.generate_child!(:done_ratio => 0)
|
||||
assert_equal 30, parent.reload.done_ratio
|
||||
|
||||
child.generate_child!(:done_ratio => 30)
|
||||
assert_equal 30, child.reload.done_ratio
|
||||
assert_equal 40, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_should_be_weighted_by_estimated_times_if_any
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:estimated_hours => 10, :done_ratio => 20)
|
||||
assert_equal 20, parent.reload.done_ratio
|
||||
parent.generate_child!(:estimated_hours => 20, :done_ratio => 50)
|
||||
assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_should_be_weighted_by_estimated_times_if_any_with_grandchildren
|
||||
# parent
|
||||
# child 1 (2h estd, 0% done)
|
||||
# child 2 (no estd)
|
||||
# child a (2h estd, 50% done)
|
||||
# child b (2h estd, 50% done)
|
||||
#
|
||||
# => parent should have a calculated progress of 33%
|
||||
#
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:estimated_hours => 2, :done_ratio => 0)
|
||||
child = parent.generate_child!
|
||||
child.generate_child!(:estimated_hours => 2, :done_ratio => 50)
|
||||
child.generate_child!(:estimated_hours => 2, :done_ratio => 50)
|
||||
assert_equal 50, child.reload.done_ratio
|
||||
assert_equal 33, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_with_child_estimate_to_0_should_reach_100
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
parent = Issue.generate!
|
||||
issue1 = parent.generate_child!
|
||||
issue2 = parent.generate_child!(:estimated_hours => 0)
|
||||
assert_equal 0, parent.reload.done_ratio
|
||||
issue1.reload.close!
|
||||
assert_equal 50, parent.reload.done_ratio
|
||||
issue2.reload.close!
|
||||
assert_equal 100, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_done_ratio_of_parent_with_a_child_without_estimated_time_should_not_exceed_100
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:estimated_hours => 40)
|
||||
parent.generate_child!(:estimated_hours => 40)
|
||||
parent.generate_child!(:estimated_hours => 20)
|
||||
parent.generate_child!
|
||||
parent.reload.children.each(&:close!)
|
||||
assert_equal 100, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_done_ratio_of_parent_with_a_child_with_estimated_time_at_0_should_not_exceed_100
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:estimated_hours => 40)
|
||||
parent.generate_child!(:estimated_hours => 40)
|
||||
parent.generate_child!(:estimated_hours => 20)
|
||||
parent.generate_child!(:estimated_hours => 0)
|
||||
parent.reload.children.each(&:close!)
|
||||
assert_equal 100, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_changing_parent_should_update_previous_parent_done_ratio
|
||||
with_settings :parent_issue_done_ratio => 'derived' do
|
||||
first_parent = Issue.generate!
|
||||
second_parent = Issue.generate!
|
||||
first_parent.generate_child!(:done_ratio => 40)
|
||||
child = first_parent.generate_child!(:done_ratio => 20)
|
||||
assert_equal 30, first_parent.reload.done_ratio
|
||||
assert_equal 0, second_parent.reload.done_ratio
|
||||
child.update_attributes(:parent_issue_id => second_parent.id)
|
||||
assert_equal 40, first_parent.reload.done_ratio
|
||||
assert_equal 20, second_parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_done_ratio_of_parent_should_reflect_children
|
||||
root = Issue.generate!
|
||||
child1 = root.generate_child!
|
||||
child2 = child1.generate_child!
|
||||
|
||||
assert_equal 0, root.done_ratio
|
||||
assert_equal 0, child1.done_ratio
|
||||
assert_equal 0, child2.done_ratio
|
||||
|
||||
with_settings :issue_done_ratio => 'issue_status' do
|
||||
status = IssueStatus.find(4)
|
||||
status.update_attribute :default_done_ratio, 50
|
||||
child1.update_attribute :status, status
|
||||
|
||||
assert_equal 50, child1.done_ratio
|
||||
root.reload
|
||||
assert_equal 50, root.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_dates_should_be_editable_with_parent_issue_dates_set_to_independent
|
||||
with_settings :parent_issue_dates => 'independent' do
|
||||
issue = Issue.generate_with_child!
|
||||
user = User.find(1)
|
||||
%w(start_date due_date).each do |attribute|
|
||||
assert issue.safe_attribute?(attribute, user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_dates_should_not_be_updated_with_parent_issue_dates_set_to_independent
|
||||
with_settings :parent_issue_dates => 'independent' do
|
||||
parent = Issue.generate!(:start_date => '2015-07-01', :due_date => '2015-08-01')
|
||||
parent.generate_child!(:start_date => '2015-06-01', :due_date => '2015-09-01')
|
||||
parent.reload
|
||||
assert_equal Date.parse('2015-07-01'), parent.start_date
|
||||
assert_equal Date.parse('2015-08-01'), parent.due_date
|
||||
end
|
||||
end
|
||||
|
||||
def test_reschuling_a_parent_should_not_reschedule_subtasks_with_parent_issue_dates_set_to_independent
|
||||
with_settings :parent_issue_dates => 'independent' do
|
||||
parent = Issue.generate!(:start_date => '2010-05-01', :due_date => '2010-05-20')
|
||||
c1 = parent.generate_child!(:start_date => '2010-05-12', :due_date => '2010-05-18')
|
||||
parent.reload.reschedule_on!(Date.parse('2010-06-01'))
|
||||
assert_equal Date.parse('2010-06-01'), parent.reload.start_date
|
||||
c1.reload
|
||||
assert_equal [Date.parse('2010-05-12'), Date.parse('2010-05-18')], [c1.start_date, c1.due_date]
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_priority_should_be_editable_with_parent_issue_priority_set_to_independent
|
||||
with_settings :parent_issue_priority => 'independent' do
|
||||
issue = Issue.generate_with_child!
|
||||
user = User.find(1)
|
||||
assert issue.safe_attribute?('priority_id', user)
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_priority_should_not_be_updated_with_parent_issue_priority_set_to_independent
|
||||
with_settings :parent_issue_priority => 'independent' do
|
||||
parent = Issue.generate!(:priority => IssuePriority.find_by_name('Normal'))
|
||||
child1 = parent.generate_child!(:priority => IssuePriority.find_by_name('High'))
|
||||
assert_equal 'Normal', parent.reload.priority.name
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_should_be_editable_with_parent_issue_done_ratio_set_to_independent
|
||||
with_settings :parent_issue_done_ratio => 'independent' do
|
||||
issue = Issue.generate_with_child!
|
||||
user = User.find(1)
|
||||
assert issue.safe_attribute?('done_ratio', user)
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_done_ratio_should_not_be_updated_with_parent_issue_done_ratio_set_to_independent
|
||||
with_settings :parent_issue_done_ratio => 'independent' do
|
||||
parent = Issue.generate!(:done_ratio => 0)
|
||||
child1 = parent.generate_child!(:done_ratio => 10)
|
||||
assert_equal 0, parent.reload.done_ratio
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent_total_estimated_hours_should_be_sum_of_descendants
|
||||
parent = Issue.generate!
|
||||
parent.generate_child!(:estimated_hours => nil)
|
||||
assert_equal 0, parent.reload.total_estimated_hours
|
||||
parent.generate_child!(:estimated_hours => 5)
|
||||
assert_equal 5, parent.reload.total_estimated_hours
|
||||
parent.generate_child!(:estimated_hours => 7)
|
||||
assert_equal 12, parent.reload.total_estimated_hours
|
||||
end
|
||||
|
||||
def test_open_issue_with_closed_parent_should_not_validate
|
||||
parent = Issue.generate!(:status_id => 5)
|
||||
child = Issue.generate!
|
||||
|
||||
child.parent_issue_id = parent.id
|
||||
assert !child.save
|
||||
assert_include I18n.t("activerecord.errors.messages.open_issue_with_closed_parent"), child.errors.full_messages
|
||||
end
|
||||
end
|
||||
3067
test/unit/issue_test.rb
Normal file
3067
test/unit/issue_test.rb
Normal file
File diff suppressed because it is too large
Load diff
52
test/unit/issue_transaction_test.rb
Normal file
52
test/unit/issue_transaction_test.rb
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# 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 IssueTransactionTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles,
|
||||
:trackers, :projects_trackers,
|
||||
:versions,
|
||||
:issue_statuses, :issue_categories, :issue_relations, :workflows,
|
||||
:enumerations,
|
||||
:issues,
|
||||
:custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
|
||||
:time_entries
|
||||
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def test_invalid_move_to_another_project
|
||||
lft1 = new_issue_lft
|
||||
parent1 = Issue.generate!
|
||||
child = Issue.generate!(:parent_issue_id => parent1.id)
|
||||
grandchild = Issue.generate!(:parent_issue_id => child.id, :tracker_id => 2)
|
||||
Project.find(2).tracker_ids = [1]
|
||||
parent1.reload
|
||||
assert_equal [1, parent1.id, lft1, lft1 + 5], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
|
||||
# child can not be moved to Project 2 because its child is on a disabled tracker
|
||||
child = Issue.find(child.id)
|
||||
child.project = Project.find(2)
|
||||
assert !child.save
|
||||
child.reload
|
||||
grandchild.reload
|
||||
parent1.reload
|
||||
# no change
|
||||
assert_equal [1, parent1.id, lft1, lft1 + 5], [parent1.project_id, parent1.root_id, parent1.lft, parent1.rgt]
|
||||
assert_equal [1, parent1.id, lft1 + 1, lft1 + 4], [child.project_id, child.root_id, child.lft, child.rgt]
|
||||
assert_equal [1, parent1.id, lft1 + 2, lft1 + 3], [grandchild.project_id, grandchild.root_id, grandchild.lft, grandchild.rgt]
|
||||
end
|
||||
end
|
||||
174
test/unit/journal_observer_test.rb
Normal file
174
test/unit/journal_observer_test.rb
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
# 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 JournalObserverTest < ActiveSupport::TestCase
|
||||
fixtures :issues, :issue_statuses, :journals, :journal_details, :projects,
|
||||
:projects_trackers, :trackers, :enabled_modules, :enumerations,
|
||||
:users, :email_addresses, :roles
|
||||
|
||||
def setup
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@journal = Journal.find 1
|
||||
end
|
||||
|
||||
# context: issue_updated notified_events
|
||||
def test_create_should_send_email_notification_with_issue_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
journal = issue.init_journal(user, "some notes")
|
||||
|
||||
with_settings :notified_events => %w(issue_updated) do
|
||||
assert journal.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_not_send_email_notification_with_notify_set_to_false
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
journal = issue.init_journal(user, "some notes")
|
||||
journal.notify = false
|
||||
|
||||
with_settings :notified_events => %w(issue_updated) do
|
||||
assert journal.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_not_send_email_notification_without_issue_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
journal = issue.init_journal(user, "some notes")
|
||||
|
||||
with_settings :notified_events => [] do
|
||||
assert journal.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification_with_issue_note_added
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
journal = issue.init_journal(user)
|
||||
journal.notes = 'This update has a note'
|
||||
|
||||
with_settings :notified_events => %w(issue_note_added) do
|
||||
assert journal.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_not_send_email_notification_without_issue_note_added
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
journal = issue.init_journal(user)
|
||||
journal.notes = 'This update has a note'
|
||||
|
||||
with_settings :notified_events => [] do
|
||||
assert journal.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification_with_issue_status_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.status = IssueStatus.last
|
||||
|
||||
with_settings :notified_events => %w(issue_status_updated) do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_not_send_email_notification_without_issue_status_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.status = IssueStatus.last
|
||||
|
||||
with_settings :notified_events => [] do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_without_status_update_should_not_send_email_notification_with_issue_status_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.subject = "No status update"
|
||||
|
||||
with_settings :notified_events => %w(issue_status_updated) do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification_with_issue_assignee_updated
|
||||
issue = Issue.generate!(:assigned_to_id => 2)
|
||||
ActionMailer::Base.deliveries.clear
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.assigned_to = User.find(3)
|
||||
|
||||
with_settings :notified_events => %w(issue_assigned_to_updated) do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_not_send_email_notification_without_issue_assignee_updated
|
||||
issue = Issue.generate!(:assigned_to_id => 2)
|
||||
ActionMailer::Base.deliveries.clear
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.assigned_to = User.find(3)
|
||||
|
||||
with_settings :notified_events => [] do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification_with_issue_priority_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.priority = IssuePriority.last
|
||||
|
||||
with_settings :notified_events => %w(issue_priority_updated) do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_should_not_send_email_notification_without_issue_priority_updated
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
issue.init_journal(user)
|
||||
issue.priority = IssuePriority.last
|
||||
|
||||
with_settings :notified_events => [] do
|
||||
assert issue.save
|
||||
end
|
||||
assert_equal 0, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
end
|
||||
223
test/unit/journal_test.rb
Normal file
223
test/unit/journal_test.rb
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
# 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 JournalTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :issues, :issue_statuses, :journals, :journal_details,
|
||||
:issue_relations, :workflows,
|
||||
:users, :members, :member_roles, :roles, :enabled_modules,
|
||||
:groups_users, :email_addresses,
|
||||
:enumerations,
|
||||
:projects_trackers, :trackers, :custom_fields
|
||||
|
||||
def setup
|
||||
@journal = Journal.find 1
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_journalized_is_an_issue
|
||||
issue = @journal.issue
|
||||
assert_kind_of Issue, issue
|
||||
assert_equal 1, issue.id
|
||||
end
|
||||
|
||||
def test_new_status
|
||||
status = @journal.new_status
|
||||
assert_not_nil status
|
||||
assert_kind_of IssueStatus, status
|
||||
assert_equal 2, status.id
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
issue = Issue.first
|
||||
user = User.first
|
||||
journal = issue.init_journal(user, issue)
|
||||
|
||||
assert journal.save
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_should_not_save_journal_with_blank_notes_and_no_details
|
||||
journal = Journal.new(:journalized => Issue.first, :user => User.first)
|
||||
|
||||
assert_no_difference 'Journal.count' do
|
||||
assert_equal false, journal.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_should_not_split_non_private_notes
|
||||
assert_difference 'Journal.count' do
|
||||
assert_no_difference 'JournalDetail.count' do
|
||||
journal = Journal.generate!(:notes => 'Notes')
|
||||
end
|
||||
end
|
||||
|
||||
assert_difference 'Journal.count' do
|
||||
assert_difference 'JournalDetail.count' do
|
||||
journal = Journal.generate!(:notes => 'Notes', :details => [JournalDetail.new])
|
||||
end
|
||||
end
|
||||
|
||||
assert_difference 'Journal.count' do
|
||||
assert_difference 'JournalDetail.count' do
|
||||
journal = Journal.generate!(:notes => '', :details => [JournalDetail.new])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_should_split_private_notes
|
||||
assert_difference 'Journal.count' do
|
||||
assert_no_difference 'JournalDetail.count' do
|
||||
journal = Journal.generate!(:notes => 'Notes', :private_notes => true)
|
||||
journal.reload
|
||||
assert_equal true, journal.private_notes
|
||||
assert_equal 'Notes', journal.notes
|
||||
end
|
||||
end
|
||||
|
||||
assert_difference 'Journal.count', 2 do
|
||||
assert_difference 'JournalDetail.count' do
|
||||
journal = Journal.generate!(:notes => 'Notes', :private_notes => true, :details => [JournalDetail.new])
|
||||
journal.reload
|
||||
assert_equal true, journal.private_notes
|
||||
assert_equal 'Notes', journal.notes
|
||||
assert_equal 0, journal.details.size
|
||||
|
||||
journal_with_changes = Journal.order('id DESC').offset(1).first
|
||||
assert_equal false, journal_with_changes.private_notes
|
||||
assert_nil journal_with_changes.notes
|
||||
assert_equal 1, journal_with_changes.details.size
|
||||
assert_equal journal.created_on, journal_with_changes.created_on
|
||||
end
|
||||
end
|
||||
|
||||
assert_difference 'Journal.count' do
|
||||
assert_difference 'JournalDetail.count' do
|
||||
journal = Journal.generate!(:notes => '', :private_notes => true, :details => [JournalDetail.new])
|
||||
journal.reload
|
||||
assert_equal false, journal.private_notes
|
||||
assert_equal '', journal.notes
|
||||
assert_equal 1, journal.details.size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_visible_scope_for_anonymous
|
||||
# Anonymous user should see issues of public projects only
|
||||
journals = Journal.visible(User.anonymous).to_a
|
||||
assert journals.any?
|
||||
assert_nil journals.detect {|journal| !journal.issue.project.is_public?}
|
||||
# Anonymous user should not see issues without permission
|
||||
Role.anonymous.remove_permission!(:view_issues)
|
||||
journals = Journal.visible(User.anonymous).to_a
|
||||
assert journals.empty?
|
||||
end
|
||||
|
||||
def test_visible_scope_for_user
|
||||
user = User.find(9)
|
||||
assert user.projects.empty?
|
||||
# Non member user should see issues of public projects only
|
||||
journals = Journal.visible(user).to_a
|
||||
assert journals.any?
|
||||
assert_nil journals.detect {|journal| !journal.issue.project.is_public?}
|
||||
# Non member user should not see issues without permission
|
||||
Role.non_member.remove_permission!(:view_issues)
|
||||
user.reload
|
||||
journals = Journal.visible(user).to_a
|
||||
assert journals.empty?
|
||||
# User should see issues of projects for which user has view_issues permissions only
|
||||
Member.create!(:principal => user, :project_id => 1, :role_ids => [1])
|
||||
user.reload
|
||||
journals = Journal.visible(user).to_a
|
||||
assert journals.any?
|
||||
assert_nil journals.detect {|journal| journal.issue.project_id != 1}
|
||||
end
|
||||
|
||||
def test_visible_scope_for_admin
|
||||
user = User.find(1)
|
||||
user.members.each(&:destroy)
|
||||
assert user.projects.empty?
|
||||
journals = Journal.visible(user).to_a
|
||||
assert journals.any?
|
||||
# Admin should see issues on private projects that admin does not belong to
|
||||
assert journals.detect {|journal| !journal.issue.project.is_public?}
|
||||
end
|
||||
|
||||
def test_preload_journals_details_custom_fields_should_set_custom_field_instance_variable
|
||||
d = JournalDetail.new(:property => 'cf', :prop_key => '2')
|
||||
journals = [Journal.new(:details => [d])]
|
||||
|
||||
d.expects(:instance_variable_set).with("@custom_field", CustomField.find(2)).once
|
||||
Journal.preload_journals_details_custom_fields(journals)
|
||||
end
|
||||
|
||||
def test_preload_journals_details_custom_fields_with_empty_set
|
||||
assert_nothing_raised do
|
||||
Journal.preload_journals_details_custom_fields([])
|
||||
end
|
||||
end
|
||||
|
||||
def test_details_should_normalize_dates
|
||||
j = JournalDetail.create!(:old_value => Date.parse('2012-11-03'), :value => Date.parse('2013-01-02'))
|
||||
j.reload
|
||||
assert_equal '2012-11-03', j.old_value
|
||||
assert_equal '2013-01-02', j.value
|
||||
end
|
||||
|
||||
def test_details_should_normalize_true_values
|
||||
j = JournalDetail.create!(:old_value => true, :value => true)
|
||||
j.reload
|
||||
assert_equal '1', j.old_value
|
||||
assert_equal '1', j.value
|
||||
end
|
||||
|
||||
def test_details_should_normalize_false_values
|
||||
j = JournalDetail.create!(:old_value => false, :value => false)
|
||||
j.reload
|
||||
assert_equal '0', j.old_value
|
||||
assert_equal '0', j.value
|
||||
end
|
||||
|
||||
def test_custom_field_should_return_custom_field_for_cf_detail
|
||||
d = JournalDetail.new(:property => 'cf', :prop_key => '2')
|
||||
assert_equal CustomField.find(2), d.custom_field
|
||||
end
|
||||
|
||||
def test_custom_field_should_return_nil_for_non_cf_detail
|
||||
d = JournalDetail.new(:property => 'subject')
|
||||
assert_nil d.custom_field
|
||||
end
|
||||
|
||||
def test_visible_details_should_include_relations_to_visible_issues_only
|
||||
issue = Issue.generate!
|
||||
visible_issue = Issue.generate!
|
||||
hidden_issue = Issue.generate!(:is_private => true)
|
||||
|
||||
journal = Journal.new
|
||||
journal.details << JournalDetail.new(:property => 'relation', :prop_key => 'relates', :value => visible_issue.id)
|
||||
journal.details << JournalDetail.new(:property => 'relation', :prop_key => 'relates', :value => hidden_issue.id)
|
||||
|
||||
visible_details = journal.visible_details(User.anonymous)
|
||||
assert_equal 1, visible_details.size
|
||||
assert_equal visible_issue.id.to_s, visible_details.first.value.to_s
|
||||
|
||||
visible_details = journal.visible_details(User.find(2))
|
||||
assert_equal 2, visible_details.size
|
||||
end
|
||||
end
|
||||
59
test/unit/lib/redmine/access_control_test.rb
Normal file
59
test/unit/lib/redmine/access_control_test.rb
Normal 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
|
||||
53
test/unit/lib/redmine/acts/positioned_with_scope_test.rb
Normal file
53
test/unit/lib/redmine/acts/positioned_with_scope_test.rb
Normal 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
|
||||
55
test/unit/lib/redmine/acts/positioned_without_scope_test.rb
Normal file
55
test/unit/lib/redmine/acts/positioned_without_scope_test.rb
Normal 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
|
||||
106
test/unit/lib/redmine/ciphering_test.rb
Normal file
106
test/unit/lib/redmine/ciphering_test.rb
Normal 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
|
||||
104
test/unit/lib/redmine/codeset_util_test.rb
Normal file
104
test/unit/lib/redmine/codeset_util_test.rb
Normal 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
|
||||
61
test/unit/lib/redmine/configuration_test.rb
Normal file
61
test/unit/lib/redmine/configuration_test.rb
Normal 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
|
||||
31
test/unit/lib/redmine/export/csv_test.rb
Normal file
31
test/unit/lib/redmine/export/csv_test.rb
Normal 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
|
||||
104
test/unit/lib/redmine/export/pdf_test.rb
Normal file
104
test/unit/lib/redmine/export/pdf_test.rb
Normal 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
|
||||
163
test/unit/lib/redmine/field_format/attachment_format_test.rb
Normal file
163
test/unit/lib/redmine/field_format/attachment_format_test.rb
Normal 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
|
||||
|
|
@ -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
|
||||
63
test/unit/lib/redmine/field_format/bool_format_test.rb
Normal file
63
test/unit/lib/redmine/field_format/bool_format_test.rb
Normal 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
|
||||
100
test/unit/lib/redmine/field_format/enumeration_format_test.rb
Normal file
100
test/unit/lib/redmine/field_format/enumeration_format_test.rb
Normal 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
|
||||
101
test/unit/lib/redmine/field_format/field_format_test.rb
Normal file
101
test/unit/lib/redmine/field_format/field_format_test.rb
Normal 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
|
||||
90
test/unit/lib/redmine/field_format/link_format_test.rb
Normal file
90
test/unit/lib/redmine/field_format/link_format_test.rb
Normal 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
|
||||
188
test/unit/lib/redmine/field_format/list_format_test.rb
Normal file
188
test/unit/lib/redmine/field_format/list_format_test.rb
Normal 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
|
||||
31
test/unit/lib/redmine/field_format/numeric_format_test.rb
Normal file
31
test/unit/lib/redmine/field_format/numeric_format_test.rb
Normal 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
|
||||
79
test/unit/lib/redmine/field_format/user_field_format_test.rb
Normal file
79
test/unit/lib/redmine/field_format/user_field_format_test.rb
Normal 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
|
||||
105
test/unit/lib/redmine/field_format/version_field_format_test.rb
Normal file
105
test/unit/lib/redmine/field_format/version_field_format_test.rb
Normal 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
|
||||
63
test/unit/lib/redmine/helpers/calendar_test.rb
Normal file
63
test/unit/lib/redmine/helpers/calendar_test.rb
Normal 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
|
||||
37
test/unit/lib/redmine/helpers/diff_test.rb
Normal file
37
test/unit/lib/redmine/helpers/diff_test.rb
Normal 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"><stuff> with html & special chars</danger></span> <span class="diff_out">other stuff <script>alert('foo');</alert></span>'
|
||||
|
||||
assert_equal computed_diff, expected_diff
|
||||
end
|
||||
end
|
||||
498
test/unit/lib/redmine/helpers/gantt_test.rb
Normal file
498
test/unit/lib/redmine/helpers/gantt_test.rb
Normal 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
|
||||
189
test/unit/lib/redmine/hook_test.rb
Normal file
189
test/unit/lib/redmine/hook_test.rb
Normal 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
|
||||
|
||||
261
test/unit/lib/redmine/i18n_test.rb
Normal file
261
test/unit/lib/redmine/i18n_test.rb
Normal 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
|
||||
27
test/unit/lib/redmine/info_test.rb
Normal file
27
test/unit/lib/redmine/info_test.rb
Normal 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
|
||||
191
test/unit/lib/redmine/menu_manager/mapper_test.rb
Normal file
191
test/unit/lib/redmine/menu_manager/mapper_test.rb
Normal 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
|
||||
342
test/unit/lib/redmine/menu_manager/menu_helper_test.rb
Normal file
342
test/unit/lib/redmine/menu_manager/menu_helper_test.rb
Normal 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
|
||||
108
test/unit/lib/redmine/menu_manager/menu_item_test.rb
Normal file
108
test/unit/lib/redmine/menu_manager/menu_item_test.rb
Normal 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
|
||||
34
test/unit/lib/redmine/menu_manager_test.rb
Normal file
34
test/unit/lib/redmine/menu_manager_test.rb
Normal 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
|
||||
75
test/unit/lib/redmine/mime_type_test.rb
Normal file
75
test/unit/lib/redmine/mime_type_test.rb
Normal 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
|
||||
29
test/unit/lib/redmine/notifiable_test.rb
Normal file
29
test/unit/lib/redmine/notifiable_test.rb
Normal 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
|
||||
34
test/unit/lib/redmine/pagination_helper_test.rb
Normal file
34
test/unit/lib/redmine/pagination_helper_test.rb
Normal 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
|
||||
94
test/unit/lib/redmine/pagination_test.rb
Normal file
94
test/unit/lib/redmine/pagination_test.rb
Normal 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
|
||||
186
test/unit/lib/redmine/plugin_test.rb
Normal file
186
test/unit/lib/redmine/plugin_test.rb
Normal 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
|
||||
102
test/unit/lib/redmine/safe_attributes_test.rb
Normal file
102
test/unit/lib/redmine/safe_attributes_test.rb
Normal 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
|
||||
218
test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb
Normal file
218
test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb
Normal 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
|
||||
106
test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb
Normal file
106
test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb
Normal 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
|
||||
60
test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb
Normal file
60
test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb
Normal 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
|
||||
|
|
@ -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
|
||||
597
test/unit/lib/redmine/scm/adapters/git_adapter_test.rb
Normal file
597
test/unit/lib/redmine/scm/adapters/git_adapter_test.rb
Normal 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
|
||||
485
test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
Normal file
485
test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
Normal 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
|
||||
|
|
@ -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
|
||||
37
test/unit/lib/redmine/syntax_highlighting/coderay_test.rb
Normal file
37
test/unit/lib/redmine/syntax_highlighting/coderay_test.rb
Normal 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
|
||||
61
test/unit/lib/redmine/themes_test.rb
Normal file
61
test/unit/lib/redmine/themes_test.rb
Normal 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
|
||||
352
test/unit/lib/redmine/unified_diff_test.rb
Normal file
352
test/unit/lib/redmine/unified_diff_test.rb
Normal 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<MyClass></span> myObj)', diff.first[2].html_line_left
|
||||
assert_equal 'void DoSomething(<span>const MyClass&</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<MyClass></span> myObj)', diff.first[2].html_line
|
||||
assert_equal 'void DoSomething(<span>const MyClass&</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: "\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbb\xd0\xbe %{count} \xd1\x87\xd0\xb0\xd1\x81<span>\xd0\xb0</span>"".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
|
||||
76
test/unit/lib/redmine/utils/date_calculation.rb
Normal file
76
test/unit/lib/redmine/utils/date_calculation.rb
Normal 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
|
||||
94
test/unit/lib/redmine/views/builders/json_test.rb
Normal file
94
test/unit/lib/redmine/views/builders/json_test.rb
Normal 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
|
||||
67
test/unit/lib/redmine/views/builders/xml_test.rb
Normal file
67
test/unit/lib/redmine/views/builders/xml_test.rb
Normal 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
|
||||
48
test/unit/lib/redmine/views/labelled_form_builder_test.rb
Normal file
48
test/unit/lib/redmine/views/labelled_form_builder_test.rb
Normal 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
|
||||
35
test/unit/lib/redmine/wiki_formatting/html_parser_test.rb
Normal file
35
test/unit/lib/redmine/wiki_formatting/html_parser_test.rb
Normal 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
|
||||
404
test/unit/lib/redmine/wiki_formatting/macros_test.rb
Normal file
404
test/unit/lib/redmine/wiki_formatting/macros_test.rb
Normal 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(<tag>)}}</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(<tag>)}}</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: <tag>', 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(<tag>)}}</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
|
||||
|
|
@ -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("").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
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue