Redmine 3.4.4
This commit is contained in:
commit
64924a6376
2112 changed files with 259028 additions and 0 deletions
192
test/functional/account_controller_openid_test.rb
Normal file
192
test/functional/account_controller_openid_test.rb
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
# 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 AccountControllerOpenidTest < Redmine::ControllerTest
|
||||
tests AccountController
|
||||
fixtures :users, :roles
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
Setting.openid = '1'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.openid = '0'
|
||||
end
|
||||
|
||||
if Object.const_defined?(:OpenID)
|
||||
|
||||
def test_login_with_openid_for_existing_user
|
||||
Setting.self_registration = '3'
|
||||
existing_user = User.new(:firstname => 'Cool',
|
||||
:lastname => 'User',
|
||||
:mail => 'user@somedomain.com',
|
||||
:identity_url => 'http://openid.example.com/good_user')
|
||||
existing_user.login = 'cool_user'
|
||||
assert existing_user.save!
|
||||
|
||||
post :login, :params => {
|
||||
:openid_url => existing_user.identity_url
|
||||
}
|
||||
assert_redirected_to '/my/page'
|
||||
end
|
||||
|
||||
def test_login_with_invalid_openid_provider
|
||||
Setting.self_registration = '0'
|
||||
post :login, :params => {
|
||||
:openid_url => 'http;//openid.example.com/good_user'
|
||||
}
|
||||
assert_redirected_to home_url
|
||||
end
|
||||
|
||||
def test_login_with_openid_for_existing_non_active_user
|
||||
Setting.self_registration = '2'
|
||||
existing_user = User.new(:firstname => 'Cool',
|
||||
:lastname => 'User',
|
||||
:mail => 'user@somedomain.com',
|
||||
:identity_url => 'http://openid.example.com/good_user',
|
||||
:status => User::STATUS_REGISTERED)
|
||||
existing_user.login = 'cool_user'
|
||||
assert existing_user.save!
|
||||
|
||||
post :login, :params => {
|
||||
:openid_url => existing_user.identity_url
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_created
|
||||
Setting.self_registration = '3'
|
||||
post :login, :params => {
|
||||
:openid_url => 'http://openid.example.com/good_user'
|
||||
}
|
||||
assert_redirected_to '/my/account'
|
||||
user = User.find_by_login('cool_user')
|
||||
assert user
|
||||
assert_equal 'Cool', user.firstname
|
||||
assert_equal 'User', user.lastname
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_and_self_registration_off
|
||||
Setting.self_registration = '0'
|
||||
post :login, :params => {
|
||||
:openid_url => 'http://openid.example.com/good_user'
|
||||
}
|
||||
assert_redirected_to home_url
|
||||
user = User.find_by_login('cool_user')
|
||||
assert_nil user
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
|
||||
Setting.self_registration = '1'
|
||||
post :login, :params => {
|
||||
:openid_url => 'http://openid.example.com/good_user'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
user = User.find_by_login('cool_user')
|
||||
assert user
|
||||
|
||||
token = Token.find_by_user_id_and_action(user.id, 'register')
|
||||
assert token
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_created_with_manual_activation
|
||||
Setting.self_registration = '2'
|
||||
post :login, :params => {
|
||||
:openid_url => 'http://openid.example.com/good_user'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
user = User.find_by_login('cool_user')
|
||||
assert user
|
||||
assert_equal User::STATUS_REGISTERED, user.status
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_with_conflict_should_register
|
||||
Setting.self_registration = '3'
|
||||
existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
|
||||
existing_user.login = 'cool_user'
|
||||
assert existing_user.save!
|
||||
|
||||
post :login, :params => {
|
||||
:openid_url => 'http://openid.example.com/good_user'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=?]', 'user[identity_url]', 'http://openid.example.com/good_user'
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_with_missing_information_should_register
|
||||
Setting.self_registration = '3'
|
||||
|
||||
post :login, :params => {
|
||||
:openid_url => 'http://openid.example.com/good_blank_user'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'user[login]'
|
||||
assert_select 'input[name=?]', 'user[password]'
|
||||
assert_select 'input[name=?]', 'user[password_confirmation]'
|
||||
assert_select 'input[name=?][value=?]', 'user[identity_url]', 'http://openid.example.com/good_blank_user'
|
||||
end
|
||||
|
||||
def test_post_login_should_not_verify_token_when_using_open_id
|
||||
ActionController::Base.allow_forgery_protection = true
|
||||
AccountController.any_instance.stubs(:using_open_id?).returns(true)
|
||||
AccountController.any_instance.stubs(:authenticate_with_open_id).returns(true)
|
||||
post :login
|
||||
assert_response 200
|
||||
ensure
|
||||
ActionController::Base.allow_forgery_protection = false
|
||||
end
|
||||
|
||||
def test_register_after_login_failure_should_not_require_user_to_enter_a_password
|
||||
Setting.self_registration = '3'
|
||||
|
||||
assert_difference 'User.count' do
|
||||
post :register, :params => {
|
||||
:user => {
|
||||
:login => 'good_blank_user',
|
||||
:password => '',
|
||||
:password_confirmation => '',
|
||||
:firstname => 'Cool',
|
||||
:lastname => 'User',
|
||||
:mail => 'user@somedomain.com',
|
||||
:identity_url => 'http://openid.example.com/good_blank_user'
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
user = User.order('id DESC').first
|
||||
assert_equal 'http://openid.example.com/good_blank_user', user.identity_url
|
||||
assert user.hashed_password.blank?, "Hashed password was #{user.hashed_password}"
|
||||
end
|
||||
|
||||
def test_setting_openid_should_return_true_when_set_to_true
|
||||
assert_equal true, Setting.openid?
|
||||
end
|
||||
|
||||
else
|
||||
puts "Skipping openid tests."
|
||||
|
||||
def test_dummy
|
||||
end
|
||||
end
|
||||
end
|
||||
607
test/functional/account_controller_test.rb
Normal file
607
test/functional/account_controller_test.rb
Normal file
|
|
@ -0,0 +1,607 @@
|
|||
# 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 AccountControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :email_addresses, :roles
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_get_login
|
||||
get :login
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=username]'
|
||||
assert_select 'input[name=password]'
|
||||
end
|
||||
|
||||
def test_get_login_while_logged_in_should_redirect_to_back_url_if_present
|
||||
@request.session[:user_id] = 2
|
||||
@request.env["HTTP_REFERER"] = 'http://test.host/issues/show/1'
|
||||
|
||||
get :login, :params => {
|
||||
:back_url => 'http://test.host/issues/show/1'
|
||||
}
|
||||
assert_redirected_to '/issues/show/1'
|
||||
assert_equal 2, @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_get_login_while_logged_in_should_redirect_to_referer_without_back_url
|
||||
@request.session[:user_id] = 2
|
||||
@request.env["HTTP_REFERER"] = 'http://test.host/issues/show/1'
|
||||
|
||||
get :login
|
||||
assert_redirected_to '/issues/show/1'
|
||||
assert_equal 2, @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_get_login_while_logged_in_should_redirect_to_home_by_default
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :login
|
||||
assert_redirected_to '/'
|
||||
assert_equal 2, @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_login_should_redirect_to_back_url_param
|
||||
# request.uri is "test.host" in test environment
|
||||
back_urls = [
|
||||
'http://test.host/issues/show/1',
|
||||
'http://test.host/',
|
||||
'/'
|
||||
]
|
||||
back_urls.each do |back_url|
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith',
|
||||
:back_url => back_url
|
||||
}
|
||||
assert_redirected_to back_url
|
||||
end
|
||||
end
|
||||
|
||||
def test_login_with_suburi_should_redirect_to_back_url_param
|
||||
@relative_url_root = Redmine::Utils.relative_url_root
|
||||
Redmine::Utils.relative_url_root = '/redmine'
|
||||
|
||||
back_urls = [
|
||||
'http://test.host/redmine/issues/show/1',
|
||||
'/redmine'
|
||||
]
|
||||
back_urls.each do |back_url|
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith',
|
||||
:back_url => back_url
|
||||
}
|
||||
assert_redirected_to back_url
|
||||
end
|
||||
ensure
|
||||
Redmine::Utils.relative_url_root = @relative_url_root
|
||||
end
|
||||
|
||||
def test_login_should_not_redirect_to_another_host
|
||||
back_urls = [
|
||||
'http://test.foo/fake',
|
||||
'//test.foo/fake'
|
||||
]
|
||||
back_urls.each do |back_url|
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith',
|
||||
:back_url => back_url
|
||||
}
|
||||
assert_redirected_to '/my/page'
|
||||
end
|
||||
end
|
||||
|
||||
def test_login_with_suburi_should_not_redirect_to_another_suburi
|
||||
@relative_url_root = Redmine::Utils.relative_url_root
|
||||
Redmine::Utils.relative_url_root = '/redmine'
|
||||
|
||||
back_urls = [
|
||||
'http://test.host/',
|
||||
'http://test.host/fake',
|
||||
'http://test.host/fake/issues',
|
||||
'http://test.host/redmine/../fake',
|
||||
'http://test.host/redmine/../fake/issues',
|
||||
'http://test.host/redmine/%2e%2e/fake',
|
||||
'//test.foo/fake',
|
||||
'http://test.host//fake',
|
||||
'http://test.host/\n//fake',
|
||||
'//bar@test.foo',
|
||||
'//test.foo',
|
||||
'////test.foo',
|
||||
'@test.foo',
|
||||
'fake@test.foo',
|
||||
'.test.foo'
|
||||
]
|
||||
back_urls.each do |back_url|
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith',
|
||||
:back_url => back_url
|
||||
}
|
||||
assert_redirected_to '/my/page'
|
||||
end
|
||||
ensure
|
||||
Redmine::Utils.relative_url_root = @relative_url_root
|
||||
end
|
||||
|
||||
def test_login_with_wrong_password
|
||||
post :login, :params => {
|
||||
:username => 'admin',
|
||||
:password => 'bad'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div.flash.error', :text => /Invalid user or password/
|
||||
assert_select 'input[name=username][value=admin]'
|
||||
assert_select 'input[name=password]'
|
||||
assert_select 'input[name=password][value]', 0
|
||||
end
|
||||
|
||||
def test_login_with_locked_account_should_fail
|
||||
User.find(2).update_attribute :status, User::STATUS_LOCKED
|
||||
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
assert_include 'locked', flash[:error]
|
||||
assert_nil @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_login_as_registered_user_with_manual_activation_should_inform_user
|
||||
User.find(2).update_attribute :status, User::STATUS_REGISTERED
|
||||
|
||||
with_settings :self_registration => '2', :default_language => 'en' do
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
assert_include 'pending administrator approval', flash[:error]
|
||||
end
|
||||
end
|
||||
|
||||
def test_login_as_registered_user_with_email_activation_should_propose_new_activation_email
|
||||
User.find(2).update_attribute :status, User::STATUS_REGISTERED
|
||||
|
||||
with_settings :self_registration => '1', :default_language => 'en' do
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
assert_equal 2, @request.session[:registered_user_id]
|
||||
assert_include 'new activation email', flash[:error]
|
||||
end
|
||||
end
|
||||
|
||||
def test_login_should_rescue_auth_source_exception
|
||||
source = AuthSource.create!(:name => 'Test')
|
||||
User.find(2).update_attribute :auth_source_id, source.id
|
||||
AuthSource.any_instance.stubs(:authenticate).raises(AuthSourceException.new("Something wrong"))
|
||||
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith'
|
||||
}
|
||||
assert_response 500
|
||||
assert_select_error /Something wrong/
|
||||
end
|
||||
|
||||
def test_login_should_reset_session
|
||||
@controller.expects(:reset_session).once
|
||||
|
||||
post :login, :params => {
|
||||
:username => 'jsmith',
|
||||
:password => 'jsmith'
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_login_should_strip_whitespaces_from_user_name
|
||||
post :login, :params => {
|
||||
:username => ' jsmith ',
|
||||
:password => 'jsmith'
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal 2, @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_get_logout_should_not_logout
|
||||
@request.session[:user_id] = 2
|
||||
get :logout
|
||||
assert_response :success
|
||||
|
||||
assert_equal 2, @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_get_logout_with_anonymous_should_redirect
|
||||
get :logout
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
|
||||
def test_logout
|
||||
@request.session[:user_id] = 2
|
||||
post :logout
|
||||
assert_redirected_to '/'
|
||||
assert_nil @request.session[:user_id]
|
||||
end
|
||||
|
||||
def test_logout_should_reset_session
|
||||
@controller.expects(:reset_session).once
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
post :logout
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_get_register_with_registration_on
|
||||
with_settings :self_registration => '3' do
|
||||
get :register
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'user[password]'
|
||||
assert_select 'input[name=?]', 'user[password_confirmation]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_register_should_detect_user_language
|
||||
with_settings :self_registration => '3' do
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
get :register
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'user[language]' do
|
||||
assert_select 'option[value=fr][selected=selected]'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_register_with_registration_off_should_redirect
|
||||
with_settings :self_registration => '0' do
|
||||
get :register
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_register_should_show_hide_mail_preference
|
||||
get :register
|
||||
assert_select 'input[name=?][checked=checked]', 'pref[hide_mail]'
|
||||
end
|
||||
|
||||
def test_get_register_should_show_hide_mail_preference_with_setting_turned_off
|
||||
with_settings :default_users_hide_mail => '0' do
|
||||
get :register
|
||||
assert_select 'input[name=?]:not([checked=checked])', 'pref[hide_mail]'
|
||||
end
|
||||
end
|
||||
|
||||
# See integration/account_test.rb for the full test
|
||||
def test_post_register_with_registration_on
|
||||
with_settings :self_registration => '3' do
|
||||
assert_difference 'User.count' do
|
||||
post :register, :params => {
|
||||
:user => {
|
||||
:login => 'register',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:mail => 'register@example.com'
|
||||
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
user = User.order('id DESC').first
|
||||
assert_equal 'register', user.login
|
||||
assert_equal 'John', user.firstname
|
||||
assert_equal 'Doe', user.lastname
|
||||
assert_equal 'register@example.com', user.mail
|
||||
assert user.check_password?('secret123')
|
||||
assert user.active?
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_register_with_registration_off_should_redirect
|
||||
with_settings :self_registration => '0' do
|
||||
assert_no_difference 'User.count' do
|
||||
post :register, :params => {
|
||||
:user => {
|
||||
:login => 'register',
|
||||
:password => 'test',
|
||||
:password_confirmation => 'test',
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:mail => 'register@example.com'
|
||||
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_register_should_create_user_with_hide_mail_preference
|
||||
with_settings :default_users_hide_mail => '0' do
|
||||
user = new_record(User) do
|
||||
post :register, :params => {
|
||||
:user => {
|
||||
:login => 'register',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:mail => 'register@example.com'
|
||||
|
||||
},
|
||||
:pref => {
|
||||
:hide_mail => '1'
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_equal true, user.pref.hide_mail
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_lost_password_should_display_lost_password_form
|
||||
get :lost_password
|
||||
assert_response :success
|
||||
assert_select 'input[name=mail]'
|
||||
end
|
||||
|
||||
def test_lost_password_for_active_user_should_create_a_token
|
||||
Token.delete_all
|
||||
ActionMailer::Base.deliveries.clear
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
assert_difference 'Token.count' do
|
||||
post :lost_password, :params => {
|
||||
:mail => 'JSmith@somenet.foo'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
|
||||
token = Token.order('id DESC').first
|
||||
assert_equal User.find(2), token.user
|
||||
assert_equal 'recovery', token.action
|
||||
|
||||
assert_select_email do
|
||||
assert_select "a[href=?]", "http://localhost:3000/account/lost_password?token=#{token.value}"
|
||||
end
|
||||
end
|
||||
|
||||
def test_lost_password_with_whitespace_should_send_email_to_the_address
|
||||
Token.delete_all
|
||||
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
assert_difference 'Token.count' do
|
||||
post :lost_password, params: {
|
||||
mail: ' JSmith@somenet.foo '
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_equal ['jsmith@somenet.foo'], mail.bcc
|
||||
end
|
||||
|
||||
def test_lost_password_using_additional_email_address_should_send_email_to_the_address
|
||||
EmailAddress.create!(:user_id => 2, :address => 'anotherAddress@foo.bar')
|
||||
Token.delete_all
|
||||
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
assert_difference 'Token.count' do
|
||||
post :lost_password, :params => {
|
||||
:mail => 'ANOTHERaddress@foo.bar'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_equal ['anotherAddress@foo.bar'], mail.bcc
|
||||
end
|
||||
|
||||
def test_lost_password_for_unknown_user_should_fail
|
||||
Token.delete_all
|
||||
assert_no_difference 'Token.count' do
|
||||
post :lost_password, :params => {
|
||||
:mail => 'invalid@somenet.foo'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_lost_password_for_non_active_user_should_fail
|
||||
Token.delete_all
|
||||
assert User.find(2).lock!
|
||||
|
||||
assert_no_difference 'Token.count' do
|
||||
post :lost_password, :params => {
|
||||
:mail => 'JSmith@somenet.foo'
|
||||
}
|
||||
assert_redirected_to '/account/lost_password'
|
||||
end
|
||||
end
|
||||
|
||||
def test_lost_password_for_user_who_cannot_change_password_should_fail
|
||||
User.any_instance.stubs(:change_password_allowed?).returns(false)
|
||||
|
||||
assert_no_difference 'Token.count' do
|
||||
post :lost_password, :params => {
|
||||
:mail => 'JSmith@somenet.foo'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_lost_password_with_token_should_redirect_with_token_in_session
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
get :lost_password, :params => {
|
||||
:token => token.value
|
||||
}
|
||||
assert_redirected_to '/account/lost_password'
|
||||
|
||||
assert_equal token.value, request.session[:password_recovery_token]
|
||||
end
|
||||
|
||||
def test_get_lost_password_with_token_in_session_should_display_the_password_recovery_form
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
request.session[:password_recovery_token] = token.value
|
||||
|
||||
get :lost_password
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[type=hidden][name=token][value=?]', token.value
|
||||
end
|
||||
|
||||
def test_get_lost_password_with_invalid_token_should_redirect
|
||||
get :lost_password, :params => {
|
||||
:token => "abcdef"
|
||||
}
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_token_should_change_the_user_password
|
||||
ActionMailer::Base.deliveries.clear
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
post :lost_password, :params => {
|
||||
:token => token.value,
|
||||
:new_password => 'newpass123',
|
||||
:new_password_confirmation => 'newpass123'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
user.reload
|
||||
assert user.check_password?('newpass123')
|
||||
assert_nil Token.find_by_id(token.id), "Token was not deleted"
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_select_email do
|
||||
assert_select 'a[href^=?]', 'http://localhost:3000/my/password', :text => 'Change password'
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_token_for_non_active_user_should_fail
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
user.lock!
|
||||
|
||||
post :lost_password, :params => {
|
||||
:token => token.value,
|
||||
:new_password => 'newpass123',
|
||||
:new_password_confirmation => 'newpass123'
|
||||
}
|
||||
assert_redirected_to '/'
|
||||
assert ! user.check_password?('newpass123')
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_token_and_password_confirmation_failure_should_redisplay_the_form
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
post :lost_password, :params => {
|
||||
:token => token.value,
|
||||
:new_password => 'newpass',
|
||||
:new_password_confirmation => 'wrongpass'
|
||||
}
|
||||
assert_response :success
|
||||
assert_not_nil Token.find_by_id(token.id), "Token was deleted"
|
||||
|
||||
assert_select 'input[type=hidden][name=token][value=?]', token.value
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_token_should_not_accept_same_password_if_user_must_change_password
|
||||
user = User.find(2)
|
||||
user.password = "originalpassword"
|
||||
user.must_change_passwd = true
|
||||
user.save!
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
post :lost_password, :params => {
|
||||
:token => token.value,
|
||||
:new_password => 'originalpassword',
|
||||
:new_password_confirmation => 'originalpassword'
|
||||
}
|
||||
assert_response :success
|
||||
assert_not_nil Token.find_by_id(token.id), "Token was deleted"
|
||||
|
||||
assert_select '.flash', :text => /The new password must be different/
|
||||
assert_select 'input[type=hidden][name=token][value=?]', token.value
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_token_should_reset_must_change_password
|
||||
user = User.find(2)
|
||||
user.password = "originalpassword"
|
||||
user.must_change_passwd = true
|
||||
user.save!
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
post :lost_password, :params => {
|
||||
:token => token.value,
|
||||
:new_password => 'newpassword',
|
||||
:new_password_confirmation => 'newpassword'
|
||||
}
|
||||
assert_redirected_to '/login'
|
||||
|
||||
assert_equal false, user.reload.must_change_passwd
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_invalid_token_should_redirect
|
||||
post :lost_password, :params => {
|
||||
:token => "abcdef",
|
||||
:new_password => 'newpass',
|
||||
:new_password_confirmation => 'newpass'
|
||||
}
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
|
||||
def test_activation_email_should_send_an_activation_email
|
||||
User.find(2).update_attribute :status, User::STATUS_REGISTERED
|
||||
@request.session[:registered_user_id] = 2
|
||||
|
||||
with_settings :self_registration => '1' do
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
get :activation_email
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_activation_email_without_session_data_should_fail
|
||||
User.find(2).update_attribute :status, User::STATUS_REGISTERED
|
||||
|
||||
with_settings :self_registration => '1' do
|
||||
assert_no_difference 'ActionMailer::Base.deliveries.size' do
|
||||
get :activation_email
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
220
test/functional/activities_controller_test.rb
Normal file
220
test/functional/activities_controller_test.rb
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
# 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 ActivitiesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:groups_users,
|
||||
:enabled_modules,
|
||||
:journals, :journal_details
|
||||
|
||||
|
||||
def test_project_index
|
||||
get :index, :params => {
|
||||
:id => 1,
|
||||
:with_subprojects => 0
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'h3', :text => /#{2.days.ago.to_date.day}/
|
||||
assert_select 'dl dt.issue-edit a', :text => /(#{IssueStatus.find(2).name})/
|
||||
end
|
||||
|
||||
def test_project_index_with_invalid_project_id_should_respond_404
|
||||
get :index, :params => {
|
||||
:id => 299
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_previous_project_index
|
||||
get :index, :params => {
|
||||
:id => 1,
|
||||
:from => 2.days.ago.to_date
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'h3', :text => /#{3.days.ago.to_date.day}/
|
||||
assert_select 'dl dt.issue a', :text => /Cannot print recipes/
|
||||
end
|
||||
|
||||
def test_global_index
|
||||
@request.session[:user_id] = 1
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
i5 = Issue.find(5)
|
||||
d5 = User.find(1).time_to_date(i5.created_on)
|
||||
|
||||
assert_select 'h3', :text => /#{d5.day}/
|
||||
assert_select 'dl dt.issue a', :text => /Subproject issue/
|
||||
end
|
||||
|
||||
def test_user_index
|
||||
@request.session[:user_id] = 1
|
||||
get :index, :params => {
|
||||
:user_id => 2
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'h2 a[href="/users/2"]', :text => 'John Smith'
|
||||
|
||||
i1 = Issue.find(1)
|
||||
d1 = User.find(1).time_to_date(i1.created_on)
|
||||
|
||||
assert_select 'h3', :text => /#{d1.day}/
|
||||
assert_select 'dl dt.issue a', :text => /Cannot print recipes/
|
||||
end
|
||||
|
||||
def test_user_index_with_invalid_user_id_should_respond_404
|
||||
get :index, :params => {
|
||||
:user_id => 299
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_index_atom_feed
|
||||
get :index, :params => {
|
||||
:format => 'atom',
|
||||
:with_subprojects => 0
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'feed' do
|
||||
assert_select 'link[rel=self][href=?]', 'http://test.host/activity.atom?with_subprojects=0'
|
||||
assert_select 'link[rel=alternate][href=?]', 'http://test.host/activity?with_subprojects=0'
|
||||
assert_select 'entry' do
|
||||
assert_select 'link[href=?]', 'http://test.host/issues/11'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_atom_feed_with_explicit_selection
|
||||
get :index, :params => {
|
||||
:format => 'atom',
|
||||
:with_subprojects => 0,
|
||||
:show_changesets => 1,
|
||||
:show_documents => 1,
|
||||
:show_files => 1,
|
||||
:show_issues => 1,
|
||||
:show_messages => 1,
|
||||
:show_news => 1,
|
||||
:show_time_entries => 1,
|
||||
:show_wiki_edits => 1
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
|
||||
assert_select 'feed' do
|
||||
assert_select 'link[rel=self][href=?]', 'http://test.host/activity.atom?show_changesets=1&show_documents=1&show_files=1&show_issues=1&show_messages=1&show_news=1&show_time_entries=1&show_wiki_edits=1&with_subprojects=0'
|
||||
assert_select 'link[rel=alternate][href=?]', 'http://test.host/activity?show_changesets=1&show_documents=1&show_files=1&show_issues=1&show_messages=1&show_news=1&show_time_entries=1&show_wiki_edits=1&with_subprojects=0'
|
||||
assert_select 'entry' do
|
||||
assert_select 'link[href=?]', 'http://test.host/issues/11'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_atom_feed_with_one_item_type
|
||||
with_settings :default_language => 'en' do
|
||||
get :index, :params => {
|
||||
:format => 'atom',
|
||||
:show_issues => '1'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'title', :text => /Issues/
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_atom_feed_with_user
|
||||
get :index, :params => {
|
||||
:user_id => 2,
|
||||
:format => 'atom'
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_select 'title', :text => "Redmine: #{User.find(2).name}"
|
||||
end
|
||||
|
||||
def test_index_should_show_private_notes_with_permission_only
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes', :private_notes => true)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'dl', :text => /Private notes/
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'dl', :text => /Private notes/, :count => 0
|
||||
end
|
||||
|
||||
def test_index_with_submitted_scope_should_save_as_preference
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index, :params => {
|
||||
:show_issues => '1',
|
||||
:show_messages => '1',
|
||||
:submit => 'Apply'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal %w(issues messages), User.find(2).pref.activity_scope.sort
|
||||
end
|
||||
|
||||
def test_index_scope_should_default_to_user_preference
|
||||
pref = User.find(2).pref
|
||||
pref.activity_scope = %w(issues news)
|
||||
pref.save!
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
assert_select '#activity_scope_form' do
|
||||
assert_select 'input[checked=checked]', 2
|
||||
assert_select 'input[name=show_issues][checked=checked]'
|
||||
assert_select 'input[name=show_news][checked=checked]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_should_not_show_next_page_link
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select '.pagination a', :text => /Previous/
|
||||
assert_select '.pagination a', :text => /Next/, :count => 0
|
||||
end
|
||||
|
||||
def test_index_up_to_yesterday_should_show_next_page_link
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index, :params => {
|
||||
:from => (User.find(2).today-1)
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '.pagination a', :text => /Previous/
|
||||
assert_select '.pagination a', :text => /Next/
|
||||
end
|
||||
end
|
||||
166
test/functional/admin_controller_test.rb
Normal file
166
test/functional/admin_controller_test.rb
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
# 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 AdminControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :email_addresses, :roles
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_select 'div.nodata', 0
|
||||
end
|
||||
|
||||
def test_index_with_no_configuration_data
|
||||
delete_configuration_data
|
||||
get :index
|
||||
assert_select 'div.nodata'
|
||||
end
|
||||
|
||||
def test_projects
|
||||
get :projects
|
||||
assert_response :success
|
||||
assert_select 'tr.project.closed', 0
|
||||
end
|
||||
|
||||
def test_projects_with_status_filter
|
||||
get :projects, :params => {
|
||||
:status => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr.project.closed', 0
|
||||
end
|
||||
|
||||
def test_projects_with_name_filter
|
||||
get :projects, :params => {
|
||||
:name => 'store',
|
||||
:status => ''
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'tr.project td.name', :text => 'OnlineStore'
|
||||
assert_select 'tr.project', 1
|
||||
end
|
||||
|
||||
def test_load_default_configuration_data
|
||||
delete_configuration_data
|
||||
post :default_configuration, :params => {
|
||||
:lang => 'fr'
|
||||
}
|
||||
assert_response :redirect
|
||||
assert_nil flash[:error]
|
||||
assert IssueStatus.find_by_name('Nouveau')
|
||||
end
|
||||
|
||||
def test_load_default_configuration_data_should_rescue_error
|
||||
delete_configuration_data
|
||||
Redmine::DefaultData::Loader.stubs(:load).raises(Exception.new("Something went wrong"))
|
||||
post :default_configuration, :params => {
|
||||
:lang => 'fr'
|
||||
}
|
||||
assert_response :redirect
|
||||
assert_not_nil flash[:error]
|
||||
assert_match /Something went wrong/, flash[:error]
|
||||
end
|
||||
|
||||
def test_test_email
|
||||
user = User.find(1)
|
||||
user.pref.no_self_notified = '1'
|
||||
user.pref.save!
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
post :test_email
|
||||
assert_redirected_to '/settings?tab=notifications'
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
user = User.find(1)
|
||||
assert_equal [user.mail], mail.bcc
|
||||
end
|
||||
|
||||
def test_test_email_failure_should_display_the_error
|
||||
Mailer.stubs(:test_email).raises(Exception, 'Some error message')
|
||||
post :test_email
|
||||
assert_redirected_to '/settings?tab=notifications'
|
||||
assert_match /Some error message/, flash[:error]
|
||||
end
|
||||
|
||||
def test_no_plugins
|
||||
Redmine::Plugin.stubs(:registered_plugins).returns({})
|
||||
|
||||
get :plugins
|
||||
assert_response :success
|
||||
assert_select '.nodata'
|
||||
end
|
||||
|
||||
def test_plugins
|
||||
# Register a few plugins
|
||||
Redmine::Plugin.register :foo do
|
||||
name 'Foo plugin'
|
||||
author 'John Smith'
|
||||
description 'This is a test plugin'
|
||||
version '0.0.1'
|
||||
settings :default => {'sample_setting' => 'value', 'foo'=>'bar'}, :partial => 'foo/settings'
|
||||
end
|
||||
Redmine::Plugin.register :bar do
|
||||
end
|
||||
|
||||
get :plugins
|
||||
assert_response :success
|
||||
|
||||
assert_select 'tr#plugin-foo' do
|
||||
assert_select 'td span.name', :text => 'Foo plugin'
|
||||
assert_select 'td.configure a[href="/settings/plugin/foo"]'
|
||||
end
|
||||
assert_select 'tr#plugin-bar' do
|
||||
assert_select 'td span.name', :text => 'Bar'
|
||||
assert_select 'td.configure a', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_info
|
||||
get :info
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_admin_menu_plugin_extension
|
||||
Redmine::MenuManager.map :admin_menu do |menu|
|
||||
menu.push :test_admin_menu_plugin_extension, '/foo/bar', :caption => 'Test'
|
||||
end
|
||||
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'div#admin-menu a[href="/foo/bar"]', :text => 'Test'
|
||||
|
||||
Redmine::MenuManager.map :admin_menu do |menu|
|
||||
menu.delete :test_admin_menu_plugin_extension
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def delete_configuration_data
|
||||
Role.where('builtin = 0').delete_all
|
||||
Tracker.delete_all
|
||||
IssueStatus.delete_all
|
||||
Enumeration.delete_all
|
||||
end
|
||||
end
|
||||
610
test/functional/attachments_controller_test.rb
Normal file
610
test/functional/attachments_controller_test.rb
Normal file
|
|
@ -0,0 +1,610 @@
|
|||
# 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 AttachmentsControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :projects, :roles, :members, :member_roles,
|
||||
:enabled_modules, :issues, :trackers, :attachments,
|
||||
:versions, :wiki_pages, :wikis, :documents
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
set_fixtures_attachments_directory
|
||||
end
|
||||
|
||||
def teardown
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_diff
|
||||
['inline', 'sbs'].each do |dt|
|
||||
# 060719210727_changeset_utf8.diff
|
||||
get :show, :params => {
|
||||
:id => 14,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'th.filename', :text => /issues_controller.rb\t\(révision 1484\)/
|
||||
assert_select 'td.line-code', :text => /Demande créée avec succès/
|
||||
end
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_diff_replace_cannot_convert_content
|
||||
with_settings :repositories_encodings => 'UTF-8' do
|
||||
['inline', 'sbs'].each do |dt|
|
||||
# 060719210727_changeset_iso8859-1.diff
|
||||
get :show, :params => {
|
||||
:id => 5,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'th.filename', :text => /issues_controller.rb\t\(r\?vision 1484\)/
|
||||
assert_select 'td.line-code', :text => /Demande cr\?\?e avec succ\?s/
|
||||
end
|
||||
end
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_diff_latin_1
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
['inline', 'sbs'].each do |dt|
|
||||
# 060719210727_changeset_iso8859-1.diff
|
||||
get :show, :params => {
|
||||
:id => 5,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'th.filename', :text => /issues_controller.rb\t\(révision 1484\)/
|
||||
assert_select 'td.line-code', :text => /Demande créée avec succès/
|
||||
end
|
||||
end
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_should_save_diff_type_as_user_preference
|
||||
user1 = User.find(1)
|
||||
user1.pref[:diff_type] = nil
|
||||
user1.preference.save
|
||||
user = User.find(1)
|
||||
assert_nil user.pref[:diff_type]
|
||||
@request.session[:user_id] = 1 # admin
|
||||
|
||||
get :show, :params => {
|
||||
:id => 5
|
||||
}
|
||||
assert_response :success
|
||||
user.reload
|
||||
assert_equal "inline", user.pref[:diff_type]
|
||||
|
||||
get :show, :params => {
|
||||
:id => 5,
|
||||
:type => 'sbs'
|
||||
}
|
||||
assert_response :success
|
||||
user.reload
|
||||
assert_equal "sbs", user.pref[:diff_type]
|
||||
end
|
||||
|
||||
def test_diff_show_filename_in_mercurial_export
|
||||
set_tmp_attachments_directory
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("hg-export.diff", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'hg-export.diff', a.filename
|
||||
|
||||
get :show, :params => {
|
||||
:id => a.id,
|
||||
:type => 'inline'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'th.filename', :text => 'test1.txt'
|
||||
end
|
||||
|
||||
def test_show_text_file
|
||||
get :show, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_text_file_utf_8
|
||||
set_tmp_attachments_directory
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("japanese-utf-8.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'japanese-utf-8.txt', a.filename
|
||||
|
||||
str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
|
||||
|
||||
get :show, :params => {
|
||||
:id => a.id
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'tr#L1' do
|
||||
assert_select 'th.line-num', :text => '1'
|
||||
assert_select 'td', :text => /#{str_japanese}/
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_text_file_replace_cannot_convert_content
|
||||
set_tmp_attachments_directory
|
||||
with_settings :repositories_encodings => 'UTF-8' do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("iso8859-1.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'iso8859-1.txt', a.filename
|
||||
|
||||
get :show, :params => {
|
||||
:id => a.id
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'tr#L7' do
|
||||
assert_select 'th.line-num', :text => '7'
|
||||
assert_select 'td', :text => /Demande cr\?\?e avec succ\?s/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_text_file_latin_1
|
||||
set_tmp_attachments_directory
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("iso8859-1.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'iso8859-1.txt', a.filename
|
||||
|
||||
get :show, :params => {
|
||||
:id => a.id
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'tr#L7' do
|
||||
assert_select 'th.line-num', :text => '7'
|
||||
assert_select 'td', :text => /Demande créée avec succès/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_text_file_should_show_other_if_too_big
|
||||
@request.session[:user_id] = 2
|
||||
with_settings :file_max_size_displayed => 512 do
|
||||
Attachment.find(4).update_attribute :filesize, 754.kilobyte
|
||||
get :show, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select '.nodata', :text => 'No preview available. Download the file instead.'
|
||||
end
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_image
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:id => 16
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'img.filecontent', :src => attachments(:attachments_010).filename
|
||||
end
|
||||
|
||||
def test_show_other_with_no_preview
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:id => 6
|
||||
}
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select '.nodata', :text => 'No preview available. Download the file instead.'
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_file_from_private_issue_without_permission
|
||||
get :show, :params => {
|
||||
:id => 15
|
||||
}
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2F15'
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_file_from_private_issue_with_permission
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:id => 15
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /private.diff/
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_file_without_container_should_be_allowed_to_author
|
||||
set_tmp_attachments_directory
|
||||
attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:id => attachment.id
|
||||
}
|
||||
assert_response 200
|
||||
end
|
||||
|
||||
def test_show_file_without_container_should_be_denied_to_other_users
|
||||
set_tmp_attachments_directory
|
||||
attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
|
||||
|
||||
@request.session[:user_id] = 3
|
||||
get :show, :params => {
|
||||
:id => attachment.id
|
||||
}
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_show_issue_attachment_should_highlight_issues_menu_item
|
||||
get :show, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '#main-menu a.issues.selected'
|
||||
end
|
||||
|
||||
def test_show_invalid_should_respond_with_404
|
||||
get :show, :params => {
|
||||
:id => 999
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_download_text_file
|
||||
get :download, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'application/x-ruby', @response.content_type
|
||||
etag = @response.etag
|
||||
assert_not_nil etag
|
||||
|
||||
@request.env["HTTP_IF_NONE_MATCH"] = etag
|
||||
get :download, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response 304
|
||||
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_download_js_file
|
||||
set_tmp_attachments_directory
|
||||
attachment = Attachment.create!(
|
||||
:file => mock_file_with_options(:original_filename => "hello.js", :content_type => "text/javascript"),
|
||||
:author_id => 2,
|
||||
:container => Issue.find(1)
|
||||
)
|
||||
|
||||
get :download, :params => {
|
||||
:id => attachment.id
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', @response.content_type
|
||||
end
|
||||
|
||||
def test_download_version_file_with_issue_tracking_disabled
|
||||
Project.find(1).disable_module! :issue_tracking
|
||||
get :download, :params => {
|
||||
:id => 9
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_download_should_assign_content_type_if_blank
|
||||
Attachment.find(4).update_attribute(:content_type, '')
|
||||
|
||||
get :download, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/x-ruby', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_download_should_assign_better_content_type_than_application_octet_stream
|
||||
Attachment.find(4).update! :content_type => "application/octet-stream"
|
||||
|
||||
get :download, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/x-ruby', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_download_missing_file
|
||||
get :download, :params => {
|
||||
:id => 2
|
||||
}
|
||||
assert_response 404
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_download_should_be_denied_without_permission
|
||||
get :download, :params => {
|
||||
:id => 7
|
||||
}
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
if convert_installed?
|
||||
def test_thumbnail
|
||||
Attachment.clear_thumbnails
|
||||
@request.session[:user_id] = 2
|
||||
get :thumbnail, :params => {
|
||||
:id => 16
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'image/png', response.content_type
|
||||
|
||||
etag = @response.etag
|
||||
assert_not_nil etag
|
||||
|
||||
@request.env["HTTP_IF_NONE_MATCH"] = etag
|
||||
get :thumbnail, :params => {
|
||||
:id => 16
|
||||
}
|
||||
assert_response 304
|
||||
end
|
||||
|
||||
def test_thumbnail_should_not_exceed_maximum_size
|
||||
Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 800}
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :thumbnail, :params => {
|
||||
:id => 16,
|
||||
:size => 2000
|
||||
}
|
||||
end
|
||||
|
||||
def test_thumbnail_should_round_size
|
||||
Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 250}
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :thumbnail, :params => {
|
||||
:id => 16,
|
||||
:size => 260
|
||||
}
|
||||
end
|
||||
|
||||
def test_thumbnail_should_return_404_for_non_image_attachment
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :thumbnail, :params => {
|
||||
:id => 15
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_thumbnail_should_return_404_if_thumbnail_generation_failed
|
||||
Attachment.any_instance.stubs(:thumbnail).returns(nil)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :thumbnail, :params => {
|
||||
:id => 16
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_thumbnail_should_be_denied_without_permission
|
||||
get :thumbnail, :params => {
|
||||
:id => 16
|
||||
}
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
|
||||
end
|
||||
else
|
||||
puts '(ImageMagick convert not available)'
|
||||
end
|
||||
|
||||
def test_edit_all
|
||||
@request.session[:user_id] = 2
|
||||
get :edit_all, :params => {
|
||||
:object_type => 'issues',
|
||||
:object_id => '2'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form[action=?]', '/attachments/issues/2' do
|
||||
Issue.find(2).attachments.each do |attachment|
|
||||
assert_select "tr#attachment-#{attachment.id}"
|
||||
end
|
||||
|
||||
assert_select 'tr#attachment-4' do
|
||||
assert_select 'input[name=?][value=?]', 'attachments[4][filename]', 'source.rb'
|
||||
assert_select 'input[name=?][value=?]', 'attachments[4][description]', 'This is a Ruby source file'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_edit_all_with_invalid_container_class_should_return_404
|
||||
get :edit_all, :params => {
|
||||
:object_type => 'nuggets',
|
||||
:object_id => '3'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_edit_all_with_invalid_object_should_return_404
|
||||
get :edit_all, :params => {
|
||||
:object_type => 'issues',
|
||||
:object_id => '999'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_edit_all_for_object_that_is_not_visible_should_return_403
|
||||
get :edit_all, :params => {
|
||||
:object_type => 'issues',
|
||||
:object_id => '4'
|
||||
}
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_update_all
|
||||
@request.session[:user_id] = 2
|
||||
patch :update_all, :params => {
|
||||
:object_type => 'issues',
|
||||
:object_id => '2',
|
||||
:attachments => {
|
||||
'1' => {
|
||||
:filename => 'newname.text',
|
||||
:description => ''
|
||||
},
|
||||
'4' => {
|
||||
:filename => 'newname.rb',
|
||||
:description => 'Renamed'
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
assert_response 302
|
||||
attachment = Attachment.find(4)
|
||||
assert_equal 'newname.rb', attachment.filename
|
||||
assert_equal 'Renamed', attachment.description
|
||||
end
|
||||
|
||||
def test_update_all_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
patch :update_all, :params => {
|
||||
:object_type => 'issues',
|
||||
:object_id => '3',
|
||||
:attachments => {
|
||||
'1' => {
|
||||
:filename => '',
|
||||
:description => ''
|
||||
},
|
||||
'4' => {
|
||||
:filename => 'newname.rb',
|
||||
:description => 'Renamed'
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_select_error /file cannot be blank/i
|
||||
|
||||
# The other attachment should not be updated
|
||||
attachment = Attachment.find(4)
|
||||
assert_equal 'source.rb', attachment.filename
|
||||
assert_equal 'This is a Ruby source file', attachment.description
|
||||
end
|
||||
|
||||
def test_destroy_issue_attachment
|
||||
set_tmp_attachments_directory
|
||||
issue = Issue.find(3)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_difference 'issue.attachments.count', -1 do
|
||||
assert_difference 'Journal.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook'
|
||||
end
|
||||
end
|
||||
assert_nil Attachment.find_by_id(1)
|
||||
j = Journal.order('id DESC').first
|
||||
assert_equal issue, j.journalized
|
||||
assert_equal 'attachment', j.details.first.property
|
||||
assert_equal '1', j.details.first.prop_key
|
||||
assert_equal 'error281.txt', j.details.first.old_value
|
||||
assert_equal User.find(2), j.user
|
||||
end
|
||||
|
||||
def test_destroy_wiki_page_attachment
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 3
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_project_attachment
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 8
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_version_attachment
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 9
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_version_attachment_with_issue_tracking_disabled
|
||||
Project.find(1).disable_module! :issue_tracking
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 9
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_without_permission
|
||||
set_tmp_attachments_directory
|
||||
assert_no_difference 'Attachment.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 3
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
assert Attachment.find_by_id(3)
|
||||
end
|
||||
end
|
||||
58
test/functional/attachments_visibility_test.rb
Normal file
58
test/functional/attachments_visibility_test.rb
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# 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 AttachmentsVisibilityTest < Redmine::ControllerTest
|
||||
tests AttachmentsController
|
||||
fixtures :users, :email_addresses, :projects, :roles, :members, :member_roles,
|
||||
:enabled_modules, :projects_trackers, :issue_statuses, :enumerations,
|
||||
:issues, :trackers, :versions
|
||||
|
||||
def setup
|
||||
set_tmp_attachments_directory
|
||||
|
||||
@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
|
||||
end
|
||||
|
||||
def test_attachment_should_be_visible
|
||||
@request.session[:user_id] = 2 # manager
|
||||
get :show, :params => {:id => @attachment.id}
|
||||
assert_response :success
|
||||
|
||||
@field.update!(:visible => false, :role_ids => [1])
|
||||
get :show, :params => {:id => @attachment.id}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_attachment_should_be_visible_with_permission
|
||||
@request.session[:user_id] = 3 # developer
|
||||
get :show, :params => {:id => @attachment.id}
|
||||
assert_response :success
|
||||
|
||||
@field.update!(:visible => false, :role_ids => [1])
|
||||
get :show, :params => {:id => @attachment.id}
|
||||
assert_response 403
|
||||
end
|
||||
end
|
||||
204
test/functional/auth_sources_controller_test.rb
Normal file
204
test/functional/auth_sources_controller_test.rb
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
# 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 AuthSourcesControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :auth_sources
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form#auth_source_form' do
|
||||
assert_select 'input[name=type][value=AuthSourceLdap]'
|
||||
assert_select 'input[name=?]', 'auth_source[host]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_with_invalid_type_should_respond_with_404
|
||||
get :new, :params => {
|
||||
:type => 'foo'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'AuthSourceLdap.count' do
|
||||
post :create, :params => {
|
||||
:type => 'AuthSourceLdap',
|
||||
:auth_source => {
|
||||
:name => 'Test',
|
||||
:host => '127.0.0.1',
|
||||
:port => '389',
|
||||
:attr_login => 'cn'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/auth_sources'
|
||||
end
|
||||
|
||||
source = AuthSourceLdap.order('id DESC').first
|
||||
assert_equal 'Test', source.name
|
||||
assert_equal '127.0.0.1', source.host
|
||||
assert_equal 389, source.port
|
||||
assert_equal 'cn', source.attr_login
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'AuthSourceLdap.count' do
|
||||
post :create, :params => {
|
||||
:type => 'AuthSourceLdap',
|
||||
:auth_source => {
|
||||
:name => 'Test',
|
||||
:host => '',
|
||||
:port => '389',
|
||||
:attr_login => 'cn'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
assert_select_error /host cannot be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form#auth_source_form' do
|
||||
assert_select 'input[name=?]', 'auth_source[host]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_edit_should_not_contain_password
|
||||
AuthSource.find(1).update_column :account_password, 'secret'
|
||||
|
||||
get :edit, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[value=secret]', 0
|
||||
assert_select 'input[name=dummy_password][value^=xxxxxx]'
|
||||
end
|
||||
|
||||
def test_edit_invalid_should_respond_with_404
|
||||
get :edit, :params => {
|
||||
:id => 99
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:auth_source => {
|
||||
:name => 'Renamed',
|
||||
:host => '192.168.0.10',
|
||||
:port => '389',
|
||||
:attr_login => 'uid'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/auth_sources'
|
||||
source = AuthSourceLdap.find(1)
|
||||
assert_equal 'Renamed', source.name
|
||||
assert_equal '192.168.0.10', source.host
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:auth_source => {
|
||||
:name => 'Renamed',
|
||||
:host => '',
|
||||
:port => '389',
|
||||
:attr_login => 'uid'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /host cannot be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'AuthSourceLdap.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/auth_sources'
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_auth_source_in_use
|
||||
User.find(2).update_attribute :auth_source_id, 1
|
||||
|
||||
assert_no_difference 'AuthSourceLdap.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/auth_sources'
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_connection
|
||||
AuthSourceLdap.any_instance.stubs(:test_connection).returns(true)
|
||||
|
||||
get :test_connection, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/auth_sources'
|
||||
assert_not_nil flash[:notice]
|
||||
assert_match /successful/i, flash[:notice]
|
||||
end
|
||||
|
||||
def test_test_connection_with_failure
|
||||
AuthSourceLdap.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError.new("Something went wrong"))
|
||||
|
||||
get :test_connection, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/auth_sources'
|
||||
assert_not_nil flash[:error]
|
||||
assert_include 'Something went wrong', flash[:error]
|
||||
end
|
||||
|
||||
def test_autocomplete_for_new_user
|
||||
AuthSource.expects(:search).with('foo').returns([
|
||||
{:login => 'foo1', :firstname => 'John', :lastname => 'Smith', :mail => 'foo1@example.net', :auth_source_id => 1},
|
||||
{:login => 'Smith', :firstname => 'John', :lastname => 'Doe', :mail => 'foo2@example.net', :auth_source_id => 1}
|
||||
])
|
||||
|
||||
get :autocomplete_for_new_user, :params => {
|
||||
:term => 'foo'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'application/json', response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Array, json
|
||||
assert_equal 2, json.size
|
||||
assert_equal 'foo1', json.first['value']
|
||||
assert_equal 'foo1 (John Smith)', json.first['label']
|
||||
end
|
||||
end
|
||||
141
test/functional/auto_completes_controller_test.rb
Normal file
141
test/functional/auto_completes_controller_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 AutoCompletesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :issues, :issue_statuses,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:journals, :journal_details
|
||||
|
||||
def test_issues_should_not_be_case_sensitive
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:q => 'ReCiPe'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "recipe", response.body
|
||||
end
|
||||
|
||||
def test_issues_should_accept_term_param
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:term => 'ReCiPe'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "recipe", response.body
|
||||
end
|
||||
|
||||
def test_issues_should_return_issue_with_given_id
|
||||
get :issues, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:q => '13'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "Bug #13", response.body
|
||||
end
|
||||
|
||||
def test_issues_should_return_issue_with_given_id_preceded_with_hash
|
||||
get :issues, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:q => '#13'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "Bug #13", response.body
|
||||
end
|
||||
|
||||
def test_auto_complete_with_scope_all_should_search_other_projects
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:q => '13',
|
||||
:scope => 'all'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "Bug #13", response.body
|
||||
end
|
||||
|
||||
def test_auto_complete_without_project_should_search_all_projects
|
||||
get :issues, :params => {
|
||||
:q => '13'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "Bug #13", response.body
|
||||
end
|
||||
|
||||
def test_auto_complete_without_scope_all_should_not_search_other_projects
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:q => '13'
|
||||
}
|
||||
assert_response :success
|
||||
assert_not_include "Bug #13", response.body
|
||||
end
|
||||
|
||||
def test_issues_should_return_json
|
||||
get :issues, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:q => '13'
|
||||
}
|
||||
assert_response :success
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Array, json
|
||||
issue = json.first
|
||||
assert_kind_of Hash, issue
|
||||
assert_equal 13, issue['id']
|
||||
assert_equal 13, issue['value']
|
||||
assert_equal 'Bug #13: Subproject issue two', issue['label']
|
||||
end
|
||||
|
||||
def test_auto_complete_with_status_o_should_return_open_issues_only
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:q => 'issue',
|
||||
:status => 'o'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "Issue due today", response.body
|
||||
assert_not_include "closed", response.body
|
||||
end
|
||||
|
||||
def test_auto_complete_with_status_c_should_return_closed_issues_only
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:q => 'issue',
|
||||
:status => 'c'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "closed", response.body
|
||||
assert_not_include "Issue due today", response.body
|
||||
end
|
||||
|
||||
def test_auto_complete_with_issue_id_should_not_return_that_issue
|
||||
get :issues, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:q => 'issue',
|
||||
:issue_id => '12'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include "issue", response.body
|
||||
assert_not_include "Bug #12: Closed issue on a locked version", response.body
|
||||
end
|
||||
end
|
||||
294
test/functional/boards_controller_test.rb
Normal file
294
test/functional/boards_controller_test.rb
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
# 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 BoardsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.boards'
|
||||
end
|
||||
|
||||
def test_index_not_found
|
||||
get :index, :params => {
|
||||
:project_id => 97
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_index_should_show_messages_if_only_one_board
|
||||
Project.find(1).boards.to_a.slice(1..-1).each(&:destroy)
|
||||
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.boards', 0
|
||||
assert_select 'table.messages'
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.messages tbody' do
|
||||
assert_select 'tr', Board.find(1).topics.count
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_should_display_sticky_messages_first
|
||||
Message.update_all(:sticky => 0)
|
||||
Message.where({:id => 1}).update_all({:sticky => 1})
|
||||
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.messages tbody' do
|
||||
# row is here...
|
||||
assert_select 'tr.sticky'
|
||||
# ...and in first position
|
||||
assert_select 'tr.sticky:first-child'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_should_display_message_with_last_reply_first
|
||||
Message.update_all(:sticky => 0)
|
||||
|
||||
# Reply to an old topic
|
||||
old_topic = Message.where(:board_id => 1, :parent_id => nil).order('created_on ASC').first
|
||||
reply = Message.new(:board_id => 1, :subject => 'New reply', :content => 'New reply', :author_id => 2)
|
||||
old_topic.children << reply
|
||||
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.messages tbody' do
|
||||
assert_select "tr#message-#{old_topic.id}"
|
||||
assert_select "tr#message-#{old_topic.id}:first-child"
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_with_permission_should_display_the_new_message_form
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form#message-form' do
|
||||
assert_select 'input[name=?]', 'message[subject]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_atom
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:id => 1,
|
||||
:format => 'atom'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'feed > entry > title', :text => 'Help: RE: post 2'
|
||||
end
|
||||
|
||||
def test_show_not_found
|
||||
get :index, :params => {
|
||||
:project_id => 1,
|
||||
:id => 97
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'board[parent_id]' do
|
||||
assert_select 'option', (Project.find(1).boards.size + 1)
|
||||
assert_select 'option[value=""]'
|
||||
assert_select 'option[value="1"]', :text => 'Help'
|
||||
end
|
||||
|
||||
# replaced by nokogiri, not easy to test in DOM assertions
|
||||
assert_not_include '<option value=""></option>', response.body
|
||||
assert_include '<option value=""> </option>', response.body
|
||||
end
|
||||
|
||||
def test_new_without_project_boards
|
||||
Project.find(1).boards.delete_all
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'board[parent_id]', 0
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Board.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:board => {
|
||||
:name => 'Testing',
|
||||
:description => 'Testing board creation'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
board = Board.order('id DESC').first
|
||||
assert_equal 'Testing', board.name
|
||||
assert_equal 'Testing board creation', board.description
|
||||
end
|
||||
|
||||
def test_create_with_parent
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Board.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:board => {
|
||||
:name => 'Testing',
|
||||
:description => 'Testing',
|
||||
:parent_id => 2
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
board = Board.order('id DESC').first
|
||||
assert_equal Board.find(2), board.parent
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Board.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:board => {
|
||||
:name => '',
|
||||
:description => 'Testing board creation'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/
|
||||
end
|
||||
|
||||
def test_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:project_id => 1,
|
||||
:id => 2
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'board[name]', 'Discussion'
|
||||
end
|
||||
|
||||
def test_edit_with_parent
|
||||
board = Board.generate!(:project_id => 1, :parent_id => 2)
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:project_id => 1,
|
||||
:id => board.id
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'board[parent_id]' do
|
||||
assert_select 'option[value="2"][selected=selected]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Board.count' do
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:id => 2,
|
||||
:board => {
|
||||
:name => 'Testing',
|
||||
:description => 'Testing board update'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
assert_equal 'Testing', Board.find(2).name
|
||||
end
|
||||
|
||||
def test_update_position
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:id => 2,
|
||||
:board => {
|
||||
:position => 1
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
board = Board.find(2)
|
||||
assert_equal 1, board.position
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:id => 2,
|
||||
:board => {
|
||||
:name => '',
|
||||
:description => 'Testing board update'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Board.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:project_id => 1,
|
||||
:id => 2
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
assert_nil Board.find_by_id(2)
|
||||
end
|
||||
end
|
||||
116
test/functional/calendars_controller_test.rb
Normal file
116
test/functional/calendars_controller_test.rb
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# 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 CalendarsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:issues,
|
||||
:issue_statuses,
|
||||
:issue_relations,
|
||||
:issue_categories,
|
||||
:enumerations,
|
||||
:queries
|
||||
|
||||
def test_show
|
||||
get :show, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_show_should_run_custom_queries
|
||||
@query = IssueQuery.create!(:name => 'Calendar Query', :visibility => IssueQuery::VISIBILITY_PUBLIC)
|
||||
|
||||
get :show, :params => {
|
||||
:query_id => @query.id
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => 'Calendar Query'
|
||||
end
|
||||
|
||||
def test_cross_project_calendar
|
||||
get :show
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_week_number_calculation
|
||||
with_settings :start_of_week => 7 do
|
||||
get :show, :params => {
|
||||
:month => '1',
|
||||
:year => '2010'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
assert_select 'tr' do
|
||||
assert_select 'td.week-number', :text => '53'
|
||||
assert_select 'td.odd', :text => '27'
|
||||
assert_select 'td.even', :text => '2'
|
||||
end
|
||||
|
||||
assert_select 'tr' do
|
||||
assert_select 'td.week-number', :text => '1'
|
||||
assert_select 'td.odd', :text => '3'
|
||||
assert_select 'td.even', :text => '9'
|
||||
end
|
||||
|
||||
with_settings :start_of_week => 1 do
|
||||
get :show, :params => {
|
||||
:month => '1',
|
||||
:year => '2010'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
assert_select 'tr' do
|
||||
assert_select 'td.week-number', :text => '53'
|
||||
assert_select 'td.even', :text => '28'
|
||||
assert_select 'td.even', :text => '3'
|
||||
end
|
||||
|
||||
assert_select 'tr' do
|
||||
assert_select 'td.week-number', :text => '1'
|
||||
assert_select 'td.even', :text => '4'
|
||||
assert_select 'td.even', :text => '10'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_custom_query_with_multiple_sort_criteria
|
||||
get :show, :params => {
|
||||
:query_id => 5
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => 'Open issues by priority and tracker'
|
||||
end
|
||||
|
||||
def test_show_custom_query_with_group_by_option
|
||||
get :show, :params => {
|
||||
:query_id => 6
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => 'Open issues grouped by tracker'
|
||||
end
|
||||
end
|
||||
82
test/functional/comments_controller_test.rb
Normal file
82
test/functional/comments_controller_test.rb
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# 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 CommentsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules, :news, :comments
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_add_comment
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :params => {
|
||||
:id => 1,
|
||||
:comment => {
|
||||
:comments => 'This is a test comment'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/news/1'
|
||||
|
||||
comment = News.find(1).comments.last
|
||||
assert_not_nil comment
|
||||
assert_equal 'This is a test comment', comment.comments
|
||||
assert_equal User.find(2), comment.author
|
||||
end
|
||||
|
||||
def test_empty_comment_should_not_be_added
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Comment.count' do
|
||||
post :create, :params => {
|
||||
:id => 1,
|
||||
:comment => {
|
||||
:comments => ''
|
||||
}
|
||||
}
|
||||
assert_response :redirect
|
||||
assert_redirected_to '/news/1'
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_should_be_denied_if_news_is_not_commentable
|
||||
News.any_instance.stubs(:commentable?).returns(false)
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Comment.count' do
|
||||
post :create, :params => {
|
||||
:id => 1,
|
||||
:comment => {
|
||||
:comments => 'This is a test comment'
|
||||
}
|
||||
}
|
||||
assert_response 403
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_comment
|
||||
comments_count = News.find(1).comments.size
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :params => {
|
||||
:id => 1,
|
||||
:comment_id => 2
|
||||
}
|
||||
assert_redirected_to '/news/1'
|
||||
assert_nil Comment.find_by_id(2)
|
||||
assert_equal comments_count - 1, News.find(1).comments.size
|
||||
end
|
||||
end
|
||||
327
test/functional/context_menus_controller_test.rb
Normal file
327
test/functional/context_menus_controller_test.rb
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
# 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 ContextMenusControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:workflows,
|
||||
:journals, :journal_details,
|
||||
:versions,
|
||||
:issues, :issue_statuses, :issue_categories,
|
||||
:users,
|
||||
:enumerations,
|
||||
:time_entries
|
||||
|
||||
def test_context_menu_one_issue
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a.icon-edit[href=?]', '/issues/1/edit', :text => 'Edit'
|
||||
assert_select 'a.icon-copy[href=?]', '/projects/ecookbook/issues/1/copy', :text => 'Copy'
|
||||
assert_select 'a.icon-del[href=?]', '/issues?ids%5B%5D=1', :text => 'Delete'
|
||||
|
||||
# Statuses
|
||||
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&issue%5Bstatus_id%5D=5', :text => 'Closed'
|
||||
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&issue%5Bpriority_id%5D=8', :text => 'Immediate'
|
||||
# No inactive priorities
|
||||
assert_select 'a', :text => /Inactive Priority/, :count => 0
|
||||
# Versions
|
||||
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&issue%5Bfixed_version_id%5D=3', :text => '2.0'
|
||||
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&issue%5Bfixed_version_id%5D=4', :text => 'eCookbook Subproject 1 - 2.0'
|
||||
# Assignees
|
||||
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&issue%5Bassigned_to_id%5D=3', :text => 'Dave Lopper'
|
||||
end
|
||||
|
||||
def test_context_menu_one_issue_by_anonymous
|
||||
with_settings :default_language => 'en' do
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a.icon-del.disabled[href="#"]', :text => 'Delete'
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_multiple_issues_of_same_project
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1, 2]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
ids = [1, 2].map {|i| "ids%5B%5D=#{i}"}.join('&')
|
||||
|
||||
assert_select 'a.icon-edit[href=?]', "/issues/bulk_edit?#{ids}", :text => 'Edit'
|
||||
assert_select 'a.icon-copy[href=?]', "/issues/bulk_edit?copy=1&#{ids}", :text => 'Copy'
|
||||
assert_select 'a.icon-del[href=?]', "/issues?#{ids}", :text => 'Delete'
|
||||
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bstatus_id%5D=5", :text => 'Closed'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bpriority_id%5D=8", :text => 'Immediate'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bassigned_to_id%5D=3", :text => 'Dave Lopper'
|
||||
end
|
||||
|
||||
def test_context_menu_multiple_issues_of_different_projects
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1, 2, 6]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
ids = [1, 2, 6].map {|i| "ids%5B%5D=#{i}"}.join('&')
|
||||
|
||||
assert_select 'a.icon-edit[href=?]', "/issues/bulk_edit?#{ids}", :text => 'Edit'
|
||||
assert_select 'a.icon-del[href=?]', "/issues?#{ids}", :text => 'Delete'
|
||||
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bstatus_id%5D=5", :text => 'Closed'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bpriority_id%5D=8", :text => 'Immediate'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&issue%5Bassigned_to_id%5D=2", :text => 'John Smith'
|
||||
end
|
||||
|
||||
def test_context_menu_should_include_list_custom_fields
|
||||
field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
|
||||
:possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => 'List'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', 3
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=Foo", :text => 'Foo'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_should_not_include_null_value_for_required_custom_fields
|
||||
field = IssueCustomField.create!(:name => 'List', :is_required => true, :field_format => 'list',
|
||||
:possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1, 2]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => 'List'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', 2
|
||||
assert_select 'a', :text => 'none', :count => 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_on_single_issue_should_select_current_custom_field_value
|
||||
field = IssueCustomField.create!(:name => 'List', :field_format => 'list',
|
||||
:possible_values => ['Foo', 'Bar'], :is_for_all => true, :tracker_ids => [1, 2, 3])
|
||||
issue = Issue.find(1)
|
||||
issue.custom_field_values = {field.id => 'Bar'}
|
||||
issue.save!
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => 'List'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', 3
|
||||
assert_select 'a.icon-checked', :text => 'Bar'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_should_include_bool_custom_fields
|
||||
field = IssueCustomField.create!(:name => 'Bool', :field_format => 'bool',
|
||||
:is_for_all => true, :tracker_ids => [1, 2, 3])
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => 'Bool'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', 3
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=0", :text => 'No'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=1", :text => 'Yes'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_should_include_user_custom_fields
|
||||
field = IssueCustomField.create!(:name => 'User', :field_format => 'user',
|
||||
:is_for_all => true, :tracker_ids => [1, 2, 3])
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => 'User'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', Project.find(1).members.count + 1
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=2", :text => 'John Smith'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_should_include_version_custom_fields
|
||||
field = IssueCustomField.create!(:name => 'Version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1, 2, 3])
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => 'Version'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', Project.find(1).shared_versions.count + 1
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=3", :text => '2.0'
|
||||
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&issue%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_context_menu_should_show_enabled_custom_fields_for_the_role_only
|
||||
enabled_cf = IssueCustomField.generate!(:field_format => 'bool', :is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2])
|
||||
disabled_cf = IssueCustomField.generate!(:field_format => 'bool', :is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2])
|
||||
issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [issue.id]
|
||||
}
|
||||
|
||||
assert_select "li.cf_#{enabled_cf.id}"
|
||||
assert_select "li.cf_#{disabled_cf.id}", 0
|
||||
end
|
||||
|
||||
def test_context_menu_by_assignable_user_should_include_assigned_to_me_link
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&issue%5Bassigned_to_id%5D=2', :text => / me /
|
||||
end
|
||||
|
||||
def test_context_menu_should_propose_shared_versions_for_issues_from_different_projects
|
||||
@request.session[:user_id] = 2
|
||||
version = Version.create!(:name => 'Shared', :sharing => 'system', :project_id => 1)
|
||||
|
||||
get :issues, :params => {
|
||||
:ids => [1, 4]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a', :text => 'eCookbook - Shared'
|
||||
end
|
||||
|
||||
def test_context_menu_with_issue_that_is_not_visible_should_fail
|
||||
get :issues, :params => {
|
||||
:ids => [1, 4] # issue 4 is not visible
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_should_respond_with_404_without_ids
|
||||
get :issues
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_time_entries_context_menu
|
||||
@request.session[:user_id] = 2
|
||||
get :time_entries, :params => {
|
||||
:ids => [1, 2]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a:not(.disabled)', :text => 'Edit'
|
||||
end
|
||||
|
||||
def test_context_menu_for_one_time_entry
|
||||
@request.session[:user_id] = 2
|
||||
get :time_entries, :params => {
|
||||
:ids => [1]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a:not(.disabled)', :text => 'Edit'
|
||||
end
|
||||
|
||||
def test_time_entries_context_menu_should_include_custom_fields
|
||||
field = TimeEntryCustomField.generate!(:name => "Field", :field_format => "list", :possible_values => ["foo", "bar"])
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :time_entries, :params => {
|
||||
:ids => [1, 2]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select "li.cf_#{field.id}" do
|
||||
assert_select 'a[href="#"]', :text => "Field"
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', 3
|
||||
assert_select 'a[href=?]', "/time_entries/bulk_update?ids%5B%5D=1&ids%5B%5D=2&time_entry%5Bcustom_field_values%5D%5B#{field.id}%5D=foo", :text => 'foo'
|
||||
assert_select 'a[href=?]', "/time_entries/bulk_update?ids%5B%5D=1&ids%5B%5D=2&time_entry%5Bcustom_field_values%5D%5B#{field.id}%5D=bar", :text => 'bar'
|
||||
assert_select 'a[href=?]', "/time_entries/bulk_update?ids%5B%5D=1&ids%5B%5D=2&time_entry%5Bcustom_field_values%5D%5B#{field.id}%5D=__none__", :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_time_entries_context_menu_with_edit_own_time_entries_permission
|
||||
@request.session[:user_id] = 2
|
||||
Role.find_by_name('Manager').remove_permission! :edit_time_entries
|
||||
Role.find_by_name('Manager').add_permission! :edit_own_time_entries
|
||||
ids = (0..1).map {TimeEntry.generate!(:user => User.find(2)).id}
|
||||
|
||||
get :time_entries, :params => {
|
||||
:ids => ids
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a:not(.disabled)', :text => 'Edit'
|
||||
end
|
||||
|
||||
def test_time_entries_context_menu_without_edit_permission
|
||||
@request.session[:user_id] = 2
|
||||
Role.find_by_name('Manager').remove_permission! :edit_time_entries
|
||||
|
||||
get :time_entries, :params => {
|
||||
:ids => [1, 2]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a.disabled', :text => 'Edit'
|
||||
end
|
||||
end
|
||||
150
test/functional/custom_field_enumerations_controller_test.rb
Normal file
150
test/functional/custom_field_enumerations_controller_test.rb
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# 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 CustomFieldEnumerationsControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :email_addresses
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
@field = GroupCustomField.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_index
|
||||
get :index, :params => {
|
||||
:custom_field_id => @field.id
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'ul#custom_field_enumerations' do
|
||||
assert_select 'li', 2
|
||||
end
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'CustomFieldEnumeration.count' do
|
||||
post :create, :params => {
|
||||
:custom_field_id => @field.id,
|
||||
:custom_field_enumeration => {
|
||||
:name => 'Baz'
|
||||
}
|
||||
}
|
||||
assert_redirected_to "/custom_fields/#{@field.id}/enumerations"
|
||||
end
|
||||
|
||||
assert_equal 3, @field.reload.enumerations.count
|
||||
enum = @field.enumerations.last
|
||||
assert_equal 'Baz', enum.name
|
||||
assert_equal true, enum.active
|
||||
assert_equal 3, enum.position
|
||||
end
|
||||
|
||||
def test_create_xhr
|
||||
assert_difference 'CustomFieldEnumeration.count' do
|
||||
post :create, :params => {
|
||||
:custom_field_id => @field.id,
|
||||
:custom_field_enumeration => {
|
||||
:name => 'Baz'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_each
|
||||
put :update_each, :params => {
|
||||
:custom_field_id => @field.id,
|
||||
:custom_field_enumerations => {
|
||||
@bar.id.to_s => {
|
||||
:position => "1",
|
||||
:name => "Baz",
|
||||
:active => "1"
|
||||
},
|
||||
@foo.id.to_s => {
|
||||
:position => "2",
|
||||
:name => "Foo",
|
||||
:active => "0"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
|
||||
@bar.reload
|
||||
assert_equal "Baz", @bar.name
|
||||
assert_equal true, @bar.active
|
||||
assert_equal 1, @bar.position
|
||||
|
||||
@foo.reload
|
||||
assert_equal "Foo", @foo.name
|
||||
assert_equal false, @foo.active
|
||||
assert_equal 2, @foo.position
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'CustomFieldEnumeration.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:custom_field_id => @field.id,
|
||||
:id => @foo.id
|
||||
}
|
||||
assert_redirected_to "/custom_fields/#{@field.id}/enumerations"
|
||||
end
|
||||
|
||||
assert_equal 1, @field.reload.enumerations.count
|
||||
enum = @field.enumerations.last
|
||||
assert_equal 'Bar', enum.name
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_in_use_should_display_destroy_form
|
||||
group = Group.generate!
|
||||
group.custom_field_values = {@field.id.to_s => @foo.id.to_s}
|
||||
group.save!
|
||||
|
||||
assert_no_difference 'CustomFieldEnumeration.count' do
|
||||
delete :destroy, :params => {
|
||||
:custom_field_id => @field.id,
|
||||
:id => @foo.id
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'reassign_to_id'
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_in_use_should_destroy_and_reassign_values
|
||||
group = Group.generate!
|
||||
group.custom_field_values = {@field.id.to_s => @foo.id.to_s}
|
||||
group.save!
|
||||
|
||||
assert_difference 'CustomFieldEnumeration.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:custom_field_id => @field.id,
|
||||
:id => @foo.id,
|
||||
:reassign_to_id => @bar.id
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
assert_equal @bar.id.to_s, group.reload.custom_field_value(@field)
|
||||
end
|
||||
end
|
||||
344
test/functional/custom_fields_controller_test.rb
Normal file
344
test/functional/custom_fields_controller_test.rb
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
# 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 CustomFieldsControllerTest < Redmine::ControllerTest
|
||||
fixtures :custom_fields, :custom_values,
|
||||
:custom_fields_projects, :custom_fields_trackers,
|
||||
:roles, :users,
|
||||
:members, :member_roles,
|
||||
:groups_users,
|
||||
:trackers, :projects_trackers,
|
||||
:enabled_modules,
|
||||
:projects, :issues,
|
||||
:issue_statuses,
|
||||
:issue_categories,
|
||||
:enumerations,
|
||||
:workflows
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.custom_fields'
|
||||
end
|
||||
|
||||
def test_new_without_type_should_render_select_type
|
||||
get :new
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=type]', CustomFieldsHelper::CUSTOM_FIELDS_TABS.size
|
||||
assert_select 'input[name=type][checked=checked]', 1
|
||||
end
|
||||
|
||||
def test_new_should_work_for_each_customized_class_and_format
|
||||
custom_field_classes.each do |klass|
|
||||
Redmine::FieldFormat.formats_for_custom_field_class(klass).each do |format|
|
||||
get :new, :params => {
|
||||
:type => klass.name,
|
||||
:custom_field => {
|
||||
:field_format => format.name
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form#custom_field_form' do
|
||||
assert_select 'select[name=?]', 'custom_field[field_format]' do
|
||||
assert_select 'option[value=?][selected=selected]', format.name
|
||||
end
|
||||
assert_select 'input[type=hidden][name=type][value=?]', klass.name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_should_have_string_default_format
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'custom_field[field_format]' do
|
||||
assert_select 'option[value=?][selected=selected]', 'string'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_issue_custom_field
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form#custom_field_form' do
|
||||
assert_select 'select#custom_field_field_format[name=?]', 'custom_field[field_format]' do
|
||||
assert_select 'option[value=user]', :text => 'User'
|
||||
assert_select 'option[value=version]', :text => 'Version'
|
||||
end
|
||||
assert_select 'input[type=checkbox][name=?]', 'custom_field[project_ids][]', Project.count
|
||||
assert_select 'input[type=hidden][name=?]', 'custom_field[project_ids][]', 1
|
||||
assert_select 'input[type=hidden][name=type][value=IssueCustomField]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_time_entry_custom_field_should_not_show_trackers_and_projects
|
||||
get :new, :params => {
|
||||
:type => 'TimeEntryCustomField'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form#custom_field_form' do
|
||||
assert_select 'input[name=?]', 'custom_field[tracker_ids][]', 0
|
||||
assert_select 'input[name=?]', 'custom_field[project_ids][]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_default_value_should_be_an_input_for_string_custom_field
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'string'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'custom_field[default_value]'
|
||||
end
|
||||
|
||||
def test_default_value_should_be_a_textarea_for_text_custom_field
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'text'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'textarea[name=?]', 'custom_field[default_value]'
|
||||
end
|
||||
|
||||
def test_default_value_should_be_a_checkbox_for_bool_custom_field
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'bool'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'custom_field[default_value]' do
|
||||
assert_select 'option', 3
|
||||
end
|
||||
end
|
||||
|
||||
def test_default_value_should_not_be_present_for_user_custom_field
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'user'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '[name=?]', 'custom_field[default_value]', 0
|
||||
end
|
||||
|
||||
def test_setting_full_width_layout_shoul_be_present_only_for_long_text_issue_custom_field
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'text'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '[name=?]', 'custom_field[full_width_layout]'
|
||||
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'list'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '[name=?]', 'custom_field[full_width_layout]', 0
|
||||
|
||||
get :new, :params => {
|
||||
:type => 'TimeEntryCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'text'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '[name=?]', 'custom_field[full_width_layout]', 0
|
||||
end
|
||||
|
||||
def test_new_js
|
||||
get :new, :params => {
|
||||
:type => 'IssueCustomField',
|
||||
:custom_field => {
|
||||
:field_format => 'list'
|
||||
},
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
|
||||
assert_include '<option selected=\"selected\" value=\"list\">List<\/option>', response.body
|
||||
end
|
||||
|
||||
def test_new_with_invalid_custom_field_class_should_render_select_type
|
||||
get :new, :params => {
|
||||
:type => 'UnknownCustomField'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[type=radio][name=type]'
|
||||
end
|
||||
|
||||
def test_create_list_custom_field
|
||||
field = new_record(IssueCustomField) do
|
||||
post :create, :params => {
|
||||
:type => "IssueCustomField",
|
||||
:custom_field => {
|
||||
:name => "test_post_new_list",
|
||||
:default_value => "",
|
||||
:min_length => "0",
|
||||
:searchable => "0",
|
||||
:regexp => "",
|
||||
:is_for_all => "1",
|
||||
:possible_values => "0.1\n0.2\n",
|
||||
:max_length => "0",
|
||||
:is_filter => "0",
|
||||
:is_required =>"0",
|
||||
:field_format => "list",
|
||||
:tracker_ids => ["1", ""]
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to "/custom_fields/#{field.id}/edit"
|
||||
assert_equal "test_post_new_list", field.name
|
||||
assert_equal ["0.1", "0.2"], field.possible_values
|
||||
assert_equal 1, field.trackers.size
|
||||
end
|
||||
|
||||
def test_create_with_project_ids
|
||||
assert_difference 'CustomField.count' do
|
||||
post :create, :params => {
|
||||
:type => "IssueCustomField",
|
||||
:custom_field => {
|
||||
:name => "foo",
|
||||
:field_format => "string",
|
||||
:is_for_all => "0",
|
||||
:project_ids => ["1", "3", ""]
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
field = IssueCustomField.order("id desc").first
|
||||
assert_equal [1, 3], field.projects.map(&:id).sort
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'CustomField.count' do
|
||||
post :create, :params => {
|
||||
:type => "IssueCustomField",
|
||||
:custom_field => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_create_without_type_should_render_select_type
|
||||
assert_no_difference 'CustomField.count' do
|
||||
post :create, :params => {
|
||||
:custom_field => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select 'input[type=radio][name=type]'
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'custom_field[name]', 'Database'
|
||||
end
|
||||
|
||||
def test_edit_invalid_custom_field_should_render_404
|
||||
get :edit, :params => {
|
||||
:id => 99
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:custom_field => {
|
||||
:name => 'New name'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/custom_fields/1/edit'
|
||||
|
||||
field = CustomField.find(1)
|
||||
assert_equal 'New name', field.name
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:custom_field => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
custom_values_count = CustomValue.where(:custom_field_id => 1).count
|
||||
assert custom_values_count > 0
|
||||
|
||||
assert_difference 'CustomField.count', -1 do
|
||||
assert_difference 'CustomValue.count', - custom_values_count do
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
assert_redirected_to '/custom_fields?tab=IssueCustomField'
|
||||
assert_nil CustomField.find_by_id(1)
|
||||
assert_nil CustomValue.find_by_custom_field_id(1)
|
||||
end
|
||||
|
||||
def custom_field_classes
|
||||
files = Dir.glob(File.join(Rails.root, 'app/models/*_custom_field.rb')).map {|f| File.basename(f).sub(/\.rb$/, '') }
|
||||
classes = files.map(&:classify).map(&:constantize)
|
||||
assert classes.size > 0
|
||||
classes
|
||||
end
|
||||
end
|
||||
230
test/functional/documents_controller_test.rb
Normal file
230
test/functional/documents_controller_test.rb
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
# 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 DocumentsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:enabled_modules, :documents, :enumerations,
|
||||
:groups_users, :attachments
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
# Sets a default category
|
||||
e = Enumeration.find_by_name('Technical documentation')
|
||||
e.update_attributes(:is_default => true)
|
||||
|
||||
get :index, :params => {
|
||||
:project_id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# Default category selected in the new document form
|
||||
assert_select 'select[name=?]', 'document[category_id]' do
|
||||
assert_select 'option[selected=selected]', :text => 'Technical documentation'
|
||||
|
||||
assert ! DocumentCategory.find(16).active?
|
||||
assert_select 'option[value="16"]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_grouped_by_date
|
||||
get :index, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:sort_by => 'date'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h3', :text => '2007-02-12'
|
||||
end
|
||||
|
||||
def test_index_grouped_by_title
|
||||
get :index, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:sort_by => 'title'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h3', :text => 'T'
|
||||
end
|
||||
|
||||
def test_index_grouped_by_author
|
||||
get :index, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:sort_by => 'author'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h3', :text => 'John Smith'
|
||||
end
|
||||
|
||||
def test_index_with_long_description
|
||||
# adds a long description to the first document
|
||||
doc = documents(:documents_001)
|
||||
doc.update_attributes(:description => <<LOREM)
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut egestas, mi vehicula varius varius, ipsum massa fermentum orci, eget tristique ante sem vel mi. Nulla facilisi. Donec enim libero, luctus ac sagittis sit amet, vehicula sagittis magna. Duis ultrices molestie ante, eget scelerisque sem iaculis vitae. Etiam fermentum mauris vitae metus pharetra condimentum fermentum est pretium. Proin sollicitudin elementum quam quis pharetra. Aenean facilisis nunc quis elit volutpat mollis. Aenean eleifend varius euismod. Ut dolor est, congue eget dapibus eget, elementum eu odio. Integer et lectus neque, nec scelerisque nisi. EndOfLineHere
|
||||
|
||||
Vestibulum non velit mi. Aliquam scelerisque libero ut nulla fringilla a sollicitudin magna rhoncus. Praesent a nunc lorem, ac porttitor eros. Sed ac diam nec neque interdum adipiscing quis quis justo. Donec arcu nunc, fringilla eu dictum at, venenatis ac sem. Vestibulum quis elit urna, ac mattis sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
LOREM
|
||||
|
||||
get :index, :params => {
|
||||
:project_id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# should only truncate on new lines to avoid breaking wiki formatting
|
||||
assert_select '.wiki p', :text => (doc.description.split("\n").first + '...')
|
||||
assert_select '.wiki p', :text => Regexp.new(Regexp.escape("EndOfLineHere..."))
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_create_with_one_attachment
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@request.session[:user_id] = 2
|
||||
set_tmp_attachments_directory
|
||||
|
||||
with_settings :notified_events => %w(document_added) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:document => {
|
||||
:title => 'DocumentsControllerTest#test_post_new',
|
||||
:description => 'This is a new document',
|
||||
:category_id => 2
|
||||
},
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/documents'
|
||||
|
||||
document = Document.find_by_title('DocumentsControllerTest#test_post_new')
|
||||
assert_not_nil document
|
||||
assert_equal Enumeration.find(2), document.category
|
||||
assert_equal 1, document.attachments.size
|
||||
assert_equal 'testfile.txt', document.attachments.first.filename
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Document.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:document => {
|
||||
:title => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /title cannot be blank/i
|
||||
end
|
||||
|
||||
def test_create_non_default_category
|
||||
@request.session[:user_id] = 2
|
||||
category2 = Enumeration.find_by_name('User documentation')
|
||||
category2.update_attributes(:is_default => true)
|
||||
category1 = Enumeration.find_by_name('Uncategorized')
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:document => {
|
||||
:title => 'no default',
|
||||
:description => 'This is a new document',
|
||||
:category_id => category1.id
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/documents'
|
||||
doc = Document.find_by_title('no default')
|
||||
assert_not_nil doc
|
||||
assert_equal category1.id, doc.category_id
|
||||
assert_equal category1, doc.category
|
||||
end
|
||||
|
||||
def test_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:document => {
|
||||
:title => 'test_update'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/documents/1'
|
||||
document = Document.find(1)
|
||||
assert_equal 'test_update', document.title
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:document => {
|
||||
:title => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /title cannot be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Document.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/documents'
|
||||
assert_nil Document.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_add_attachment
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Attachment.count' do
|
||||
post :add_attachment, :params => {
|
||||
:id => 1,
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
}
|
||||
}
|
||||
end
|
||||
attachment = Attachment.order('id DESC').first
|
||||
assert_equal Document.find(1), attachment.container
|
||||
end
|
||||
end
|
||||
246
test/functional/email_addresses_controller_test.rb
Normal file
246
test/functional/email_addresses_controller_test.rb
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
# 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 EmailAddressesControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :email_addresses
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index_with_no_additional_emails
|
||||
@request.session[:user_id] = 2
|
||||
get :index, :params => {
|
||||
:user_id => 2
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_index_with_additional_emails
|
||||
@request.session[:user_id] = 2
|
||||
EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
get :index, :params => {
|
||||
:user_id => 2
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '.email', :text => 'another@somenet.foo'
|
||||
end
|
||||
|
||||
def test_index_with_additional_emails_as_js
|
||||
@request.session[:user_id] = 2
|
||||
EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
get :index, :params => {
|
||||
:user_id => 2
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_include 'another@somenet.foo', response.body
|
||||
end
|
||||
|
||||
def test_index_by_admin_should_be_allowed
|
||||
@request.session[:user_id] = 1
|
||||
get :index, :params => {
|
||||
:user_id => 2
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_index_by_another_user_should_be_denied
|
||||
@request.session[:user_id] = 3
|
||||
get :index, :params => {
|
||||
:user_id => 2
|
||||
}
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'EmailAddress.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 2,
|
||||
:email_address => {
|
||||
:address => 'another@somenet.foo'
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
assert_redirected_to '/users/2/email_addresses'
|
||||
end
|
||||
email = EmailAddress.order('id DESC').first
|
||||
assert_equal 2, email.user_id
|
||||
assert_equal 'another@somenet.foo', email.address
|
||||
end
|
||||
|
||||
def test_create_as_js
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'EmailAddress.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 2,
|
||||
:email_address => {
|
||||
:address => 'another@somenet.foo'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response 200
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'EmailAddress.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 2,
|
||||
:email_address => {
|
||||
:address => 'invalid'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /email is invalid/i
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_should_send_security_notification
|
||||
@request.session[:user_id] = 2
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :create, :params => {
|
||||
:user_id => 2,
|
||||
:email_address => {
|
||||
:address => 'something@example.fr'
|
||||
}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match '0.0.0.0', mail
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_mail), value: 'something@example.fr'), mail
|
||||
assert_select_email do
|
||||
assert_select 'a[href^=?]', 'http://localhost:3000/my/account', :text => 'My account'
|
||||
end
|
||||
# The old email address should be notified about a new address for security purposes
|
||||
assert [mail.bcc, mail.cc].flatten.include?(User.find(2).mail)
|
||||
assert [mail.bcc, mail.cc].flatten.include?('something@example.fr')
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 2
|
||||
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
put :update, :params => {
|
||||
:user_id => 2,
|
||||
:id => email.id,
|
||||
:notify => '0'
|
||||
}
|
||||
assert_response 302
|
||||
|
||||
assert_equal false, email.reload.notify
|
||||
end
|
||||
|
||||
def test_update_as_js
|
||||
@request.session[:user_id] = 2
|
||||
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
put :update, :params => {
|
||||
:user_id => 2,
|
||||
:id => email.id,
|
||||
:notify => '0'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response 200
|
||||
|
||||
assert_equal false, email.reload.notify
|
||||
end
|
||||
|
||||
def test_update_should_send_security_notification
|
||||
@request.session[:user_id] = 2
|
||||
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:user_id => 2,
|
||||
:id => email.id,
|
||||
:notify => '0'
|
||||
},
|
||||
:xhr => true
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_notify_disabled, value: 'another@somenet.foo'), mail
|
||||
|
||||
# The changed address should be notified for security purposes
|
||||
assert [mail.bcc, mail.cc].flatten.include?('another@somenet.foo')
|
||||
end
|
||||
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
assert_difference 'EmailAddress.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:user_id => 2,
|
||||
:id => email.id
|
||||
}
|
||||
assert_response 302
|
||||
assert_redirected_to '/users/2/email_addresses'
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_as_js
|
||||
@request.session[:user_id] = 2
|
||||
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
assert_difference 'EmailAddress.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:user_id => 2,
|
||||
:id => email.id
|
||||
},
|
||||
:xhr => true
|
||||
assert_response 200
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_not_destroy_default
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'EmailAddress.count' do
|
||||
delete :destroy, :params => {
|
||||
:user_id => 2,
|
||||
:id => User.find(2).email_address.id
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_should_send_security_notification
|
||||
@request.session[:user_id] = 2
|
||||
email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo')
|
||||
|
||||
ActionMailer::Base.deliveries.clear
|
||||
delete :destroy, :params => {
|
||||
:user_id => 2,
|
||||
:id => email.id
|
||||
},
|
||||
:xhr => true
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_mail), value: 'another@somenet.foo'), mail
|
||||
|
||||
# The removed address should be notified for security purposes
|
||||
assert [mail.bcc, mail.cc].flatten.include?('another@somenet.foo')
|
||||
end
|
||||
end
|
||||
186
test/functional/enumerations_controller_test.rb
Normal file
186
test/functional/enumerations_controller_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 EnumerationsControllerTest < Redmine::ControllerTest
|
||||
fixtures :enumerations, :issues, :users
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'table.enumerations'
|
||||
end
|
||||
|
||||
def test_index_should_require_admin
|
||||
@request.session[:user_id] = nil
|
||||
get :index
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new, :params => {
|
||||
:type => 'IssuePriority'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=?]', 'enumeration[type]', 'IssuePriority'
|
||||
assert_select 'input[name=?]', 'enumeration[name]'
|
||||
end
|
||||
|
||||
def test_new_with_invalid_type_should_respond_with_404
|
||||
get :new, :params => {
|
||||
:type => 'UnknownType'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'IssuePriority.count' do
|
||||
post :create, :params => {
|
||||
:enumeration => {
|
||||
:type => 'IssuePriority',
|
||||
:name => 'Lowest'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/enumerations'
|
||||
e = IssuePriority.find_by_name('Lowest')
|
||||
assert_not_nil e
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'IssuePriority.count' do
|
||||
post :create, :params => {
|
||||
:enumeration => {
|
||||
:type => 'IssuePriority',
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {
|
||||
:id => 6
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'enumeration[name]', 'High'
|
||||
end
|
||||
|
||||
def test_edit_invalid_should_respond_with_404
|
||||
get :edit, :params => {
|
||||
:id => 999
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
assert_no_difference 'IssuePriority.count' do
|
||||
put :update, :params => {
|
||||
:id => 6,
|
||||
:enumeration => {
|
||||
:type => 'IssuePriority',
|
||||
:name => 'New name'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/enumerations'
|
||||
e = IssuePriority.find(6)
|
||||
assert_equal 'New name', e.name
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
assert_no_difference 'IssuePriority.count' do
|
||||
put :update, :params => {
|
||||
:id => 6,
|
||||
:enumeration => {
|
||||
:type => 'IssuePriority',
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_update_position
|
||||
assert_equal 2, Enumeration.find(2).position
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:enumeration => {
|
||||
:position => 1,
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal 1, Enumeration.find(2).position
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_not_in_use
|
||||
assert_difference 'IssuePriority.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 7
|
||||
}
|
||||
end
|
||||
assert_redirected_to :controller => 'enumerations', :action => 'index'
|
||||
assert_nil Enumeration.find_by_id(7)
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_in_use
|
||||
assert_no_difference 'IssuePriority.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 4
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
|
||||
assert_not_nil Enumeration.find_by_id(4)
|
||||
assert_select 'select[name=reassign_to_id]' do
|
||||
assert_select 'option[value="6"]', :text => 'High'
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_in_use_with_reassignment
|
||||
issue = Issue.where(:priority_id => 4).first
|
||||
assert_difference 'IssuePriority.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 4,
|
||||
:reassign_to_id => 6
|
||||
}
|
||||
end
|
||||
assert_redirected_to :controller => 'enumerations', :action => 'index'
|
||||
assert_nil Enumeration.find_by_id(4)
|
||||
# check that the issue was reassign
|
||||
assert_equal 6, issue.reload.priority_id
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_in_use_with_blank_reassignment
|
||||
assert_no_difference 'IssuePriority.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 4,
|
||||
:reassign_to_id => ''
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
136
test/functional/files_controller_test.rb
Normal file
136
test/functional/files_controller_test.rb
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
# 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 FilesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users,
|
||||
:email_addresses,
|
||||
:issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:journals, :journal_details,
|
||||
:attachments,
|
||||
:versions
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = nil
|
||||
Setting.default_language = 'en'
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# file attached to the project
|
||||
assert_select 'a[href=?]', '/attachments/download/8/project_file.zip', :text => 'project_file.zip'
|
||||
|
||||
# file attached to a project's version
|
||||
assert_select 'a[href=?]', '/attachments/download/9/version_file.zip', :text => 'version_file.zip'
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'version_id'
|
||||
end
|
||||
|
||||
def test_new_without_versions
|
||||
Version.delete_all
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'version_id', 0
|
||||
end
|
||||
|
||||
def test_create_file
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
with_settings :notified_events => %w(file_added) do
|
||||
assert_difference 'Attachment.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:version_id => '',
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
}
|
||||
}
|
||||
assert_response :redirect
|
||||
end
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/files'
|
||||
a = Attachment.order('created_on DESC').first
|
||||
assert_equal 'testfile.txt', a.filename
|
||||
assert_equal Project.find(1), a.container
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
assert_equal "[eCookbook] New file", mail.subject
|
||||
assert_mail_body_match 'testfile.txt', mail
|
||||
end
|
||||
|
||||
def test_create_version_file
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_difference 'Attachment.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:version_id => '2',
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
}
|
||||
}
|
||||
assert_response :redirect
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/files'
|
||||
a = Attachment.order('created_on DESC').first
|
||||
assert_equal 'testfile.txt', a.filename
|
||||
assert_equal Version.find(2), a.container
|
||||
end
|
||||
|
||||
def test_create_without_file
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'Attachment.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:version_id => ''
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
assert_select 'div.error', 'File is invalid'
|
||||
end
|
||||
end
|
||||
140
test/functional/gantts_controller_test.rb
Normal file
140
test/functional/gantts_controller_test.rb
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
# 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 GanttsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:versions
|
||||
|
||||
def test_gantt_should_work
|
||||
i2 = Issue.find(2)
|
||||
i2.update_attribute(:due_date, 1.month.from_now)
|
||||
get :show, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# Issue with start and due dates
|
||||
i = Issue.find(1)
|
||||
assert_not_nil i.due_date
|
||||
assert_select "div a.issue", /##{i.id}/
|
||||
# Issue with on a targeted version should not be in the events but loaded in the html
|
||||
i = Issue.find(2)
|
||||
assert_select "div a.issue", /##{i.id}/
|
||||
end
|
||||
|
||||
def test_gantt_at_minimal_zoom
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:zoom => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[type=hidden][name=zoom][value=?]', '1'
|
||||
end
|
||||
|
||||
def test_gantt_at_maximal_zoom
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:zoom => 4
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[type=hidden][name=zoom][value=?]', '4'
|
||||
end
|
||||
|
||||
def test_gantt_should_work_without_issue_due_dates
|
||||
Issue.update_all("due_date = NULL")
|
||||
get :show, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_gantt_should_work_without_issue_and_version_due_dates
|
||||
Issue.update_all("due_date = NULL")
|
||||
Version.update_all("effective_date = NULL")
|
||||
get :show, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_gantt_should_work_cross_project
|
||||
get :show
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_gantt_should_not_disclose_private_projects
|
||||
get :show
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a', :text => /eCookbook/
|
||||
# Root private project
|
||||
assert_select 'a', :text => /OnlineStore/, :count => 0
|
||||
# Private children of a public project
|
||||
assert_select 'a', :text => /Private child of eCookbook/, :count => 0
|
||||
end
|
||||
|
||||
def test_gantt_should_display_relations
|
||||
IssueRelation.delete_all
|
||||
issue1 = Issue.generate!(:start_date => 1.day.from_now.to_date, :due_date => 3.day.from_now.to_date)
|
||||
issue2 = Issue.generate!(:start_date => 1.day.from_now.to_date, :due_date => 3.day.from_now.to_date)
|
||||
IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => 'precedes')
|
||||
|
||||
get :show
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div.task_todo[id=?][data-rels*=?]', "task-todo-issue-#{issue1.id}", issue2.id.to_s
|
||||
assert_select 'div.task_todo[id=?]:not([data-rels])', "task-todo-issue-#{issue2.id}"
|
||||
end
|
||||
|
||||
def test_gantt_should_export_to_pdf
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:format => 'pdf'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'application/pdf', @response.content_type
|
||||
assert @response.body.starts_with?('%PDF')
|
||||
end
|
||||
|
||||
def test_gantt_should_export_to_pdf_cross_project
|
||||
get :show, :params => {
|
||||
:format => 'pdf'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'application/pdf', @response.content_type
|
||||
assert @response.body.starts_with?('%PDF')
|
||||
end
|
||||
|
||||
if Object.const_defined?(:Magick)
|
||||
def test_gantt_should_export_to_png
|
||||
get :show, :params => {
|
||||
:project_id => 1,
|
||||
:format => 'png'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'image/png', @response.content_type
|
||||
end
|
||||
end
|
||||
end
|
||||
225
test/functional/groups_controller_test.rb
Normal file
225
test/functional/groups_controller_test.rb
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
# 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 GroupsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :groups_users
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'table.groups'
|
||||
end
|
||||
|
||||
def test_index_should_show_user_count
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'tr#group-11 td.user_count', :text => '1'
|
||||
end
|
||||
|
||||
def test_index_with_name_filter
|
||||
Group.generate!(:name => "Clients")
|
||||
|
||||
get :index, :params => {
|
||||
:name => "cli"
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.groups tbody tr', 1
|
||||
assert_select 'table.groups tbody td.name', :text => 'Clients'
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :params => {
|
||||
:id => 10
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_show_invalid_should_return_404
|
||||
get :show, :params => {
|
||||
:id => 99
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'group[name]'
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'Group.count' do
|
||||
post :create, :params => {
|
||||
:group => {
|
||||
:name => 'New group'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/groups'
|
||||
group = Group.order('id DESC').first
|
||||
assert_equal 'New group', group.name
|
||||
assert_equal [], group.users
|
||||
end
|
||||
|
||||
def test_create_and_continue
|
||||
assert_difference 'Group.count' do
|
||||
post :create, :params => {
|
||||
:group => {
|
||||
:name => 'New group'
|
||||
},
|
||||
:continue => 'Create and continue'
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/groups/new'
|
||||
group = Group.order('id DESC').first
|
||||
assert_equal 'New group', group.name
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'Group.count' do
|
||||
post :create, :params => {
|
||||
:group => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {
|
||||
:id => 10
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div#tab-content-users'
|
||||
assert_select 'div#tab-content-memberships' do
|
||||
assert_select 'a', :text => 'Private child of eCookbook'
|
||||
end
|
||||
end
|
||||
|
||||
def test_update
|
||||
new_name = 'New name'
|
||||
put :update, :params => {
|
||||
:id => 10,
|
||||
:group => {
|
||||
:name => new_name
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/groups'
|
||||
group = Group.find(10)
|
||||
assert_equal new_name, group.name
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :params => {
|
||||
:id => 10,
|
||||
:group => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'Group.count', -1 do
|
||||
post :destroy, :params => {
|
||||
:id => 10
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/groups'
|
||||
end
|
||||
|
||||
def test_new_users
|
||||
get :new_users, :params => {
|
||||
:id => 10
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'user_search'
|
||||
end
|
||||
|
||||
def test_xhr_new_users
|
||||
get :new_users, :params => {
|
||||
:id => 10
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_add_users
|
||||
assert_difference 'Group.find(10).users.count', 2 do
|
||||
post :add_users, :params => {
|
||||
:id => 10,
|
||||
:user_ids => ['2', '3']
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_add_users
|
||||
assert_difference 'Group.find(10).users.count', 2 do
|
||||
post :add_users, :params => {
|
||||
:id => 10,
|
||||
:user_ids => ['2', '3']
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /John Smith/, response.body
|
||||
end
|
||||
|
||||
def test_remove_user
|
||||
assert_difference 'Group.find(10).users.count', -1 do
|
||||
delete :remove_user, :params => {
|
||||
:id => 10,
|
||||
:user_id => '8'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_remove_user
|
||||
assert_difference 'Group.find(10).users.count', -1 do
|
||||
delete :remove_user, :params => {
|
||||
:id => 10,
|
||||
:user_id => '8'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
end
|
||||
|
||||
def test_autocomplete_for_user
|
||||
get :autocomplete_for_user, :params => {
|
||||
:id => 10,
|
||||
:q => 'smi',
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_include 'John Smith', response.body
|
||||
end
|
||||
end
|
||||
266
test/functional/imports_controller_test.rb
Normal file
266
test/functional/imports_controller_test.rb
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
# 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 ImportsControllerTest < Redmine::ControllerTest
|
||||
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
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def teardown
|
||||
Import.destroy_all
|
||||
end
|
||||
|
||||
def test_new_should_display_the_upload_form
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'file'
|
||||
end
|
||||
|
||||
def test_create_should_save_the_file
|
||||
import = new_record(Import) do
|
||||
post :create, :params => {
|
||||
:file => uploaded_test_file('import_issues.csv', 'text/csv')
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_equal 2, import.user_id
|
||||
assert_match /\A[0-9a-f]+\z/, import.filename
|
||||
assert import.file_exists?
|
||||
end
|
||||
|
||||
def test_get_settings_should_display_settings_form
|
||||
import = generate_import
|
||||
get :settings, :params => {
|
||||
:id => import.to_param
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'import_settings[separator]'
|
||||
assert_select 'select[name=?]', 'import_settings[wrapper]'
|
||||
assert_select 'select[name=?]', 'import_settings[encoding]'
|
||||
assert_select 'select[name=?]', 'import_settings[date_format]'
|
||||
end
|
||||
|
||||
def test_post_settings_should_update_settings
|
||||
import = generate_import
|
||||
|
||||
post :settings, :params => {
|
||||
:id => import.to_param,
|
||||
:import_settings => {
|
||||
:separator => ":",
|
||||
:wrapper => "|",
|
||||
:encoding => "UTF-8",
|
||||
:date_format => '%m/%d/%Y'
|
||||
}
|
||||
}
|
||||
assert_redirected_to "/imports/#{import.to_param}/mapping"
|
||||
|
||||
import.reload
|
||||
assert_equal ":", import.settings['separator']
|
||||
assert_equal "|", import.settings['wrapper']
|
||||
assert_equal "UTF-8", import.settings['encoding']
|
||||
assert_equal '%m/%d/%Y', import.settings['date_format']
|
||||
end
|
||||
|
||||
def test_post_settings_should_update_total_items_count
|
||||
import = generate_import('import_iso8859-1.csv')
|
||||
|
||||
post :settings, :params => {
|
||||
:id => import.to_param,
|
||||
:import_settings => {
|
||||
:separator => ";",
|
||||
:wrapper => '"',
|
||||
:encoding => "ISO-8859-1"
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
import.reload
|
||||
assert_equal 2, import.total_items
|
||||
end
|
||||
|
||||
def test_post_settings_with_wrong_encoding_should_display_error
|
||||
import = generate_import('import_iso8859-1.csv')
|
||||
|
||||
post :settings, :params => {
|
||||
:id => import.to_param,
|
||||
:import_settings => {
|
||||
:separator => ";",
|
||||
:wrapper => '"',
|
||||
:encoding => "UTF-8"
|
||||
}
|
||||
}
|
||||
assert_response 200
|
||||
import.reload
|
||||
assert_nil import.total_items
|
||||
assert_select 'div#flash_error', /not a valid UTF-8 encoded file/
|
||||
end
|
||||
|
||||
def test_post_settings_with_invalid_encoding_should_display_error
|
||||
import = generate_import('invalid-Shift_JIS.csv')
|
||||
|
||||
post :settings, :params => {
|
||||
:id => import.to_param,
|
||||
:import_settings => {
|
||||
:separator => ";",
|
||||
:wrapper => '"',
|
||||
:encoding => "Shift_JIS"
|
||||
}
|
||||
}
|
||||
assert_response 200
|
||||
import.reload
|
||||
assert_nil import.total_items
|
||||
assert_select 'div#flash_error', /not a valid Shift_JIS encoded file/
|
||||
end
|
||||
|
||||
def test_get_mapping_should_display_mapping_form
|
||||
import = generate_import('import_iso8859-1.csv')
|
||||
import.settings = {'separator' => ";", 'wrapper' => '"', 'encoding' => "ISO-8859-1"}
|
||||
import.save!
|
||||
|
||||
get :mapping, :params => {
|
||||
:id => import.to_param
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'import_settings[mapping][subject]' do
|
||||
assert_select 'option', 4
|
||||
assert_select 'option[value="0"]', :text => 'column A'
|
||||
end
|
||||
|
||||
assert_select 'table.sample-data' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'td', 9
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_mapping_should_update_mapping
|
||||
import = generate_import('import_iso8859-1.csv')
|
||||
|
||||
post :mapping, :params => {
|
||||
:id => import.to_param,
|
||||
:import_settings => {
|
||||
:mapping => {
|
||||
:project_id => '1',
|
||||
:tracker_id => '2',
|
||||
:subject => '0'}
|
||||
}
|
||||
}
|
||||
assert_redirected_to "/imports/#{import.to_param}/run"
|
||||
import.reload
|
||||
mapping = import.settings['mapping']
|
||||
assert mapping
|
||||
assert_equal '1', mapping['project_id']
|
||||
assert_equal '2', mapping['tracker_id']
|
||||
assert_equal '0', mapping['subject']
|
||||
end
|
||||
|
||||
def test_get_run
|
||||
import = generate_import_with_mapping
|
||||
|
||||
get :run, :params => {
|
||||
:id => import
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '#import-progress'
|
||||
end
|
||||
|
||||
def test_post_run_should_import_the_file
|
||||
import = generate_import_with_mapping
|
||||
|
||||
assert_difference 'Issue.count', 3 do
|
||||
post :run, :params => {
|
||||
:id => import
|
||||
}
|
||||
assert_redirected_to "/imports/#{import.to_param}"
|
||||
end
|
||||
|
||||
import.reload
|
||||
assert_equal true, import.finished
|
||||
assert_equal 3, import.items.count
|
||||
|
||||
issues = Issue.order(:id => :desc).limit(3).to_a
|
||||
assert_equal ["Child of existing issue", "Child 1", "First"], issues.map(&:subject)
|
||||
end
|
||||
|
||||
def test_post_run_should_import_max_items_and_resume
|
||||
ImportsController.any_instance.stubs(:max_items_per_request).returns(2)
|
||||
import = generate_import_with_mapping
|
||||
|
||||
assert_difference 'Issue.count', 2 do
|
||||
post :run, :params => {
|
||||
:id => import
|
||||
}
|
||||
assert_redirected_to "/imports/#{import.to_param}/run"
|
||||
end
|
||||
|
||||
assert_difference 'Issue.count', 1 do
|
||||
post :run, :params => {
|
||||
:id => import
|
||||
}
|
||||
assert_redirected_to "/imports/#{import.to_param}"
|
||||
end
|
||||
|
||||
issues = Issue.order(:id => :desc).limit(3).to_a
|
||||
assert_equal ["Child of existing issue", "Child 1", "First"], issues.map(&:subject)
|
||||
end
|
||||
|
||||
def test_show_without_errors
|
||||
import = generate_import_with_mapping
|
||||
import.run
|
||||
assert_equal 0, import.unsaved_items.count
|
||||
|
||||
get :show, :params => {
|
||||
:id => import.to_param
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'ul#saved-items'
|
||||
assert_select 'ul#saved-items li', import.saved_items.count
|
||||
assert_select 'table#unsaved-items', 0
|
||||
end
|
||||
|
||||
def test_show_with_errors_should_show_unsaved_items
|
||||
import = generate_import_with_mapping
|
||||
import.mapping.merge! 'subject' => 20
|
||||
import.run
|
||||
assert_not_equal 0, import.unsaved_items.count
|
||||
|
||||
get :show, :params => {
|
||||
:id => import.to_param
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table#unsaved-items'
|
||||
assert_select 'table#unsaved-items tbody tr', import.unsaved_items.count
|
||||
end
|
||||
end
|
||||
196
test/functional/issue_categories_controller_test.rb
Normal file
196
test/functional/issue_categories_controller_test.rb
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
# 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 IssueCategoriesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules, :issue_categories,
|
||||
:issues
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2 # manager
|
||||
get :new, :params => {
|
||||
:project_id => '1'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'issue_category[name]'
|
||||
end
|
||||
|
||||
def test_new_from_issue_form
|
||||
@request.session[:user_id] = 2 # manager
|
||||
get :new, :params => {
|
||||
:project_id => '1'
|
||||
},
|
||||
:xhr => true
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2 # manager
|
||||
assert_difference 'IssueCategory.count' do
|
||||
post :create, :params => {
|
||||
:project_id => '1',
|
||||
:issue_category => {
|
||||
:name => 'New category'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/categories'
|
||||
category = IssueCategory.find_by_name('New category')
|
||||
assert_not_nil category
|
||||
assert_equal 1, category.project_id
|
||||
end
|
||||
|
||||
def test_create_failure
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :params => {
|
||||
:project_id => '1',
|
||||
:issue_category => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_create_from_issue_form
|
||||
@request.session[:user_id] = 2 # manager
|
||||
assert_difference 'IssueCategory.count' do
|
||||
post :create, :params => {
|
||||
:project_id => '1',
|
||||
:issue_category => {
|
||||
:name => 'New category'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
end
|
||||
category = IssueCategory.order('id DESC').first
|
||||
assert_equal 'New category', category.name
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create_from_issue_form_with_failure
|
||||
@request.session[:user_id] = 2 # manager
|
||||
assert_no_difference 'IssueCategory.count' do
|
||||
post :create, :params => {
|
||||
:project_id => '1',
|
||||
:issue_category => {
|
||||
:name => ''
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include 'Name cannot be blank', response.body
|
||||
end
|
||||
|
||||
def test_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:id => 2
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'issue_category[name]', 'Recipes'
|
||||
end
|
||||
|
||||
def test_update
|
||||
assert_no_difference 'IssueCategory.count' do
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:issue_category => {
|
||||
:name => 'Testing'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/categories'
|
||||
assert_equal 'Testing', IssueCategory.find(2).name
|
||||
end
|
||||
|
||||
def test_update_failure
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:issue_category => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_update_not_found
|
||||
put :update, :params => {
|
||||
:id => 97,
|
||||
:issue_category => {
|
||||
:name => 'Testing'
|
||||
}
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_destroy_category_not_in_use
|
||||
delete :destroy, :params => {
|
||||
:id => 2
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/settings/categories'
|
||||
assert_nil IssueCategory.find_by_id(2)
|
||||
end
|
||||
|
||||
def test_destroy_category_in_use
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_not_nil IssueCategory.find_by_id(1)
|
||||
assert_select 'select[name=?]', 'reassign_to_id'
|
||||
end
|
||||
|
||||
def test_destroy_category_in_use_with_reassignment
|
||||
issue = Issue.where(:category_id => 1).first
|
||||
delete :destroy, :params => {
|
||||
:id => 1,
|
||||
:todo => 'reassign',
|
||||
:reassign_to_id => 2
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/settings/categories'
|
||||
assert_nil IssueCategory.find_by_id(1)
|
||||
# check that the issue was reassign
|
||||
assert_equal 2, issue.reload.category_id
|
||||
end
|
||||
|
||||
def test_destroy_category_in_use_without_reassignment
|
||||
issue = Issue.where(:category_id => 1).first
|
||||
delete :destroy, :params => {
|
||||
:id => 1,
|
||||
:todo => 'nullify'
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/settings/categories'
|
||||
assert_nil IssueCategory.find_by_id(1)
|
||||
# check that the issue category was nullified
|
||||
assert_nil issue.reload.category_id
|
||||
end
|
||||
end
|
||||
222
test/functional/issue_relations_controller_test.rb
Normal file
222
test/functional/issue_relations_controller_test.rb
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
# 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 IssueRelationsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issues,
|
||||
:issue_statuses,
|
||||
:issue_relations,
|
||||
:enabled_modules,
|
||||
:enumerations,
|
||||
:trackers,
|
||||
:projects_trackers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 3
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 1,
|
||||
:relation => {
|
||||
:issue_to_id => '2',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
relation = IssueRelation.order('id DESC').first
|
||||
assert_equal 1, relation.issue_from_id
|
||||
assert_equal 2, relation.issue_to_id
|
||||
assert_equal 'relates', relation.relation_type
|
||||
end
|
||||
|
||||
def test_create_on_invalid_issue
|
||||
assert_no_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 999,
|
||||
:relation => {
|
||||
:issue_to_id => '2',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_xhr
|
||||
assert_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 3,
|
||||
:relation => {
|
||||
:issue_to_id => '1',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
relation = IssueRelation.order('id DESC').first
|
||||
assert_equal 1, relation.issue_from_id
|
||||
assert_equal 3, relation.issue_to_id
|
||||
|
||||
assert_include 'Bug #1', response.body
|
||||
end
|
||||
|
||||
def test_create_should_accept_id_with_hash
|
||||
assert_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 1,
|
||||
:relation => {
|
||||
:issue_to_id => '#2',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
relation = IssueRelation.order('id DESC').first
|
||||
assert_equal 2, relation.issue_to_id
|
||||
end
|
||||
|
||||
def test_create_should_strip_id
|
||||
assert_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 1,
|
||||
:relation => {
|
||||
:issue_to_id => ' 2 ',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
relation = IssueRelation.order('id DESC').first
|
||||
assert_equal 2, relation.issue_to_id
|
||||
end
|
||||
|
||||
def test_create_should_not_break_with_non_numerical_id
|
||||
assert_no_difference 'IssueRelation.count' do
|
||||
assert_nothing_raised do
|
||||
post :create, :params => {
|
||||
:issue_id => 1,
|
||||
:relation => {
|
||||
:issue_to_id => 'foo',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_follows_relation_should_update_relations_list
|
||||
issue1 = Issue.generate!(:subject => 'Followed issue', :start_date => Date.yesterday, :due_date => Date.today)
|
||||
issue2 = Issue.generate!
|
||||
|
||||
assert_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => issue2.id,
|
||||
:relation => {
|
||||
:issue_to_id => issue1.id,
|
||||
:relation_type => 'follows',
|
||||
:delay => ''
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
end
|
||||
assert_include 'Followed issue', response.body
|
||||
end
|
||||
|
||||
def test_should_create_relations_with_visible_issues_only
|
||||
Setting.cross_project_issue_relations = '1'
|
||||
assert_nil Issue.visible(User.find(3)).find_by_id(4)
|
||||
|
||||
assert_no_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 1,
|
||||
:relation => {
|
||||
:issue_to_id => '4',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_xhr_with_failure
|
||||
assert_no_difference 'IssueRelation.count' do
|
||||
post :create, :params => {
|
||||
:issue_id => 3,
|
||||
:relation => {
|
||||
:issue_to_id => '999',
|
||||
:relation_type => 'relates',
|
||||
:delay => ''
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_include 'Related issue cannot be blank', response.body
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'IssueRelation.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => '2'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_invalid_relation
|
||||
assert_no_difference 'IssueRelation.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => '999'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_xhr
|
||||
IssueRelation.create!(:relation_type => IssueRelation::TYPE_RELATES) do |r|
|
||||
r.issue_from_id = 3
|
||||
r.issue_to_id = 1
|
||||
end
|
||||
|
||||
assert_difference 'IssueRelation.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => '2'
|
||||
},
|
||||
:xhr => true
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include 'relation-2', response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
160
test/functional/issue_statuses_controller_test.rb
Normal file
160
test/functional/issue_statuses_controller_test.rb
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# 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 IssueStatusesControllerTest < Redmine::ControllerTest
|
||||
fixtures :issue_statuses, :issues, :users, :trackers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'table.issue_statuses'
|
||||
end
|
||||
|
||||
def test_index_by_anonymous_should_redirect_to_login_form
|
||||
@request.session[:user_id] = nil
|
||||
get :index
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fissue_statuses'
|
||||
end
|
||||
|
||||
def test_index_by_user_should_respond_with_406
|
||||
@request.session[:user_id] = 2
|
||||
get :index
|
||||
assert_response 406
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'issue_status[name]'
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'IssueStatus.count' do
|
||||
post :create, :params => {
|
||||
:issue_status => {
|
||||
:name => 'New status'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
status = IssueStatus.order('id DESC').first
|
||||
assert_equal 'New status', status.name
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
post :create, :params => {
|
||||
:issue_status => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {
|
||||
:id => '3'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'issue_status[name]', 'Resolved'
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :params => {
|
||||
:id => '3',
|
||||
:issue_status => {
|
||||
:name => 'Renamed status'
|
||||
}
|
||||
}
|
||||
assert_redirected_to :action => 'index'
|
||||
status = IssueStatus.find(3)
|
||||
assert_equal 'Renamed status', status.name
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :params => {
|
||||
:id => '3',
|
||||
:issue_status => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
Issue.where(:status_id => 1).delete_all
|
||||
Tracker.where(:default_status_id => 1).delete_all
|
||||
|
||||
assert_difference 'IssueStatus.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => '1'
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_nil IssueStatus.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_destroy_should_block_if_status_is_used_by_issues
|
||||
assert Issue.where(:status_id => 1).any?
|
||||
Tracker.where(:default_status_id => 1).delete_all
|
||||
|
||||
assert_no_difference 'IssueStatus.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => '1'
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_not_nil IssueStatus.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_destroy_should_block_if_status_is_used_as_tracker_default_status
|
||||
Issue.where(:status_id => 1).delete_all
|
||||
assert Tracker.where(:default_status_id => 1).any?
|
||||
|
||||
assert_no_difference 'IssueStatus.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => '1'
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_not_nil IssueStatus.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_update_issue_done_ratio_with_issue_done_ratio_set_to_issue_field
|
||||
with_settings :issue_done_ratio => 'issue_field' do
|
||||
post :update_issue_done_ratio
|
||||
assert_match /not updated/, flash[:error].to_s
|
||||
assert_redirected_to '/issue_statuses'
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_issue_done_ratio_with_issue_done_ratio_set_to_issue_status
|
||||
with_settings :issue_done_ratio => 'issue_status' do
|
||||
post :update_issue_done_ratio
|
||||
assert_match /Issue done ratios updated/, flash[:notice].to_s
|
||||
assert_redirected_to '/issue_statuses'
|
||||
end
|
||||
end
|
||||
end
|
||||
6480
test/functional/issues_controller_test.rb
Normal file
6480
test/functional/issues_controller_test.rb
Normal file
File diff suppressed because it is too large
Load diff
339
test/functional/issues_controller_transaction_test.rb
Normal file
339
test/functional/issues_controller_transaction_test.rb
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
# 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 'issues_controller'
|
||||
|
||||
class IssuesControllerTransactionTest < Redmine::ControllerTest
|
||||
tests IssuesController
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issues,
|
||||
:issue_statuses,
|
||||
:versions,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:issue_categories,
|
||||
:enabled_modules,
|
||||
:enumerations,
|
||||
:attachments,
|
||||
:workflows,
|
||||
:custom_fields,
|
||||
:custom_values,
|
||||
:custom_fields_projects,
|
||||
:custom_fields_trackers,
|
||||
:time_entries,
|
||||
:journals,
|
||||
:journal_details,
|
||||
:queries
|
||||
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_update_stale_issue_should_not_update_the_issue
|
||||
issue = Issue.find(2)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'Journal.count' do
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
put :update, :params => {
|
||||
:id => issue.id,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => 'My notes',
|
||||
:lock_version => (issue.lock_version - 1)
|
||||
|
||||
},
|
||||
:time_entry => {
|
||||
:hours => '2.5',
|
||||
:comments => '',
|
||||
:activity_id => TimeEntryActivity.first.id
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div.conflict'
|
||||
assert_select 'input[name=?][value=?]', 'conflict_resolution', 'overwrite'
|
||||
assert_select 'input[name=?][value=?]', 'conflict_resolution', 'add_notes'
|
||||
assert_select 'label' do
|
||||
assert_select 'input[name=?][value=?]', 'conflict_resolution', 'cancel'
|
||||
assert_select 'a[href="/issues/2"]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_stale_issue_should_save_attachments
|
||||
set_tmp_attachments_directory
|
||||
issue = Issue.find(2)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'Journal.count' do
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
assert_difference 'Attachment.count' do
|
||||
put :update, :params => {
|
||||
:id => issue.id,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => 'My notes',
|
||||
:lock_version => (issue.lock_version - 1)
|
||||
|
||||
},
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
},
|
||||
:time_entry => {
|
||||
:hours => '2.5',
|
||||
:comments => '',
|
||||
:activity_id => TimeEntryActivity.first.id
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
|
||||
attachment = Attachment.order('id DESC').first
|
||||
assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
|
||||
assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
|
||||
end
|
||||
|
||||
def test_update_stale_issue_without_notes_should_not_show_add_notes_option
|
||||
issue = Issue.find(2)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
put :update, :params => {
|
||||
:id => issue.id,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => '',
|
||||
:lock_version => (issue.lock_version - 1)
|
||||
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div.conflict'
|
||||
assert_select 'input[name=conflict_resolution][value=overwrite]'
|
||||
assert_select 'input[name=conflict_resolution][value=add_notes]', 0
|
||||
assert_select 'input[name=conflict_resolution][value=cancel]'
|
||||
end
|
||||
|
||||
def test_update_stale_issue_should_show_conflicting_journals
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => '',
|
||||
:lock_version => 2
|
||||
|
||||
},
|
||||
:last_journal_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select '.conflict-journal', 1
|
||||
assert_select 'div.conflict', :text => /Some notes with Redmine links/
|
||||
end
|
||||
|
||||
def test_update_stale_issue_without_previous_journal_should_show_all_journals
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => '',
|
||||
:lock_version => 2
|
||||
|
||||
},
|
||||
:last_journal_id => ''
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select '.conflict-journal', 2
|
||||
assert_select 'div.conflict', :text => /Some notes with Redmine links/
|
||||
assert_select 'div.conflict', :text => /Journal notes/
|
||||
end
|
||||
|
||||
def test_update_stale_issue_should_show_private_journals_with_permission_only
|
||||
journal = Journal.create!(:journalized => Issue.find(1), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:lock_version => 2
|
||||
},
|
||||
:last_journal_id => ''
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '.conflict-journal', :text => /Privates notes/
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:lock_version => 2
|
||||
},
|
||||
:last_journal_id => ''
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '.conflict-journal', :text => /Privates notes/, :count => 0
|
||||
end
|
||||
|
||||
def test_update_stale_issue_with_overwrite_conflict_resolution_should_update
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_difference 'Journal.count' do
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => 'overwrite_conflict_resolution',
|
||||
:lock_version => 2
|
||||
|
||||
},
|
||||
:conflict_resolution => 'overwrite'
|
||||
}
|
||||
end
|
||||
|
||||
assert_response 302
|
||||
issue = Issue.find(1)
|
||||
assert_equal 4, issue.fixed_version_id
|
||||
journal = Journal.order('id DESC').first
|
||||
assert_equal 'overwrite_conflict_resolution', journal.notes
|
||||
assert journal.details.any?
|
||||
end
|
||||
|
||||
def test_update_stale_issue_with_add_notes_conflict_resolution_should_update
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_difference 'Journal.count' do
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => 'add_notes_conflict_resolution',
|
||||
:lock_version => 2
|
||||
|
||||
},
|
||||
:conflict_resolution => 'add_notes'
|
||||
}
|
||||
end
|
||||
|
||||
assert_response 302
|
||||
issue = Issue.find(1)
|
||||
assert_nil issue.fixed_version_id
|
||||
journal = Journal.order('id DESC').first
|
||||
assert_equal 'add_notes_conflict_resolution', journal.notes
|
||||
assert_equal false, journal.private_notes
|
||||
assert journal.details.empty?
|
||||
end
|
||||
|
||||
def test_update_stale_issue_with_add_notes_conflict_resolution_should_preserve_private_notes
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
journal = new_record(Journal) do
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => 'add_privates_notes_conflict_resolution',
|
||||
:private_notes => '1',
|
||||
:lock_version => 2
|
||||
|
||||
},
|
||||
:conflict_resolution => 'add_notes'
|
||||
}
|
||||
end
|
||||
|
||||
assert_response 302
|
||||
assert_equal 'add_privates_notes_conflict_resolution', journal.notes
|
||||
assert_equal true, journal.private_notes
|
||||
assert journal.details.empty?
|
||||
end
|
||||
|
||||
def test_update_stale_issue_with_cancel_conflict_resolution_should_redirect_without_updating
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'Journal.count' do
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => 'add_notes_conflict_resolution',
|
||||
:lock_version => 2
|
||||
|
||||
},
|
||||
:conflict_resolution => 'cancel'
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to '/issues/1'
|
||||
issue = Issue.find(1)
|
||||
assert_nil issue.fixed_version_id
|
||||
end
|
||||
|
||||
def test_put_update_with_spent_time_and_failure_should_not_add_spent_time
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference('TimeEntry.count') do
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:subject => ''
|
||||
},
|
||||
:time_entry => {
|
||||
:hours => '2.5',
|
||||
:comments => 'should not be added',
|
||||
:activity_id => TimeEntryActivity.first.id
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2.50'
|
||||
assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'should not be added'
|
||||
assert_select 'select[name=?]', 'time_entry[activity_id]' do
|
||||
assert_select 'option[value=?][selected=selected]', TimeEntryActivity.first.id.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_should_rescue_invalid_sql_query
|
||||
IssueQuery.any_instance.stubs(:statement).returns("INVALID STATEMENT")
|
||||
|
||||
get :index
|
||||
assert_response 500
|
||||
assert_select 'p', :text => /An error occurred/
|
||||
assert_nil session[:query]
|
||||
assert_nil session[:issues_index_sort]
|
||||
end
|
||||
end
|
||||
368
test/functional/issues_custom_fields_visibility_test.rb
Normal file
368
test/functional/issues_custom_fields_visibility_test.rb
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
# 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 IssuesCustomFieldsVisibilityTest < Redmine::ControllerTest
|
||||
tests IssuesController
|
||||
fixtures :projects,
|
||||
:users, :email_addresses, :user_preferences,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issue_statuses,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:enabled_modules,
|
||||
:enumerations,
|
||||
:workflows
|
||||
|
||||
def setup
|
||||
CustomField.delete_all
|
||||
Issue.delete_all
|
||||
field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all}
|
||||
@fields = []
|
||||
@fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
|
||||
@fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
|
||||
@fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
|
||||
@issue = Issue.generate!(
|
||||
:author_id => 1,
|
||||
:project_id => 1,
|
||||
:tracker_id => 1,
|
||||
:custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
|
||||
)
|
||||
|
||||
@user_with_role_on_other_project = User.generate!
|
||||
User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
|
||||
|
||||
@users_to_test = {
|
||||
User.find(1) => [@field1, @field2, @field3],
|
||||
User.find(3) => [@field1, @field2],
|
||||
@user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
|
||||
User.generate! => [@field1],
|
||||
User.anonymous => [@field1]
|
||||
}
|
||||
|
||||
Member.where(:project_id => 1).each do |member|
|
||||
member.destroy unless @users_to_test.keys.include?(member.principal)
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_should_show_visible_custom_fields_only
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :show, :params => {
|
||||
:id => @issue.id
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select '.value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
|
||||
else
|
||||
assert_select '.value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_should_show_visible_custom_fields_only_in_api
|
||||
@users_to_test.each do |user, fields|
|
||||
with_settings :rest_api_enabled => '1' do
|
||||
get :show, :params => {
|
||||
:id => @issue.id,
|
||||
:format => 'xml',
|
||||
:include => 'custom_fields',
|
||||
:key => user.api_key
|
||||
}
|
||||
end
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select "custom_field[id=?] value", field.id.to_s, {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} in API"
|
||||
else
|
||||
assert_select "custom_field[id=?] value", field.id.to_s, {:text => "Value#{i}", :count => 0}, "User #{user.id} was not able to view #{field.name} in API"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_should_show_visible_custom_fields_only_in_history
|
||||
@issue.init_journal(User.find(1))
|
||||
@issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
|
||||
@issue.save!
|
||||
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :show, :params => {
|
||||
:id => @issue.id
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
|
||||
else
|
||||
assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_should_show_visible_custom_fields_only_in_history_api
|
||||
@issue.init_journal(User.find(1))
|
||||
@issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
|
||||
@issue.save!
|
||||
|
||||
@users_to_test.each do |user, fields|
|
||||
with_settings :rest_api_enabled => '1' do
|
||||
get :show, :params => {
|
||||
:id => @issue.id,
|
||||
:format => 'xml',
|
||||
:include => 'journals',
|
||||
:key => user.api_key
|
||||
}
|
||||
end
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select 'details old_value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change in API"
|
||||
else
|
||||
assert_select 'details old_value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change in API"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_edit_should_show_visible_custom_fields_only
|
||||
Role.anonymous.add_permission! :edit_issues
|
||||
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :edit, :params => {
|
||||
:id => @issue.id
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select 'input[value=?]', "Value#{i}", 1, "User #{user.id} was not able to edit #{field.name}"
|
||||
else
|
||||
assert_select 'input[value=?]', "Value#{i}", 0, "User #{user.id} was able to edit #{field.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_should_update_visible_custom_fields_only
|
||||
Role.anonymous.add_permission! :edit_issues
|
||||
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
put :update, :params => {
|
||||
:id => @issue.id,
|
||||
:issue => {
|
||||
:custom_field_values => {
|
||||
@field1.id.to_s => "User#{user.id}Value0",
|
||||
@field2.id.to_s => "User#{user.id}Value1",
|
||||
@field3.id.to_s => "User#{user.id}Value2",
|
||||
}
|
||||
}
|
||||
}
|
||||
@issue.reload
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was not able to update #{field.name}"
|
||||
else
|
||||
assert_not_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was able to update #{field.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_should_show_visible_custom_fields_only
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :index, :params => {
|
||||
:c => (["subject"] + @fields.map{|f| "cf_#{f.id}"})
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
|
||||
else
|
||||
assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_as_csv_should_show_visible_custom_fields_only
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :index, :params => {
|
||||
:c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}),
|
||||
:format => 'csv'
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV"
|
||||
else
|
||||
assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_with_partial_custom_field_visibility
|
||||
Issue.delete_all
|
||||
p1 = Project.generate!
|
||||
p2 = Project.generate!
|
||||
user = User.generate!
|
||||
User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a)
|
||||
User.add_to_project(user, p2, Role.where(:id => 3).to_a)
|
||||
Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'})
|
||||
Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'})
|
||||
Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'})
|
||||
|
||||
@request.session[:user_id] = user.id
|
||||
get :index, :params => {
|
||||
:c => ["subject", "cf_#{@field2.id}"]
|
||||
}
|
||||
assert_select 'td', :text => 'ValueA'
|
||||
assert_select 'td', :text => 'ValueB', :count => 0
|
||||
assert_select 'td', :text => 'ValueC'
|
||||
|
||||
get :index, :params => {
|
||||
:sort => "cf_#{@field2.id}"
|
||||
}
|
||||
# ValueB is not visible to user and ignored while sorting
|
||||
assert_equal %w(ValueB ValueA ValueC), issues_in_list.map{|i| i.custom_field_value(@field2)}
|
||||
|
||||
get :index, :params => {
|
||||
:set_filter => '1', "cf_#{@field2.id}" => '*',
|
||||
:sort => "cf_#{@field2.id}"
|
||||
}
|
||||
assert_equal %w(ValueA ValueC), issues_in_list.map{|i| i.custom_field_value(@field2)}
|
||||
|
||||
CustomField.update_all(:field_format => 'list')
|
||||
get :index, :params => {
|
||||
:group => "cf_#{@field2.id}"
|
||||
}
|
||||
assert_equal %w(ValueA ValueC), issues_in_list.map{|i| i.custom_field_value(@field2)}
|
||||
end
|
||||
|
||||
def test_create_should_send_notifications_according_custom_fields_visibility
|
||||
# anonymous user is never notified
|
||||
users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
|
||||
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@request.session[:user_id] = 1
|
||||
with_settings :bcc_recipients => '1' do
|
||||
assert_difference 'Issue.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:issue => {
|
||||
:tracker_id => 1,
|
||||
:status_id => 1,
|
||||
:subject => 'New issue',
|
||||
:priority_id => 5,
|
||||
:custom_field_values => {
|
||||
@field1.id.to_s => 'Value0', @field2.id.to_s => 'Value1', @field3.id.to_s => 'Value2'
|
||||
},
|
||||
:watcher_user_ids => users_to_test.keys.map(&:id)
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
end
|
||||
assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size
|
||||
# tests that each user receives 1 email with the custom fields he is allowed to see only
|
||||
users_to_test.each do |user, fields|
|
||||
mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
|
||||
assert_equal 1, mails.size
|
||||
mail = mails.first
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification"
|
||||
else
|
||||
assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_should_send_notifications_according_custom_fields_visibility
|
||||
# anonymous user is never notified
|
||||
users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
|
||||
|
||||
users_to_test.keys.each do |user|
|
||||
Watcher.create!(:user => user, :watchable => @issue)
|
||||
end
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@request.session[:user_id] = 1
|
||||
with_settings :bcc_recipients => '1' do
|
||||
put :update, :params => {
|
||||
:id => @issue.id,
|
||||
:issue => {
|
||||
:custom_field_values => {
|
||||
@field1.id.to_s => 'NewValue0', @field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size
|
||||
# tests that each user receives 1 email with the custom fields he is allowed to see only
|
||||
users_to_test.each do |user, fields|
|
||||
mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
|
||||
assert_equal 1, mails.size
|
||||
mail = mails.first
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification"
|
||||
else
|
||||
assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_updating_hidden_custom_fields_only_should_not_notifiy_user
|
||||
# anonymous user is never notified
|
||||
users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
|
||||
|
||||
users_to_test.keys.each do |user|
|
||||
Watcher.create!(:user => user, :watchable => @issue)
|
||||
end
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@request.session[:user_id] = 1
|
||||
with_settings :bcc_recipients => '1' do
|
||||
put :update, :params => {
|
||||
:id => @issue.id,
|
||||
:issue => {
|
||||
:custom_field_values => {
|
||||
@field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
users_to_test.each do |user, fields|
|
||||
mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
|
||||
if (fields & [@field2, @field3]).any?
|
||||
assert_equal 1, mails.size, "User #{user.id} was not notified"
|
||||
else
|
||||
assert_equal 0, mails.size, "User #{user.id} was notified"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
324
test/functional/journals_controller_test.rb
Normal file
324
test/functional/journals_controller_test.rb
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
# 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 JournalsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :issues, :journals, :journal_details, :enabled_modules,
|
||||
:trackers, :issue_statuses, :enumerations, :custom_fields, :custom_values, :custom_fields_projects, :projects_trackers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'application/atom+xml', @response.content_type
|
||||
end
|
||||
|
||||
def test_index_with_invalid_query_id
|
||||
get :index, :params => {
|
||||
:project_id => 1,
|
||||
:query_id => 999
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_index_should_return_privates_notes_with_permission_only
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'entry>id', :text => "http://test.host/issues/2?journal_id=#{journal.id}"
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'entry>id', :text => "http://test.host/issues/2?journal_id=#{journal.id}", :count => 0
|
||||
end
|
||||
|
||||
def test_index_should_show_visible_custom_fields_only
|
||||
Issue.destroy_all
|
||||
Journal.delete_all
|
||||
field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all}
|
||||
@fields = []
|
||||
@fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
|
||||
@fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
|
||||
@fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
|
||||
@issue = Issue.generate!(
|
||||
:author_id => 1,
|
||||
:project_id => 1,
|
||||
:tracker_id => 1,
|
||||
:custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
|
||||
)
|
||||
@issue.init_journal(User.find(1))
|
||||
@issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
|
||||
@issue.save!
|
||||
|
||||
user_with_role_on_other_project = User.generate!
|
||||
User.add_to_project(user_with_role_on_other_project, Project.find(2), Role.find(3))
|
||||
users_to_test = {
|
||||
User.find(1) => [@field1, @field2, @field3],
|
||||
User.find(3) => [@field1, @field2],
|
||||
user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
|
||||
User.generate! => [@field1],
|
||||
User.anonymous => [@field1]
|
||||
}
|
||||
|
||||
users_to_test.each do |user, visible_fields|
|
||||
get :index, :params => {
|
||||
:format => 'atom',
|
||||
:key => user.rss_key
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if visible_fields.include?(field)
|
||||
assert_select "content[type=html]", { :text => /NewValue#{i}/, :count => 1 }, "User #{user.id} was not able to view #{field.name} in API"
|
||||
else
|
||||
assert_select "content[type=html]", { :text => /NewValue#{i}/, :count => 0 }, "User #{user.id} was able to view #{field.name} in API"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_diff_for_description_change
|
||||
get :diff, :params => {
|
||||
:id => 3,
|
||||
:detail_id => 4
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'span.diff_out', :text => /removed/
|
||||
assert_select 'span.diff_in', :text => /added/
|
||||
end
|
||||
|
||||
def test_diff_for_custom_field
|
||||
field = IssueCustomField.create!(:name => "Long field", :field_format => 'text')
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Notes', :user_id => 1)
|
||||
detail = JournalDetail.create!(:journal => journal, :property => 'cf', :prop_key => field.id,
|
||||
:old_value => 'Foo', :value => 'Bar')
|
||||
|
||||
get :diff, :params => {
|
||||
:id => journal.id,
|
||||
:detail_id => detail.id
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'span.diff_out', :text => /Foo/
|
||||
assert_select 'span.diff_in', :text => /Bar/
|
||||
end
|
||||
|
||||
def test_diff_for_custom_field_should_be_denied_if_custom_field_is_not_visible
|
||||
field = IssueCustomField.create!(:name => "Long field", :field_format => 'text', :visible => false, :role_ids => [1])
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Notes', :user_id => 1)
|
||||
detail = JournalDetail.create!(:journal => journal, :property => 'cf', :prop_key => field.id,
|
||||
:old_value => 'Foo', :value => 'Bar')
|
||||
|
||||
get :diff, :params => {
|
||||
:id => journal.id,
|
||||
:detail_id => detail.id
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_diff_should_default_to_description_diff
|
||||
get :diff, :params => {
|
||||
:id => 3
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'span.diff_out', :text => /removed/
|
||||
assert_select 'span.diff_in', :text => /added/
|
||||
end
|
||||
|
||||
def test_reply_to_issue
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:id => 6
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include '> This is an issue', response.body
|
||||
end
|
||||
|
||||
def test_reply_to_issue_without_permission
|
||||
@request.session[:user_id] = 7
|
||||
get :new, :params => {
|
||||
:id => 6
|
||||
},
|
||||
:xhr => true
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_reply_to_note
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:id => 6,
|
||||
:journal_id => 4
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include '> A comment with a private version', response.body
|
||||
end
|
||||
|
||||
def test_reply_to_private_note_should_fail_without_permission
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :new, :params => {
|
||||
:id => 2,
|
||||
:journal_id => journal.id
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include '> Privates notes', response.body
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :new, :params => {
|
||||
:id => 2,
|
||||
:journal_id => journal.id
|
||||
},
|
||||
:xhr => true
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_edit_xhr
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :params => {
|
||||
:id => 2
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include 'textarea', response.body
|
||||
end
|
||||
|
||||
def test_edit_private_note_should_fail_without_permission
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true)
|
||||
@request.session[:user_id] = 2
|
||||
Role.find(1).add_permission! :edit_issue_notes
|
||||
|
||||
get :edit, :params => {
|
||||
:id => journal.id
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include 'textarea', response.body
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :edit, :params => {
|
||||
:id => journal.id
|
||||
},
|
||||
:xhr => true
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update_xhr
|
||||
@request.session[:user_id] = 1
|
||||
post :update, :params => {
|
||||
:id => 2,
|
||||
:journal => {
|
||||
:notes => 'Updated notes'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_equal 'Updated notes', Journal.find(2).notes
|
||||
assert_include 'journal-2-notes', response.body
|
||||
end
|
||||
|
||||
def test_update_xhr_with_private_notes_checked
|
||||
@request.session[:user_id] = 1
|
||||
post :update, :params => {
|
||||
:id => 2,
|
||||
:journal => {
|
||||
:private_notes => '1'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_equal true, Journal.find(2).private_notes
|
||||
assert_include 'change-2', response.body
|
||||
assert_include 'journal-2-private_notes', response.body
|
||||
end
|
||||
|
||||
def test_update_xhr_with_private_notes_unchecked
|
||||
Journal.find(2).update_attributes(:private_notes => true)
|
||||
@request.session[:user_id] = 1
|
||||
post :update, :params => {
|
||||
:id => 2,
|
||||
:journal => {
|
||||
:private_notes => '0'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_equal false, Journal.find(2).private_notes
|
||||
assert_include 'change-2', response.body
|
||||
assert_include 'journal-2-private_notes', response.body
|
||||
end
|
||||
|
||||
def test_update_xhr_without_set_private_notes_permission_should_ignore_private_notes
|
||||
@request.session[:user_id] = 2
|
||||
Role.find(1).add_permission! :edit_issue_notes
|
||||
Role.find(1).add_permission! :view_private_notes
|
||||
Role.find(1).remove_permission! :set_notes_private
|
||||
|
||||
post :update, :params => {
|
||||
:id => 2,
|
||||
:journal => {
|
||||
:private_notes => '1'
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal false, Journal.find(2).private_notes
|
||||
end
|
||||
|
||||
def test_update_xhr_with_empty_notes_should_delete_the_journal
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Journal.count', -1 do
|
||||
post :update, :params => {
|
||||
:id => 2,
|
||||
:journal => {
|
||||
:notes => ''
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_nil Journal.find_by_id(2)
|
||||
assert_include 'change-2', response.body
|
||||
end
|
||||
end
|
||||
116
test/functional/mail_handler_controller_test.rb
Normal file
116
test/functional/mail_handler_controller_test.rb
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# 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 MailHandlerControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :email_addresses, :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :issue_statuses,
|
||||
:trackers, :projects_trackers, :enumerations
|
||||
|
||||
FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_should_create_issue
|
||||
# Enable API and set a key
|
||||
Setting.mail_handler_api_enabled = 1
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
assert_difference 'Issue.count' do
|
||||
post :index, :params => {
|
||||
:key => 'secret',
|
||||
:email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
}
|
||||
end
|
||||
assert_response 201
|
||||
end
|
||||
|
||||
def test_should_create_issue_with_options
|
||||
# Enable API and set a key
|
||||
Setting.mail_handler_api_enabled = 1
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
assert_difference 'Issue.count' do
|
||||
post :index, :params => {
|
||||
:key => 'secret',
|
||||
:email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml')),
|
||||
:issue => {
|
||||
:is_private => '1'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response 201
|
||||
issue = Issue.order(:id => :desc).first
|
||||
assert_equal true, issue.is_private
|
||||
end
|
||||
|
||||
def test_should_respond_with_422_if_not_created
|
||||
Project.find('onlinestore').destroy
|
||||
|
||||
Setting.mail_handler_api_enabled = 1
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
assert_no_difference 'Issue.count' do
|
||||
post :index, :params => {
|
||||
:key => 'secret',
|
||||
:email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
}
|
||||
end
|
||||
assert_response 422
|
||||
end
|
||||
|
||||
def test_should_not_allow_with_api_disabled
|
||||
# Disable API
|
||||
Setting.mail_handler_api_enabled = 0
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
assert_no_difference 'Issue.count' do
|
||||
post :index, :params => {
|
||||
:key => 'secret',
|
||||
:email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
}
|
||||
end
|
||||
assert_response 403
|
||||
assert_include 'Access denied', response.body
|
||||
end
|
||||
|
||||
def test_should_not_allow_with_wrong_key
|
||||
Setting.mail_handler_api_enabled = 1
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
assert_no_difference 'Issue.count' do
|
||||
post :index, :params => {
|
||||
:key => 'wrong',
|
||||
:email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
}
|
||||
end
|
||||
assert_response 403
|
||||
assert_include 'Access denied', response.body
|
||||
end
|
||||
|
||||
def test_new
|
||||
Setting.mail_handler_api_enabled = 1
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
get :new, :params => {
|
||||
:key => 'secret'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
320
test/functional/members_controller_test.rb
Normal file
320
test/functional/members_controller_test.rb
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
# 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 MembersControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :members, :member_roles, :roles, :users
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_new_should_propose_managed_roles_only
|
||||
role = Role.find(1)
|
||||
role.update! :all_roles_managed => false
|
||||
role.managed_roles = Role.where(:id => [2, 3]).to_a
|
||||
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'div.roles-selection' do
|
||||
assert_select 'label', :text => 'Manager', :count => 0
|
||||
assert_select 'label', :text => 'Developer'
|
||||
assert_select 'label', :text => 'Reporter'
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_new
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:membership => {
|
||||
:role_ids => [1],
|
||||
:user_id => 7
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/members'
|
||||
assert User.find(7).member_of?(Project.find(1))
|
||||
end
|
||||
|
||||
def test_create_multiple
|
||||
assert_difference 'Member.count', 3 do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:membership => {
|
||||
:role_ids => [1],
|
||||
:user_ids => [7, 8, 9]
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/members'
|
||||
assert User.find(7).member_of?(Project.find(1))
|
||||
end
|
||||
|
||||
def test_create_should_ignore_unmanaged_roles
|
||||
role = Role.find(1)
|
||||
role.update! :all_roles_managed => false
|
||||
role.managed_roles = Role.where(:id => [2, 3]).to_a
|
||||
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:membership => {
|
||||
:role_ids => [1, 2],
|
||||
:user_id => 7
|
||||
}
|
||||
}
|
||||
end
|
||||
member = Member.order(:id => :desc).first
|
||||
assert_equal [2], member.role_ids
|
||||
end
|
||||
|
||||
def test_create_should_be_allowed_for_admin_without_role
|
||||
User.find(1).members.delete_all
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:membership => {
|
||||
:role_ids => [1, 2],
|
||||
:user_id => 7
|
||||
}
|
||||
}
|
||||
end
|
||||
member = Member.order(:id => :desc).first
|
||||
assert_equal [1, 2], member.role_ids
|
||||
end
|
||||
|
||||
def test_xhr_create
|
||||
assert_difference 'Member.count', 3 do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:membership => {
|
||||
:role_ids => [1],
|
||||
:user_ids => [7, 8, 9]
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert User.find(7).member_of?(Project.find(1))
|
||||
assert User.find(8).member_of?(Project.find(1))
|
||||
assert User.find(9).member_of?(Project.find(1))
|
||||
assert_include 'tab-content-members', response.body
|
||||
end
|
||||
|
||||
def test_xhr_create_with_failure
|
||||
assert_no_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:membership => {
|
||||
:role_ids => [],
|
||||
:user_ids => [7, 8, 9]
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /alert/, response.body, "Alert message not sent"
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {
|
||||
:id => 2
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?][checked=checked]', 'membership[role_ids][]', '2'
|
||||
end
|
||||
|
||||
def test_xhr_edit
|
||||
get :edit, :params => {
|
||||
:id => 2
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_update
|
||||
assert_no_difference 'Member.count' do
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:membership => {
|
||||
:role_ids => [1],
|
||||
:user_id => 3
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/members'
|
||||
end
|
||||
|
||||
def test_update_locked_member_should_be_allowed
|
||||
User.find(3).lock!
|
||||
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:membership => {
|
||||
:role_ids => [1]
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
member = Member.find(2)
|
||||
assert member.user.locked?
|
||||
assert_equal [1], member.role_ids
|
||||
end
|
||||
|
||||
def test_update_should_not_add_unmanaged_roles
|
||||
role = Role.find(1)
|
||||
role.update! :all_roles_managed => false
|
||||
role.managed_roles = Role.where(:id => [2, 3]).to_a
|
||||
member = Member.create!(:user => User.find(9), :role_ids => [3], :project_id => 1)
|
||||
|
||||
put :update, :params => {
|
||||
:id => member.id,
|
||||
:membership => {
|
||||
:role_ids => [1, 2, 3]
|
||||
}
|
||||
}
|
||||
assert_equal [2, 3], member.reload.role_ids.sort
|
||||
end
|
||||
|
||||
def test_update_should_not_remove_unmanaged_roles
|
||||
role = Role.find(1)
|
||||
role.update! :all_roles_managed => false
|
||||
role.managed_roles = Role.where(:id => [2, 3]).to_a
|
||||
member = Member.create!(:user => User.find(9), :role_ids => [1, 3], :project_id => 1)
|
||||
|
||||
put :update, :params => {
|
||||
:id => member.id,
|
||||
:membership => {
|
||||
:role_ids => [2]
|
||||
}
|
||||
}
|
||||
assert_equal [1, 2], member.reload.role_ids.sort
|
||||
end
|
||||
|
||||
def test_xhr_update
|
||||
assert_no_difference 'Member.count' do
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:membership => {
|
||||
:role_ids => [1],
|
||||
:user_id => 3
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
member = Member.find(2)
|
||||
assert_equal [1], member.role_ids
|
||||
assert_equal 3, member.user_id
|
||||
assert_include 'tab-content-members', response.body
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 2
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/members'
|
||||
assert !User.find(3).member_of?(Project.find(1))
|
||||
end
|
||||
|
||||
def test_destroy_locked_member_should_be_allowed
|
||||
assert User.find(3).lock!
|
||||
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 2
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_should_fail_with_unmanaged_roles
|
||||
role = Role.find(1)
|
||||
role.update! :all_roles_managed => false
|
||||
role.managed_roles = Role.where(:id => [2, 3]).to_a
|
||||
member = Member.create!(:user => User.find(9), :role_ids => [1, 3], :project_id => 1)
|
||||
|
||||
assert_no_difference 'Member.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => member.id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_should_succeed_with_managed_roles_only
|
||||
role = Role.find(1)
|
||||
role.update! :all_roles_managed => false
|
||||
role.managed_roles = Role.where(:id => [2, 3]).to_a
|
||||
member = Member.create!(:user => User.find(9), :role_ids => [3], :project_id => 1)
|
||||
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => member.id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_destroy
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 2
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_nil Member.find_by_id(2)
|
||||
assert_include 'tab-content-members', response.body
|
||||
end
|
||||
|
||||
def test_autocomplete
|
||||
get :autocomplete, :params => {
|
||||
:project_id => 1,
|
||||
:q => 'mis',
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_include 'User Misc', response.body
|
||||
end
|
||||
end
|
||||
289
test/functional/messages_controller_test.rb
Normal file
289
test/functional/messages_controller_test.rb
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
# 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 MessagesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'h2', :text => 'First post'
|
||||
end
|
||||
|
||||
def test_show_should_contain_reply_field_tags_for_quoting
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# tags required by MessagesController#quote
|
||||
assert_select 'input#message_subject'
|
||||
assert_select 'textarea#message_content'
|
||||
assert_select 'div#reply'
|
||||
end
|
||||
|
||||
def test_show_with_pagination
|
||||
message = Message.find(1)
|
||||
assert_difference 'Message.count', 30 do
|
||||
30.times do
|
||||
message.children << Message.new(:subject => 'Reply',
|
||||
:content => 'Reply body',
|
||||
:author_id => 2,
|
||||
:board_id => 1)
|
||||
end
|
||||
end
|
||||
reply_ids = message.children.map(&:id).sort
|
||||
|
||||
get :show, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1,
|
||||
:r => reply_ids.last
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'a[href=?]', "/boards/1/topics/1?r=#{reply_ids.last}#message-#{reply_ids.last}"
|
||||
assert_select 'a[href=?]', "/boards/1/topics/1?r=#{reply_ids.first}#message-#{reply_ids.first}", 0
|
||||
end
|
||||
|
||||
def test_show_with_reply_permission
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div#reply textarea#message_content'
|
||||
end
|
||||
|
||||
def test_show_message_not_found
|
||||
get :show, :params => {
|
||||
:board_id => 1,
|
||||
:id => 99999
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_show_message_from_invalid_board_should_respond_with_404
|
||||
get :show, :params => {
|
||||
:board_id => 999,
|
||||
:id => 1
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:board_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'message[subject]'
|
||||
end
|
||||
|
||||
def test_get_new_with_invalid_board
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:board_id => 99
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_post_new
|
||||
@request.session[:user_id] = 2
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
with_settings :notified_events => %w(message_posted) do
|
||||
post :new, :params => {
|
||||
:board_id => 1,
|
||||
:message => {
|
||||
:subject => 'Test created message',
|
||||
:content => 'Message body'
|
||||
}
|
||||
}
|
||||
end
|
||||
message = Message.find_by_subject('Test created message')
|
||||
assert_not_nil message
|
||||
assert_redirected_to "/boards/1/topics/#{message.to_param}"
|
||||
assert_equal 'Message body', message.content
|
||||
assert_equal 2, message.author_id
|
||||
assert_equal 1, message.board_id
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
assert_equal "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] Test created message", mail.subject
|
||||
assert_mail_body_match 'Message body', mail
|
||||
# author
|
||||
assert mail.bcc.include?('jsmith@somenet.foo')
|
||||
# project member
|
||||
assert mail.bcc.include?('dlopper@somenet.foo')
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=?]', 'message[subject]', 'First post'
|
||||
end
|
||||
|
||||
def test_post_edit
|
||||
@request.session[:user_id] = 2
|
||||
post :edit, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1,
|
||||
:message => {
|
||||
:subject => 'New subject',
|
||||
:content => 'New body'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/boards/1/topics/1'
|
||||
message = Message.find(1)
|
||||
assert_equal 'New subject', message.subject
|
||||
assert_equal 'New body', message.content
|
||||
end
|
||||
|
||||
def test_post_edit_sticky_and_locked
|
||||
@request.session[:user_id] = 2
|
||||
post :edit, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1,
|
||||
:message => {
|
||||
:subject => 'New subject',
|
||||
:content => 'New body',
|
||||
:locked => '1',
|
||||
:sticky => '1'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/boards/1/topics/1'
|
||||
message = Message.find(1)
|
||||
assert_equal true, message.sticky?
|
||||
assert_equal true, message.locked?
|
||||
end
|
||||
|
||||
def test_post_edit_should_allow_to_change_board
|
||||
@request.session[:user_id] = 2
|
||||
post :edit, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1,
|
||||
:message => {
|
||||
:subject => 'New subject',
|
||||
:content => 'New body',
|
||||
:board_id => 2
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/boards/2/topics/1'
|
||||
message = Message.find(1)
|
||||
assert_equal Board.find(2), message.board
|
||||
end
|
||||
|
||||
def test_reply
|
||||
@request.session[:user_id] = 2
|
||||
post :reply, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1,
|
||||
:reply => {
|
||||
:content => 'This is a test reply',
|
||||
:subject => 'Test reply'
|
||||
}
|
||||
}
|
||||
reply = Message.order('id DESC').first
|
||||
assert_redirected_to "/boards/1/topics/1?r=#{reply.id}"
|
||||
assert Message.find_by_subject('Test reply')
|
||||
end
|
||||
|
||||
def test_destroy_topic
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Message.count', -3 do
|
||||
post :destroy, :params => {
|
||||
:board_id => 1,
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/boards/1'
|
||||
assert_nil Message.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_destroy_reply
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Message.count', -1 do
|
||||
post :destroy, :params => {
|
||||
:board_id => 1,
|
||||
:id => 2
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/boards/1/topics/1?r=2'
|
||||
assert_nil Message.find_by_id(2)
|
||||
end
|
||||
|
||||
def test_quote
|
||||
@request.session[:user_id] = 2
|
||||
get :quote, :params => {
|
||||
:board_id => 1,
|
||||
:id => 3
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
|
||||
assert_include 'RE: First post', response.body
|
||||
assert_include '> An other reply', response.body
|
||||
end
|
||||
|
||||
def test_preview_new
|
||||
@request.session[:user_id] = 2
|
||||
post :preview, :params => {
|
||||
:board_id => 1,
|
||||
:message => {
|
||||
:subject => "",
|
||||
:content => "Previewed text"
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_include 'Previewed text', response.body
|
||||
end
|
||||
|
||||
def test_preview_edit
|
||||
@request.session[:user_id] = 2
|
||||
post :preview, :params => {
|
||||
:id => 4,
|
||||
:board_id => 1,
|
||||
:message => {
|
||||
:subject => "",
|
||||
:content => "Previewed text"
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_include 'Previewed text', response.body
|
||||
end
|
||||
end
|
||||
521
test/functional/my_controller_test.rb
Normal file
521
test/functional/my_controller_test.rb
Normal file
|
|
@ -0,0 +1,521 @@
|
|||
# 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 MyControllerTest < Redmine::ControllerTest
|
||||
fixtures :users, :email_addresses, :user_preferences, :roles, :projects, :members, :member_roles,
|
||||
:issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources, :queries
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'h2', 'My page'
|
||||
end
|
||||
|
||||
def test_page
|
||||
get :page
|
||||
assert_response :success
|
||||
assert_select 'h2', 'My page'
|
||||
end
|
||||
|
||||
def test_page_with_timelog_block
|
||||
preferences = User.find(2).pref
|
||||
preferences[:my_page_layout] = {'top' => ['timelog']}
|
||||
preferences.save!
|
||||
with_issue = TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :hours => 2.5, :activity_id => 10, :issue_id => 1)
|
||||
without_issue = TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :hours => 3.5, :activity_id => 10, :project_id => 1)
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
assert_select "tr#time-entry-#{with_issue.id}" do
|
||||
assert_select 'td.subject a[href="/issues/1"]'
|
||||
assert_select 'td.hours', :text => '2.50'
|
||||
end
|
||||
assert_select "tr#time-entry-#{without_issue.id}" do
|
||||
assert_select 'td.hours', :text => '3.50'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_assigned_issues_block_and_no_custom_settings
|
||||
preferences = User.find(2).pref
|
||||
preferences.my_page_layout = {'top' => ['issuesassignedtome']}
|
||||
preferences.my_page_settings = nil
|
||||
preferences.save!
|
||||
|
||||
get :page
|
||||
assert_select '#block-issuesassignedtome' do
|
||||
assert_select 'table.issues' do
|
||||
assert_select 'th a[data-remote=true][data-method=post]', :text => 'Tracker'
|
||||
end
|
||||
assert_select '#issuesassignedtome-settings' do
|
||||
assert_select 'select[name=?]', 'settings[issuesassignedtome][columns][]'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_assigned_issues_block_and_custom_columns
|
||||
preferences = User.find(2).pref
|
||||
preferences.my_page_layout = {'top' => ['issuesassignedtome']}
|
||||
preferences.my_page_settings = {'issuesassignedtome' => {:columns => ['tracker', 'subject', 'due_date']}}
|
||||
preferences.save!
|
||||
|
||||
get :page
|
||||
assert_select '#block-issuesassignedtome' do
|
||||
assert_select 'table.issues td.due_date'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_assigned_issues_block_and_custom_sort
|
||||
preferences = User.find(2).pref
|
||||
preferences.my_page_layout = {'top' => ['issuesassignedtome']}
|
||||
preferences.my_page_settings = {'issuesassignedtome' => {:sort => 'due_date'}}
|
||||
preferences.save!
|
||||
|
||||
get :page
|
||||
assert_select '#block-issuesassignedtome' do
|
||||
assert_select 'table.issues.sort-by-due-date'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_issuequery_block_and_no_settings
|
||||
user = User.find(2)
|
||||
user.pref.my_page_layout = {'top' => ['issuequery']}
|
||||
user.pref.save!
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
|
||||
assert_select '#block-issuequery' do
|
||||
assert_select 'h3', :text => 'Issues'
|
||||
assert_select 'select[name=?]', 'settings[issuequery][query_id]' do
|
||||
assert_select 'option[value="5"]', :text => 'Open issues by priority and tracker'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_issuequery_block_and_global_query
|
||||
user = User.find(2)
|
||||
query = IssueQuery.create!(:name => 'All issues', :user => user, :column_names => [:tracker, :subject, :status, :assigned_to])
|
||||
user.pref.my_page_layout = {'top' => ['issuequery']}
|
||||
user.pref.my_page_settings = {'issuequery' => {:query_id => query.id}}
|
||||
user.pref.save!
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
|
||||
assert_select '#block-issuequery' do
|
||||
assert_select 'a[href=?]', "/issues?query_id=#{query.id}"
|
||||
# assert number of columns (columns from query + id column + checkbox column)
|
||||
assert_select 'table.issues th', 6
|
||||
# assert results limit
|
||||
assert_select 'table.issues tr.issue', 10
|
||||
assert_select 'table.issues td.assigned_to'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_issuequery_block_and_project_query
|
||||
user = User.find(2)
|
||||
query = IssueQuery.create!(:name => 'All issues', :project => Project.find(1), :user => user, :column_names => [:tracker, :subject, :status, :assigned_to])
|
||||
user.pref.my_page_layout = {'top' => ['issuequery']}
|
||||
user.pref.my_page_settings = {'issuequery' => {:query_id => query.id}}
|
||||
user.pref.save!
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
|
||||
assert_select '#block-issuequery' do
|
||||
assert_select 'a[href=?]', "/projects/ecookbook/issues?query_id=#{query.id}"
|
||||
# assert number of columns (columns from query + id column + checkbox column)
|
||||
assert_select 'table.issues th', 6
|
||||
# assert results limit
|
||||
assert_select 'table.issues tr.issue', 10
|
||||
assert_select 'table.issues td.assigned_to'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_issuequery_block_and_query_should_display_custom_columns
|
||||
user = User.find(2)
|
||||
query = IssueQuery.create!(:name => 'All issues', :user => user, :column_names => [:tracker, :subject, :status, :assigned_to])
|
||||
user.pref.my_page_layout = {'top' => ['issuequery']}
|
||||
user.pref.my_page_settings = {'issuequery' => {:query_id => query.id, :columns => [:subject, :due_date]}}
|
||||
user.pref.save!
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
|
||||
assert_select '#block-issuequery' do
|
||||
# assert number of columns (columns from query + id column + checkbox column)
|
||||
assert_select 'table.issues th', 4
|
||||
assert_select 'table.issues th', :text => 'Due date'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_multiple_issuequery_blocks
|
||||
user = User.find(2)
|
||||
query1 = IssueQuery.create!(:name => 'All issues', :user => user, :column_names => [:tracker, :subject, :status, :assigned_to])
|
||||
query2 = IssueQuery.create!(:name => 'Other issues', :user => user, :column_names => [:tracker, :subject, :priority])
|
||||
user.pref.my_page_layout = {'top' => ['issuequery__1', 'issuequery']}
|
||||
user.pref.my_page_settings = {
|
||||
'issuequery' => {:query_id => query1.id, :columns => [:subject, :due_date]},
|
||||
'issuequery__1' => {:query_id => query2.id}
|
||||
}
|
||||
user.pref.save!
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
|
||||
assert_select '#block-issuequery' do
|
||||
assert_select 'h3', :text => /All issues/
|
||||
assert_select 'table.issues th', :text => 'Due date'
|
||||
end
|
||||
|
||||
assert_select '#block-issuequery__1' do
|
||||
assert_select 'h3', :text => /Other issues/
|
||||
assert_select 'table.issues th', :text => 'Priority'
|
||||
end
|
||||
|
||||
assert_select '#block-select' do
|
||||
assert_select 'option[value=?]:not([disabled])', 'issuequery__2', :text => 'Issues'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_all_blocks
|
||||
blocks = Redmine::MyPage.blocks.keys
|
||||
preferences = User.find(2).pref
|
||||
preferences[:my_page_layout] = {'top' => blocks}
|
||||
preferences.save!
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
assert_select 'div.mypage-box', blocks.size
|
||||
end
|
||||
|
||||
def test_my_account_should_show_editable_custom_fields
|
||||
get :account
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'user[custom_field_values][4]'
|
||||
end
|
||||
|
||||
def test_my_account_should_not_show_non_editable_custom_fields
|
||||
UserCustomField.find(4).update_attribute :editable, false
|
||||
|
||||
get :account
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'user[custom_field_values][4]', 0
|
||||
end
|
||||
|
||||
def test_my_account_should_show_language_select
|
||||
get :account
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'user[language]'
|
||||
end
|
||||
|
||||
def test_my_account_should_not_show_language_select_with_force_default_language_for_loggedin
|
||||
with_settings :force_default_language_for_loggedin => '1' do
|
||||
get :account
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'user[language]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_account
|
||||
post :account, :params => {
|
||||
:user => {
|
||||
:firstname => "Joe",
|
||||
:login => "root",
|
||||
:admin => 1,
|
||||
:group_ids => ['10'],
|
||||
:custom_field_values => {
|
||||
"4" => "0100562500"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
assert_redirected_to '/my/account'
|
||||
user = User.find(2)
|
||||
assert_equal "Joe", user.firstname
|
||||
assert_equal "jsmith", user.login
|
||||
assert_equal "0100562500", user.custom_value_for(4).value
|
||||
# ignored
|
||||
assert !user.admin?
|
||||
assert user.groups.empty?
|
||||
end
|
||||
|
||||
def test_update_account_should_send_security_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :account, :params => {
|
||||
:user => {
|
||||
:mail => 'foobar@example.com'
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match '0.0.0.0', mail
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_change_to, field: I18n.t(:field_mail), value: 'foobar@example.com'), mail
|
||||
assert_select_email do
|
||||
assert_select 'a[href^=?]', 'http://localhost:3000/my/account', :text => 'My account'
|
||||
end
|
||||
# The old email address should be notified about the change for security purposes
|
||||
assert [mail.bcc, mail.cc].flatten.include?(User.find(2).mail)
|
||||
assert [mail.bcc, mail.cc].flatten.include?('foobar@example.com')
|
||||
end
|
||||
|
||||
def test_my_account_should_show_destroy_link
|
||||
get :account
|
||||
assert_select 'a[href="/my/account/destroy"]'
|
||||
end
|
||||
|
||||
def test_get_destroy_should_display_the_destroy_confirmation
|
||||
get :destroy
|
||||
assert_response :success
|
||||
assert_select 'form[action="/my/account/destroy"]' do
|
||||
assert_select 'input[name=confirm]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_destroy_without_confirmation_should_not_destroy_account
|
||||
assert_no_difference 'User.count' do
|
||||
post :destroy
|
||||
end
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_post_destroy_without_confirmation_should_destroy_account
|
||||
assert_difference 'User.count', -1 do
|
||||
post :destroy, :params => {
|
||||
:confirm => '1'
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/'
|
||||
assert_match /deleted/i, flash[:notice]
|
||||
end
|
||||
|
||||
def test_post_destroy_with_unsubscribe_not_allowed_should_not_destroy_account
|
||||
User.any_instance.stubs(:own_account_deletable?).returns(false)
|
||||
|
||||
assert_no_difference 'User.count' do
|
||||
post :destroy, :params => {
|
||||
:confirm => '1'
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
|
||||
def test_change_password
|
||||
get :password
|
||||
assert_response :success
|
||||
assert_select 'input[type=password][name=password]'
|
||||
assert_select 'input[type=password][name=new_password]'
|
||||
assert_select 'input[type=password][name=new_password_confirmation]'
|
||||
end
|
||||
|
||||
def test_update_password
|
||||
post :password, :params => {
|
||||
:password => 'jsmith',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret123'
|
||||
}
|
||||
assert_redirected_to '/my/account'
|
||||
assert User.try_to_login('jsmith', 'secret123')
|
||||
end
|
||||
|
||||
def test_update_password_with_non_matching_confirmation
|
||||
post :password, :params => {
|
||||
:password => 'jsmith',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret1234'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Password doesn.*t match confirmation/
|
||||
assert User.try_to_login('jsmith', 'jsmith')
|
||||
end
|
||||
|
||||
def test_update_password_with_wrong_password
|
||||
# wrong password
|
||||
post :password, :params => {
|
||||
:password => 'wrongpassword',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret123'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'Wrong password', flash[:error]
|
||||
assert User.try_to_login('jsmith', 'jsmith')
|
||||
end
|
||||
|
||||
def test_change_password_should_redirect_if_user_cannot_change_its_password
|
||||
User.find(2).update_attribute(:auth_source_id, 1)
|
||||
|
||||
get :password
|
||||
assert_not_nil flash[:error]
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
|
||||
def test_update_password_should_send_security_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :password, :params => {
|
||||
:password => 'jsmith',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret123'
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_no_match 'secret123', mail # just to be sure: pw should never be sent!
|
||||
assert_select_email do
|
||||
assert_select 'a[href^=?]', 'http://localhost:3000/my/password', :text => 'Change password'
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_page_with_blank_preferences
|
||||
user = User.generate!(:language => 'en')
|
||||
@request.session[:user_id] = user.id
|
||||
|
||||
post :update_page, :params => {
|
||||
:settings => {
|
||||
'issuesassignedtome' => {
|
||||
'columns' => ['subject', 'due_date']}
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_include '$("#block-issuesassignedtome").replaceWith(', response.body
|
||||
assert_include 'Due date', response.body
|
||||
|
||||
assert_equal({:columns => ['subject', 'due_date']}, user.reload.pref.my_page_settings('issuesassignedtome'))
|
||||
end
|
||||
|
||||
def test_add_block
|
||||
post :add_block, :params => {
|
||||
:block => 'issueswatched'
|
||||
}
|
||||
assert_redirected_to '/my/page'
|
||||
assert User.find(2).pref[:my_page_layout]['top'].include?('issueswatched')
|
||||
end
|
||||
|
||||
def test_add_block_xhr
|
||||
post :add_block, :params => {
|
||||
:block => 'issueswatched'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_include 'issueswatched', User.find(2).pref[:my_page_layout]['top']
|
||||
end
|
||||
|
||||
def test_add_invalid_block_should_error
|
||||
post :add_block, :params => {
|
||||
:block => 'invalid'
|
||||
}
|
||||
assert_response 422
|
||||
end
|
||||
|
||||
def test_remove_block
|
||||
post :remove_block, :params => {
|
||||
:block => 'issuesassignedtome'
|
||||
}
|
||||
assert_redirected_to '/my/page'
|
||||
assert !User.find(2).pref[:my_page_layout].values.flatten.include?('issuesassignedtome')
|
||||
end
|
||||
|
||||
def test_remove_block_xhr
|
||||
post :remove_block, :params => {
|
||||
:block => 'issuesassignedtome'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_include '$("#block-issuesassignedtome").remove();', response.body
|
||||
assert !User.find(2).pref[:my_page_layout].values.flatten.include?('issuesassignedtome')
|
||||
end
|
||||
|
||||
def test_order_blocks
|
||||
pref = User.find(2).pref
|
||||
pref.my_page_layout = {'left' => ['news', 'calendar','documents']}
|
||||
pref.save!
|
||||
|
||||
post :order_blocks, :params => {
|
||||
:group => 'left',
|
||||
:blocks => ['documents', 'calendar', 'news']
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal ['documents', 'calendar', 'news'], User.find(2).pref.my_page_layout['left']
|
||||
end
|
||||
|
||||
def test_move_block
|
||||
pref = User.find(2).pref
|
||||
pref.my_page_layout = {'left' => ['news','documents'], 'right' => ['calendar']}
|
||||
pref.save!
|
||||
|
||||
post :order_blocks, :params => {
|
||||
:group => 'left',
|
||||
:blocks => ['news', 'calendar', 'documents']
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal({'left' => ['news', 'calendar', 'documents'], 'right' => []}, User.find(2).pref.my_page_layout)
|
||||
end
|
||||
|
||||
def test_reset_rss_key_with_existing_key
|
||||
@previous_token_value = User.find(2).rss_key # Will generate one if it's missing
|
||||
post :reset_rss_key
|
||||
|
||||
assert_not_equal @previous_token_value, User.find(2).rss_key
|
||||
assert User.find(2).rss_token
|
||||
assert_match /reset/, flash[:notice]
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
|
||||
def test_reset_rss_key_without_existing_key
|
||||
Token.delete_all
|
||||
assert_nil User.find(2).rss_token
|
||||
post :reset_rss_key
|
||||
|
||||
assert User.find(2).rss_token
|
||||
assert_match /reset/, flash[:notice]
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
|
||||
def test_show_api_key
|
||||
get :show_api_key
|
||||
assert_response :success
|
||||
assert_select 'pre', User.find(2).api_key
|
||||
end
|
||||
|
||||
def test_reset_api_key_with_existing_key
|
||||
@previous_token_value = User.find(2).api_key # Will generate one if it's missing
|
||||
post :reset_api_key
|
||||
|
||||
assert_not_equal @previous_token_value, User.find(2).api_key
|
||||
assert User.find(2).api_token
|
||||
assert_match /reset/, flash[:notice]
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
|
||||
def test_reset_api_key_without_existing_key
|
||||
assert_nil User.find(2).api_token
|
||||
post :reset_api_key
|
||||
|
||||
assert User.find(2).api_token
|
||||
assert_match /reset/, flash[:notice]
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
end
|
||||
233
test/functional/news_controller_test.rb
Normal file
233
test/functional/news_controller_test.rb
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
# 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 NewsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:enabled_modules, :news, :comments,
|
||||
:attachments
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'h3 a', :text => 'eCookbook first release !'
|
||||
end
|
||||
|
||||
def test_index_with_project
|
||||
get :index, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h3 a', :text => 'eCookbook first release !'
|
||||
end
|
||||
|
||||
def test_index_with_invalid_project_should_respond_with_404
|
||||
get :index, :params => {
|
||||
:project_id => 999
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_index_without_permission_should_fail
|
||||
Role.all.each {|r| r.remove_permission! :view_news}
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => 'eCookbook first release !'
|
||||
end
|
||||
|
||||
def test_show_should_show_attachments
|
||||
attachment = Attachment.first
|
||||
attachment.container = News.find(1)
|
||||
attachment.save!
|
||||
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'a', :text => attachment.filename
|
||||
end
|
||||
|
||||
def test_show_with_comments_in_reverse_order
|
||||
user = User.find(1)
|
||||
user.pref[:comments_sorting] = 'desc'
|
||||
user.pref.save!
|
||||
|
||||
@request.session[:user_id] = 1
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
comments = css_select('#comments .wiki').map(&:text).map(&:strip)
|
||||
assert_equal ["This is an other comment", "my first comment"], comments
|
||||
end
|
||||
|
||||
def test_show_not_found
|
||||
get :show, :params => {
|
||||
:id => 999
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'news[title]'
|
||||
end
|
||||
|
||||
def test_post_create
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
with_settings :notified_events => %w(news_added) do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:news => {
|
||||
:title => 'NewsControllerTest',
|
||||
:description => 'This is the description',
|
||||
:summary => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/news'
|
||||
|
||||
news = News.find_by_title('NewsControllerTest')
|
||||
assert_not_nil news
|
||||
assert_equal 'This is the description', news.description
|
||||
assert_equal User.find(2), news.author
|
||||
assert_equal Project.find(1), news.project
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_post_create_with_attachment
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'News.count' do
|
||||
assert_difference 'Attachment.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:news => {
|
||||
:title => 'Test',
|
||||
:description => 'This is the description'
|
||||
},
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
attachment = Attachment.order('id DESC').first
|
||||
news = News.order('id DESC').first
|
||||
assert_equal news, attachment.container
|
||||
end
|
||||
|
||||
def test_post_create_with_validation_failure
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :params => {
|
||||
:project_id => 1,
|
||||
:news => {
|
||||
:title => '',
|
||||
:description => 'This is the description',
|
||||
:summary => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /title cannot be blank/i
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'news[title]', 'eCookbook first release !'
|
||||
end
|
||||
|
||||
def test_put_update
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:news => {
|
||||
:description => 'Description changed by test_post_edit'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/news/1'
|
||||
news = News.find(1)
|
||||
assert_equal 'Description changed by test_post_edit', news.description
|
||||
end
|
||||
|
||||
def test_put_update_with_attachment
|
||||
set_tmp_attachments_directory
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'News.count' do
|
||||
assert_difference 'Attachment.count' do
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:news => {
|
||||
:description => 'This is the description'
|
||||
},
|
||||
:attachments => {
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain')}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
attachment = Attachment.order('id DESC').first
|
||||
assert_equal News.find(1), attachment.container
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:news => {
|
||||
:description => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /description cannot be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/news'
|
||||
assert_nil News.find_by_id(1)
|
||||
end
|
||||
end
|
||||
144
test/functional/previews_controller_test.rb
Normal file
144
test/functional/previews_controller_test.rb
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# 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 PreviewsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:journals, :journal_details,
|
||||
:news
|
||||
|
||||
def test_preview_new_issue
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :params => {
|
||||
:project_id => '1',
|
||||
:issue => {
|
||||
:description => 'Foo'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset' do
|
||||
assert_select 'legend', :text => 'Description'
|
||||
assert_select 'p', :text => 'Foo'
|
||||
end
|
||||
end
|
||||
|
||||
def test_preview_issue_notes_with_no_change_to_description
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :params => {
|
||||
:project_id => '1',
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:description => Issue.find(1).description,
|
||||
:notes => 'Foo'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'legend', :text => 'Description', :count => 0
|
||||
assert_select 'legend', :text => 'Notes'
|
||||
end
|
||||
|
||||
def test_preview_issue_notes_with_change_to_description
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :params => {
|
||||
:project_id => '1',
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:description => 'Changed description',
|
||||
:notes => 'Foo'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'legend', :text => 'Description'
|
||||
assert_select 'legend', :text => 'Notes'
|
||||
end
|
||||
|
||||
def test_preview_journal_notes_for_update
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :params => {
|
||||
:project_id => '1',
|
||||
:id => 1,
|
||||
:journal => {
|
||||
:notes => 'Foo'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'legend', :text => 'Notes'
|
||||
assert_select 'p', :text => 'Foo'
|
||||
end
|
||||
|
||||
def test_preview_issue_notes_should_support_links_to_existing_attachments
|
||||
Attachment.generate!(:container => Issue.find(1), :filename => 'foo.bar')
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :params => {
|
||||
:project_id => '1',
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:notes => 'attachment:foo.bar'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'a.attachment', :text => 'foo.bar'
|
||||
end
|
||||
|
||||
def test_preview_issue_with_project_changed
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :params => {
|
||||
:project_id => '1',
|
||||
:id => 1,
|
||||
:issue => {
|
||||
:notes => 'notes',
|
||||
:project_id => 2
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'legend', :text => 'Notes'
|
||||
end
|
||||
|
||||
def test_preview_new_news
|
||||
get :news, :params => {
|
||||
:project_id => 1,
|
||||
:news => {
|
||||
:title => '',
|
||||
:description => 'News description',
|
||||
:summary => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset.preview', :text => /News description/
|
||||
end
|
||||
|
||||
def test_preview_existing_news
|
||||
get :news, :params => {
|
||||
:project_id => 1,
|
||||
:id => 2,
|
||||
:news => {
|
||||
:title => '',
|
||||
:description => 'News description',
|
||||
:summary => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset.preview', :text => /News description/
|
||||
end
|
||||
end
|
||||
323
test/functional/principal_memberships_controller_test.rb
Normal file
323
test/functional/principal_memberships_controller_test.rb
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
# 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 PrincipalMembershipsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :groups_users
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
end
|
||||
|
||||
def test_new_user_membership
|
||||
get :new, :params => {
|
||||
:user_id => 7
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'label', :text => 'eCookbook' do
|
||||
assert_select 'input[name=?][value="1"]:not([disabled])', 'membership[project_ids][]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_user_membership_should_disable_user_projects
|
||||
Member.create!(:user_id => 7, :project_id => 1, :role_ids => [1])
|
||||
|
||||
get :new, :params => {
|
||||
:user_id => 7
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'label', :text => 'eCookbook' do
|
||||
assert_select 'input[name=?][value="1"][disabled=disabled]', 'membership[project_ids][]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_new_user_membership
|
||||
get :new, :params => {
|
||||
:user_id => 7
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create_user_membership
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 7,
|
||||
:membership => {
|
||||
:project_ids => [3],
|
||||
:role_ids => [2]
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/users/7/edit?tab=memberships'
|
||||
member = Member.order('id DESC').first
|
||||
assert_equal User.find(7), member.principal
|
||||
assert_equal [2], member.role_ids
|
||||
assert_equal 3, member.project_id
|
||||
end
|
||||
|
||||
def test_create_user_membership_with_multiple_roles
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 7,
|
||||
:membership => {
|
||||
:project_ids => [3],
|
||||
:role_ids => [2, 3]
|
||||
}
|
||||
}
|
||||
end
|
||||
member = Member.order('id DESC').first
|
||||
assert_equal User.find(7), member.principal
|
||||
assert_equal [2, 3], member.role_ids.sort
|
||||
assert_equal 3, member.project_id
|
||||
end
|
||||
|
||||
def test_create_user_membership_with_multiple_projects_and_roles
|
||||
assert_difference 'Member.count', 2 do
|
||||
post :create, :params => {
|
||||
:user_id => 7,
|
||||
:membership => {
|
||||
:project_ids => [1, 3],
|
||||
:role_ids => [2, 3]
|
||||
}
|
||||
}
|
||||
end
|
||||
members = Member.order('id DESC').limit(2).sort_by(&:project_id)
|
||||
assert_equal 1, members[0].project_id
|
||||
assert_equal 3, members[1].project_id
|
||||
members.each do |member|
|
||||
assert_equal User.find(7), member.principal
|
||||
assert_equal [2, 3], member.role_ids.sort
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_create_user_membership
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 7,
|
||||
:membership => {
|
||||
:project_ids => [3],
|
||||
:role_ids => [2]
|
||||
},
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
member = Member.order('id DESC').first
|
||||
assert_equal User.find(7), member.principal
|
||||
assert_equal [2], member.role_ids
|
||||
assert_equal 3, member.project_id
|
||||
assert_include 'tab-content-memberships', response.body
|
||||
end
|
||||
|
||||
def test_xhr_create_user_membership_with_failure
|
||||
assert_no_difference 'Member.count' do
|
||||
post :create, :params => {
|
||||
:user_id => 7,
|
||||
:membership => {
|
||||
:project_ids => [3]
|
||||
},
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_include 'alert', response.body, "Alert message not sent"
|
||||
assert_include 'Role cannot be empty', response.body, "Error message not sent"
|
||||
end
|
||||
|
||||
def test_edit_user_membership
|
||||
get :edit, :params => {
|
||||
:user_id => 2,
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?][checked=checked]', 'membership[role_ids][]', '1'
|
||||
end
|
||||
|
||||
def test_xhr_edit_user_membership
|
||||
get :edit, :params => {
|
||||
:user_id => 2,
|
||||
:id => 1
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_update_user_membership
|
||||
assert_no_difference 'Member.count' do
|
||||
put :update, :params => {
|
||||
:user_id => 2,
|
||||
:id => 1,
|
||||
:membership => {
|
||||
:role_ids => [2]
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/users/2/edit?tab=memberships'
|
||||
end
|
||||
assert_equal [2], Member.find(1).role_ids
|
||||
end
|
||||
|
||||
def test_xhr_update_user_membership
|
||||
assert_no_difference 'Member.count' do
|
||||
put :update, :params => {
|
||||
:user_id => 2,
|
||||
:id => 1,
|
||||
:membership => {
|
||||
:role_ids => [2]
|
||||
},
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_equal [2], Member.find(1).role_ids
|
||||
assert_include '$("#member-1-roles").html("Developer").show();', response.body
|
||||
end
|
||||
|
||||
def test_destroy_user_membership
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:user_id => 2,
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/users/2/edit?tab=memberships'
|
||||
assert_nil Member.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_xhr_destroy_user_membership_js_format
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:user_id => 2,
|
||||
:id => 1
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_nil Member.find_by_id(1)
|
||||
assert_include 'tab-content-memberships', response.body
|
||||
end
|
||||
|
||||
def test_xhr_new_group_membership
|
||||
get :new, :params => {
|
||||
:group_id => 10
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create_group_membership
|
||||
assert_difference 'Group.find(10).members.count' do
|
||||
post :create, :params => {
|
||||
:group_id => 10,
|
||||
:membership => {
|
||||
:project_ids => [2],
|
||||
:role_ids => ['1', '2']
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_create_group_membership
|
||||
assert_difference 'Group.find(10).members.count' do
|
||||
post :create, :params => {
|
||||
:group_id => 10,
|
||||
:membership => {
|
||||
:project_ids => [2],
|
||||
:role_ids => ['1', '2']
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /OnlineStore/, response.body
|
||||
end
|
||||
|
||||
def test_xhr_create_group_membership_with_failure
|
||||
assert_no_difference 'Group.find(10).members.count' do
|
||||
post :create, :params => {
|
||||
:group_id => 10,
|
||||
:membership => {
|
||||
:project_ids => [999],
|
||||
:role_ids => ['1', '2']
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /alert/, response.body, "Alert message not sent"
|
||||
end
|
||||
|
||||
def test_update_group_membership
|
||||
assert_no_difference 'Group.find(10).members.count' do
|
||||
put :update, :params => {
|
||||
:group_id => 10,
|
||||
:id => 6,
|
||||
:membership => {
|
||||
:role_ids => ['1', '3']
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_update_group_membership
|
||||
assert_no_difference 'Group.find(10).members.count' do
|
||||
post :update, :params => {
|
||||
:group_id => 10,
|
||||
:id => 6,
|
||||
:membership => {
|
||||
:role_ids => ['1', '3']
|
||||
}
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_group_membership
|
||||
assert_difference 'Group.find(10).members.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:group_id => 10,
|
||||
:id => 6
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_destroy_group_membership
|
||||
assert_difference 'Group.find(10).members.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:group_id => 10,
|
||||
:id => 6
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
end
|
||||
end
|
||||
254
test/functional/project_enumerations_controller_test.rb
Normal file
254
test/functional/project_enumerations_controller_test.rb
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
# 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 ProjectEnumerationsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:custom_fields, :custom_fields_projects,
|
||||
:custom_fields_trackers, :custom_values,
|
||||
:time_entries
|
||||
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = nil
|
||||
Setting.default_language = 'en'
|
||||
end
|
||||
|
||||
def test_update_to_override_system_activities
|
||||
@request.session[:user_id] = 2 # manager
|
||||
billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
|
||||
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:enumerations => {
|
||||
"9"=> {"parent_id"=>"9", "custom_field_values"=> {"7" => "1"}, "active"=>"0"}, # Design, De-activate
|
||||
"10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
|
||||
"14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
|
||||
"11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
|
||||
}
|
||||
}
|
||||
|
||||
assert_response :redirect
|
||||
assert_redirected_to '/projects/ecookbook/settings/activities'
|
||||
|
||||
# Created project specific activities...
|
||||
project = Project.find('ecookbook')
|
||||
|
||||
# ... Design
|
||||
design = project.time_entry_activities.find_by_name("Design")
|
||||
assert design, "Project activity not found"
|
||||
|
||||
assert_equal 9, design.parent_id # Relate to the system activity
|
||||
assert_not_equal design.parent.id, design.id # Different records
|
||||
assert_equal design.parent.name, design.name # Same name
|
||||
assert !design.active?
|
||||
|
||||
# ... Development
|
||||
development = project.time_entry_activities.find_by_name("Development")
|
||||
assert development, "Project activity not found"
|
||||
|
||||
assert_equal 10, development.parent_id # Relate to the system activity
|
||||
assert_not_equal development.parent.id, development.id # Different records
|
||||
assert_equal development.parent.name, development.name # Same name
|
||||
assert development.active?
|
||||
assert_equal "0", development.custom_value_for(billable_field).value
|
||||
|
||||
# ... Inactive Activity
|
||||
previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
|
||||
assert previously_inactive, "Project activity not found"
|
||||
|
||||
assert_equal 14, previously_inactive.parent_id # Relate to the system activity
|
||||
assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
|
||||
assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
|
||||
assert previously_inactive.active?
|
||||
assert_equal "1", previously_inactive.custom_value_for(billable_field).value
|
||||
|
||||
# ... QA
|
||||
assert_nil project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
|
||||
end
|
||||
|
||||
def test_update_will_update_project_specific_activities
|
||||
@request.session[:user_id] = 2 # manager
|
||||
|
||||
project_activity = TimeEntryActivity.new({
|
||||
:name => 'Project Specific',
|
||||
:parent => TimeEntryActivity.first,
|
||||
:project => Project.find(1),
|
||||
:active => true
|
||||
})
|
||||
assert project_activity.save
|
||||
project_activity_two = TimeEntryActivity.new({
|
||||
:name => 'Project Specific Two',
|
||||
:parent => TimeEntryActivity.last,
|
||||
:project => Project.find(1),
|
||||
:active => true
|
||||
})
|
||||
assert project_activity_two.save
|
||||
|
||||
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:enumerations => {
|
||||
project_activity.id => {"custom_field_values"=> {"7" => "1"}, "active"=>"0"}, # De-activate
|
||||
project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
|
||||
}
|
||||
}
|
||||
|
||||
assert_response :redirect
|
||||
assert_redirected_to '/projects/ecookbook/settings/activities'
|
||||
|
||||
# Created project specific activities...
|
||||
project = Project.find('ecookbook')
|
||||
assert_equal 2, project.time_entry_activities.count
|
||||
|
||||
activity_one = project.time_entry_activities.find_by_name(project_activity.name)
|
||||
assert activity_one, "Project activity not found"
|
||||
assert_equal project_activity.id, activity_one.id
|
||||
assert !activity_one.active?
|
||||
|
||||
activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
|
||||
assert activity_two, "Project activity not found"
|
||||
assert_equal project_activity_two.id, activity_two.id
|
||||
assert !activity_two.active?
|
||||
end
|
||||
|
||||
def test_update_when_creating_new_activities_will_convert_existing_data
|
||||
assert_equal 3, TimeEntry.where(:activity_id => 9, :project_id => 1).count
|
||||
|
||||
@request.session[:user_id] = 2 # manager
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:enumerations => {
|
||||
"9"=> {
|
||||
"parent_id"=>"9", "custom_field_values"=> {
|
||||
"7" => "1"}, "active"=>"0"} # Design, De-activate
|
||||
|
||||
}
|
||||
}
|
||||
assert_response :redirect
|
||||
|
||||
# No more TimeEntries using the system activity
|
||||
assert_equal 0, TimeEntry.where(:activity_id => 9, :project_id => 1).count,
|
||||
"Time Entries still assigned to system activities"
|
||||
# All TimeEntries using project activity
|
||||
project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
|
||||
assert_equal 3, TimeEntry.where(:activity_id => project_specific_activity.id,
|
||||
:project_id => 1).count
|
||||
"No Time Entries assigned to the project activity"
|
||||
end
|
||||
|
||||
def test_update_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
|
||||
# TODO: Need to cause an exception on create but these tests
|
||||
# aren't setup for mocking. Just create a record now so the
|
||||
# second one is a dupicate
|
||||
parent = TimeEntryActivity.find(9)
|
||||
TimeEntryActivity.create!({:name => parent.name, :project_id => 1,
|
||||
:position => parent.position, :active => true, :parent_id => 9})
|
||||
TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1),
|
||||
:issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
|
||||
assert_equal 3, TimeEntry.where(:activity_id => 9, :project_id => 1).count
|
||||
assert_equal 1, TimeEntry.where(:activity_id => 10, :project_id => 1).count
|
||||
|
||||
@request.session[:user_id] = 2 # manager
|
||||
put :update, :params => {
|
||||
:project_id => 1,
|
||||
:enumerations => {
|
||||
# Design
|
||||
"9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"},
|
||||
# Development, Change custom value
|
||||
"10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}
|
||||
}
|
||||
}
|
||||
assert_response :redirect
|
||||
|
||||
# TimeEntries shouldn't have been reassigned on the failed record
|
||||
assert_equal 3, TimeEntry.where(:activity_id => 9,
|
||||
:project_id => 1).count
|
||||
"Time Entries are not assigned to system activities"
|
||||
# TimeEntries shouldn't have been reassigned on the saved record either
|
||||
assert_equal 1, TimeEntry.where(:activity_id => 10,
|
||||
:project_id => 1).count
|
||||
"Time Entries are not assigned to system activities"
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2 # manager
|
||||
project_activity = TimeEntryActivity.new({
|
||||
:name => 'Project Specific',
|
||||
:parent => TimeEntryActivity.first,
|
||||
:project => Project.find(1),
|
||||
:active => true
|
||||
})
|
||||
assert project_activity.save
|
||||
project_activity_two = TimeEntryActivity.new({
|
||||
:name => 'Project Specific Two',
|
||||
:parent => TimeEntryActivity.last,
|
||||
:project => Project.find(1),
|
||||
:active => true
|
||||
})
|
||||
assert project_activity_two.save
|
||||
|
||||
delete :destroy, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :redirect
|
||||
assert_redirected_to '/projects/ecookbook/settings/activities'
|
||||
|
||||
assert_nil TimeEntryActivity.find_by_id(project_activity.id)
|
||||
assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
|
||||
end
|
||||
|
||||
def test_destroy_should_reassign_time_entries_back_to_the_system_activity
|
||||
@request.session[:user_id] = 2 # manager
|
||||
project_activity = TimeEntryActivity.new({
|
||||
:name => 'Project Specific Design',
|
||||
:parent => TimeEntryActivity.find(9),
|
||||
:project => Project.find(1),
|
||||
:active => true
|
||||
})
|
||||
assert project_activity.save
|
||||
assert TimeEntry.where(["project_id = ? AND activity_id = ?", 1, 9]).
|
||||
update_all("activity_id = '#{project_activity.id}'")
|
||||
assert_equal 3, TimeEntry.where(:activity_id => project_activity.id,
|
||||
:project_id => 1).count
|
||||
delete :destroy, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :redirect
|
||||
assert_redirected_to '/projects/ecookbook/settings/activities'
|
||||
|
||||
assert_nil TimeEntryActivity.find_by_id(project_activity.id)
|
||||
assert_equal 0, TimeEntry.where(
|
||||
:activity_id => project_activity.id,
|
||||
:project_id => 1
|
||||
).count,
|
||||
"TimeEntries still assigned to project specific activity"
|
||||
assert_equal 3, TimeEntry.where(
|
||||
:activity_id => 9,
|
||||
:project_id => 1
|
||||
).count,
|
||||
"TimeEntries still assigned to project specific activity"
|
||||
end
|
||||
end
|
||||
982
test/functional/projects_controller_test.rb
Normal file
982
test/functional/projects_controller_test.rb
Normal file
|
|
@ -0,0 +1,982 @@
|
|||
# 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 ProjectsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :versions, :users, :email_addresses, :roles, :members,
|
||||
:member_roles, :issues, :journals, :journal_details,
|
||||
:trackers, :projects_trackers, :issue_statuses,
|
||||
:enabled_modules, :enumerations, :boards, :messages,
|
||||
:attachments, :custom_fields, :custom_values, :time_entries,
|
||||
:wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = nil
|
||||
Setting.default_language = 'en'
|
||||
end
|
||||
|
||||
def test_index_by_anonymous_should_not_show_private_projects
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
assert_select 'ul' do
|
||||
assert_select 'li' do
|
||||
assert_select 'a', :text => 'eCookbook'
|
||||
assert_select 'ul' do
|
||||
assert_select 'a', :text => 'Child of private child'
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_select 'a', :text => /Private child of eCookbook/, :count => 0
|
||||
end
|
||||
|
||||
def test_index_atom
|
||||
get :index, :params => {
|
||||
:format => 'atom'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'feed>title', :text => 'Redmine: Latest projects'
|
||||
assert_select 'feed>entry', :count => Project.visible(User.current).count
|
||||
end
|
||||
|
||||
def test_autocomplete_js
|
||||
get :autocomplete, :params => {
|
||||
:format => 'js',
|
||||
:q => 'coo'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
test "#index by non-admin user with view_time_entries permission should show overall spent time link" do
|
||||
@request.session[:user_id] = 3
|
||||
get :index
|
||||
assert_select 'a[href=?]', '/time_entries'
|
||||
end
|
||||
|
||||
test "#index by non-admin user without view_time_entries permission should not show overall spent time link" do
|
||||
Role.find(2).remove_permission! :view_time_entries
|
||||
Role.non_member.remove_permission! :view_time_entries
|
||||
Role.anonymous.remove_permission! :view_time_entries
|
||||
@request.session[:user_id] = 3
|
||||
|
||||
get :index
|
||||
assert_select 'a[href=?]', '/time_entries', 0
|
||||
end
|
||||
|
||||
test "#index by non-admin user with permission should show add project link" do
|
||||
Role.find(1).add_permission! :add_project
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_select 'a[href=?]', '/projects/new'
|
||||
end
|
||||
|
||||
test "#new by admin user should accept get" do
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'project[name]'
|
||||
assert_select 'select[name=?]', 'project[parent_id]'
|
||||
end
|
||||
|
||||
test "#new by non-admin user with add_project permission should accept get" do
|
||||
Role.non_member.add_permission! :add_project
|
||||
@request.session[:user_id] = 9
|
||||
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'project[name]'
|
||||
assert_select 'select[name=?]', 'project[parent_id]', 0
|
||||
end
|
||||
|
||||
test "#new by non-admin user with add_subprojects permission should accept get" do
|
||||
Role.find(1).remove_permission! :add_project
|
||||
Role.find(1).add_permission! :add_subprojects
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :new, :params => {
|
||||
:parent_id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'project[parent_id]' do
|
||||
# parent project selected
|
||||
assert_select 'option[value="1"][selected=selected]'
|
||||
# no empty value
|
||||
assert_select 'option[value=""]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_by_non_admin_should_display_modules_if_default_role_is_allowed_to_select_modules
|
||||
Role.non_member.add_permission!(:add_project)
|
||||
default_role = Role.generate!(:permissions => [:view_issues])
|
||||
user = User.generate!
|
||||
@request.session[:user_id] = user.id
|
||||
|
||||
with_settings :new_project_user_role_id => default_role.id.to_s do
|
||||
get :new
|
||||
assert_select 'input[name=?]', 'project[enabled_module_names][]', 0
|
||||
|
||||
default_role.add_permission!(:select_project_modules)
|
||||
get :new
|
||||
assert_select 'input[name=?]', 'project[enabled_module_names][]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_should_not_display_invalid_search_link
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select '#quick-search form[action=?]', '/search'
|
||||
assert_select '#quick-search a[href=?]', '/search'
|
||||
end
|
||||
|
||||
test "#create by admin user should create a new project" do
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:homepage => 'http://weblog',
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
},
|
||||
:tracker_ids => ['1', '3'],
|
||||
# an issue custom field that is not for all project
|
||||
:issue_custom_field_ids => ['9'],
|
||||
:enabled_module_names => ['issue_tracking', 'news', 'repository']
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/projects/blog/settings'
|
||||
|
||||
project = Project.find_by_name('blog')
|
||||
assert_kind_of Project, project
|
||||
assert project.active?
|
||||
assert_equal 'weblog', project.description
|
||||
assert_equal 'http://weblog', project.homepage
|
||||
assert_equal true, project.is_public?
|
||||
assert_nil project.parent
|
||||
assert_equal 'Beta', project.custom_value_for(3).value
|
||||
assert_equal [1, 3], project.trackers.map(&:id).sort
|
||||
assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
|
||||
assert project.issue_custom_fields.include?(IssueCustomField.find(9))
|
||||
end
|
||||
|
||||
test "#create by admin user should create a new subproject" do
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
assert_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
},
|
||||
:parent_id => 1
|
||||
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/projects/blog/settings'
|
||||
end
|
||||
|
||||
project = Project.find_by_name('blog')
|
||||
assert_kind_of Project, project
|
||||
assert_equal Project.find(1), project.parent
|
||||
end
|
||||
|
||||
test "#create by admin user should continue" do
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
assert_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:identifier => "blog"
|
||||
},
|
||||
:continue => 'Create and continue'
|
||||
}
|
||||
end
|
||||
assert_redirected_to '/projects/new'
|
||||
end
|
||||
|
||||
test "#create by non-admin user with add_project permission should create a new project" do
|
||||
Role.non_member.add_permission! :add_project
|
||||
@request.session[:user_id] = 9
|
||||
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
},
|
||||
:tracker_ids => ['1', '3'],
|
||||
:enabled_module_names => ['issue_tracking', 'news', 'repository']
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
assert_redirected_to '/projects/blog/settings'
|
||||
|
||||
project = Project.find_by_name('blog')
|
||||
assert_kind_of Project, project
|
||||
assert_equal 'weblog', project.description
|
||||
assert_equal true, project.is_public?
|
||||
assert_equal [1, 3], project.trackers.map(&:id).sort
|
||||
assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
|
||||
|
||||
# User should be added as a project member
|
||||
assert User.find(9).member_of?(project)
|
||||
assert_equal 1, project.members.size
|
||||
end
|
||||
|
||||
test "#create by non-admin user with add_project permission should fail with parent_id" do
|
||||
Role.non_member.add_permission! :add_project
|
||||
User.find(9).update! :language => 'en'
|
||||
@request.session[:user_id] = 9
|
||||
|
||||
assert_no_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
},
|
||||
:parent_id => 1
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /Subproject of is invalid/
|
||||
end
|
||||
|
||||
test "#create by non-admin user with add_subprojects permission should create a project with a parent_id" do
|
||||
Role.find(1).remove_permission! :add_project
|
||||
Role.find(1).add_permission! :add_subprojects
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
},
|
||||
:parent_id => 1
|
||||
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/projects/blog/settings'
|
||||
project = Project.find_by_name('blog')
|
||||
assert_equal 1, project.parent_id
|
||||
end
|
||||
|
||||
test "#create by non-admin user with add_subprojects permission should fail without parent_id" do
|
||||
Role.find(1).remove_permission! :add_project
|
||||
Role.find(1).add_permission! :add_subprojects
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /Subproject of is invalid/
|
||||
end
|
||||
|
||||
test "#create by non-admin user with add_subprojects permission should fail with unauthorized parent_id" do
|
||||
Role.find(1).remove_permission! :add_project
|
||||
Role.find(1).add_permission! :add_subprojects
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert !User.find(2).member_of?(Project.find(6))
|
||||
assert_no_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:description => "weblog",
|
||||
:identifier => "blog",
|
||||
:is_public => 1,
|
||||
:custom_field_values => {
|
||||
'3' => 'Beta'
|
||||
},
|
||||
:parent_id => 6
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /Subproject of is invalid/
|
||||
end
|
||||
|
||||
def test_create_by_non_admin_should_accept_modules_if_default_role_is_allowed_to_select_modules
|
||||
Role.non_member.add_permission!(:add_project)
|
||||
default_role = Role.generate!(:permissions => [:view_issues, :add_project])
|
||||
user = User.generate!
|
||||
@request.session[:user_id] = user.id
|
||||
|
||||
with_settings :new_project_user_role_id => default_role.id.to_s, :default_projects_modules => %w(news files) do
|
||||
project = new_record(Project) do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog1",
|
||||
:identifier => "blog1",
|
||||
:enabled_module_names => ["issue_tracking", "repository"]
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_equal %w(files news), project.enabled_module_names.sort
|
||||
|
||||
default_role.add_permission!(:select_project_modules)
|
||||
project = new_record(Project) do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog2",
|
||||
:identifier => "blog2",
|
||||
:enabled_module_names => ["issue_tracking", "repository"]
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_equal %w(issue_tracking repository), project.enabled_module_names.sort
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_subproject_with_inherit_members_should_inherit_members
|
||||
Role.find_by_name('Manager').add_permission! :add_subprojects
|
||||
parent = Project.find(1)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => 'inherited',
|
||||
:identifier => 'inherited',
|
||||
:parent_id => parent.id,
|
||||
:inherit_members => '1'
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
project = Project.order('id desc').first
|
||||
assert_equal 'inherited', project.name
|
||||
assert_equal parent, project.parent
|
||||
assert project.memberships.count > 0
|
||||
assert_equal parent.memberships.count, project.memberships.count
|
||||
end
|
||||
|
||||
def test_create_should_preserve_modules_on_validation_failure
|
||||
with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
|
||||
@request.session[:user_id] = 1
|
||||
assert_no_difference 'Project.count' do
|
||||
post :create, :params => {
|
||||
:project => {
|
||||
:name => "blog",
|
||||
:identifier => "",
|
||||
:enabled_module_names => %w(issue_tracking news)
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
%w(issue_tracking news).each do |mod|
|
||||
assert_select 'input[name=?][value=?][checked=checked]', 'project[enabled_module_names][]', mod
|
||||
end
|
||||
assert_select 'input[name=?][checked=checked]', 'project[enabled_module_names][]', :count => 2
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_by_id
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '#header h1', :text => "eCookbook"
|
||||
end
|
||||
|
||||
def test_show_by_identifier
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '#header h1', :text => "eCookbook"
|
||||
end
|
||||
|
||||
def test_show_should_not_display_empty_sidebar
|
||||
p = Project.find(1)
|
||||
p.enabled_module_names = []
|
||||
p.save!
|
||||
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '#main.nosidebar'
|
||||
end
|
||||
|
||||
def test_show_should_display_visible_custom_fields
|
||||
ProjectCustomField.find_by_name('Development status').update_attribute :visible, true
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'li', :text => /Development status/
|
||||
end
|
||||
|
||||
def test_show_should_not_display_hidden_custom_fields
|
||||
ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'li', :text => /Development status/, :count => 0
|
||||
end
|
||||
|
||||
def test_show_should_not_display_blank_custom_fields_with_multiple_values
|
||||
f1 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Foo Bar), :multiple => true
|
||||
f2 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Baz Qux), :multiple => true
|
||||
project = Project.generate!(:custom_field_values => {f2.id.to_s => %w(Qux)})
|
||||
|
||||
get :show, :params => {
|
||||
:id => project.id
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'li', :text => /#{f1.name}/, :count => 0
|
||||
assert_select 'li', :text => /#{f2.name}/
|
||||
end
|
||||
|
||||
def test_show_should_not_display_blank_text_custom_fields
|
||||
f1 = ProjectCustomField.generate! :field_format => 'text'
|
||||
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'li', :text => /#{f1.name}/, :count => 0
|
||||
end
|
||||
|
||||
def test_show_should_not_fail_when_custom_values_are_nil
|
||||
project = Project.find_by_identifier('ecookbook')
|
||||
project.custom_values.first.update_attribute(:value, nil)
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def show_archived_project_should_be_denied
|
||||
project = Project.find_by_identifier('ecookbook')
|
||||
project.archive!
|
||||
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response 403
|
||||
assert_select 'p', :text => /archived/
|
||||
assert_not_include project.name, response.body
|
||||
end
|
||||
|
||||
def test_show_should_not_show_private_subprojects_that_are_not_visible
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'a', :text => /Private child/, :count => 0
|
||||
end
|
||||
|
||||
def test_show_should_show_private_subprojects_that_are_visible
|
||||
@request.session[:user_id] = 2 # manager who is a member of the private subproject
|
||||
get :show, :params => {
|
||||
:id => 'ecookbook'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'a', :text => /Private child/
|
||||
end
|
||||
|
||||
def test_show_by_member_on_leaf_project_should_display_issue_counts
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {
|
||||
:id => 'onlinestore'
|
||||
}
|
||||
assert_response :success
|
||||
# Make sure there's a > 0 issue count
|
||||
assert_select 'table.issue-report td.total a', :text => %r{\A[1-9]\d*\z}
|
||||
end
|
||||
|
||||
def test_settings
|
||||
@request.session[:user_id] = 2 # manager
|
||||
get :settings, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'project[name]'
|
||||
end
|
||||
|
||||
def test_settings_of_subproject
|
||||
@request.session[:user_id] = 2
|
||||
get :settings, :params => {
|
||||
:id => 'private-child'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[type=checkbox][name=?]', 'project[inherit_members]'
|
||||
end
|
||||
|
||||
def test_settings_should_be_denied_for_member_on_closed_project
|
||||
Project.find(1).close
|
||||
@request.session[:user_id] = 2 # manager
|
||||
|
||||
get :settings, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_settings_should_be_denied_for_anonymous_on_closed_project
|
||||
Project.find(1).close
|
||||
|
||||
get :settings, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_setting_with_wiki_module_and_no_wiki
|
||||
Project.find(1).wiki.destroy
|
||||
Role.find(1).add_permission! :manage_wiki
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :settings, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form[action=?]', '/projects/ecookbook/wiki' do
|
||||
assert_select 'input[name=?]', 'wiki[start_page]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_settings_should_accept_version_status_filter
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :settings, :params => {
|
||||
:id => 'ecookbook',
|
||||
:tab => 'versions',
|
||||
:version_status => 'locked'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=version_status]' do
|
||||
assert_select 'option[value=locked][selected=selected]'
|
||||
end
|
||||
assert_select 'table.versions tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'td.name', :text => '1.0'
|
||||
end
|
||||
assert_select 'a#tab-versions[href=?]', '/projects/ecookbook/settings/versions?version_status=locked'
|
||||
end
|
||||
|
||||
def test_settings_should_accept_version_name_filter
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :settings, :params => {
|
||||
:id => 'ecookbook',
|
||||
:tab => 'versions',
|
||||
:version_status => '',
|
||||
:version_name => '.1'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=version_name][value=?]', '.1'
|
||||
assert_select 'table.versions tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'td.name', :text => '0.1'
|
||||
end
|
||||
assert_select 'a#tab-versions[href=?]', '/projects/ecookbook/settings/versions?version_name=.1&version_status='
|
||||
end
|
||||
|
||||
def test_settings_should_show_locked_members
|
||||
user = User.generate!
|
||||
member = User.add_to_project(user, Project.find(1))
|
||||
user.lock!
|
||||
assert user.reload.locked?
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :settings, :params => {
|
||||
:id => 'ecookbook',
|
||||
:tab => 'members'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select "tr#member-#{member.id}"
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 2 # manager
|
||||
post :update, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => 'Test changed name',
|
||||
:issue_custom_field_ids => ['']
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/settings'
|
||||
project = Project.find(1)
|
||||
assert_equal 'Test changed name', project.name
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 2 # manager
|
||||
post :update, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_update_should_be_denied_for_member_on_closed_project
|
||||
Project.find(1).close
|
||||
@request.session[:user_id] = 2 # manager
|
||||
|
||||
post :update, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => 'Closed'
|
||||
}
|
||||
}
|
||||
assert_response 403
|
||||
assert_equal 'eCookbook', Project.find(1).name
|
||||
end
|
||||
|
||||
def test_update_should_be_denied_for_anonymous_on_closed_project
|
||||
Project.find(1).close
|
||||
|
||||
post :update, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => 'Closed'
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal 'eCookbook', Project.find(1).name
|
||||
end
|
||||
|
||||
def test_update_child_project_without_parent_permission_should_not_show_validation_error
|
||||
child = Project.generate_with_parent!
|
||||
user = User.generate!
|
||||
User.add_to_project(user, child, Role.generate!(:permissions => [:edit_project]))
|
||||
@request.session[:user_id] = user.id
|
||||
|
||||
post :update, :params => {
|
||||
:id => child.id,
|
||||
:project => {
|
||||
:name => 'Updated'
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
assert_match /Successful update/, flash[:notice]
|
||||
end
|
||||
|
||||
def test_modules
|
||||
@request.session[:user_id] = 2
|
||||
Project.find(1).enabled_module_names = ['issue_tracking', 'news']
|
||||
|
||||
post :modules, :params => {
|
||||
:id => 1,
|
||||
:enabled_module_names => ['issue_tracking', 'repository', 'documents']
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/settings/modules'
|
||||
assert_equal ['documents', 'issue_tracking', 'repository'], Project.find(1).enabled_module_names.sort
|
||||
end
|
||||
|
||||
def test_destroy_leaf_project_without_confirmation_should_show_confirmation
|
||||
@request.session[:user_id] = 1 # admin
|
||||
|
||||
assert_no_difference 'Project.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 2
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
assert_select '.warning', :text => /Are you sure you want to delete this project/
|
||||
end
|
||||
|
||||
def test_destroy_without_confirmation_should_show_confirmation_with_subprojects
|
||||
@request.session[:user_id] = 1 # admin
|
||||
|
||||
assert_no_difference 'Project.count' do
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
assert_select 'strong',
|
||||
:text => ['Private child of eCookbook',
|
||||
'Child of private child, eCookbook Subproject 1',
|
||||
'eCookbook Subproject 2'].join(', ')
|
||||
end
|
||||
|
||||
def test_destroy_with_confirmation_should_destroy_the_project_and_subprojects
|
||||
@request.session[:user_id] = 1 # admin
|
||||
|
||||
assert_difference 'Project.count', -5 do
|
||||
delete :destroy, :params => {
|
||||
:id => 1,
|
||||
:confirm => 1
|
||||
}
|
||||
assert_redirected_to '/admin/projects'
|
||||
end
|
||||
assert_nil Project.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_archive
|
||||
@request.session[:user_id] = 1 # admin
|
||||
post :archive, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/admin/projects'
|
||||
assert !Project.find(1).active?
|
||||
end
|
||||
|
||||
def test_archive_with_failure
|
||||
@request.session[:user_id] = 1
|
||||
Project.any_instance.stubs(:archive).returns(false)
|
||||
post :archive, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/admin/projects'
|
||||
assert_match /project cannot be archived/i, flash[:error]
|
||||
end
|
||||
|
||||
def test_unarchive
|
||||
@request.session[:user_id] = 1 # admin
|
||||
Project.find(1).archive
|
||||
post :unarchive, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/admin/projects'
|
||||
assert Project.find(1).active?
|
||||
end
|
||||
|
||||
def test_close
|
||||
@request.session[:user_id] = 2
|
||||
post :close, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook'
|
||||
assert_equal Project::STATUS_CLOSED, Project.find(1).status
|
||||
end
|
||||
|
||||
def test_reopen
|
||||
Project.find(1).close
|
||||
@request.session[:user_id] = 2
|
||||
post :reopen, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook'
|
||||
assert Project.find(1).active?
|
||||
end
|
||||
|
||||
def test_project_breadcrumbs_should_be_limited_to_3_ancestors
|
||||
CustomField.delete_all
|
||||
parent = nil
|
||||
6.times do |i|
|
||||
p = Project.generate_with_parent!(parent)
|
||||
get :show, :params => {
|
||||
:id => p
|
||||
}
|
||||
assert_select '#header h1' do
|
||||
assert_select 'a', :count => [i, 3].min
|
||||
end
|
||||
|
||||
parent = p
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_copy
|
||||
@request.session[:user_id] = 1 # admin
|
||||
orig = Project.find(1)
|
||||
|
||||
get :copy, :params => {
|
||||
:id => orig.id
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'textarea[name=?]', 'project[description]', :text => orig.description
|
||||
assert_select 'input[name=?][value=?]', 'project[enabled_module_names][]', 'issue_tracking', 1
|
||||
end
|
||||
|
||||
def test_get_copy_with_invalid_source_should_respond_with_404
|
||||
@request.session[:user_id] = 1
|
||||
get :copy, :params => {
|
||||
:id => 99
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_copy_should_preselect_custom_fields
|
||||
field1 = IssueCustomField.generate!(:is_for_all => false)
|
||||
field2 = IssueCustomField.generate!(:is_for_all => false)
|
||||
source = Project.generate!(:issue_custom_fields => [field1])
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
get :copy, :params => {
|
||||
:id => source.id
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'fieldset#project_issue_custom_fields' do
|
||||
assert_select 'input[type=checkbox][value=?][checked=checked]', field1.id.to_s
|
||||
assert_select 'input[type=checkbox][value=?]:not([checked])', field2.id.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_copy_should_copy_requested_items
|
||||
@request.session[:user_id] = 1 # admin
|
||||
CustomField.delete_all
|
||||
|
||||
assert_difference 'Project.count' do
|
||||
post :copy, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => 'Copy',
|
||||
:identifier => 'unique-copy',
|
||||
:tracker_ids => ['1', '2', '3', ''],
|
||||
:enabled_module_names => %w(issue_tracking time_tracking)
|
||||
|
||||
},
|
||||
:only => %w(issues versions)
|
||||
}
|
||||
end
|
||||
project = Project.find('unique-copy')
|
||||
source = Project.find(1)
|
||||
assert_equal %w(issue_tracking time_tracking), project.enabled_module_names.sort
|
||||
|
||||
assert_equal source.versions.count, project.versions.count, "All versions were not copied"
|
||||
assert_equal source.issues.count, project.issues.count, "All issues were not copied"
|
||||
assert_equal 0, project.members.count
|
||||
end
|
||||
|
||||
def test_post_copy_should_redirect_to_settings_when_successful
|
||||
@request.session[:user_id] = 1 # admin
|
||||
post :copy, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => 'Copy',
|
||||
:identifier => 'unique-copy'
|
||||
}
|
||||
}
|
||||
assert_response :redirect
|
||||
assert_redirected_to :controller => 'projects', :action => 'settings', :id => 'unique-copy'
|
||||
end
|
||||
|
||||
def test_post_copy_with_failure
|
||||
@request.session[:user_id] = 1
|
||||
post :copy, :params => {
|
||||
:id => 1,
|
||||
:project => {
|
||||
:name => 'Copy',
|
||||
:identifier => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Identifier cannot be blank/
|
||||
end
|
||||
|
||||
def test_jump_without_project_id_should_redirect_to_active_tab
|
||||
get :index, :params => {
|
||||
:jump => 'issues'
|
||||
}
|
||||
assert_redirected_to '/issues'
|
||||
end
|
||||
|
||||
def test_jump_should_not_redirect_to_unknown_tab
|
||||
get :index, :params => {
|
||||
:jump => 'foobar'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_jump_should_redirect_to_active_tab
|
||||
get :show, :params => {
|
||||
:id => 1,
|
||||
:jump => 'issues'
|
||||
}
|
||||
assert_redirected_to '/projects/ecookbook/issues'
|
||||
end
|
||||
|
||||
def test_jump_should_not_redirect_to_inactive_tab
|
||||
get :show, :params => {
|
||||
:id => 3,
|
||||
:jump => 'documents'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_jump_should_not_redirect_to_unknown_tab
|
||||
get :show, :params => {
|
||||
:id => 3,
|
||||
:jump => 'foobar'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_body_should_have_project_css_class
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_select 'body.project-ecookbook'
|
||||
end
|
||||
end
|
||||
599
test/functional/queries_controller_test.rb
Normal file
599
test/functional/queries_controller_test.rb
Normal file
|
|
@ -0,0 +1,599 @@
|
|||
# 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 QueriesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :enabled_modules,
|
||||
:users, :email_addresses,
|
||||
:members, :member_roles, :roles,
|
||||
:trackers, :issue_statuses, :issue_categories, :enumerations, :versions,
|
||||
:issues, :custom_fields, :custom_values,
|
||||
:queries
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
# HTML response not implemented
|
||||
assert_response 406
|
||||
end
|
||||
|
||||
def test_new_project_query
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value="0"][checked=checked]', 'query[visibility]'
|
||||
assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked]):not([disabled])'
|
||||
assert_select 'select[name=?]', 'c[]' do
|
||||
assert_select 'option[value=tracker]'
|
||||
assert_select 'option[value=subject]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_global_query
|
||||
@request.session[:user_id] = 2
|
||||
get :new
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'query[visibility]', 0
|
||||
assert_select 'input[name=query_is_for_all][type=checkbox][checked]:not([disabled])'
|
||||
end
|
||||
|
||||
def test_new_on_invalid_project
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 'invalid'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_new_time_entry_query
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1,
|
||||
:type => 'TimeEntryQuery'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=type][value=?]', 'TimeEntryQuery'
|
||||
end
|
||||
|
||||
def test_new_time_entry_query_with_issue_tracking_module_disabled_should_be_allowed
|
||||
Project.find(1).disable_module! :issue_tracking
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:project_id => 1,
|
||||
:type => 'TimeEntryQuery'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_create_project_public_query
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:default_columns => '1',
|
||||
:f => ["status_id", "assigned_to_id"],
|
||||
:op => {
|
||||
"assigned_to_id" => "=", "status_id" => "o"
|
||||
},
|
||||
:v => {
|
||||
"assigned_to_id" => ["1"], "status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_new_project_public_query", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
|
||||
q = Query.find_by_name('test_new_project_public_query')
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
|
||||
assert q.is_public?
|
||||
assert q.has_default_columns?
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_create_project_private_query
|
||||
@request.session[:user_id] = 3
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:default_columns => '1',
|
||||
:fields => ["status_id", "assigned_to_id"],
|
||||
:operators => {
|
||||
"assigned_to_id" => "=", "status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"assigned_to_id" => ["1"], "status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_new_project_private_query", "visibility" => "0"
|
||||
}
|
||||
}
|
||||
|
||||
q = Query.find_by_name('test_new_project_private_query')
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
|
||||
assert !q.is_public?
|
||||
assert q.has_default_columns?
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_create_project_roles_query
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:default_columns => '1',
|
||||
:fields => ["status_id", "assigned_to_id"],
|
||||
:operators => {
|
||||
"assigned_to_id" => "=", "status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"assigned_to_id" => ["1"], "status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_create_project_roles_query", "visibility" => "1", "role_ids" => ["1", "2", ""]
|
||||
}
|
||||
}
|
||||
|
||||
q = Query.find_by_name('test_create_project_roles_query')
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
|
||||
assert_equal Query::VISIBILITY_ROLES, q.visibility
|
||||
assert_equal [1, 2], q.roles.ids.sort
|
||||
end
|
||||
|
||||
def test_create_global_private_query_with_custom_columns
|
||||
@request.session[:user_id] = 3
|
||||
post :create, :params => {
|
||||
:fields => ["status_id", "assigned_to_id"],
|
||||
:operators => {
|
||||
"assigned_to_id" => "=", "status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"assigned_to_id" => ["me"], "status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_new_global_private_query", "visibility" => "0"
|
||||
},
|
||||
:c => ["", "tracker", "subject", "priority", "category"]
|
||||
}
|
||||
|
||||
q = Query.find_by_name('test_new_global_private_query')
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
|
||||
assert !q.is_public?
|
||||
assert !q.has_default_columns?
|
||||
assert_equal [:id, :tracker, :subject, :priority, :category], q.columns.collect {|c| c.name}
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_create_global_query_with_custom_filters
|
||||
@request.session[:user_id] = 3
|
||||
post :create, :params => {
|
||||
:fields => ["assigned_to_id"],
|
||||
:operators => {
|
||||
"assigned_to_id" => "="
|
||||
},
|
||||
:values => {
|
||||
"assigned_to_id" => ["me"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_new_global_query"
|
||||
}
|
||||
}
|
||||
|
||||
q = Query.find_by_name('test_new_global_query')
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
|
||||
assert !q.is_public?
|
||||
assert !q.has_filter?(:status_id)
|
||||
assert_equal ['assigned_to_id'], q.filters.keys
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_create_with_sort
|
||||
@request.session[:user_id] = 1
|
||||
post :create, :params => {
|
||||
:default_columns => '1',
|
||||
:operators => {
|
||||
"status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
:name => "test_new_with_sort",
|
||||
:visibility => "2",
|
||||
:sort_criteria => {
|
||||
"0" => ["due_date", "desc"], "1" => ["tracker", ""]}
|
||||
}
|
||||
}
|
||||
|
||||
query = Query.find_by_name("test_new_with_sort")
|
||||
assert_not_nil query
|
||||
assert_equal [['due_date', 'desc'], ['tracker', 'asc']], query.sort_criteria
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference '::Query.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:query => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'query[name]'
|
||||
end
|
||||
|
||||
def test_create_global_query_from_gantt
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'IssueQuery.count' do
|
||||
post :create, :params => {
|
||||
:gantt => 1,
|
||||
:operators => {
|
||||
"status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
:name => "test_create_from_gantt",
|
||||
:draw_relations => '1',
|
||||
:draw_progress_line => '1'
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
query = IssueQuery.order('id DESC').first
|
||||
assert_redirected_to "/issues/gantt?query_id=#{query.id}"
|
||||
assert_equal true, query.draw_relations
|
||||
assert_equal true, query.draw_progress_line
|
||||
end
|
||||
|
||||
def test_create_project_query_from_gantt
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'IssueQuery.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:gantt => 1,
|
||||
:operators => {
|
||||
"status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
:name => "test_create_from_gantt",
|
||||
:draw_relations => '0',
|
||||
:draw_progress_line => '0'
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
query = IssueQuery.order('id DESC').first
|
||||
assert_redirected_to "/projects/ecookbook/issues/gantt?query_id=#{query.id}"
|
||||
assert_equal false, query.draw_relations
|
||||
assert_equal false, query.draw_progress_line
|
||||
end
|
||||
|
||||
def test_create_project_public_query_should_force_private_without_manage_public_queries_permission
|
||||
@request.session[:user_id] = 3
|
||||
query = new_record(Query) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:query => {
|
||||
"name" => "name", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_not_nil query.project
|
||||
assert_equal Query::VISIBILITY_PRIVATE, query.visibility
|
||||
end
|
||||
|
||||
def test_create_global_public_query_should_force_private_without_manage_public_queries_permission
|
||||
@request.session[:user_id] = 3
|
||||
query = new_record(Query) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:query_is_for_all => '1',
|
||||
:query => {
|
||||
"name" => "name", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_nil query.project
|
||||
assert_equal Query::VISIBILITY_PRIVATE, query.visibility
|
||||
end
|
||||
|
||||
def test_create_project_public_query_with_manage_public_queries_permission
|
||||
@request.session[:user_id] = 2
|
||||
query = new_record(Query) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:query => {
|
||||
"name" => "name", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_not_nil query.project
|
||||
assert_equal Query::VISIBILITY_PUBLIC, query.visibility
|
||||
end
|
||||
|
||||
def test_create_global_public_query_should_force_private_with_manage_public_queries_permission
|
||||
@request.session[:user_id] = 2
|
||||
query = new_record(Query) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:query_is_for_all => '1',
|
||||
:query => {
|
||||
"name" => "name", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_nil query.project
|
||||
assert_equal Query::VISIBILITY_PRIVATE, query.visibility
|
||||
end
|
||||
|
||||
def test_create_global_public_query_by_admin
|
||||
@request.session[:user_id] = 1
|
||||
query = new_record(Query) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:query_is_for_all => '1',
|
||||
:query => {
|
||||
"name" => "name", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_nil query.project
|
||||
assert_equal Query::VISIBILITY_PUBLIC, query.visibility
|
||||
end
|
||||
|
||||
def test_create_project_public_time_entry_query
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
q = new_record(TimeEntryQuery) do
|
||||
post :create, :params => {
|
||||
:project_id => 'ecookbook',
|
||||
:type => 'TimeEntryQuery',
|
||||
:default_columns => '1',
|
||||
:f => ["spent_on"],
|
||||
:op => {
|
||||
"spent_on" => "="
|
||||
},
|
||||
:v => {
|
||||
"spent_on" => ["2016-07-14"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_new_project_public_query", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => 'ecookbook', :query_id => q.id
|
||||
assert q.is_public?
|
||||
assert q.has_default_columns?
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_edit_global_public_query
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :params => {
|
||||
:id => 4
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value="2"][checked=checked]', 'query[visibility]'
|
||||
assert_select 'input[name=query_is_for_all][type=checkbox][checked=checked]'
|
||||
end
|
||||
|
||||
def test_edit_global_private_query
|
||||
@request.session[:user_id] = 3
|
||||
get :edit, :params => {
|
||||
:id => 3
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'query[visibility]', 0
|
||||
assert_select 'input[name=query_is_for_all][type=checkbox][checked=checked]'
|
||||
end
|
||||
|
||||
def test_edit_project_private_query
|
||||
@request.session[:user_id] = 3
|
||||
get :edit, :params => {
|
||||
:id => 2
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'query[visibility]', 0
|
||||
assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked])'
|
||||
end
|
||||
|
||||
def test_edit_project_public_query
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value="2"][checked=checked]', 'query[visibility]'
|
||||
assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked])'
|
||||
end
|
||||
|
||||
def test_edit_sort_criteria
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :params => {
|
||||
:id => 5
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'query[sort_criteria][0][]' do
|
||||
assert_select 'option[value=priority][selected=selected]'
|
||||
assert_select 'option[value=desc][selected=selected]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_edit_invalid_query
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {
|
||||
:id => 99
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_udpate_global_private_query
|
||||
@request.session[:user_id] = 3
|
||||
put :update, :params => {
|
||||
:id => 3,
|
||||
:default_columns => '1',
|
||||
:fields => ["status_id", "assigned_to_id"],
|
||||
:operators => {
|
||||
"assigned_to_id" => "=", "status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"assigned_to_id" => ["me"], "status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_edit_global_private_query", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 3
|
||||
q = Query.find_by_name('test_edit_global_private_query')
|
||||
assert !q.is_public?
|
||||
assert q.has_default_columns?
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_update_global_public_query
|
||||
@request.session[:user_id] = 1
|
||||
put :update, :params => {
|
||||
:id => 4,
|
||||
:default_columns => '1',
|
||||
:fields => ["status_id", "assigned_to_id"],
|
||||
:operators => {
|
||||
"assigned_to_id" => "=", "status_id" => "o"
|
||||
},
|
||||
:values => {
|
||||
"assigned_to_id" => ["1"], "status_id" => ["1"]
|
||||
},
|
||||
:query => {
|
||||
"name" => "test_edit_global_public_query", "visibility" => "2"
|
||||
}
|
||||
}
|
||||
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 4
|
||||
q = Query.find_by_name('test_edit_global_public_query')
|
||||
assert q.is_public?
|
||||
assert q.has_default_columns?
|
||||
assert q.valid?
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 1
|
||||
put :update, :params => {
|
||||
:id => 4,
|
||||
:query => {
|
||||
:name => ''
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :set_filter => 1, :query_id => nil
|
||||
assert_nil Query.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_backslash_should_be_escaped_in_filters
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {
|
||||
:subject => 'foo/bar'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include 'addFilter("subject", "=", ["foo\/bar"]);', response.body
|
||||
end
|
||||
|
||||
def test_filter_with_project_id_should_return_filter_values
|
||||
@request.session[:user_id] = 2
|
||||
get :filter, :params => {
|
||||
:project_id => 1,
|
||||
:name => 'fixed_version_id'
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_include ["eCookbook - 2.0", "3", "open"], json
|
||||
end
|
||||
|
||||
def test_version_filter_time_entries_with_project_id_should_return_filter_values
|
||||
@request.session[:user_id] = 2
|
||||
get :filter, :params => {
|
||||
:project_id => 1,
|
||||
:type => 'TimeEntryQuery',
|
||||
:name => 'issue.fixed_version_id'
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_include ["eCookbook - 2.0", "3", "open"], json
|
||||
end
|
||||
|
||||
def test_filter_without_project_id_should_return_filter_values
|
||||
@request.session[:user_id] = 2
|
||||
get :filter, :params => {
|
||||
:name => 'fixed_version_id'
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_include ["OnlineStore - Systemwide visible version", "7", "open"], json
|
||||
end
|
||||
|
||||
def test_subproject_filter_time_entries_with_project_id_should_return_filter_values
|
||||
@request.session[:user_id] = 2
|
||||
get :filter, :params => {
|
||||
:project_id => 1,
|
||||
:type => 'TimeEntryQuery',
|
||||
:name => 'subproject_id'
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_equal 4, json.count
|
||||
assert_include ["Private child of eCookbook","5"], json
|
||||
end
|
||||
end
|
||||
75
test/functional/reports_controller_test.rb
Normal file
75
test/functional/reports_controller_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 ReportsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:versions
|
||||
|
||||
def test_get_issue_report
|
||||
get :issue_report, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_get_issue_report_details
|
||||
%w(tracker version priority category assigned_to author subproject).each do |detail|
|
||||
get :issue_report_details, :params => {
|
||||
:id => 1,
|
||||
:detail => detail
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_issue_report_details_by_tracker_should_show_issue_count
|
||||
Issue.delete_all
|
||||
Issue.generate!(:tracker_id => 1)
|
||||
Issue.generate!(:tracker_id => 1)
|
||||
Issue.generate!(:tracker_id => 1, :status_id => 5)
|
||||
Issue.generate!(:tracker_id => 2)
|
||||
|
||||
get :issue_report_details, :params => {
|
||||
:id => 1,
|
||||
:detail => 'tracker'
|
||||
}
|
||||
assert_select 'table.list tbody :nth-child(1)' do
|
||||
assert_select 'td', :text => 'Bug'
|
||||
assert_select ':nth-child(2)', :text => '2' # status:1
|
||||
assert_select ':nth-child(3)', :text => '-' # status:2
|
||||
assert_select ':nth-child(8)', :text => '2' # open
|
||||
assert_select ':nth-child(9)', :text => '1' # closed
|
||||
assert_select ':nth-child(10)', :text => '3' # total
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_issue_report_details_with_an_invalid_detail
|
||||
get :issue_report_details, :params => {
|
||||
:id => 1,
|
||||
:detail => 'invalid'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
265
test/functional/repositories_bazaar_controller_test.rb
Normal file
265
test/functional/repositories_bazaar_controller_test.rb
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
# 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 RepositoriesBazaarControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
|
||||
REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk")
|
||||
PRJ_ID = 3
|
||||
CHAR_1_UTF8_HEX = "\xc3\x9c".dup.force_encoding('UTF-8')
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Bazaar.create(
|
||||
:project => @project,
|
||||
:url => REPOSITORY_PATH_TRUNK,
|
||||
:log_encoding => 'UTF-8')
|
||||
assert @repository
|
||||
end
|
||||
|
||||
if File.directory?(REPOSITORY_PATH)
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Bazaar'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Bazaar'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 2
|
||||
assert_select 'tr.dir td.filename a', :text => 'directory'
|
||||
assert_select 'tr.file td.filename a', :text => 'doc-mkdir.txt'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_directory
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['directory'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'tr.file td.filename a', :text => 'doc-ls.txt'
|
||||
assert_select 'tr.file td.filename a', :text => 'document.txt'
|
||||
assert_select 'tr.file td.filename a', :text => 'edit.png'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_at_given_revision
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash([])[:param],
|
||||
:rev => 3
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 4
|
||||
assert_select 'tr.dir td.filename a', :text => 'directory'
|
||||
assert_select 'tr.file td.filename a', :text => 'doc-deleted.txt'
|
||||
assert_select 'tr.file td.filename a', :text => 'doc-ls.txt'
|
||||
assert_select 'tr.file td.filename a', :text => 'doc-mkdir.txt'
|
||||
end
|
||||
end
|
||||
|
||||
def test_changes
|
||||
get :changes, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['doc-mkdir.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /doc-mkdir.txt/
|
||||
end
|
||||
|
||||
def test_entry_show
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['directory', 'doc-ls.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
# Line 19
|
||||
assert_select 'tr#L29 td.line-code', :text => /Show help message/
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['directory', 'doc-ls.txt'])[:param],
|
||||
:format => 'raw'
|
||||
}
|
||||
assert_response :success
|
||||
# File content
|
||||
assert @response.body.include?('Show help message')
|
||||
end
|
||||
|
||||
def test_directory_entry
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['directory'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody'
|
||||
end
|
||||
|
||||
def test_diff
|
||||
# Full diff of changeset 3
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 3,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
# Line 11 removed
|
||||
assert_select 'th.line-num:contains(11) ~ td.diff_out', :text => /Display more information/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['doc-mkdir.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select "th.line-num", :text => '2' do
|
||||
assert_select "+ td.revision" do
|
||||
assert_select "a", :text => '3'
|
||||
assert_select "+ td.author", :text => "jsmith@" do
|
||||
assert_select "+ td",
|
||||
:text => "Main purpose:"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_author_escaping
|
||||
repository = Repository::Bazaar.create(
|
||||
:project => @project,
|
||||
:url => File.join(REPOSITORY_PATH, "author_escaping"),
|
||||
:identifier => 'author_escaping',
|
||||
:log_encoding => 'UTF-8')
|
||||
assert repository
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:repository_id => 'author_escaping',
|
||||
:path => repository_path_hash(['author-escaping-test.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select "th.line-num", :text => '1' do
|
||||
assert_select "+ td.revision" do
|
||||
assert_select "a", :text => '2'
|
||||
assert_select "+ td.author", :text => "test &" do
|
||||
assert_select "+ td",
|
||||
:text => "author escaping test"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_author_non_ascii
|
||||
log_encoding = nil
|
||||
if Encoding.locale_charmap == "UTF-8" ||
|
||||
Encoding.locale_charmap == "ISO-8859-1"
|
||||
log_encoding = Encoding.locale_charmap
|
||||
end
|
||||
unless log_encoding.nil?
|
||||
repository = Repository::Bazaar.create(
|
||||
:project => @project,
|
||||
:url => File.join(REPOSITORY_PATH, "author_non_ascii"),
|
||||
:identifier => 'author_non_ascii',
|
||||
:log_encoding => log_encoding)
|
||||
assert repository
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:repository_id => 'author_non_ascii',
|
||||
:path => repository_path_hash(['author-non-ascii-test.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select "th.line-num", :text => '1' do
|
||||
assert_select "+ td.revision" do
|
||||
assert_select "a", :text => '2'
|
||||
assert_select "+ td.author", :text => "test #{CHAR_1_UTF8_HEX}" do
|
||||
assert_select "+ td",
|
||||
:text => "author non ASCII test"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
assert @repository.changesets.count > 0
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Bazaar.create!(
|
||||
:project => @project,
|
||||
:url => "/invalid",
|
||||
:log_encoding => 'UTF-8')
|
||||
@repository.fetch_changesets
|
||||
@repository.reload
|
||||
assert_equal 0, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
else
|
||||
puts "Bazaar test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
end
|
||||
411
test/functional/repositories_controller_test.rb
Normal file
411
test/functional/repositories_controller_test.rb
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
# 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 RepositoriesControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules,
|
||||
:repositories, :issues, :issue_statuses, :changesets, :changes,
|
||||
:issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 1
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Subversion'
|
||||
end
|
||||
assert_select 'input[name=?]:not([disabled])', 'repository[url]'
|
||||
end
|
||||
|
||||
def test_new_should_propose_enabled_scm_only
|
||||
@request.session[:user_id] = 1
|
||||
with_settings :enabled_scm => ['Mercurial', 'Git'] do
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1'
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=repository_scm]' do
|
||||
assert_select 'option', 3
|
||||
assert_select 'option[value=Mercurial][selected=selected]'
|
||||
assert_select 'option[value=Git]:not([selected])'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_new_with_type
|
||||
@request.session[:user_id] = 1
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Git'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Git'
|
||||
end
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Repository.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Subversion',
|
||||
:repository => {
|
||||
:url => 'file:///test',
|
||||
:is_default => '1',
|
||||
:identifier => ''
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
repository = Repository.order('id DESC').first
|
||||
assert_kind_of Repository::Subversion, repository
|
||||
assert_equal 'file:///test', repository.url
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 1
|
||||
assert_no_difference 'Repository.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Subversion',
|
||||
:repository => {
|
||||
:url => 'invalid'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /URL is invalid/
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Subversion'
|
||||
end
|
||||
end
|
||||
|
||||
def test_edit
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :params => {
|
||||
:id => 11
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?][disabled=disabled]', 'repository[url]', 'svn://localhost/test'
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 1
|
||||
put :update, :params => {
|
||||
:id => 11,
|
||||
:repository => {
|
||||
:password => 'test_update'
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal 'test_update', Repository.find(11).password
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 1
|
||||
put :update, :params => {
|
||||
:id => 11,
|
||||
:repository => {
|
||||
:password => 'x'*260
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Password is too long/
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => 11
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
assert_nil Repository.find_by_id(11)
|
||||
end
|
||||
|
||||
def test_show_with_autofetch_changesets_enabled_should_fetch_changesets
|
||||
Repository::Subversion.any_instance.expects(:fetch_changesets).once
|
||||
|
||||
with_settings :autofetch_changesets => '1' do
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_with_autofetch_changesets_disabled_should_not_fetch_changesets
|
||||
Repository::Subversion.any_instance.expects(:fetch_changesets).never
|
||||
|
||||
with_settings :autofetch_changesets => '0' do
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_with_closed_project_should_not_fetch_changesets
|
||||
Repository::Subversion.any_instance.expects(:fetch_changesets).never
|
||||
Project.find(1).close
|
||||
|
||||
with_settings :autofetch_changesets => '1' do
|
||||
get :show, :params => {
|
||||
:id => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_revisions
|
||||
get :revisions, :params => {
|
||||
:id => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.changesets'
|
||||
end
|
||||
|
||||
def test_revisions_for_other_repository
|
||||
repository = Repository::Subversion.create!(:project_id => 1, :identifier => 'foo', :url => 'file:///foo')
|
||||
|
||||
get :revisions, :params => {
|
||||
:id => 1,
|
||||
:repository_id => 'foo'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.changesets'
|
||||
end
|
||||
|
||||
def test_revisions_for_invalid_repository
|
||||
get :revisions, :params => {
|
||||
:id => 1,
|
||||
:repository_id => 'foo'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_revision
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => 'Revision 1'
|
||||
end
|
||||
|
||||
def test_revision_should_not_format_comments_when_disabled
|
||||
Changeset.where(:id => 100).update_all(:comments => 'Simple *text*')
|
||||
|
||||
with_settings :commit_logs_formatting => '0' do
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select '.changeset-comments', :text => 'Simple *text*'
|
||||
end
|
||||
end
|
||||
|
||||
def test_revision_should_show_add_related_issue_form
|
||||
Role.find(1).add_permission! :manage_related_issues
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form[action=?]', '/projects/ecookbook/repository/revisions/1/issues' do
|
||||
assert_select 'input[name=?]', 'issue_id'
|
||||
end
|
||||
end
|
||||
|
||||
def test_revision_should_not_change_the_project_menu_link
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#main-menu a.repository[href=?]', '/projects/ecookbook/repository'
|
||||
end
|
||||
|
||||
def test_revision_with_before_nil_and_afer_normal
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'div.contextual' do
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/0', 0
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2'
|
||||
end
|
||||
end
|
||||
|
||||
def test_add_related_issue
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Changeset.find(103).issues.size' do
|
||||
post :add_related_issue, :params => {
|
||||
:id => 1,
|
||||
:rev => 4,
|
||||
:issue_id => 2,
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_equal [2], Changeset.find(103).issue_ids
|
||||
assert_include 'related-issues', response.body
|
||||
assert_include 'Feature request #2', response.body
|
||||
end
|
||||
|
||||
def test_add_related_issue_should_accept_issue_id_with_sharp
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Changeset.find(103).issues.size' do
|
||||
post :add_related_issue, :params => {
|
||||
:id => 1,
|
||||
:rev => 4,
|
||||
:issue_id => "#2",
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
end
|
||||
assert_equal [2], Changeset.find(103).issue_ids
|
||||
end
|
||||
|
||||
def test_add_related_issue_with_invalid_issue_id
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Changeset.find(103).issues.size' do
|
||||
post :add_related_issue, :params => {
|
||||
:id => 1,
|
||||
:rev => 4,
|
||||
:issue_id => 9999,
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_include 'alert("Issue is invalid")', response.body
|
||||
end
|
||||
|
||||
def test_remove_related_issue
|
||||
Changeset.find(103).issues << Issue.find(1)
|
||||
Changeset.find(103).issues << Issue.find(2)
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Changeset.find(103).issues.size', -1 do
|
||||
delete :remove_related_issue, :params => {
|
||||
:id => 1,
|
||||
:rev => 4,
|
||||
:issue_id => 2,
|
||||
:format => 'js'
|
||||
},
|
||||
:xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_equal [1], Changeset.find(103).issue_ids
|
||||
assert_include 'related-issue-2', response.body
|
||||
end
|
||||
|
||||
def test_graph_commits_per_month
|
||||
# Make sure there's some data to display
|
||||
latest = Project.find(1).repository.changesets.maximum(:commit_date)
|
||||
assert_not_nil latest
|
||||
Date.stubs(:today).returns(latest.to_date + 10)
|
||||
|
||||
get :graph, :params => {
|
||||
:id => 1,
|
||||
:graph => 'commits_per_month'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'image/svg+xml', @response.content_type
|
||||
end
|
||||
|
||||
def test_graph_commits_per_author
|
||||
get :graph, :params => {
|
||||
:id => 1,
|
||||
:graph => 'commits_per_author'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'image/svg+xml', @response.content_type
|
||||
end
|
||||
|
||||
def test_get_committers
|
||||
@request.session[:user_id] = 2
|
||||
# add a commit with an unknown user
|
||||
Changeset.create!(
|
||||
:repository => Project.find(1).repository,
|
||||
:committer => 'foo',
|
||||
:committed_on => Time.now,
|
||||
:revision => 100,
|
||||
:comments => 'Committed by foo.'
|
||||
)
|
||||
|
||||
get :committers, :params => {
|
||||
:id => 10
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[value=dlopper] + select option[value="3"][selected=selected]', :text => 'Dave Lopper'
|
||||
assert_select 'input[value=foo] + select option[selected=selected]', 0 # no option selected
|
||||
end
|
||||
|
||||
def test_get_committers_without_changesets
|
||||
Changeset.delete_all
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :committers, :params => {
|
||||
:id => 10
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_post_committers
|
||||
@request.session[:user_id] = 2
|
||||
# add a commit with an unknown user
|
||||
c = Changeset.create!(
|
||||
:repository => Project.find(1).repository,
|
||||
:committer => 'foo',
|
||||
:committed_on => Time.now,
|
||||
:revision => 100,
|
||||
:comments => 'Committed by foo.'
|
||||
)
|
||||
assert_no_difference "Changeset.where(:user_id => 3).count" do
|
||||
post :committers, :params => {
|
||||
:id => 10,
|
||||
:committers => {
|
||||
'0' => ['foo', '2'], '1' => ['dlopper', '3']
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal User.find(2), c.reload.user
|
||||
end
|
||||
end
|
||||
end
|
||||
295
test/functional/repositories_cvs_controller_test.rb
Normal file
295
test/functional/repositories_cvs_controller_test.rb
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
# 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 RepositoriesCvsControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s
|
||||
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
|
||||
# CVS module
|
||||
MODULE_NAME = 'test'
|
||||
PRJ_ID = 3
|
||||
NUM_REV = 7
|
||||
|
||||
def setup
|
||||
Setting.default_language = 'en'
|
||||
User.current = nil
|
||||
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Cvs.create(:project => Project.find(PRJ_ID),
|
||||
:root_url => REPOSITORY_PATH,
|
||||
:url => MODULE_NAME,
|
||||
:log_encoding => 'UTF-8')
|
||||
assert @repository
|
||||
end
|
||||
|
||||
if File.directory?(REPOSITORY_PATH)
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Cvs'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Cvs'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'tr.dir td.filename a', :text => 'images'
|
||||
assert_select 'tr.file td.filename a', :text => 'README'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_directory
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'tr.file td.filename a', :text => 'add.png'
|
||||
assert_select 'tr.file td.filename a', :text => 'delete.png'
|
||||
assert_select 'tr.file td.filename a', :text => 'edit.png'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param],
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 2
|
||||
assert_select 'tr.file td.filename a', :text => 'delete.png'
|
||||
assert_select 'tr.file td.filename a', :text => 'edit.png'
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'td.line-code', :text => /before_filter/, :count => 0
|
||||
end
|
||||
|
||||
def test_entry_at_given_revision
|
||||
# changesets must be loaded
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:rev => 2
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# this line was removed in r3
|
||||
assert_select 'td.line-code', :text => /before_filter/
|
||||
end
|
||||
|
||||
def test_entry_not_found
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'zzz.c'])[:param]
|
||||
}
|
||||
assert_select 'p#errorExplanation', :text => /The entry or revision was not found in the repository/
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:format => 'raw'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_directory_entry
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody'
|
||||
end
|
||||
|
||||
def test_diff
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 3,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'td.line-code.diff_out', :text => /before_filter :require_login/
|
||||
assert_select 'td.line-code.diff_in', :text => /with one change/
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_new_files
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 1,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'td.line-code.diff_in', :text => /watched.remove_watcher/
|
||||
assert_select 'th.filename', :text => /test\/README/
|
||||
assert_select 'th.filename', :text => /test\/images\/delete.png/
|
||||
assert_select 'th.filename', :text => /test\/images\/edit.png/
|
||||
assert_select 'th.filename', :text => /test\/sources\/watchers_controller.rb/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# 1.1 line
|
||||
assert_select 'tr' do
|
||||
assert_select 'th.line-num', :text => '21'
|
||||
assert_select 'td.revision', :text => /1.1/
|
||||
assert_select 'td.author', :text => /LANG/
|
||||
end
|
||||
# 1.2 line
|
||||
assert_select 'tr' do
|
||||
assert_select 'th.line-num', :text => '32'
|
||||
assert_select 'td.revision', :text => /1.2/
|
||||
assert_select 'td.author', :text => /LANG/
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Cvs.create!(
|
||||
:project => Project.find(PRJ_ID),
|
||||
:root_url => "/invalid",
|
||||
:url => MODULE_NAME,
|
||||
:log_encoding => 'UTF-8'
|
||||
)
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal 0, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
else
|
||||
puts "CVS test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
end
|
||||
178
test/functional/repositories_darcs_controller_test.rb
Normal file
178
test/functional/repositories_darcs_controller_test.rb
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# 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 RepositoriesDarcsControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s
|
||||
PRJ_ID = 3
|
||||
NUM_REV = 6
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Darcs.create(
|
||||
:project => @project,
|
||||
:url => REPOSITORY_PATH,
|
||||
:log_encoding => 'UTF-8'
|
||||
)
|
||||
assert @repository
|
||||
end
|
||||
|
||||
if File.directory?(REPOSITORY_PATH)
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Darcs'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Darcs'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'tr.dir td.filename a', :text => 'images'
|
||||
assert_select 'tr.dir td.filename a', :text => 'sources'
|
||||
assert_select 'tr.file td.filename a', :text => 'README'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_directory
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 2
|
||||
assert_select 'tr.file td.filename a', :text => 'delete.png'
|
||||
assert_select 'tr.file td.filename a', :text => 'edit.png'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param],
|
||||
:rev => 1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'tr.file td.filename a', :text => 'delete.png'
|
||||
end
|
||||
end
|
||||
|
||||
def test_changes
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :changes, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /edit.png/
|
||||
end
|
||||
|
||||
def test_diff
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
# Full diff of changeset 5
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 5,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
# Line 22 removed
|
||||
assert_select 'th.line-num:contains(22) ~ td.diff_out', :text => /def remove/
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Darcs.create!(
|
||||
:project => @project,
|
||||
:url => "/invalid",
|
||||
:log_encoding => 'UTF-8'
|
||||
)
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal 0, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
else
|
||||
puts "Darcs test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
end
|
||||
174
test/functional/repositories_filesystem_controller_test.rb
Normal file
174
test/functional/repositories_filesystem_controller_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 RepositoriesFilesystemControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s
|
||||
PRJ_ID = 3
|
||||
|
||||
def setup
|
||||
@ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8'
|
||||
User.current = nil
|
||||
Setting.enabled_scm << 'Filesystem' unless Setting.enabled_scm.include?('Filesystem')
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Filesystem.create(
|
||||
:project => @project,
|
||||
:url => REPOSITORY_PATH,
|
||||
:path_encoding => ''
|
||||
)
|
||||
assert @repository
|
||||
end
|
||||
|
||||
if File.directory?(REPOSITORY_PATH)
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Filesystem'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Filesystem'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
@repository.fetch_changesets
|
||||
@repository.reload
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'tr.dir td.filename a', :text => 'dir'
|
||||
assert_select 'tr.dir td.filename a', :text => 'japanese'
|
||||
assert_select 'tr.file td.filename a', :text => 'test'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody', 0
|
||||
|
||||
assert_select 'input[name=rev]', 0
|
||||
assert_select 'a', :text => 'Statistics', :count => 0
|
||||
assert_select 'a', :text => 'Atom', :count => 0
|
||||
end
|
||||
|
||||
def test_show_no_extension
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['test'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr#L1 td.line-code', :text => /TEST CAT/
|
||||
end
|
||||
|
||||
def test_entry_download_no_extension
|
||||
get :raw, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['test'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'application/octet-stream', @response.content_type
|
||||
end
|
||||
|
||||
def test_show_non_ascii_contents
|
||||
with_settings :repositories_encodings => 'UTF-8,EUC-JP' do
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['japanese', 'euc-jp.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr#L2 td.line-code', :text => /japanese/
|
||||
if @ruby19_non_utf8_pass
|
||||
puts "TODO: show repository file contents test fails " +
|
||||
"when Encoding.default_external is not UTF-8. " +
|
||||
"Current value is '#{Encoding.default_external.to_s}'"
|
||||
else
|
||||
str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
|
||||
assert_select 'tr#L3 td.line-code', :text => /#{str_japanese}/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_utf16
|
||||
enc = 'UTF-16'
|
||||
with_settings :repositories_encodings => enc do
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr#L2 td.line-code', :text => /japanese/
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_text_file_should_show_other_if_too_big
|
||||
with_settings :file_max_size_displayed => 1 do
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['japanese', 'big-file.txt'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'p.nodata'
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Filesystem.create!(
|
||||
:project => @project,
|
||||
:url => "/invalid",
|
||||
:path_encoding => ''
|
||||
)
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
else
|
||||
puts "Filesystem test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
end
|
||||
667
test/functional/repositories_git_controller_test.rb
Normal file
667
test/functional/repositories_git_controller_test.rb
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
# 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 RepositoriesGitControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
|
||||
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
|
||||
PRJ_ID = 3
|
||||
CHAR_1_HEX = "\xc3\x9c".force_encoding('UTF-8')
|
||||
FELIX_HEX = "Felix Sch\xC3\xA4fer".force_encoding('UTF-8')
|
||||
NUM_REV = 28
|
||||
|
||||
## 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"
|
||||
|
||||
def setup
|
||||
@ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8'
|
||||
|
||||
User.current = nil
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Git.create(
|
||||
:project => @project,
|
||||
:url => REPOSITORY_PATH,
|
||||
:path_encoding => 'ISO-8859-1'
|
||||
)
|
||||
assert @repository
|
||||
end
|
||||
|
||||
def test_create_and_update
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Repository.count' do
|
||||
post :create, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Git',
|
||||
:repository => {
|
||||
:url => '/test',
|
||||
:is_default => '0',
|
||||
:identifier => 'test-create',
|
||||
:report_last_commit => '1',
|
||||
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
repository = Repository.order('id DESC').first
|
||||
assert_kind_of Repository::Git, repository
|
||||
assert_equal '/test', repository.url
|
||||
assert_equal true, repository.report_last_commit
|
||||
|
||||
put :update, :params => {
|
||||
:id => repository.id,
|
||||
:repository => {
|
||||
:report_last_commit => '0'
|
||||
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
repo2 = Repository.find(repository.id)
|
||||
assert_equal false, repo2.report_last_commit
|
||||
end
|
||||
|
||||
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 test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Git'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Git'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 9
|
||||
assert_select 'tr.dir td.filename_no_report a', :text => 'images'
|
||||
assert_select 'tr.dir td.filename_no_report a', :text => 'this_is_a_really_long_and_verbose_directory_name'
|
||||
assert_select 'tr.dir td.filename_no_report a', :text => 'sources'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'README'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'copied_README'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'new_file.txt'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'renamed_test.txt'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'filemane with spaces.txt'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'filename with a leading space.txt'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_branch
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 'test_branch'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 4
|
||||
assert_select 'tr.dir td.filename_no_report a', :text => 'images'
|
||||
assert_select 'tr.dir td.filename_no_report a', :text => 'sources'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'README'
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'test.txt'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_tag
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[
|
||||
"tag00.lightweight",
|
||||
"tag01.annotated",
|
||||
].each do |t1|
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => t1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody tr'
|
||||
assert_select 'table.changesets tbody tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_browse_directory
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'edit.png'
|
||||
end
|
||||
assert_select 'table.changesets tbody tr'
|
||||
end
|
||||
|
||||
def test_browse_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param],
|
||||
:rev => '7234cb2750b63f47bff735edc50a1c0a433c2518'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'tr.file td.filename_no_report a', :text => 'delete.png'
|
||||
end
|
||||
end
|
||||
|
||||
def test_changes
|
||||
get :changes, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /edit.png/
|
||||
end
|
||||
|
||||
def test_entry_show
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
# Line 11
|
||||
assert_select 'tr#L11 td.line-code', :text => /WITHOUT ANY WARRANTY/
|
||||
end
|
||||
|
||||
def test_entry_show_latin_1
|
||||
if @ruby19_non_utf8_pass
|
||||
puts_ruby19_non_utf8_pass()
|
||||
elsif WINDOWS_PASS
|
||||
puts WINDOWS_SKIP_STR
|
||||
elsif JRUBY_SKIP
|
||||
puts JRUBY_SKIP_STR
|
||||
else
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{CHAR_1_HEX}.txt"])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr#L1 td.line-code', :text => /test-#{CHAR_1_HEX}.txt/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:format => 'raw'
|
||||
}
|
||||
assert_response :success
|
||||
# File content
|
||||
assert @response.body.include?('WITHOUT ANY WARRANTY')
|
||||
end
|
||||
|
||||
def test_directory_entry
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2 a', :text => 'sources'
|
||||
assert_select 'table.entries tbody'
|
||||
assert_select 'div.contextual > a.icon-download', false
|
||||
|
||||
end
|
||||
|
||||
def test_diff
|
||||
assert_equal true, @repository.is_default
|
||||
assert @repository.identifier.blank?
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
# Full diff of changeset 2f9c0091
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
# Line 22 removed
|
||||
assert_select 'th.line-num:contains(22) ~ td.diff_out', :text => /def remove/
|
||||
assert_select 'h2', :text => /2f9c0091/
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_with_rev_and_path
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
with_settings :diff_max_lines_displayed => 1000 do
|
||||
# Full diff of changeset 2f9c0091
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
# Line 22 removed
|
||||
assert_select 'th.line-num:contains(22) ~ td.diff_out', :text => /def remove/
|
||||
assert_select 'h2', :text => /2f9c0091/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_truncated
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
with_settings :diff_max_lines_displayed => 5 do
|
||||
# Truncated diff of changeset 2f9c0091
|
||||
with_cache do
|
||||
with_settings :default_language => 'en' do
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:type => 'inline',
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||
}
|
||||
assert_response :success
|
||||
assert @response.body.include?("... This diff was truncated")
|
||||
end
|
||||
with_settings :default_language => 'fr' do
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:type => 'inline',
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||
}
|
||||
assert_response :success
|
||||
assert ! @response.body.include?("... This diff was truncated")
|
||||
assert @response.body.include?("... Ce diff")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_two_revs
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
|
||||
:rev_to => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /2f9c0091:61b685fb/
|
||||
assert_select 'form[action=?]', '/projects/subproject1/repository/revisions/61b685fbe55ab05b5ac68402d5720c1a6ac973d1/diff'
|
||||
assert_select 'input#rev_to[type=hidden][name=rev_to][value=?]', '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_path_in_subrepo
|
||||
repo = Repository::Git.create(
|
||||
:project => @project,
|
||||
:url => REPOSITORY_PATH,
|
||||
:identifier => 'test-diff-path',
|
||||
:path_encoding => 'ISO-8859-1'
|
||||
)
|
||||
assert repo
|
||||
assert_equal false, repo.is_default
|
||||
assert_equal 'test-diff-path', repo.identifier
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:repository_id => 'test-diff-path',
|
||||
:rev => '61b685fbe55ab05b',
|
||||
:rev_to => '2f9c0091c754a91a',
|
||||
:type => 'inline'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'form[action=?]', '/projects/subproject1/repository/test-diff-path/revisions/61b685fbe55ab05b/diff'
|
||||
assert_select 'input#rev_to[type=hidden][name=rev_to][value=?]', '2f9c0091c754a91a'
|
||||
end
|
||||
|
||||
def test_diff_latin_1
|
||||
if @ruby19_non_utf8_pass
|
||||
puts_ruby19_non_utf8_pass()
|
||||
else
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r1,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table' do
|
||||
assert_select 'thead th.filename', :text => /latin-1-dir\/test-#{CHAR_1_HEX}.txt/
|
||||
assert_select 'tbody td.diff_in', :text => /test-#{CHAR_1_HEX}.txt/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_should_show_filenames
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 'deff712f05a90d96edbd70facc47d944be5897e3',
|
||||
:type => 'inline'
|
||||
}
|
||||
assert_response :success
|
||||
# modified file
|
||||
assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
|
||||
# deleted file
|
||||
assert_select 'th.filename', :text => 'test.txt'
|
||||
end
|
||||
|
||||
def test_save_diff_type
|
||||
user1 = User.find(1)
|
||||
user1.pref[:diff_type] = nil
|
||||
user1.preference.save
|
||||
user = User.find(1)
|
||||
assert_nil user.pref[:diff_type]
|
||||
|
||||
@request.session[:user_id] = 1 # admin
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||
}
|
||||
assert_response :success
|
||||
user.reload
|
||||
assert_equal "inline", user.pref[:diff_type]
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:type => 'sbs'
|
||||
}
|
||||
assert_response :success
|
||||
user.reload
|
||||
assert_equal "sbs", user.pref[:diff_type]
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# Line 23, changeset 2f9c0091
|
||||
assert_select 'tr' do
|
||||
assert_select 'th.line-num', :text => '23'
|
||||
assert_select 'td.revision', :text => /2f9c0091/
|
||||
assert_select 'td.author', :text => 'jsmith'
|
||||
assert_select 'td', :text => /remove_watcher/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 'deff7',
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /@ deff712f/
|
||||
end
|
||||
|
||||
def test_annotate_binary_file
|
||||
with_settings :default_language => 'en' do
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'p#errorExplanation', :text => /cannot be annotated/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_error_when_too_big
|
||||
with_settings :file_max_size_displayed => 1 do
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:rev => 'deff712f'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'p#errorExplanation', :text => /exceeds the maximum text file size/
|
||||
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['README'])[:param],
|
||||
:rev => '7234cb2'
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_latin_1
|
||||
if @ruby19_non_utf8_pass
|
||||
puts_ruby19_non_utf8_pass()
|
||||
elsif WINDOWS_PASS
|
||||
puts WINDOWS_SKIP_STR
|
||||
elsif JRUBY_SKIP
|
||||
puts JRUBY_SKIP_STR
|
||||
else
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
['57ca437c', '57ca437c0acbbcb749821fdf3726a1367056d364'].each do |r1|
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{CHAR_1_HEX}.txt"])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_select "th.line-num", :text => '1' do
|
||||
assert_select "+ td.revision" do
|
||||
assert_select "a", :text => '57ca437c'
|
||||
assert_select "+ td.author", :text => "jsmith" do
|
||||
assert_select "+ td",
|
||||
:text => "test-#{CHAR_1_HEX}.txt"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_latin_1_author
|
||||
['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash([" filename with a leading space.txt "])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_select "th.line-num", :text => '1' do
|
||||
assert_select "+ td.revision" do
|
||||
assert_select "a", :text => '83ca5fd5'
|
||||
assert_select "+ td.author", :text => FELIX_HEX do
|
||||
assert_select "+ td",
|
||||
:text => "And this is a file with a leading and trailing space..."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_revisions
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :revisions, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_select 'form[method=get][action=?]', '/projects/subproject1/repository/revision'
|
||||
end
|
||||
|
||||
def test_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['61b685fbe55ab05b5ac68402d5720c1a6ac973d1', '61b685f'].each do |r|
|
||||
get :revision, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_empty_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['', ' ', nil].each do |r|
|
||||
get :revision, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r
|
||||
}
|
||||
assert_response 404
|
||||
assert_select_error /was not found/
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Git.create!(
|
||||
:project => @project,
|
||||
:url => "/invalid",
|
||||
:path_encoding => 'ISO-8859-1'
|
||||
)
|
||||
@repository.fetch_changesets
|
||||
@repository.reload
|
||||
assert_equal 0, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def puts_ruby19_non_utf8_pass
|
||||
puts "TODO: This test fails " +
|
||||
"when Encoding.default_external is not UTF-8. " +
|
||||
"Current value is '#{Encoding.default_external.to_s}'"
|
||||
end
|
||||
else
|
||||
puts "Git test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
|
||||
private
|
||||
def with_cache(&block)
|
||||
before = ActionController::Base.perform_caching
|
||||
ActionController::Base.perform_caching = true
|
||||
block.call
|
||||
ActionController::Base.perform_caching = before
|
||||
end
|
||||
end
|
||||
559
test/functional/repositories_mercurial_controller_test.rb
Normal file
559
test/functional/repositories_mercurial_controller_test.rb
Normal file
|
|
@ -0,0 +1,559 @@
|
|||
# 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 RepositoriesMercurialControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
|
||||
CHAR_1_HEX = "\xc3\x9c"
|
||||
PRJ_ID = 3
|
||||
NUM_REV = 34
|
||||
|
||||
ruby19_non_utf8_pass = Encoding.default_external.to_s != 'UTF-8'
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Mercurial.create(
|
||||
:project => @project,
|
||||
:url => REPOSITORY_PATH,
|
||||
:path_encoding => 'ISO-8859-1'
|
||||
)
|
||||
assert @repository
|
||||
@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
|
||||
|
||||
if ruby19_non_utf8_pass
|
||||
puts "TODO: Mercurial functional test fails " +
|
||||
"when Encoding.default_external is not UTF-8. " +
|
||||
"Current value is '#{Encoding.default_external.to_s}'"
|
||||
def test_fake; assert true end
|
||||
elsif File.directory?(REPOSITORY_PATH)
|
||||
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Mercurial'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Mercurial'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_root
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 4
|
||||
assert_select 'tr.dir td.filename a', :text => 'images'
|
||||
assert_select 'tr.dir td.filename a', :text => 'sources'
|
||||
assert_select 'tr.file td.filename a', :text => '.hgtags'
|
||||
assert_select 'tr.file td.filename a', :text => 'README'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_directory
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 2
|
||||
assert_select 'tr.file td.filename a', :text => 'delete.png'
|
||||
assert_select 'tr.file td.filename a', :text => 'edit.png'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[0, '0', '0885933ad4f6'].each do |r1|
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images'])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'tr.file td.filename a', :text => 'delete.png'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_directory_sql_escape_percent
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[13, '13', '3a330eb32958'].each do |r1|
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sql_escape', 'percent%dir'])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 2
|
||||
assert_select 'tr.file td.filename a', :text => 'percent%file1.txt'
|
||||
assert_select 'tr.file td.filename a', :text => 'percentfile1.txt'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr td.id a', :text => /^13:/
|
||||
assert_select 'tr td.id a', :text => /^11:/
|
||||
assert_select 'tr td.id a', :text => /^10:/
|
||||
assert_select 'tr td.id a', :text => /^9:/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_directory_latin_1_path
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[21, '21', 'adf805632193'].each do |r1|
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir'])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 4
|
||||
assert_select 'tr.file td.filename a', :text => "make-latin-1-file.rb"
|
||||
assert_select 'tr.file td.filename a', :text => "test-#{@char_1}-1.txt"
|
||||
assert_select 'tr.file td.filename a', :text => "test-#{@char_1}-2.txt"
|
||||
assert_select 'tr.file td.filename a', :text => "test-#{@char_1}.txt"
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr td.id a', :text => /^21:/
|
||||
assert_select 'tr td.id a', :text => /^20:/
|
||||
assert_select 'tr td.id a', :text => /^19:/
|
||||
assert_select 'tr td.id a', :text => /^18:/
|
||||
assert_select 'tr td.id a', :text => /^17:/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show_should_show_branch_selection_form
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_select 'form#revision_selector[action=?]', '/projects/subproject1/repository/show' do
|
||||
assert_select 'select[name=branch]' do
|
||||
assert_select 'option[value=?]', 'test-branch-01'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_branch
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[
|
||||
'default',
|
||||
@branch_char_1,
|
||||
'branch (1)[2]&,%.-3_4',
|
||||
@branch_char_0,
|
||||
'test_branch.latin-1',
|
||||
'test-branch-00',
|
||||
].each do |bra|
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => bra
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody tr'
|
||||
assert_select 'table.changesets tbody tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_tag
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[
|
||||
@tag_char_1,
|
||||
'tag_test.00',
|
||||
'tag-init-revision'
|
||||
].each do |tag|
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => tag
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody tr'
|
||||
assert_select 'table.changesets tbody tr'
|
||||
end
|
||||
end
|
||||
|
||||
def test_changes
|
||||
get :changes, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /edit.png/
|
||||
end
|
||||
|
||||
def test_entry_show
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
# Line 10
|
||||
assert_select 'tr#L10 td.line-code', :text => /WITHOUT ANY WARRANTY/
|
||||
end
|
||||
|
||||
def test_entry_show_latin_1_path
|
||||
[21, '21', 'adf805632193'].each do |r1|
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr#L1 td.line-code', :text => /Mercurial is a distributed version control system/
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry_show_latin_1_contents
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
[27, '27', '7bbf4c738e71'].each do |r1|
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'tr#L1 td.line-code', :text => /test-#{@char_1}.txt/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:format => 'raw'
|
||||
}
|
||||
assert_response :success
|
||||
# File content
|
||||
assert @response.body.include?('WITHOUT ANY WARRANTY')
|
||||
end
|
||||
|
||||
def test_entry_binary_force_download
|
||||
# TODO: add a binary file which is not an image to the test repo
|
||||
end
|
||||
|
||||
def test_directory_entry
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2 a', :text => 'sources'
|
||||
assert_select 'table.entries tbody'
|
||||
end
|
||||
|
||||
def test_diff
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[4, '4', 'def6d2f1254a'].each do |r1|
|
||||
# Full diff of changeset 4
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r1,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
if @diff_c_support
|
||||
# Line 22 removed
|
||||
assert_select 'th.line-num:contains(22) ~ td.diff_out', :text => /def remove/
|
||||
assert_select 'h2', :text => /4:def6d2f1254a/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_two_revs
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[2, '400bb8672109', '400', 400].each do |r1|
|
||||
[4, 'def6d2f1254a'].each do |r2|
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r1,
|
||||
:rev_to => r2,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /4:def6d2f1254a 2:400bb8672109/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_latin_1_path
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
[21, 'adf805632193'].each do |r1|
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r1,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'table' do
|
||||
assert_select 'thead th.filename', :text => /latin-1-dir\/test-#{@char_1}-2.txt/
|
||||
assert_select 'tbody td.diff_in', :text => /It is written in Python/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_should_show_modified_filenames
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '400bb8672109',
|
||||
:type => 'inline'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
|
||||
end
|
||||
|
||||
def test_diff_should_show_deleted_filenames
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 'b3a615152df8',
|
||||
:type => 'inline'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'th.filename', :text => 'sources/welcome_controller.rb'
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
# Line 22, revision 4:def6d2f1254a
|
||||
assert_select 'tr' do
|
||||
assert_select 'th.line-num', :text => '22'
|
||||
assert_select 'td.revision', :text => '4:def6d2f1254a'
|
||||
assert_select 'td.author', :text => 'jsmith'
|
||||
assert_select 'td', :text => /remove_watcher/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_not_in_tip
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param]
|
||||
}
|
||||
assert_response 404
|
||||
assert_select_error /was not found/
|
||||
end
|
||||
|
||||
def test_annotate_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
[2, '400bb8672109', '400', 400].each do |r1|
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r1,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /@ 2:400bb8672109/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_latin_1_path
|
||||
[21, '21', 'adf805632193'].each do |r1|
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_response :success
|
||||
assert_select "th.line-num", :text => '1' do
|
||||
assert_select "+ td.revision" do
|
||||
assert_select "a", :text => '20:709858aafd1b'
|
||||
assert_select "+ td.author", :text => "jsmith" do
|
||||
assert_select "+ td",
|
||||
:text => "Mercurial is a distributed version control system."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_latin_1_contents
|
||||
with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
|
||||
[27, '7bbf4c738e71'].each do |r1|
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||
:rev => r1
|
||||
}
|
||||
assert_select 'tr#L1 td.line-code', :text => /test-#{@char_1}.txt/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['1', '9d5b5b', '9d5b5b004199'].each do |r|
|
||||
with_settings :default_language => "en" do
|
||||
get :revision, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'title',
|
||||
:text => 'Revision 1:9d5b5b004199 - Added 2 files and modified one. - eCookbook Subproject 1 - Redmine'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_empty_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['', ' ', nil].each do |r|
|
||||
get :revision, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r
|
||||
}
|
||||
assert_response 404
|
||||
assert_select_error /was not found/
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Mercurial.create!(
|
||||
:project => Project.find(PRJ_ID),
|
||||
:url => "/invalid",
|
||||
:path_encoding => 'ISO-8859-1'
|
||||
)
|
||||
@repository.fetch_changesets
|
||||
assert_equal 0, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
else
|
||||
puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
end
|
||||
496
test/functional/repositories_subversion_controller_test.rb
Normal file
496
test/functional/repositories_subversion_controller_test.rb
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
# 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 RepositoriesSubversionControllerTest < Redmine::ControllerTest
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules,
|
||||
:repositories, :issues, :issue_statuses, :changesets, :changes,
|
||||
:issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
|
||||
|
||||
PRJ_ID = 3
|
||||
NUM_REV = 11
|
||||
|
||||
def setup
|
||||
Setting.default_language = 'en'
|
||||
User.current = nil
|
||||
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Subversion.create(:project => @project,
|
||||
:url => self.class.subversion_repository_url)
|
||||
assert @repository
|
||||
end
|
||||
|
||||
if repository_configured?('subversion')
|
||||
def test_new
|
||||
@request.session[:user_id] = 1
|
||||
@project.repository.destroy
|
||||
get :new, :params => {
|
||||
:project_id => 'subproject1',
|
||||
:repository_scm => 'Subversion'
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'repository_scm' do
|
||||
assert_select 'option[value=?][selected=selected]', 'Subversion'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 1
|
||||
assert_select 'tr.dir td.filename a', :text => 'subversion_test'
|
||||
assert_select 'tr.dir td.filename a[href=?]', '/projects/subproject1/repository/show/subversion_test'
|
||||
end
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr', 10
|
||||
assert_select 'tr td.id a', :text => '11'
|
||||
end
|
||||
|
||||
assert_select 'input[name=rev]'
|
||||
assert_select 'a', :text => 'Statistics'
|
||||
assert_select 'a', :text => 'Atom'
|
||||
assert_select 'a[href=?]', '/projects/subproject1/repository', :text => 'root'
|
||||
end
|
||||
|
||||
def test_show_non_default
|
||||
Repository::Subversion.create(:project => @project,
|
||||
:url => self.class.subversion_repository_url,
|
||||
:is_default => false, :identifier => 'svn')
|
||||
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:repository_id => 'svn'
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'tr.dir a[href="/projects/subproject1/repository/svn/show/subversion_test"]'
|
||||
# Repository menu should link to the main repo
|
||||
assert_select '#main-menu a[href="/projects/subproject1/repository"]'
|
||||
end
|
||||
|
||||
def test_browse_directory
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 5
|
||||
assert_select 'tr.dir td.filename a', :text => '[folder_with_brackets]'
|
||||
assert_select 'tr.dir td.filename a', :text => 'folder'
|
||||
assert_select 'tr.file td.filename a', :text => '.project'
|
||||
assert_select 'tr.file td.filename a', :text => 'helloworld.c'
|
||||
assert_select 'tr.file td.filename a', :text => 'textfile.txt'
|
||||
end
|
||||
|
||||
assert_select 'a.text-x-c', :text => 'helloworld.c'
|
||||
end
|
||||
|
||||
def test_browse_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test'])[:param],
|
||||
:rev => 4
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.entries tbody' do
|
||||
assert_select 'tr', 5
|
||||
assert_select 'tr.dir td.filename a', :text => 'folder'
|
||||
assert_select 'tr.file td.filename a', :text => '.project'
|
||||
assert_select 'tr.file td.filename a', :text => 'helloworld.c'
|
||||
assert_select 'tr.file td.filename a', :text => 'helloworld.rb'
|
||||
assert_select 'tr.file td.filename a', :text => 'textfile.txt'
|
||||
end
|
||||
end
|
||||
|
||||
def test_file_changes
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :changes, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder', 'helloworld.rb'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr', 3
|
||||
assert_select 'tr td.id a', :text => '6'
|
||||
assert_select 'tr td.id a', :text => '3'
|
||||
assert_select 'tr td.id a', :text => '2'
|
||||
end
|
||||
|
||||
# svn properties displayed with svn >= 1.5 only
|
||||
if Redmine::Scm::Adapters::SubversionAdapter.client_version_above?([1, 5, 0])
|
||||
assert_select 'ul li' do
|
||||
assert_select 'b', :text => 'svn:eol-style'
|
||||
assert_select 'span', :text => 'native'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_directory_changes
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :changes, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.changesets tbody' do
|
||||
assert_select 'tr', 6
|
||||
assert_select 'tr td.id a', :text => '10'
|
||||
assert_select 'tr td.id a', :text => '9'
|
||||
assert_select 'tr td.id a', :text => '7'
|
||||
assert_select 'tr td.id a', :text => '6'
|
||||
assert_select 'tr td.id a', :text => '5'
|
||||
assert_select 'tr td.id a', :text => '2'
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2 a', :text => 'subversion_test'
|
||||
assert_select 'h2 a', :text => 'helloworld.c'
|
||||
end
|
||||
|
||||
def test_entry_should_show_other_if_too_big
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
# no files in the test repo is larger than 1KB...
|
||||
with_settings :file_max_size_displayed => 0 do
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'p.nodata'
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry_should_display_images
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder', 'subfolder', 'rubylogo.gif'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'img[src=?]', '/projects/subproject1/repository/raw/subversion_test/folder/subfolder/rubylogo.gif'
|
||||
end
|
||||
|
||||
def test_entry_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.rb'])[:param],
|
||||
:rev => 2
|
||||
}
|
||||
assert_response :success
|
||||
# this line was removed in r3 and file was moved in r6
|
||||
assert_select 'td.line-code', :text => /Here's the code/
|
||||
end
|
||||
|
||||
def test_entry_not_found
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'zzz.c'])[:param]
|
||||
}
|
||||
assert_select 'p#errorExplanation', :text => /The entry or revision was not found in the repository/
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :raw, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'attachment; filename="helloworld.c"', @response.headers['Content-Disposition']
|
||||
end
|
||||
|
||||
def test_directory_entry
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2 a', :text => 'subversion_test'
|
||||
assert_select 'h2 a', :text => 'folder'
|
||||
end
|
||||
|
||||
# TODO: this test needs fixtures.
|
||||
def test_revision
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 2
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'ul' do
|
||||
assert_select 'li' do
|
||||
# link to the entry at rev 2
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/entry/test/some/path/in/the/repo', :text => 'repo'
|
||||
# link to partial diff
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/diff/test/some/path/in/the/repo'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_invalid_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :revision, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 'something_weird'
|
||||
}
|
||||
assert_response 404
|
||||
assert_select_error /was not found/
|
||||
end
|
||||
|
||||
def test_invalid_revision_diff
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => '1',
|
||||
:rev_to => 'something_weird'
|
||||
}
|
||||
assert_response 404
|
||||
assert_select_error /was not found/
|
||||
end
|
||||
|
||||
def test_empty_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['', ' ', nil].each do |r|
|
||||
get :revision, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => r
|
||||
}
|
||||
assert_response 404
|
||||
assert_select_error /was not found/
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: this test needs fixtures.
|
||||
def test_revision_with_repository_pointing_to_a_subdirectory
|
||||
r = Project.find(1).repository
|
||||
# Changes repository url to a subdirectory
|
||||
r.update_attribute :url, (r.url + '/test/some')
|
||||
|
||||
get :revision, :params => {
|
||||
:id => 1,
|
||||
:rev => 2
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'ul' do
|
||||
assert_select 'li' do
|
||||
# link to the entry at rev 2
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/entry/path/in/the/repo', :text => 'repo'
|
||||
# link to partial diff
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/2/diff/path/in/the/repo'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_revision_diff
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 3,
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /Revision 3/
|
||||
assert_select 'th.filename', :text => 'subversion_test/textfile.txt'
|
||||
end
|
||||
end
|
||||
|
||||
def test_revision_diff_raw_format
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 5,
|
||||
:format => 'diff'
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/x-patch', @response.content_type
|
||||
assert_equal 'Index: subversion_test/folder/greeter.rb', @response.body.split(/\r?\n/).first
|
||||
end
|
||||
|
||||
def test_directory_diff
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 6,
|
||||
:rev_to => 2,
|
||||
:path => repository_path_hash(['subversion_test', 'folder'])[:param],
|
||||
:type => dt
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'h2', :text => /2:6/
|
||||
# 2 files modified
|
||||
assert_select 'table.filecontent', 2
|
||||
assert_select 'table.filecontent thead th.filename', :text => 'greeter.rb'
|
||||
assert_select 'table.filecontent thead th.filename', :text => 'helloworld.rb'
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'tr' do
|
||||
assert_select 'th.line-num', :text => '1'
|
||||
assert_select 'td.revision', :text => '4'
|
||||
assert_select 'td.author', :text => 'jp'
|
||||
assert_select 'td', :text => /stdio.h/
|
||||
end
|
||||
# Same revision
|
||||
assert_select 'tr' do
|
||||
assert_select 'th.line-num', :text => '2'
|
||||
assert_select 'td.revision', :text => ''
|
||||
assert_select 'td.author', :text => ''
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_at_given_revision
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :annotate, :params => {
|
||||
:id => PRJ_ID,
|
||||
:rev => 8,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /@ 8/
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
|
||||
def test_destroy_invalid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
@project.repository.destroy
|
||||
@repository = Repository::Subversion.create!(
|
||||
:project => @project,
|
||||
:url => "file:///invalid")
|
||||
@repository.fetch_changesets
|
||||
assert_equal 0, @repository.changesets.count
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :params => {
|
||||
:id => @repository.id
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
@project.reload
|
||||
assert_nil @project.repository
|
||||
end
|
||||
else
|
||||
puts "Subversion test repository NOT FOUND. Skipping functional tests !!!"
|
||||
def test_fake; assert true end
|
||||
end
|
||||
end
|
||||
263
test/functional/roles_controller_test.rb
Normal file
263
test/functional/roles_controller_test.rb
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
# 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 RolesControllerTest < Redmine::ControllerTest
|
||||
fixtures :roles, :users, :members, :member_roles, :workflows, :trackers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
assert_select 'table.roles tbody' do
|
||||
assert_select 'tr', Role.count
|
||||
assert_select 'a[href="/roles/1/edit"]', :text => 'Manager'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'role[name]'
|
||||
assert_select 'input[name=?]', 'role[permissions][]'
|
||||
end
|
||||
|
||||
def test_new_should_prefill_permissions_with_non_member_permissions
|
||||
role = Role.non_member
|
||||
role.permissions = [:view_issues, :view_documents]
|
||||
role.save!
|
||||
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_equal %w(view_documents view_issues),
|
||||
css_select('input[name="role[permissions][]"][checked=checked]').map {|e| e.attr('value')}.sort
|
||||
end
|
||||
|
||||
def test_new_with_copy
|
||||
copy_from = Role.find(2)
|
||||
|
||||
get :new, :params => {:copy => copy_from.id.to_s}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'role[name]'
|
||||
|
||||
assert_select 'form' do
|
||||
# blank name
|
||||
assert_select 'input[name=?][value=""]', 'role[name]'
|
||||
# edit_project permission checked
|
||||
assert_select 'input[type=checkbox][name=?][value=edit_project][checked=checked]', 'role[permissions][]'
|
||||
# add_project permission not checked
|
||||
assert_select 'input[type=checkbox][name=?][value=add_project]', 'role[permissions][]'
|
||||
assert_select 'input[type=checkbox][name=?][value=add_project][checked=checked]', 'role[permissions][]', 0
|
||||
# workflow copy selected
|
||||
assert_select 'select[name=?]', 'copy_workflow_from' do
|
||||
assert_select 'option[value="2"][selected=selected]'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_with_validaton_failure
|
||||
post :create, :params => {
|
||||
:role => {
|
||||
:name => '',
|
||||
:permissions => ['add_issues', 'edit_issues', 'log_time', ''],
|
||||
:assignable => '0'
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/
|
||||
end
|
||||
|
||||
def test_create_without_workflow_copy
|
||||
post :create, :params => {
|
||||
:role => {
|
||||
:name => 'RoleWithoutWorkflowCopy',
|
||||
:permissions => ['add_issues', 'edit_issues', 'log_time', ''],
|
||||
:assignable => '0'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/roles'
|
||||
role = Role.find_by_name('RoleWithoutWorkflowCopy')
|
||||
assert_not_nil role
|
||||
assert_equal [:add_issues, :edit_issues, :log_time], role.permissions
|
||||
assert !role.assignable?
|
||||
end
|
||||
|
||||
def test_create_with_workflow_copy
|
||||
post :create, :params => {
|
||||
:role => {
|
||||
:name => 'RoleWithWorkflowCopy',
|
||||
:permissions => ['add_issues', 'edit_issues', 'log_time', ''],
|
||||
:assignable => '0'
|
||||
},
|
||||
:copy_workflow_from => '1'
|
||||
}
|
||||
assert_redirected_to '/roles'
|
||||
role = Role.find_by_name('RoleWithWorkflowCopy')
|
||||
assert_not_nil role
|
||||
assert_equal Role.find(1).workflow_rules.size, role.workflow_rules.size
|
||||
end
|
||||
|
||||
def test_create_with_managed_roles
|
||||
role = new_record(Role) do
|
||||
post :create, :params => {
|
||||
:role => {
|
||||
:name => 'Role',
|
||||
:all_roles_managed => '0',
|
||||
:managed_role_ids => ['2', '3', '']
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
assert_equal false, role.all_roles_managed
|
||||
assert_equal [2, 3], role.managed_role_ids.sort
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {:id => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=?]', 'role[name]', 'Manager'
|
||||
assert_select 'select[name=?]', 'role[issues_visibility]'
|
||||
end
|
||||
|
||||
def test_edit_anonymous
|
||||
get :edit, :params => {:id => Role.anonymous.id}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?]', 'role[name]', 0
|
||||
assert_select 'select[name=?]', 'role[issues_visibility]', 0
|
||||
end
|
||||
|
||||
def test_edit_invalid_should_respond_with_404
|
||||
get :edit, :params => {:id => 999}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:role => {
|
||||
:name => 'Manager',
|
||||
:permissions => ['edit_project', ''],
|
||||
:assignable => '0'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/roles'
|
||||
role = Role.find(1)
|
||||
assert_equal [:edit_project], role.permissions
|
||||
end
|
||||
|
||||
def test_update_trackers_permissions
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:role => {
|
||||
:permissions_all_trackers => {'add_issues' => '0'},
|
||||
:permissions_tracker_ids => {'add_issues' => ['1', '3', '']}
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/roles'
|
||||
role = Role.find(1)
|
||||
|
||||
assert_equal({'add_issues' => '0'}, role.permissions_all_trackers)
|
||||
assert_equal({'add_issues' => ['1', '3']}, role.permissions_tracker_ids)
|
||||
|
||||
assert_equal false, role.permissions_all_trackers?(:add_issues)
|
||||
assert_equal [1, 3], role.permissions_tracker_ids(:add_issues).sort
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :params => {:id => 1, :role => {:name => ''}}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
r = Role.create!(:name => 'ToBeDestroyed', :permissions => [:view_wiki_pages])
|
||||
|
||||
delete :destroy, :params => {:id => r}
|
||||
assert_redirected_to '/roles'
|
||||
assert_nil Role.find_by_id(r.id)
|
||||
end
|
||||
|
||||
def test_destroy_role_in_use
|
||||
delete :destroy, :params => {:id => 1}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal 'This role is in use and cannot be deleted.', flash[:error]
|
||||
assert_not_nil Role.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_get_permissions
|
||||
get :permissions
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][type=checkbox][value=add_issues][checked=checked]', 'permissions[3][]'
|
||||
assert_select 'input[name=?][type=checkbox][value=delete_issues]:not([checked])', 'permissions[3][]'
|
||||
end
|
||||
|
||||
def test_post_permissions
|
||||
post :permissions, :params => {
|
||||
:permissions => {
|
||||
'0' => '',
|
||||
'1' => ['edit_issues'],
|
||||
'3' => ['add_issues', 'delete_issues']
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/roles'
|
||||
|
||||
assert_equal [:edit_issues], Role.find(1).permissions
|
||||
assert_equal [:add_issues, :delete_issues], Role.find(3).permissions
|
||||
assert Role.find(2).permissions.empty?
|
||||
end
|
||||
|
||||
def test_clear_all_permissions
|
||||
post :permissions, :params => {:permissions => { '0' => '' }}
|
||||
assert_redirected_to '/roles'
|
||||
assert Role.find(1).permissions.empty?
|
||||
end
|
||||
|
||||
def test_move_highest
|
||||
put :update, :params => {:id => 3, :role => {:position => 1}}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal 1, Role.find(3).position
|
||||
end
|
||||
|
||||
def test_move_higher
|
||||
position = Role.find(3).position
|
||||
put :update, :params => {:id => 3, :role => {:position => position - 1}}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal position - 1, Role.find(3).position
|
||||
end
|
||||
|
||||
def test_move_lower
|
||||
position = Role.find(2).position
|
||||
put :update, :params => {:id => 2, :role => {:position => position + 1}}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal position + 1, Role.find(2).position
|
||||
end
|
||||
|
||||
def test_move_lowest
|
||||
put :update, :params => {:id => 2, :role => {:position => Role.givable.count}}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal Role.givable.count, Role.find(2).position
|
||||
end
|
||||
end
|
||||
389
test/functional/search_controller_test.rb
Normal file
389
test/functional/search_controller_test.rb
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
# 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 SearchControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :projects_trackers,
|
||||
:enabled_modules, :roles, :users, :members, :member_roles,
|
||||
:issues, :trackers, :issue_statuses, :enumerations,
|
||||
:workflows,
|
||||
:custom_fields, :custom_values,
|
||||
:custom_fields_projects, :custom_fields_trackers,
|
||||
:repositories, :changesets
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_search_without_q_should_display_search_form
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select '#content input[name=q]'
|
||||
end
|
||||
|
||||
def test_search_for_projects
|
||||
get :index, :params => {:q => "cook"}
|
||||
assert_response :success
|
||||
assert_select '#search-results dt.project a', :text => /eCookbook/
|
||||
end
|
||||
|
||||
def test_search_on_archived_project_should_return_404
|
||||
Project.find(3).archive
|
||||
get :index, :params => {:id => 3}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_search_on_invisible_project_by_user_should_be_denied
|
||||
@request.session[:user_id] = 7
|
||||
get :index, :params => {:id => 2}
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_search_on_invisible_project_by_anonymous_user_should_redirect
|
||||
get :index, :params => {:id => 2}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_search_on_private_project_by_member_should_succeed
|
||||
@request.session[:user_id] = 2
|
||||
get :index, :params => {:id => 2}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_search_all_projects
|
||||
with_settings :default_language => 'en' do
|
||||
get :index, :params => {:q => 'recipe subproject commit', :all_words => ''}
|
||||
end
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => /Feature request #2/
|
||||
assert_select 'dt.issue a', :text => /Bug #5/
|
||||
assert_select 'dt.changeset a', :text => /Revision 1/
|
||||
|
||||
assert_select 'dt.issue a', :text => /Add ingredients categories/
|
||||
assert_select 'dd', :text => /should be classified by categories/
|
||||
end
|
||||
|
||||
assert_select '#search-results-counts' do
|
||||
assert_select 'a', :text => 'Changesets (5)'
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_issues
|
||||
get :index, :params => {:q => 'issue', :issues => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=all_words][checked=checked]'
|
||||
assert_select 'input[name=titles_only]:not([checked])'
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => /Bug #5/
|
||||
assert_select 'dt.issue-closed a', :text => /Bug #8 \(Closed\)/
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_issues_should_search_notes
|
||||
Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
|
||||
|
||||
get :index, :params => {:q => 'searchkeyword', :issues => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => /Feature request #2/
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_issues_with_multiple_matches_in_journals_should_return_issue_once
|
||||
Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
|
||||
Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
|
||||
|
||||
get :index, :params => {:q => 'searchkeyword', :issues => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => /Feature request #2/
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_issues_should_search_private_notes_with_permission_only
|
||||
Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes with searchkeyword', :private_notes => true)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
Role.find(1).add_permission! :view_private_notes
|
||||
get :index, :params => {:q => 'searchkeyword', :issues => 1}
|
||||
assert_response :success
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => /Feature request #2/
|
||||
end
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :index, :params => {:q => 'searchkeyword', :issues => 1}
|
||||
assert_response :success
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt', :text => /Feature request #2/, :count => 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_all_projects_with_scope_param
|
||||
get :index, :params => {:q => 'issue', :scope => 'all'}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results dt'
|
||||
end
|
||||
|
||||
def test_search_my_projects
|
||||
@request.session[:user_id] = 2
|
||||
get :index, :params => {:id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => ''}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => /Bug #1/
|
||||
assert_select 'dt', :text => /Bug #5/, :count => 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_my_projects_without_memberships
|
||||
# anonymous user has no memberships
|
||||
get :index, :params => {:id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => ''}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_project_and_subprojects
|
||||
get :index, :params => {:id => 1, :q => 'recipe subproject', :scope => 'subprojects', :all_words => ''}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => /Bug #1/
|
||||
assert_select 'dt.issue', :text => /Bug #5/
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_without_searchable_custom_fields
|
||||
CustomField.update_all :searchable => false
|
||||
|
||||
get :index, :params => {:id => 1}
|
||||
assert_response :success
|
||||
|
||||
get :index, :params => {:id => 1, :q => "can"}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_search_with_searchable_custom_fields
|
||||
get :index, :params => {:id => 1, :q => "stringforcustomfield"}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => /#7/
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_without_attachments
|
||||
issue = Issue.generate! :subject => 'search_attachments'
|
||||
attachment = Attachment.generate! :container => Issue.find(1), :filename => 'search_attachments.patch'
|
||||
|
||||
get :index, :params => {:id => 1, :q => 'search_attachments', :attachments => '0'}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => /##{issue.id}/
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_attachments_only
|
||||
issue = Issue.generate! :subject => 'search_attachments'
|
||||
attachment = Attachment.generate! :container => Issue.find(1), :filename => 'search_attachments.patch'
|
||||
|
||||
get :index, :params => {:id => 1, :q => 'search_attachments', :attachments => 'only'}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => / #1 /
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_with_attachments
|
||||
issue = Issue.generate! :subject => 'search_attachments'
|
||||
Attachment.generate! :container => Issue.find(1), :filename => 'search_attachments.patch'
|
||||
|
||||
get :index, :params => {:id => 1, :q => 'search_attachments', :attachments => '1'}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => / #1 /
|
||||
assert_select 'dt.issue', :text => / ##{issue.id} /
|
||||
assert_select 'dt', 2
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_open_issues
|
||||
Issue.generate! :subject => 'search_open'
|
||||
Issue.generate! :subject => 'search_open', :status_id => 5
|
||||
|
||||
get :index, :params => {:id => 1, :q => 'search_open', :open_issues => '1'}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_all_words
|
||||
# 'all words' is on by default
|
||||
get :index, :params => {:id => 1, :q => 'recipe updating saving', :all_words => '1'}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=all_words][checked=checked]'
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => / #3 /
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_one_of_the_words
|
||||
get :index, :params => {:id => 1, :q => 'recipe updating saving', :all_words => ''}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=all_words]:not([checked])'
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => / #3 /
|
||||
assert_select 'dt', 3
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_titles_only_without_result
|
||||
get :index, :params => {:id => 1, :q => 'recipe updating saving', :titles_only => '1'}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=titles_only][checked=checked]'
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_titles_only
|
||||
get :index, :params => {:id => 1, :q => 'recipe', :titles_only => '1'}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=titles_only][checked=checked]'
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt', 2
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_content
|
||||
Issue.where(:id => 1).update_all("description = 'This is a searchkeywordinthecontent'")
|
||||
|
||||
get :index, :params => {:id => 1, :q => 'searchkeywordinthecontent', :titles_only => ''}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=titles_only]:not([checked])'
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue', :text => / #1 /
|
||||
assert_select 'dt', 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_with_pagination
|
||||
issues = (0..24).map {Issue.generate! :subject => 'search_with_limited_results'}.reverse
|
||||
|
||||
get :index, :params => {:q => 'search_with_limited_results'}
|
||||
assert_response :success
|
||||
issues[0..9].each do |issue|
|
||||
assert_select '#search-results dt.issue', :text => / ##{issue.id} /
|
||||
end
|
||||
|
||||
get :index, :params => {:q => 'search_with_limited_results', :page => 2}
|
||||
assert_response :success
|
||||
issues[10..19].each do |issue|
|
||||
assert_select '#search-results dt.issue', :text => / ##{issue.id} /
|
||||
end
|
||||
|
||||
get :index, :params => {:q => 'search_with_limited_results', :page => 3}
|
||||
assert_response :success
|
||||
issues[20..24].each do |issue|
|
||||
assert_select '#search-results dt.issue', :text => / ##{issue.id} /
|
||||
end
|
||||
|
||||
get :index, :params => {:q => 'search_with_limited_results', :page => 4}
|
||||
assert_response :success
|
||||
assert_select '#search-results dt', 0
|
||||
end
|
||||
|
||||
def test_search_with_invalid_project_id
|
||||
get :index, :params => {:id => 195, :q => 'recipe'}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_quick_jump_to_issue
|
||||
# issue of a public project
|
||||
get :index, :params => {:q => "3"}
|
||||
assert_redirected_to '/issues/3'
|
||||
|
||||
# issue of a private project
|
||||
get :index, :params => {:q => "4"}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_large_integer
|
||||
get :index, :params => {:q => '4615713488'}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_tokens_with_quotes
|
||||
issue1 = Issue.generate! :subject => 'say hello'
|
||||
issue2 = Issue.generate! :subject => 'say good bye'
|
||||
issue3 = Issue.generate! :subject => 'say goodbye'
|
||||
|
||||
get :index, :params => {:q => '"good bye" hello "bye bye"', :all_words => ''}
|
||||
assert_response :success
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => / ##{issue1.id} /
|
||||
assert_select 'dt.issue a', :text => / ##{issue2.id} /
|
||||
assert_select 'dt.issue a', :text => / ##{issue3.id} /, :count => 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_results_should_be_escaped_once
|
||||
assert Issue.find(1).update_attributes(:subject => '<subject> escaped_once', :description => '<description> escaped_once')
|
||||
get :index, :params => {:q => 'escaped_once'}
|
||||
assert_response :success
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a', :text => /<subject>/
|
||||
assert_select 'dd', :text => /<description>/
|
||||
end
|
||||
end
|
||||
|
||||
def test_keywords_should_be_highlighted
|
||||
assert Issue.find(1).update_attributes(:subject => 'subject highlighted', :description => 'description highlighted')
|
||||
get :index, :params => {:q => 'highlighted'}
|
||||
assert_response :success
|
||||
assert_select '#search-results' do
|
||||
assert_select 'dt.issue a span.highlight', :text => 'highlighted'
|
||||
assert_select 'dd span.highlight', :text => 'highlighted'
|
||||
end
|
||||
end
|
||||
end
|
||||
78
test/functional/search_custom_fields_visibility_test.rb
Normal file
78
test/functional/search_custom_fields_visibility_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 SearchCustomFieldsVisibilityTest < Redmine::ControllerTest
|
||||
tests SearchController
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issue_statuses,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:enabled_modules,
|
||||
:enumerations,
|
||||
:workflows
|
||||
|
||||
def setup
|
||||
field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :searchable => true, :trackers => Tracker.all}
|
||||
@fields = []
|
||||
@fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
|
||||
@fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
|
||||
@fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
|
||||
@issue = Issue.generate!(
|
||||
:author_id => 1,
|
||||
:project_id => 1,
|
||||
:tracker_id => 1,
|
||||
:custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
|
||||
)
|
||||
|
||||
@user_with_role_on_other_project = User.generate!
|
||||
User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
|
||||
|
||||
@users_to_test = {
|
||||
User.find(1) => [@field1, @field2, @field3],
|
||||
User.find(3) => [@field1, @field2],
|
||||
@user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
|
||||
User.generate! => [@field1],
|
||||
User.anonymous => [@field1]
|
||||
}
|
||||
|
||||
Member.where(:project_id => 1).each do |member|
|
||||
member.destroy unless @users_to_test.keys.include?(member.principal)
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_should_search_visible_custom_fields_only
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
@fields.each_with_index do |field, i|
|
||||
get :index, :params => {:q => "value#{i}"}
|
||||
assert_response :success
|
||||
# we should get a result only if the custom field is visible
|
||||
if fields.include?(field)
|
||||
assert_select '#search-results dt', 1
|
||||
else
|
||||
assert_select '#search-results dt', 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
164
test/functional/sessions_controller_test.rb
Normal file
164
test/functional/sessions_controller_test.rb
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# 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 SessionsControllerTest < Redmine::ControllerTest
|
||||
include Redmine::I18n
|
||||
tests WelcomeController
|
||||
|
||||
fixtures :users, :email_addresses
|
||||
|
||||
def setup
|
||||
Rails.application.config.redmine_verify_sessions = true
|
||||
end
|
||||
|
||||
def teardown
|
||||
Rails.application.config.redmine_verify_sessions = false
|
||||
end
|
||||
|
||||
def test_session_token_should_be_updated
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => 10.hours.ago, :updated_on => 10.hours.ago)
|
||||
created = token.reload.created_on
|
||||
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_response :success
|
||||
token.reload
|
||||
assert_equal created.to_i, token.created_on.to_i
|
||||
assert_not_equal created.to_i, token.updated_on.to_i
|
||||
assert token.updated_on > created
|
||||
end
|
||||
|
||||
def test_user_session_should_not_be_reset_if_lifetime_and_timeout_disabled
|
||||
created = 2.years.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_lifetime => '0', :session_timeout => '0' do
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_without_token_should_be_reset
|
||||
get :index, :session => {
|
||||
:user_id => 2
|
||||
}
|
||||
assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F'
|
||||
end
|
||||
|
||||
def test_expired_user_session_should_be_reset_if_lifetime_enabled
|
||||
created = 2.days.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_timeout => '720' do
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F'
|
||||
end
|
||||
end
|
||||
|
||||
def test_valid_user_session_should_not_be_reset_if_lifetime_enabled
|
||||
created = 3.hours.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_timeout => '720' do
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_expired_user_session_should_be_reset_if_timeout_enabled
|
||||
created = 4.hours.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_timeout => '60' do
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F'
|
||||
end
|
||||
end
|
||||
|
||||
def test_valid_user_session_should_not_be_reset_if_timeout_enabled
|
||||
created = 10.minutes.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_timeout => '60' do
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_expired_user_session_should_be_restarted_if_autologin
|
||||
created = 2.hours.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_lifetime => '720', :session_timeout => '60', :autologin => 7 do
|
||||
autologin_token = Token.create!(:user_id => 2, :action => 'autologin', :created_on => 1.day.ago)
|
||||
@request.cookies['autologin'] = autologin_token.value
|
||||
|
||||
get :index, :session => {
|
||||
:user_id => 2,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_equal 2, session[:user_id]
|
||||
assert_response :success
|
||||
assert_not_equal token.value, session[:tk]
|
||||
end
|
||||
end
|
||||
|
||||
def test_expired_user_session_should_set_locale
|
||||
set_language_if_valid 'it'
|
||||
user = User.find(2)
|
||||
user.language = 'fr'
|
||||
user.save!
|
||||
created = 4.hours.ago
|
||||
token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created)
|
||||
|
||||
with_settings :session_timeout => '60' do
|
||||
get :index, :session => {
|
||||
:user_id => user.id,
|
||||
:tk => token.value
|
||||
}
|
||||
assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F'
|
||||
assert_include "Veuillez vous reconnecter", flash[:error]
|
||||
assert_equal :fr, current_language
|
||||
end
|
||||
end
|
||||
|
||||
def test_anonymous_session_should_not_be_reset
|
||||
with_settings :session_lifetime => '720', :session_timeout => '60' do
|
||||
get :index
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
end
|
||||
300
test/functional/settings_controller_test.rb
Normal file
300
test/functional/settings_controller_test.rb
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
# 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 SettingsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:users
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.delete_all
|
||||
Setting.clear_cache
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=?]', 'settings[app_title]', Setting.app_title
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
get :edit
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=""]', 'settings[enabled_scm][]'
|
||||
end
|
||||
|
||||
def test_get_edit_should_preselect_default_issue_list_columns
|
||||
with_settings :issue_list_default_columns => %w(tracker subject status updated_on) do
|
||||
get :edit
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
assert_select 'select[name=?]', 'settings[issue_list_default_columns][]' do
|
||||
assert_select 'option', 4
|
||||
assert_select 'option[value=tracker]', :text => 'Tracker'
|
||||
assert_select 'option[value=subject]', :text => 'Subject'
|
||||
assert_select 'option[value=status]', :text => 'Status'
|
||||
assert_select 'option[value=updated_on]', :text => 'Updated'
|
||||
end
|
||||
|
||||
assert_select 'select[name=?]', 'available_columns[]' do
|
||||
assert_select 'option[value=tracker]', 0
|
||||
assert_select 'option[value=priority]', :text => 'Priority'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_edit_without_trackers_should_succeed
|
||||
Tracker.delete_all
|
||||
|
||||
get :edit
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_post_edit_notifications
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:mail_from => 'functional@test.foo',
|
||||
:bcc_recipients => '0',
|
||||
:notified_events => %w(issue_added issue_updated news_added),
|
||||
:emails_footer => 'Test footer'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/settings'
|
||||
assert_equal 'functional@test.foo', Setting.mail_from
|
||||
assert !Setting.bcc_recipients?
|
||||
assert_equal %w(issue_added issue_updated news_added), Setting.notified_events
|
||||
assert_equal 'Test footer', Setting.emails_footer
|
||||
end
|
||||
|
||||
def test_edit_commit_update_keywords
|
||||
with_settings :commit_update_keywords => [
|
||||
{"keywords" => "fixes, resolves", "status_id" => "3"},
|
||||
{"keywords" => "closes", "status_id" => "5", "done_ratio" => "100", "if_tracker_id" => "2"}
|
||||
] do
|
||||
get :edit
|
||||
end
|
||||
assert_response :success
|
||||
assert_select 'tr.commit-keywords', 2
|
||||
assert_select 'tr.commit-keywords:nth-child(1)' do
|
||||
assert_select 'input[name=?][value=?]', 'settings[commit_update_keywords][keywords][]', 'fixes, resolves'
|
||||
assert_select 'select[name=?]', 'settings[commit_update_keywords][status_id][]' do
|
||||
assert_select 'option[value="3"][selected=selected]'
|
||||
end
|
||||
end
|
||||
assert_select 'tr.commit-keywords:nth-child(2)' do
|
||||
assert_select 'input[name=?][value=?]', 'settings[commit_update_keywords][keywords][]', 'closes'
|
||||
assert_select 'select[name=?]', 'settings[commit_update_keywords][status_id][]' do
|
||||
assert_select 'option[value="5"][selected=selected]', :text => 'Closed'
|
||||
end
|
||||
assert_select 'select[name=?]', 'settings[commit_update_keywords][done_ratio][]' do
|
||||
assert_select 'option[value="100"][selected=selected]', :text => '100 %'
|
||||
end
|
||||
assert_select 'select[name=?]', 'settings[commit_update_keywords][if_tracker_id][]' do
|
||||
assert_select 'option[value="2"][selected=selected]', :text => 'Feature request'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_edit_without_commit_update_keywords_should_show_blank_line
|
||||
with_settings :commit_update_keywords => [] do
|
||||
get :edit
|
||||
end
|
||||
assert_response :success
|
||||
assert_select 'tr.commit-keywords', 1 do
|
||||
assert_select 'input[name=?]:not([value])', 'settings[commit_update_keywords][keywords][]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_edit_commit_update_keywords
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:commit_update_keywords => {
|
||||
:keywords => ["resolves", "closes"],
|
||||
:status_id => ["3", "5"],
|
||||
:done_ratio => ["", "100"],
|
||||
:if_tracker_id => ["", "2"]
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/settings'
|
||||
assert_equal([
|
||||
{"keywords" => "resolves", "status_id" => "3"},
|
||||
{"keywords" => "closes", "status_id" => "5", "done_ratio" => "100", "if_tracker_id" => "2"}
|
||||
], Setting.commit_update_keywords)
|
||||
end
|
||||
|
||||
def test_post_edit_with_invalid_setting_should_not_error
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:invalid_setting => '1'
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/settings'
|
||||
end
|
||||
|
||||
def test_post_edit_should_send_security_notification_for_notified_settings
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:login_required => 1
|
||||
}
|
||||
}
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match '0.0.0.0', mail
|
||||
assert_mail_body_match I18n.t(:setting_login_required), mail
|
||||
assert_select_email do
|
||||
assert_select 'a[href^=?]', 'http://localhost:3000/settings'
|
||||
end
|
||||
# All admins should receive this
|
||||
recipients = [mail.bcc, mail.cc].flatten
|
||||
User.active.where(admin: true).each do |admin|
|
||||
assert_include admin.mail, recipients
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_edit_should_not_send_security_notification_for_non_notified_settings
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:app_title => 'MineRed'
|
||||
}
|
||||
}
|
||||
assert_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
end
|
||||
|
||||
def test_post_edit_should_not_send_security_notification_for_unchanged_settings
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:login_required => 0
|
||||
}
|
||||
}
|
||||
assert_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
end
|
||||
|
||||
|
||||
def test_get_plugin_settings
|
||||
ActionController::Base.append_view_path(File.join(Rails.root, "test/fixtures/plugins"))
|
||||
Redmine::Plugin.register :foo do
|
||||
settings :partial => "foo_plugin/foo_plugin_settings"
|
||||
end
|
||||
Setting.plugin_foo = {'sample_setting' => 'Plugin setting value'}
|
||||
|
||||
get :plugin, :params => {:id => 'foo'}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form[action="/settings/plugin/foo"]' do
|
||||
assert_select 'input[name=?][value=?]', 'settings[sample_setting]', 'Plugin setting value'
|
||||
end
|
||||
ensure
|
||||
Redmine::Plugin.unregister(:foo)
|
||||
end
|
||||
|
||||
def test_get_invalid_plugin_settings
|
||||
get :plugin, :params => {:id => 'none'}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_non_configurable_plugin_settings
|
||||
Redmine::Plugin.register(:foo) {}
|
||||
|
||||
get :plugin, :params => {:id => 'foo'}
|
||||
assert_response 404
|
||||
|
||||
ensure
|
||||
Redmine::Plugin.unregister(:foo)
|
||||
end
|
||||
|
||||
def test_post_plugin_settings
|
||||
Redmine::Plugin.register(:foo) do
|
||||
settings :partial => 'not blank', # so that configurable? is true
|
||||
:default => {'sample_setting' => 'Plugin setting value'}
|
||||
end
|
||||
|
||||
post :plugin, :params => {
|
||||
:id => 'foo',
|
||||
:settings => {'sample_setting' => 'Value'}
|
||||
}
|
||||
assert_redirected_to '/settings/plugin/foo'
|
||||
|
||||
assert_equal({'sample_setting' => 'Value'}, Setting.plugin_foo)
|
||||
end
|
||||
|
||||
def test_post_empty_plugin_settings
|
||||
Redmine::Plugin.register(:foo) do
|
||||
settings :partial => 'not blank', # so that configurable? is true
|
||||
:default => {'sample_setting' => 'Plugin setting value'}
|
||||
end
|
||||
|
||||
post :plugin, :params => {
|
||||
:id => 'foo'
|
||||
}
|
||||
assert_redirected_to '/settings/plugin/foo'
|
||||
|
||||
assert_equal({}, Setting.plugin_foo)
|
||||
end
|
||||
|
||||
def test_post_non_configurable_plugin_settings
|
||||
Redmine::Plugin.register(:foo) {}
|
||||
|
||||
post :plugin, :params => {
|
||||
:id => 'foo',
|
||||
:settings => {'sample_setting' => 'Value'}
|
||||
}
|
||||
assert_response 404
|
||||
|
||||
ensure
|
||||
Redmine::Plugin.unregister(:foo)
|
||||
end
|
||||
|
||||
def test_post_mail_handler_delimiters_should_not_save_invalid_regex_delimiters
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:mail_handler_enable_regex_delimiters => '1',
|
||||
:mail_handler_body_delimiters => 'Abc[',
|
||||
}
|
||||
}
|
||||
|
||||
assert_response :success
|
||||
assert_equal '0', Setting.mail_handler_enable_regex_delimiters
|
||||
assert_equal '', Setting.mail_handler_body_delimiters
|
||||
|
||||
assert_select_error /is not a valid regular expression/
|
||||
assert_select 'textarea[name=?]', 'settings[mail_handler_body_delimiters]', :text => 'Abc['
|
||||
end
|
||||
|
||||
def test_post_mail_handler_delimiters_should_save_valid_regex_delimiters
|
||||
post :edit, :params => {
|
||||
:settings => {
|
||||
:mail_handler_enable_regex_delimiters => '1',
|
||||
:mail_handler_body_delimiters => 'On .*, .* at .*, .* <.*<mailto:.*>> wrote:',
|
||||
}
|
||||
}
|
||||
|
||||
assert_redirected_to '/settings'
|
||||
assert_equal '1', Setting.mail_handler_enable_regex_delimiters
|
||||
assert_equal 'On .*, .* at .*, .* <.*<mailto:.*>> wrote:', Setting.mail_handler_body_delimiters
|
||||
end
|
||||
end
|
||||
135
test/functional/sys_controller_test.rb
Normal file
135
test/functional/sys_controller_test.rb
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# 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 SysControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :repositories, :enabled_modules
|
||||
|
||||
def setup
|
||||
Setting.sys_api_enabled = '1'
|
||||
Setting.enabled_scm = %w(Subversion Git)
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.clear_cache
|
||||
end
|
||||
|
||||
def test_projects_with_repository_enabled
|
||||
get :projects
|
||||
assert_response :success
|
||||
assert_equal 'application/json', @response.content_type
|
||||
|
||||
data = ActiveSupport::JSON.decode(response.body)
|
||||
|
||||
assert_equal Project.active.has_module(:repository).count, data.size
|
||||
project = data.first
|
||||
assert project['identifier']
|
||||
assert project['is_public']
|
||||
|
||||
assert_not_include 'extra-info', response.body
|
||||
assert_not_include 'extra_info', response.body
|
||||
end
|
||||
|
||||
def test_create_project_repository
|
||||
assert_nil Project.find(4).repository
|
||||
|
||||
post :create_project_repository, :params => {
|
||||
:id => 4,
|
||||
:vendor => 'Subversion',
|
||||
:repository => { :url => 'file:///create/project/repository/subproject2'}
|
||||
}
|
||||
assert_response :created
|
||||
assert_equal 'application/json', @response.content_type
|
||||
|
||||
r = Project.find(4).repository
|
||||
assert r.is_a?(Repository::Subversion)
|
||||
assert_equal 'file:///create/project/repository/subproject2', r.url
|
||||
|
||||
data = ActiveSupport::JSON.decode(response.body)
|
||||
assert data['repository-subversion']
|
||||
assert_equal r.id, data['repository-subversion']['id']
|
||||
assert_equal r.url, data['repository-subversion']['url']
|
||||
|
||||
assert_not_include 'extra-info', response.body
|
||||
assert_not_include 'extra_info', response.body
|
||||
end
|
||||
|
||||
def test_create_already_existing
|
||||
post :create_project_repository, :params => {
|
||||
:id => 1,
|
||||
:vendor => 'Subversion',
|
||||
:repository => { :url => 'file:///create/project/repository/subproject2'}
|
||||
}
|
||||
assert_response :conflict
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
post :create_project_repository, :params => {
|
||||
:id => 4,
|
||||
:vendor => 'Subversion',
|
||||
:repository => { :url => 'invalid url'}
|
||||
}
|
||||
assert_response :unprocessable_entity
|
||||
end
|
||||
|
||||
def test_fetch_changesets
|
||||
Repository::Subversion.any_instance.expects(:fetch_changesets).twice.returns(true)
|
||||
get :fetch_changesets
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_fetch_changesets_one_project_by_identifier
|
||||
Repository::Subversion.any_instance.expects(:fetch_changesets).once.returns(true)
|
||||
get :fetch_changesets, :params => {:id => 'ecookbook'}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_fetch_changesets_one_project_by_id
|
||||
Repository::Subversion.any_instance.expects(:fetch_changesets).once.returns(true)
|
||||
get :fetch_changesets, :params => {:id => '1'}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_fetch_changesets_unknown_project
|
||||
get :fetch_changesets, :params => {:id => 'unknown'}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_disabled_ws_should_respond_with_403_error
|
||||
with_settings :sys_api_enabled => '0' do
|
||||
get :projects
|
||||
assert_response 403
|
||||
assert_include 'Access denied', response.body
|
||||
end
|
||||
end
|
||||
|
||||
def test_api_key
|
||||
with_settings :sys_api_key => 'my_secret_key' do
|
||||
get :projects, :params => {:key => 'my_secret_key'}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_wrong_key_should_respond_with_403_error
|
||||
with_settings :sys_api_enabled => 'my_secret_key' do
|
||||
get :projects, :params => {:key => 'wrong_key'}
|
||||
assert_response 403
|
||||
assert_include 'Access denied', response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
352
test/functional/time_entry_reports_controller_test.rb
Normal file
352
test/functional/time_entry_reports_controller_test.rb
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
# -*- coding: 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 TimeEntryReportsControllerTest < Redmine::ControllerTest
|
||||
tests TimelogController
|
||||
|
||||
fixtures :projects, :enabled_modules, :roles, :members, :member_roles,
|
||||
:email_addresses,
|
||||
:issues, :time_entries, :users, :trackers, :enumerations,
|
||||
:issue_statuses, :custom_fields, :custom_values,
|
||||
:projects_trackers, :custom_fields_trackers,
|
||||
:custom_fields_projects
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def setup
|
||||
Setting.default_language = "en"
|
||||
end
|
||||
|
||||
def test_report_at_project_level
|
||||
get :report, :params => {:project_id => 'ecookbook'}
|
||||
assert_response :success
|
||||
assert_select 'form#query_form[action=?]', '/projects/ecookbook/time_entries/report'
|
||||
end
|
||||
|
||||
def test_report_all_projects
|
||||
get :report
|
||||
assert_response :success
|
||||
assert_select 'form#query_form[action=?]', '/time_entries/report'
|
||||
end
|
||||
|
||||
def test_report_all_projects_denied
|
||||
r = Role.anonymous
|
||||
r.permissions.delete(:view_time_entries)
|
||||
r.permissions_will_change!
|
||||
r.save
|
||||
get :report
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Ftime_entries%2Freport'
|
||||
end
|
||||
|
||||
def test_report_all_projects_one_criteria
|
||||
get :report, :params => {:columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']}
|
||||
assert_response :success
|
||||
assert_select 'tr.total td:last', :text => '8.65'
|
||||
end
|
||||
|
||||
def test_report_all_time
|
||||
get :report, :params => {:project_id => 1, :criteria => ['project', 'issue']}
|
||||
assert_response :success
|
||||
assert_select 'tr.total td:last', :text => '162.90'
|
||||
end
|
||||
|
||||
def test_report_all_time_by_day
|
||||
get :report, :params => {:project_id => 1, :criteria => ['project', 'issue'], :columns => 'day'}
|
||||
assert_response :success
|
||||
assert_select 'tr.total td:last', :text => '162.90'
|
||||
assert_select 'th', :text => '2007-03-12'
|
||||
end
|
||||
|
||||
def test_report_one_criteria
|
||||
get :report, :params => {:project_id => 1, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']}
|
||||
assert_response :success
|
||||
assert_select 'tr.total td:last', :text => '8.65'
|
||||
end
|
||||
|
||||
def test_report_two_criteria
|
||||
get :report, :params => {:project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]}
|
||||
assert_response :success
|
||||
assert_select 'tr.total td:last', :text => '162.90'
|
||||
end
|
||||
|
||||
def test_report_custom_field_criteria_with_multiple_values_on_single_value_custom_field_should_not_fail
|
||||
field = TimeEntryCustomField.create!(:name => 'multi', :field_format => 'list', :possible_values => ['value1', 'value2'])
|
||||
entry = TimeEntry.create!(:project => Project.find(1), :hours => 1, :activity_id => 10, :user => User.find(2), :spent_on => Date.today)
|
||||
CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value1')
|
||||
CustomValue.create!(:customized => entry, :custom_field => field, :value => 'value2')
|
||||
|
||||
get :report, :params => {:project_id => 1, :columns => 'day', :criteria => ["cf_#{field.id}"]}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_report_multiple_values_custom_fields_should_not_be_proposed
|
||||
TimeEntryCustomField.create!(:name => 'Single', :field_format => 'list', :possible_values => ['value1', 'value2'])
|
||||
TimeEntryCustomField.create!(:name => 'Multi', :field_format => 'list', :multiple => true, :possible_values => ['value1', 'value2'])
|
||||
|
||||
get :report, :params => {:project_id => 1}
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'criteria[]' do
|
||||
assert_select 'option', :text => 'Single'
|
||||
assert_select 'option', :text => 'Multi', :count => 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_report_one_day
|
||||
get :report, :params => {:project_id => 1, :columns => 'day', :from => "2007-03-23", :to => "2007-03-23", :criteria => ["user", "activity"]}
|
||||
assert_response :success
|
||||
assert_select 'tr.total td:last', :text => '4.25'
|
||||
end
|
||||
|
||||
def test_report_by_week_should_use_commercial_year
|
||||
TimeEntry.delete_all
|
||||
TimeEntry.generate!(:hours => '2', :spent_on => '2009-12-25') # 2009-52
|
||||
TimeEntry.generate!(:hours => '4', :spent_on => '2009-12-31') # 2009-53
|
||||
TimeEntry.generate!(:hours => '8', :spent_on => '2010-01-01') # 2009-53
|
||||
TimeEntry.generate!(:hours => '16', :spent_on => '2010-01-05') # 2010-1
|
||||
|
||||
get :report, :params => {:columns => 'week', :from => "2009-12-25", :to => "2010-01-05", :criteria => ["project"]}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#time-report thead tr' do
|
||||
assert_select 'th:nth-child(1)', :text => 'Project'
|
||||
assert_select 'th:nth-child(2)', :text => '2009-52'
|
||||
assert_select 'th:nth-child(3)', :text => '2009-53'
|
||||
assert_select 'th:nth-child(4)', :text => '2010-1'
|
||||
assert_select 'th:nth-child(5)', :text => 'Total time'
|
||||
end
|
||||
assert_select '#time-report tbody tr' do
|
||||
assert_select 'td:nth-child(1)', :text => 'eCookbook'
|
||||
assert_select 'td:nth-child(2)', :text => '2.00'
|
||||
assert_select 'td:nth-child(3)', :text => '12.00'
|
||||
assert_select 'td:nth-child(4)', :text => '16.00'
|
||||
assert_select 'td:nth-child(5)', :text => '30.00' # Total
|
||||
end
|
||||
end
|
||||
|
||||
def test_report_should_propose_association_custom_fields
|
||||
get :report
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'criteria[]' do
|
||||
assert_select 'option[value=cf_1]', {:text => 'Database'}, 'Issue custom field not found'
|
||||
assert_select 'option[value=cf_3]', {:text => 'Development status'}, 'Project custom field not found'
|
||||
assert_select 'option[value=cf_7]', {:text => 'Billable'}, 'TimeEntryActivity custom field not found'
|
||||
end
|
||||
end
|
||||
|
||||
def test_report_with_association_custom_fields
|
||||
get :report, :params => {:criteria => ['cf_1', 'cf_3', 'cf_7']}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'tr.total td:last', :text => '162.90'
|
||||
|
||||
# Custom fields columns
|
||||
assert_select 'th', :text => 'Database'
|
||||
assert_select 'th', :text => 'Development status'
|
||||
assert_select 'th', :text => 'Billable'
|
||||
|
||||
# Custom field row
|
||||
assert_select 'tr' do
|
||||
assert_select 'td', :text => 'MySQL'
|
||||
assert_select 'td.hours', :text => '1.00'
|
||||
end
|
||||
end
|
||||
|
||||
def test_report_one_criteria_no_result
|
||||
get :report, :params => {:project_id => 1, :columns => 'week', :from => "1998-04-01", :to => "1998-04-30", :criteria => ['project']}
|
||||
assert_response :success
|
||||
|
||||
assert_select '.nodata'
|
||||
end
|
||||
|
||||
def test_report_status_criterion
|
||||
get :report, :params => {:project_id => 1, :criteria => ['status']}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'th', :text => 'Status'
|
||||
assert_select 'td', :text => 'New'
|
||||
end
|
||||
|
||||
def test_report_all_projects_csv_export
|
||||
get :report, :params => {
|
||||
:columns => 'month',
|
||||
:from => "2007-01-01",
|
||||
:to => "2007-06-30",
|
||||
:criteria => ["project", "user", "activity"],
|
||||
:format => "csv"
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', @response.content_type
|
||||
lines = @response.body.chomp.split("\n")
|
||||
# Headers
|
||||
assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
|
||||
# Total row
|
||||
assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
|
||||
end
|
||||
|
||||
def test_report_csv_export
|
||||
get :report, :params => {
|
||||
:project_id => 1,
|
||||
:columns => 'month',
|
||||
:from => "2007-01-01",
|
||||
:to => "2007-06-30",
|
||||
:criteria => ["project", "user", "activity"],
|
||||
:format => "csv"
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', @response.content_type
|
||||
lines = @response.body.chomp.split("\n")
|
||||
# Headers
|
||||
assert_equal 'Project,User,Activity,2007-3,2007-4,Total time', lines.first
|
||||
# Total row
|
||||
assert_equal 'Total time,"","",154.25,8.65,162.90', lines.last
|
||||
end
|
||||
|
||||
def test_csv_big_5
|
||||
str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8')
|
||||
str_big5 = "\xa4@\xa4\xeb".force_encoding('Big5')
|
||||
user = User.find_by_id(3)
|
||||
user.firstname = str_utf8
|
||||
user.lastname = "test-lastname"
|
||||
assert user.save
|
||||
comments = "test_csv_big_5"
|
||||
te1 = TimeEntry.create(:spent_on => '2011-11-11',
|
||||
:hours => 7.3,
|
||||
:project => Project.find(1),
|
||||
:user => user,
|
||||
:activity => TimeEntryActivity.find_by_name('Design'),
|
||||
:comments => comments)
|
||||
|
||||
te2 = TimeEntry.find_by_comments(comments)
|
||||
assert_not_nil te2
|
||||
assert_equal 7.3, te2.hours
|
||||
assert_equal 3, te2.user_id
|
||||
|
||||
with_settings :default_language => "zh-TW" do
|
||||
get :report, :params => {
|
||||
:project_id => 1,
|
||||
:columns => 'day',
|
||||
:from => "2011-11-11",
|
||||
:to => "2011-11-11",
|
||||
:criteria => ["user"],
|
||||
:format => "csv"
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', @response.content_type
|
||||
lines = @response.body.chomp.split("\n")
|
||||
# Headers
|
||||
s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5')
|
||||
s2 = "\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5')
|
||||
assert_equal s1, lines.first
|
||||
# Total row
|
||||
assert_equal "#{str_big5} #{user.lastname},7.30,7.30", lines[1]
|
||||
assert_equal "#{s2},7.30,7.30", lines[2]
|
||||
|
||||
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)
|
||||
assert_equal 'Big5', l(:general_csv_encoding)
|
||||
assert_equal ',', l(:general_csv_separator)
|
||||
assert_equal '.', l(:general_csv_decimal_separator)
|
||||
end
|
||||
|
||||
def test_csv_cannot_convert_should_be_replaced_big_5
|
||||
str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8')
|
||||
user = User.find_by_id(3)
|
||||
user.firstname = str_utf8
|
||||
user.lastname = "test-lastname"
|
||||
assert user.save
|
||||
comments = "test_replaced"
|
||||
te1 = TimeEntry.create(:spent_on => '2011-11-11',
|
||||
:hours => 7.3,
|
||||
:project => Project.find(1),
|
||||
:user => user,
|
||||
:activity => TimeEntryActivity.find_by_name('Design'),
|
||||
:comments => comments)
|
||||
|
||||
te2 = TimeEntry.find_by_comments(comments)
|
||||
assert_not_nil te2
|
||||
assert_equal 7.3, te2.hours
|
||||
assert_equal 3, te2.user_id
|
||||
|
||||
with_settings :default_language => "zh-TW" do
|
||||
get :report, :params => {
|
||||
:project_id => 1,
|
||||
:columns => 'day',
|
||||
:from => "2011-11-11",
|
||||
:to => "2011-11-11",
|
||||
:criteria => ["user"],
|
||||
:format => "csv"
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', @response.content_type
|
||||
lines = @response.body.chomp.split("\n")
|
||||
# Headers
|
||||
s1 = "\xa5\xce\xa4\xe1,2011-11-11,\xa4u\xae\xc9\xc1`\xadp".force_encoding('Big5')
|
||||
assert_equal s1, lines.first
|
||||
# Total row
|
||||
s2 = "\xa5H?".force_encoding('Big5')
|
||||
assert_equal "#{s2} #{user.lastname},7.30,7.30", lines[1]
|
||||
end
|
||||
|
||||
def test_csv_fr
|
||||
with_settings :default_language => "fr" do
|
||||
str1 = "test_csv_fr"
|
||||
user = User.find_by_id(3)
|
||||
te1 = TimeEntry.create(:spent_on => '2011-11-11',
|
||||
:hours => 7.3,
|
||||
:project => Project.find(1),
|
||||
:user => user,
|
||||
:activity => TimeEntryActivity.find_by_name('Design'),
|
||||
:comments => str1)
|
||||
|
||||
te2 = TimeEntry.find_by_comments(str1)
|
||||
assert_not_nil te2
|
||||
assert_equal 7.3, te2.hours
|
||||
assert_equal 3, te2.user_id
|
||||
|
||||
get :report, :params => {
|
||||
:project_id => 1,
|
||||
:columns => 'day',
|
||||
:from => "2011-11-11",
|
||||
:to => "2011-11-11",
|
||||
:criteria => ["user"],
|
||||
:format => "csv"
|
||||
}
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', @response.content_type
|
||||
lines = @response.body.chomp.split("\n")
|
||||
# Headers
|
||||
s1 = "Utilisateur;2011-11-11;Temps total".force_encoding('ISO-8859-1')
|
||||
s2 = "Temps total".force_encoding('ISO-8859-1')
|
||||
assert_equal s1, lines.first
|
||||
# Total row
|
||||
assert_equal "#{user.firstname} #{user.lastname};7,30;7,30", lines[1]
|
||||
assert_equal "#{s2};7,30;7,30", lines[2]
|
||||
|
||||
str_fr = "French (Fran\xc3\xa7ais)".force_encoding('UTF-8')
|
||||
assert_equal str_fr, l(:general_lang_name)
|
||||
assert_equal 'ISO-8859-1', l(:general_csv_encoding)
|
||||
assert_equal ';', l(:general_csv_separator)
|
||||
assert_equal ',', l(:general_csv_decimal_separator)
|
||||
end
|
||||
end
|
||||
end
|
||||
1120
test/functional/timelog_controller_test.rb
Normal file
1120
test/functional/timelog_controller_test.rb
Normal file
File diff suppressed because it is too large
Load diff
130
test/functional/timelog_custom_fields_visibility_test.rb
Normal file
130
test/functional/timelog_custom_fields_visibility_test.rb
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# 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 TimelogCustomFieldsVisibilityTest < Redmine::ControllerTest
|
||||
tests TimelogController
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issue_statuses,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:enabled_modules,
|
||||
:enumerations,
|
||||
:workflows
|
||||
|
||||
def setup
|
||||
field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all}
|
||||
@fields = []
|
||||
@fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
|
||||
@fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
|
||||
@fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
|
||||
@issue = Issue.generate!(
|
||||
:author_id => 1,
|
||||
:project_id => 1,
|
||||
:tracker_id => 1,
|
||||
:custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
|
||||
)
|
||||
TimeEntry.generate!(:issue => @issue)
|
||||
|
||||
@user_with_role_on_other_project = User.generate!
|
||||
User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
|
||||
|
||||
@users_to_test = {
|
||||
User.find(1) => [@field1, @field2, @field3],
|
||||
User.find(3) => [@field1, @field2],
|
||||
@user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
|
||||
User.generate! => [@field1],
|
||||
User.anonymous => [@field1]
|
||||
}
|
||||
|
||||
Member.where(:project_id => 1).each do |member|
|
||||
member.destroy unless @users_to_test.keys.include?(member.principal)
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_should_show_visible_custom_fields_only
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :index, :params => {
|
||||
:project_id => 1,
|
||||
:issue_id => @issue.id,
|
||||
:c => (['hours'] + @fields.map{|f| "issue.cf_#{f.id}"})
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
|
||||
else
|
||||
assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_as_csv_should_show_visible_custom_fields_only
|
||||
@users_to_test.each do |user, fields|
|
||||
@request.session[:user_id] = user.id
|
||||
get :index, :params => {
|
||||
:project_id => 1,
|
||||
:issue_id => @issue.id,
|
||||
:c => (['hours'] + @fields.map{|f| "issue.cf_#{f.id}"}),
|
||||
:format => 'csv'
|
||||
}
|
||||
@fields.each_with_index do |field, i|
|
||||
if fields.include?(field)
|
||||
assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV"
|
||||
else
|
||||
assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_with_partial_custom_field_visibility_should_show_visible_custom_fields_only
|
||||
Issue.delete_all
|
||||
TimeEntry.delete_all
|
||||
p1 = Project.generate!
|
||||
p2 = Project.generate!
|
||||
user = User.generate!
|
||||
User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a)
|
||||
User.add_to_project(user, p2, Role.where(:id => 3).to_a)
|
||||
TimeEntry.generate!(
|
||||
:issue => Issue.generate!(:project => p1, :tracker_id => 1,
|
||||
:custom_field_values => {@field2.id => 'ValueA'}))
|
||||
TimeEntry.generate!(
|
||||
:issue => Issue.generate!(:project => p2, :tracker_id => 1,
|
||||
:custom_field_values => {@field2.id => 'ValueB'}))
|
||||
TimeEntry.generate!(
|
||||
:issue => Issue.generate!(:project => p1, :tracker_id => 1,
|
||||
:custom_field_values => {@field2.id => 'ValueC'}))
|
||||
@request.session[:user_id] = user.id
|
||||
|
||||
get :index, :params => {:c => ["hours", "issue.cf_#{@field2.id}"]}
|
||||
assert_select 'td', {:text => 'ValueA'}, "ValueA not found in:\n#{response.body}"
|
||||
assert_select 'td', :text => 'ValueB', :count => 0
|
||||
assert_select 'td', {:text => 'ValueC'}, "ValueC not found in:\n#{response.body}"
|
||||
|
||||
get :index, :params => {:set_filter => '1', "issue.cf_#{@field2.id}" => '*', :c => ["issue.cf_#{@field2.id}"]}
|
||||
assert_select 'td', :text => "ValueA"
|
||||
assert_select 'td', :text => "ValueC"
|
||||
assert_select 'td', :text => "ValueB", :count => 0
|
||||
end
|
||||
end
|
||||
243
test/functional/trackers_controller_test.rb
Normal file
243
test/functional/trackers_controller_test.rb
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
# 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 TrackersControllerTest < Redmine::ControllerTest
|
||||
fixtures :trackers, :projects, :projects_trackers, :users, :issues, :custom_fields, :issue_statuses
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'table.trackers'
|
||||
end
|
||||
|
||||
def test_index_by_anonymous_should_redirect_to_login_form
|
||||
@request.session[:user_id] = nil
|
||||
get :index
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Ftrackers'
|
||||
end
|
||||
|
||||
def test_index_by_user_should_respond_with_406
|
||||
@request.session[:user_id] = 2
|
||||
get :index
|
||||
assert_response 406
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'tracker[name]'
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'Tracker.count' do
|
||||
post :create, :params => {
|
||||
:tracker => {
|
||||
:name => 'New tracker',
|
||||
:default_status_id => 1,
|
||||
:project_ids => ['1', '', ''],
|
||||
:custom_field_ids => ['1', '6', '']
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
tracker = Tracker.order('id DESC').first
|
||||
assert_equal 'New tracker', tracker.name
|
||||
assert_equal [1], tracker.project_ids.sort
|
||||
assert_equal Tracker::CORE_FIELDS, tracker.core_fields
|
||||
assert_equal [1, 6], tracker.custom_field_ids.sort
|
||||
assert_equal 0, tracker.workflow_rules.count
|
||||
end
|
||||
|
||||
def test_create_with_disabled_core_fields
|
||||
assert_difference 'Tracker.count' do
|
||||
post :create, :params => {
|
||||
:tracker => {
|
||||
:name => 'New tracker',
|
||||
:default_status_id => 1,
|
||||
:core_fields => ['assigned_to_id', 'fixed_version_id', '']
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
tracker = Tracker.order('id DESC').first
|
||||
assert_equal 'New tracker', tracker.name
|
||||
assert_equal %w(assigned_to_id fixed_version_id), tracker.core_fields
|
||||
end
|
||||
|
||||
def test_create_new_with_workflow_copy
|
||||
assert_difference 'Tracker.count' do
|
||||
post :create, :params => {
|
||||
:tracker => {
|
||||
:name => 'New tracker',
|
||||
:default_status_id => 1
|
||||
},
|
||||
:copy_workflow_from => 1
|
||||
}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
tracker = Tracker.find_by_name('New tracker')
|
||||
assert_equal 0, tracker.projects.count
|
||||
assert_equal Tracker.find(1).workflow_rules.count, tracker.workflow_rules.count
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'Tracker.count' do
|
||||
post :create, :params => {
|
||||
:tracker => {
|
||||
:name => '',
|
||||
:project_ids => ['1', '', ''],
|
||||
:custom_field_ids => ['1', '6', '']
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
Tracker.find(1).project_ids = [1, 3]
|
||||
|
||||
get :edit, :params => {:id => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value="1"][checked=checked]', 'tracker[project_ids][]'
|
||||
assert_select 'input[name=?][value="2"]:not([checked])', 'tracker[project_ids][]'
|
||||
|
||||
assert_select 'input[name=?][value=""][type=hidden]', 'tracker[project_ids][]'
|
||||
end
|
||||
|
||||
def test_edit_should_check_core_fields
|
||||
tracker = Tracker.find(1)
|
||||
tracker.core_fields = %w(assigned_to_id fixed_version_id)
|
||||
tracker.save!
|
||||
|
||||
get :edit, :params => {:id => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value=assigned_to_id][checked=checked]', 'tracker[core_fields][]'
|
||||
assert_select 'input[name=?][value=fixed_version_id][checked=checked]', 'tracker[core_fields][]'
|
||||
|
||||
assert_select 'input[name=?][value=category_id]', 'tracker[core_fields][]'
|
||||
assert_select 'input[name=?][value=category_id][checked=checked]', 'tracker[core_fields][]', 0
|
||||
|
||||
assert_select 'input[name=?][value=""][type=hidden]', 'tracker[core_fields][]'
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:tracker => {
|
||||
:name => 'Renamed',
|
||||
:project_ids => ['1', '2', '']
|
||||
}
|
||||
}
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_equal [1, 2], Tracker.find(1).project_ids.sort
|
||||
end
|
||||
|
||||
def test_update_without_projects
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:tracker => {
|
||||
:name => 'Renamed',
|
||||
:project_ids => ['']
|
||||
}
|
||||
}
|
||||
assert_redirected_to :action => 'index'
|
||||
assert Tracker.find(1).project_ids.empty?
|
||||
end
|
||||
|
||||
def test_update_without_core_fields
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:tracker => {
|
||||
:name => 'Renamed',
|
||||
:core_fields => ['']
|
||||
}
|
||||
}
|
||||
assert_redirected_to :action => 'index'
|
||||
assert Tracker.find(1).core_fields.empty?
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :params => {:id => 1, :tracker => { :name => '' }}
|
||||
assert_response :success
|
||||
|
||||
assert_select_error /name cannot be blank/i
|
||||
end
|
||||
|
||||
def test_move_lower
|
||||
tracker = Tracker.find_by_position(1)
|
||||
put :update, :params => {:id => 1, :tracker => { :position => '2' }}
|
||||
assert_equal 2, tracker.reload.position
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
tracker = Tracker.generate!(:name => 'Destroyable')
|
||||
assert_difference 'Tracker.count', -1 do
|
||||
delete :destroy, :params => {:id => tracker.id}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_nil flash[:error]
|
||||
end
|
||||
|
||||
def test_destroy_tracker_in_use
|
||||
assert_no_difference 'Tracker.count' do
|
||||
delete :destroy, :params => {:id => 1}
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_not_nil flash[:error]
|
||||
end
|
||||
|
||||
def test_get_fields
|
||||
get :fields
|
||||
assert_response :success
|
||||
|
||||
assert_select 'form' do
|
||||
assert_select 'input[type=checkbox][name=?][value=assigned_to_id]', 'trackers[1][core_fields][]'
|
||||
assert_select 'input[type=checkbox][name=?][value="2"]', 'trackers[1][custom_field_ids][]'
|
||||
|
||||
assert_select 'input[type=hidden][name=?][value=""]', 'trackers[1][core_fields][]'
|
||||
assert_select 'input[type=hidden][name=?][value=""]', 'trackers[1][custom_field_ids][]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_fields
|
||||
post :fields, :params => {
|
||||
:trackers => {
|
||||
'1' => {'core_fields' => ['assigned_to_id', 'due_date', ''], 'custom_field_ids' => ['1', '2']},
|
||||
'2' => {'core_fields' => [''], 'custom_field_ids' => ['']}
|
||||
}
|
||||
}
|
||||
assert_redirected_to '/trackers/fields'
|
||||
|
||||
tracker = Tracker.find(1)
|
||||
assert_equal %w(assigned_to_id due_date), tracker.core_fields
|
||||
assert_equal [1, 2], tracker.custom_field_ids.sort
|
||||
|
||||
tracker = Tracker.find(2)
|
||||
assert_equal [], tracker.core_fields
|
||||
assert_equal [], tracker.custom_field_ids.sort
|
||||
end
|
||||
end
|
||||
655
test/functional/users_controller_test.rb
Normal file
655
test/functional/users_controller_test.rb
Normal file
|
|
@ -0,0 +1,655 @@
|
|||
# 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 UsersControllerTest < Redmine::ControllerTest
|
||||
include Redmine::I18n
|
||||
|
||||
fixtures :users, :email_addresses, :projects, :members, :member_roles, :roles,
|
||||
:custom_fields, :custom_values, :groups_users,
|
||||
:auth_sources,
|
||||
:enabled_modules,
|
||||
:issues, :issue_statuses,
|
||||
:trackers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'table.users'
|
||||
assert_select 'tr.user.active'
|
||||
assert_select 'tr.user.locked', 0
|
||||
end
|
||||
|
||||
def test_index_with_status_filter
|
||||
get :index, :params => {:status => 3}
|
||||
assert_response :success
|
||||
assert_select 'tr.user.active', 0
|
||||
assert_select 'tr.user.locked'
|
||||
end
|
||||
|
||||
def test_index_with_name_filter
|
||||
get :index, :params => {:name => 'john'}
|
||||
assert_response :success
|
||||
assert_select 'tr.user td.username', :text => 'jsmith'
|
||||
assert_select 'tr.user', 1
|
||||
end
|
||||
|
||||
def test_index_with_group_filter
|
||||
get :index, :params => {:group_id => '10'}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'tr.user', Group.find(10).users.count
|
||||
assert_select 'select[name=group_id]' do
|
||||
assert_select 'option[value="10"][selected=selected]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show
|
||||
@request.session[:user_id] = nil
|
||||
get :show, :params => {:id => 2}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /John Smith/
|
||||
end
|
||||
|
||||
def test_show_should_display_visible_custom_fields
|
||||
@request.session[:user_id] = nil
|
||||
UserCustomField.find_by_name('Phone number').update_attribute :visible, true
|
||||
get :show, :params => {:id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'li', :text => /Phone number/
|
||||
end
|
||||
|
||||
def test_show_should_not_display_hidden_custom_fields
|
||||
@request.session[:user_id] = nil
|
||||
UserCustomField.find_by_name('Phone number').update_attribute :visible, false
|
||||
get :show, :params => {:id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'li', :text => /Phone number/, :count => 0
|
||||
end
|
||||
|
||||
def test_show_should_not_fail_when_custom_values_are_nil
|
||||
user = User.find(2)
|
||||
|
||||
# Create a custom field to illustrate the issue
|
||||
custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
|
||||
custom_value = user.custom_values.build(:custom_field => custom_field).save!
|
||||
|
||||
get :show, :params => {:id => 2}
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_show_inactive
|
||||
@request.session[:user_id] = nil
|
||||
get :show, :params => {:id => 5}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_show_inactive_by_admin
|
||||
@request.session[:user_id] = 1
|
||||
get :show, :params => {:id => 5}
|
||||
assert_response 200
|
||||
assert_select 'h2', :text => /Dave2 Lopper2/
|
||||
end
|
||||
|
||||
def test_show_user_who_is_not_visible_should_return_404
|
||||
Role.anonymous.update! :users_visibility => 'members_of_visible_projects'
|
||||
user = User.generate!
|
||||
|
||||
@request.session[:user_id] = nil
|
||||
get :show, :params => {:id => user.id}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_show_displays_memberships_based_on_project_visibility
|
||||
@request.session[:user_id] = 1
|
||||
get :show, :params => {:id => 2}
|
||||
assert_response :success
|
||||
|
||||
# membership of private project admin can see
|
||||
assert_select 'li a', :text => "OnlineStore"
|
||||
end
|
||||
|
||||
def test_show_current_should_require_authentication
|
||||
@request.session[:user_id] = nil
|
||||
get :show, :params => {:id => 'current'}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_show_current
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :params => {:id => 'current'}
|
||||
assert_response :success
|
||||
assert_select 'h2', :text => /John Smith/
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'user[login]'
|
||||
end
|
||||
|
||||
def test_create
|
||||
Setting.bcc_recipients = '1'
|
||||
|
||||
assert_difference 'User.count' do
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
post :create, :params => {
|
||||
:user => {
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:login => 'jdoe',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:mail => 'jdoe@gmail.com',
|
||||
:mail_notification => 'none'
|
||||
},
|
||||
:send_information => '1'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
user = User.order('id DESC').first
|
||||
assert_redirected_to :controller => 'users', :action => 'edit', :id => user.id
|
||||
|
||||
assert_equal 'John', user.firstname
|
||||
assert_equal 'Doe', user.lastname
|
||||
assert_equal 'jdoe', user.login
|
||||
assert_equal 'jdoe@gmail.com', user.mail
|
||||
assert_equal 'none', user.mail_notification
|
||||
assert user.check_password?('secret123')
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
assert_equal [user.mail], mail.bcc
|
||||
assert_mail_body_match 'secret', mail
|
||||
end
|
||||
|
||||
def test_create_with_preferences
|
||||
assert_difference 'User.count' do
|
||||
post :create, :params => {
|
||||
:user => {
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:login => 'jdoe',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:mail => 'jdoe@gmail.com',
|
||||
:mail_notification => 'none'
|
||||
},
|
||||
:pref => {
|
||||
'hide_mail' => '1',
|
||||
'time_zone' => 'Paris',
|
||||
'comments_sorting' => 'desc',
|
||||
'warn_on_leaving_unsaved' => '0',
|
||||
'textarea_font' => 'proportional'
|
||||
}
|
||||
}
|
||||
end
|
||||
user = User.order('id DESC').first
|
||||
assert_equal 'jdoe', user.login
|
||||
assert_equal true, user.pref.hide_mail
|
||||
assert_equal 'Paris', user.pref.time_zone
|
||||
assert_equal 'desc', user.pref[:comments_sorting]
|
||||
assert_equal '0', user.pref[:warn_on_leaving_unsaved]
|
||||
assert_equal 'proportional', user.pref[:textarea_font]
|
||||
end
|
||||
|
||||
def test_create_with_generate_password_should_email_the_password
|
||||
assert_difference 'User.count' do
|
||||
post :create, :params => {
|
||||
:user => {
|
||||
:login => 'randompass',
|
||||
:firstname => 'Random',
|
||||
:lastname => 'Pass',
|
||||
:mail => 'randompass@example.net',
|
||||
:language => 'en',
|
||||
:generate_password => '1',
|
||||
:password => '',
|
||||
:password_confirmation => ''
|
||||
},
|
||||
:send_information => 1
|
||||
}
|
||||
end
|
||||
user = User.order('id DESC').first
|
||||
assert_equal 'randompass', user.login
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
|
||||
assert m
|
||||
password = m[1]
|
||||
assert user.check_password?(password)
|
||||
end
|
||||
|
||||
def test_create_and_continue
|
||||
post :create, :params => {
|
||||
:user => {
|
||||
:login => 'randompass',
|
||||
:firstname => 'Random',
|
||||
:lastname => 'Pass',
|
||||
:mail => 'randompass@example.net',
|
||||
:generate_password => '1'
|
||||
},
|
||||
:continue => '1'
|
||||
}
|
||||
assert_redirected_to '/users/new?user%5Bgenerate_password%5D=1'
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'User.count' do
|
||||
post :create, :params => {:user => {}}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /Email cannot be blank/
|
||||
end
|
||||
|
||||
def test_create_with_failure_sould_preserve_preference
|
||||
assert_no_difference 'User.count' do
|
||||
post :create, :params => {
|
||||
:user => {},
|
||||
:pref => {
|
||||
'no_self_notified' => '1',
|
||||
'hide_mail' => '1',
|
||||
'time_zone' => 'Paris',
|
||||
'comments_sorting' => 'desc',
|
||||
'warn_on_leaving_unsaved' => '0'
|
||||
}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select#pref_time_zone option[selected=selected]', :text => /Paris/
|
||||
assert_select 'input#pref_no_self_notified[value="1"][checked=checked]'
|
||||
end
|
||||
|
||||
def test_create_admin_should_send_security_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :create, :params => {
|
||||
:user => {
|
||||
:firstname => 'Edgar',
|
||||
:lastname => 'Schmoe',
|
||||
:login => 'eschmoe',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:mail => 'eschmoe@example.foo',
|
||||
:admin => '1'
|
||||
}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match '0.0.0.0', mail
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: 'eschmoe'), mail
|
||||
assert_select_email do
|
||||
assert_select 'a[href^=?]', 'http://localhost:3000/users', :text => 'Users'
|
||||
end
|
||||
|
||||
# All admins should receive this
|
||||
User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
|
||||
assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_non_admin_should_not_send_security_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
post :create, :params => {
|
||||
:user => {
|
||||
:firstname => 'Edgar',
|
||||
:lastname => 'Schmoe',
|
||||
:login => 'eschmoe',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:mail => 'eschmoe@example.foo',
|
||||
:admin => '0'
|
||||
}
|
||||
}
|
||||
assert_nil ActionMailer::Base.deliveries.last
|
||||
end
|
||||
|
||||
|
||||
def test_edit
|
||||
get :edit, :params => {:id => 2}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][value=?]', 'user[login]', 'jsmith'
|
||||
end
|
||||
|
||||
def test_edit_registered_user
|
||||
assert User.find(2).register!
|
||||
|
||||
get :edit, :params => {:id => 2}
|
||||
assert_response :success
|
||||
assert_select 'a', :text => 'Activate'
|
||||
end
|
||||
|
||||
def test_edit_should_be_denied_for_anonymous
|
||||
assert User.find(6).anonymous?
|
||||
get :edit, :params => {:id => 6}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:firstname => 'Changed', :mail_notification => 'only_assigned'},
|
||||
:pref => {:hide_mail => '1', :comments_sorting => 'desc'}
|
||||
}
|
||||
user = User.find(2)
|
||||
assert_equal 'Changed', user.firstname
|
||||
assert_equal 'only_assigned', user.mail_notification
|
||||
assert_equal true, user.pref[:hide_mail]
|
||||
assert_equal 'desc', user.pref[:comments_sorting]
|
||||
assert ActionMailer::Base.deliveries.empty?
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
assert_no_difference 'User.count' do
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:firstname => ''}
|
||||
}
|
||||
end
|
||||
assert_response :success
|
||||
assert_select_error /First name cannot be blank/
|
||||
end
|
||||
|
||||
def test_update_with_group_ids_should_assign_groups
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:group_ids => ['10']}
|
||||
}
|
||||
user = User.find(2)
|
||||
assert_equal [10], user.group_ids
|
||||
end
|
||||
|
||||
def test_update_with_activation_should_send_a_notification
|
||||
u = User.new(:firstname => 'Foo', :lastname => 'Bar', :mail => 'foo.bar@somenet.foo', :language => 'fr')
|
||||
u.login = 'foo'
|
||||
u.status = User::STATUS_REGISTERED
|
||||
u.save!
|
||||
ActionMailer::Base.deliveries.clear
|
||||
Setting.bcc_recipients = '1'
|
||||
|
||||
put :update, :params => {
|
||||
:id => u.id,
|
||||
:user => {:status => User::STATUS_ACTIVE}
|
||||
}
|
||||
assert u.reload.active?
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
assert_equal ['foo.bar@somenet.foo'], mail.bcc
|
||||
assert_mail_body_match ll('fr', :notice_account_activated), mail
|
||||
end
|
||||
|
||||
def test_update_with_password_change_should_send_a_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
Setting.bcc_recipients = '1'
|
||||
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:password => 'newpass123', :password_confirmation => 'newpass123'},
|
||||
:send_information => '1'
|
||||
}
|
||||
u = User.find(2)
|
||||
assert u.check_password?('newpass123')
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
assert_equal [u.mail], mail.bcc
|
||||
assert_mail_body_match 'newpass123', mail
|
||||
end
|
||||
|
||||
def test_update_with_generate_password_should_email_the_password
|
||||
ActionMailer::Base.deliveries.clear
|
||||
Setting.bcc_recipients = '1'
|
||||
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {
|
||||
:generate_password => '1',
|
||||
:password => '',
|
||||
:password_confirmation => ''
|
||||
},
|
||||
:send_information => '1'
|
||||
}
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
assert_not_nil mail
|
||||
m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
|
||||
assert m
|
||||
password = m[1]
|
||||
assert User.find(2).check_password?(password)
|
||||
end
|
||||
|
||||
def test_update_without_generate_password_should_not_change_password
|
||||
put :update, :params => {
|
||||
:id => 2, :user => {
|
||||
:firstname => 'changed',
|
||||
:generate_password => '0',
|
||||
:password => '',
|
||||
:password_confirmation => ''
|
||||
},
|
||||
:send_information => '1'
|
||||
}
|
||||
|
||||
user = User.find(2)
|
||||
assert_equal 'changed', user.firstname
|
||||
assert user.check_password?('jsmith')
|
||||
end
|
||||
|
||||
def test_update_user_switchin_from_auth_source_to_password_authentication
|
||||
# Configure as auth source
|
||||
u = User.find(2)
|
||||
u.auth_source = AuthSource.find(1)
|
||||
u.save!
|
||||
|
||||
put :update, :params => {
|
||||
:id => u.id,
|
||||
:user => {:auth_source_id => '', :password => 'newpass123', :password_confirmation => 'newpass123'}
|
||||
}
|
||||
|
||||
assert_nil u.reload.auth_source
|
||||
assert u.check_password?('newpass123')
|
||||
end
|
||||
|
||||
def test_update_notified_project
|
||||
get :edit, :params => {:id => 2}
|
||||
assert_response :success
|
||||
u = User.find(2)
|
||||
assert_equal [1, 2, 5], u.projects.collect{|p| p.id}.sort
|
||||
assert_equal [1, 2, 5], u.notified_projects_ids.sort
|
||||
assert_select 'input[name=?][value=?]', 'user[notified_project_ids][]', '1'
|
||||
assert_equal 'all', u.mail_notification
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {
|
||||
:mail_notification => 'selected',
|
||||
:notified_project_ids => [1, 2]
|
||||
}
|
||||
}
|
||||
u = User.find(2)
|
||||
assert_equal 'selected', u.mail_notification
|
||||
assert_equal [1, 2], u.notified_projects_ids.sort
|
||||
end
|
||||
|
||||
def test_update_status_should_not_update_attributes
|
||||
user = User.find(2)
|
||||
user.pref[:no_self_notified] = '1'
|
||||
user.pref.save
|
||||
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:status => 3}
|
||||
}
|
||||
assert_response 302
|
||||
user = User.find(2)
|
||||
assert_equal 3, user.status
|
||||
assert_equal '1', user.pref[:no_self_notified]
|
||||
end
|
||||
|
||||
def test_update_assign_admin_should_send_security_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:admin => 1}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: User.find(2).login), mail
|
||||
|
||||
# All admins should receive this
|
||||
User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
|
||||
assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_unassign_admin_should_send_security_notification
|
||||
user = User.find(2)
|
||||
user.admin = true
|
||||
user.save!
|
||||
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:id => user.id,
|
||||
:user => {:admin => 0}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: user.login), mail
|
||||
|
||||
# All admins should receive this
|
||||
User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
|
||||
assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_lock_admin_should_send_security_notification
|
||||
user = User.find(2)
|
||||
user.admin = true
|
||||
user.save!
|
||||
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:user => {:status => Principal::STATUS_LOCKED}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: User.find(2).login), mail
|
||||
|
||||
# All admins should receive this
|
||||
User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
|
||||
assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
|
||||
end
|
||||
|
||||
# if user is already locked, destroying should not send a second mail
|
||||
# (for active admins see furtherbelow)
|
||||
ActionMailer::Base.deliveries.clear
|
||||
delete :destroy, :params => {:id => 1}
|
||||
assert_nil ActionMailer::Base.deliveries.last
|
||||
|
||||
end
|
||||
|
||||
def test_update_unlock_admin_should_send_security_notification
|
||||
user = User.find(5) # already locked
|
||||
user.admin = true
|
||||
user.save!
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:id => user.id,
|
||||
:user => {:status => Principal::STATUS_ACTIVE}
|
||||
}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: user.login), mail
|
||||
|
||||
# All admins should receive this
|
||||
User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
|
||||
assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_admin_unrelated_property_should_not_send_security_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
put :update, :params => {
|
||||
:id => 1,
|
||||
:user => {:firstname => 'Jimmy'}
|
||||
}
|
||||
assert_nil ActionMailer::Base.deliveries.last
|
||||
end
|
||||
|
||||
def test_update_should_be_denied_for_anonymous
|
||||
assert User.find(6).anonymous?
|
||||
put :update, :params => {:id => 6}
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'User.count', -1 do
|
||||
delete :destroy, :params => {:id => 2}
|
||||
end
|
||||
assert_redirected_to '/users'
|
||||
assert_nil User.find_by_id(2)
|
||||
end
|
||||
|
||||
def test_destroy_should_be_denied_for_non_admin_users
|
||||
@request.session[:user_id] = 3
|
||||
|
||||
assert_no_difference 'User.count' do
|
||||
get :destroy, :params => {:id => 2}
|
||||
end
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_destroy_should_be_denied_for_anonymous
|
||||
assert User.find(6).anonymous?
|
||||
assert_no_difference 'User.count' do
|
||||
put :destroy, :params => {:id => 6}
|
||||
end
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_destroy_should_redirect_to_back_url_param
|
||||
assert_difference 'User.count', -1 do
|
||||
delete :destroy, :params => {:id => 2, :back_url => '/users?name=foo'}
|
||||
end
|
||||
assert_redirected_to '/users?name=foo'
|
||||
end
|
||||
|
||||
def test_destroy_active_admin_should_send_security_notification
|
||||
user = User.find(2)
|
||||
user.admin = true
|
||||
user.save!
|
||||
ActionMailer::Base.deliveries.clear
|
||||
delete :destroy, :params => {:id => user.id}
|
||||
|
||||
assert_not_nil (mail = ActionMailer::Base.deliveries.last)
|
||||
assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: user.login), mail
|
||||
|
||||
# All admins should receive this
|
||||
User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
|
||||
assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
|
||||
end
|
||||
end
|
||||
end
|
||||
260
test/functional/versions_controller_test.rb
Normal file
260
test/functional/versions_controller_test.rb
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
# 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 VersionsControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :enabled_modules,
|
||||
:trackers, :projects_trackers,
|
||||
:versions, :issue_statuses, :issue_categories, :enumerations,
|
||||
:issues,
|
||||
:users, :email_addresses,
|
||||
:roles, :members, :member_roles
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :params => {:project_id => 1}
|
||||
assert_response :success
|
||||
|
||||
# Version with no date set appears
|
||||
assert_select 'h3', :text => Version.find(3).name
|
||||
# Completed version doesn't appear
|
||||
assert_select 'h3', :text => Version.find(1).name, :count => 0
|
||||
|
||||
# Context menu on issues
|
||||
assert_select "form[data-cm-url=?]", '/issues/context_menu'
|
||||
assert_select "div#sidebar" do
|
||||
# Links to versions anchors
|
||||
assert_select 'a[href=?]', '#2.0'
|
||||
# Links to completed versions in the sidebar
|
||||
assert_select 'a[href=?]', '/versions/1'
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_with_completed_versions
|
||||
get :index, :params => {:project_id => 1, :completed => 1}
|
||||
assert_response :success
|
||||
|
||||
# Version with no date set appears
|
||||
assert_select 'h3', :text => Version.find(3).name
|
||||
# Completed version appears
|
||||
assert_select 'h3', :text => Version.find(1).name
|
||||
end
|
||||
|
||||
def test_index_with_tracker_ids
|
||||
(1..3).each do |tracker_id|
|
||||
Issue.generate! :project_id => 1, :fixed_version_id => 3, :tracker_id => tracker_id
|
||||
end
|
||||
get :index, :params => {:project_id => 1, :tracker_ids => [1, 3]}
|
||||
assert_response :success
|
||||
assert_select 'a.issue.tracker-1'
|
||||
assert_select 'a.issue.tracker-2', 0
|
||||
assert_select 'a.issue.tracker-3'
|
||||
end
|
||||
|
||||
def test_index_showing_subprojects_versions
|
||||
@subproject_version = Version.create!(:project => Project.find(3), :name => "Subproject version")
|
||||
get :index, :params => {:project_id => 1, :with_subprojects => 1}
|
||||
assert_response :success
|
||||
|
||||
# Shared version
|
||||
assert_select 'h3', :text => Version.find(4).name
|
||||
# Subproject version
|
||||
assert_select 'h3', :text => /Subproject version/
|
||||
end
|
||||
|
||||
def test_index_should_prepend_shared_versions
|
||||
get :index, :params => {:project_id => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select '#sidebar' do
|
||||
assert_select 'a[href=?]', '#2.0', :text => '2.0'
|
||||
assert_select 'a[href=?]', '#subproject1-2.0', :text => 'eCookbook Subproject 1 - 2.0'
|
||||
end
|
||||
assert_select '#content' do
|
||||
assert_select 'a[name=?]', '2.0', :text => '2.0'
|
||||
assert_select 'a[name=?]', 'subproject1-2.0', :text => 'eCookbook Subproject 1 - 2.0'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :params => {:id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'h2', :text => /1.0/
|
||||
end
|
||||
|
||||
def test_show_should_link_to_spent_time_on_version
|
||||
version = Version.generate!
|
||||
issue = Issue.generate(:fixed_version => version)
|
||||
TimeEntry.generate!(:issue => issue, :hours => 7.2)
|
||||
|
||||
get :show, :params => {:id => version.id}
|
||||
assert_response :success
|
||||
|
||||
assert_select '.total-hours', :text => '7.20 hours'
|
||||
assert_select '.total-hours a[href=?]', "/projects/ecookbook/time_entries?issue.fixed_version_id=#{version.id}&set_filter=1"
|
||||
end
|
||||
|
||||
def test_show_should_display_nil_counts
|
||||
with_settings :default_language => 'en' do
|
||||
get :show, :params => {:id => 2, :status_by => 'category'}
|
||||
assert_response :success
|
||||
assert_select 'div#status_by' do
|
||||
assert_select 'select[name=status_by]' do
|
||||
assert_select 'option[value=category][selected=selected]'
|
||||
end
|
||||
assert_select 'a', :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {:project_id => '1'}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?]', 'version[name]'
|
||||
assert_select 'select[name=?]', 'version[status]', false
|
||||
end
|
||||
|
||||
def test_new_from_issue_form
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {:project_id => '1'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2 # manager
|
||||
assert_difference 'Version.count' do
|
||||
post :create, :params => {:project_id => '1', :version => {:name => 'test_add_version'}}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/versions'
|
||||
version = Version.find_by_name('test_add_version')
|
||||
assert_not_nil version
|
||||
assert_equal 1, version.project_id
|
||||
end
|
||||
|
||||
def test_create_from_issue_form
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Version.count' do
|
||||
post :create, :params => {:project_id => '1', :version => {:name => 'test_add_version_from_issue_form'}}, :xhr => true
|
||||
end
|
||||
version = Version.find_by_name('test_add_version_from_issue_form')
|
||||
assert_not_nil version
|
||||
assert_equal 1, version.project_id
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include 'test_add_version_from_issue_form', response.body
|
||||
end
|
||||
|
||||
def test_create_from_issue_form_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Version.count' do
|
||||
post :create, :params => {:project_id => '1', :version => {:name => ''}}, :xhr => true
|
||||
end
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :params => {:id => 2}
|
||||
assert_response :success
|
||||
version = Version.find(2)
|
||||
|
||||
assert_select 'select[name=?]', 'version[status]' do
|
||||
assert_select 'option[value=?][selected="selected"]', version.status
|
||||
end
|
||||
assert_select 'input[name=?][value=?]', 'version[name]', version.name
|
||||
end
|
||||
|
||||
def test_close_completed
|
||||
Version.update_all("status = 'open'")
|
||||
@request.session[:user_id] = 2
|
||||
put :close_completed, :params => {:project_id => 'ecookbook'}
|
||||
assert_redirected_to :controller => 'projects', :action => 'settings',
|
||||
:tab => 'versions', :id => 'ecookbook'
|
||||
assert_not_nil Version.find_by_status('closed')
|
||||
end
|
||||
|
||||
def test_post_update
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:version => {
|
||||
:name => 'New version name',
|
||||
:effective_date => Date.today.strftime("%Y-%m-%d")
|
||||
}
|
||||
}
|
||||
assert_redirected_to :controller => 'projects', :action => 'settings',
|
||||
:tab => 'versions', :id => 'ecookbook'
|
||||
version = Version.find(2)
|
||||
assert_equal 'New version name', version.name
|
||||
assert_equal Date.today, version.effective_date
|
||||
end
|
||||
|
||||
def test_post_update_with_validation_failure
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :params => {
|
||||
:id => 2,
|
||||
:version => {
|
||||
:name => '',
|
||||
:effective_date => Date.today.strftime("%Y-%m-%d")
|
||||
}
|
||||
}
|
||||
assert_response :success
|
||||
assert_select_error /Name cannot be blank/
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Version.count', -1 do
|
||||
delete :destroy, :params => {:id => 3}
|
||||
end
|
||||
assert_redirected_to :controller => 'projects', :action => 'settings',
|
||||
:tab => 'versions', :id => 'ecookbook'
|
||||
assert_nil Version.find_by_id(3)
|
||||
end
|
||||
|
||||
def test_destroy_version_in_use_should_fail
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Version.count' do
|
||||
delete :destroy, :params => {:id => 2}
|
||||
end
|
||||
assert_redirected_to :controller => 'projects', :action => 'settings',
|
||||
:tab => 'versions', :id => 'ecookbook'
|
||||
assert flash[:error].match(/Unable to delete version/)
|
||||
assert Version.find_by_id(2)
|
||||
end
|
||||
|
||||
def test_issue_status_by
|
||||
get :status_by, :params => {:id => 2}, :xhr => true
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_issue_status_by_status
|
||||
get :status_by, :params => {:id => 2, :status_by => 'status'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include 'Assigned', response.body
|
||||
assert_include 'Closed', response.body
|
||||
end
|
||||
end
|
||||
380
test/functional/watchers_controller_test.rb
Normal file
380
test/functional/watchers_controller_test.rb
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
# 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 WatchersControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
|
||||
:issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_watch_a_single_object_as_html
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count') do
|
||||
post :watch, :params => {:object_type => 'issue', :object_id => '1'}
|
||||
assert_response :success
|
||||
assert_include 'Watcher added', response.body
|
||||
end
|
||||
assert Issue.find(1).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_watch_a_single_object
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count') do
|
||||
post :watch, :params => {:object_type => 'issue', :object_id => '1'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include '$(".issue-1-watcher")', response.body
|
||||
end
|
||||
assert Issue.find(1).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_watch_a_collection_with_a_single_object
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count') do
|
||||
post :watch, :params => {:object_type => 'issue', :object_id => ['1']}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include '$(".issue-1-watcher")', response.body
|
||||
end
|
||||
assert Issue.find(1).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_watch_a_collection_with_multiple_objects
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count', 2) do
|
||||
post :watch, :params => {:object_type => 'issue', :object_id => ['1', '3']}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include '$(".issue-bulk-watcher")', response.body
|
||||
end
|
||||
assert Issue.find(1).watched_by?(User.find(3))
|
||||
assert Issue.find(3).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_watch_a_news_module_should_add_watcher
|
||||
@request.session[:user_id] = 7
|
||||
assert_not_nil m = Project.find(1).enabled_module('news')
|
||||
|
||||
assert_difference 'Watcher.count' do
|
||||
post :watch, :params => {:object_type => 'enabled_module', :object_id => m.id.to_s}, :xhr => true
|
||||
assert_response :success
|
||||
end
|
||||
assert m.reload.watched_by?(User.find(7))
|
||||
end
|
||||
|
||||
def test_watch_a_private_news_module_without_permission_should_fail
|
||||
@request.session[:user_id] = 7
|
||||
assert_not_nil m = Project.find(2).enabled_module('news')
|
||||
|
||||
assert_no_difference 'Watcher.count' do
|
||||
post :watch, :params => {:object_type => 'enabled_module', :object_id => m.id.to_s}, :xhr => true
|
||||
assert_response 403
|
||||
end
|
||||
end
|
||||
|
||||
def test_watch_should_be_denied_without_permission
|
||||
Role.find(2).remove_permission! :view_issues
|
||||
@request.session[:user_id] = 3
|
||||
assert_no_difference('Watcher.count') do
|
||||
post :watch, :params => {:object_type => 'issue', :object_id => '1'}, :xhr => true
|
||||
assert_response 403
|
||||
end
|
||||
end
|
||||
|
||||
def test_watch_invalid_class_should_respond_with_404
|
||||
@request.session[:user_id] = 3
|
||||
assert_no_difference('Watcher.count') do
|
||||
post :watch, :params => {:object_type => 'foo', :object_id => '1'}, :xhr => true
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
|
||||
def test_watch_invalid_object_should_respond_with_404
|
||||
@request.session[:user_id] = 3
|
||||
assert_no_difference('Watcher.count') do
|
||||
post :watch, :params => {:object_type => 'issue', :object_id => '999'}, :xhr => true
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
|
||||
def test_unwatch_as_html
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count', -1) do
|
||||
delete :unwatch, :params => {:object_type => 'issue', :object_id => '2'}
|
||||
assert_response :success
|
||||
assert_include 'Watcher removed', response.body
|
||||
end
|
||||
assert !Issue.find(1).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_unwatch
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count', -1) do
|
||||
delete :unwatch, :params => {:object_type => 'issue', :object_id => '2'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include '$(".issue-2-watcher")', response.body
|
||||
end
|
||||
assert !Issue.find(1).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_unwatch_a_collection_with_multiple_objects
|
||||
@request.session[:user_id] = 3
|
||||
Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
|
||||
Watcher.create!(:user_id => 3, :watchable => Issue.find(3))
|
||||
|
||||
assert_difference('Watcher.count', -2) do
|
||||
delete :unwatch, :params => {:object_type => 'issue', :object_id => ['1', '3']}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include '$(".issue-bulk-watcher")', response.body
|
||||
end
|
||||
assert !Issue.find(1).watched_by?(User.find(3))
|
||||
assert !Issue.find(3).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {:object_type => 'issue', :object_id => '2'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_new_with_multiple_objects
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {:object_type => 'issue', :object_id => ['1', '2']}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_new_for_new_record_with_project_id
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {:project_id => 1}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_new_for_new_record_with_project_identifier
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :params => {:project_id => 'ecookbook'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_create_as_html
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count') do
|
||||
post :create, :params => {
|
||||
:object_type => 'issue', :object_id => '2',
|
||||
:watcher => {:user_id => '4'}
|
||||
}
|
||||
assert_response :success
|
||||
assert_include 'Watcher added', response.body
|
||||
end
|
||||
assert Issue.find(2).watched_by?(User.find(4))
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count') do
|
||||
post :create, :params => {
|
||||
:object_type => 'issue', :object_id => '2',
|
||||
:watcher => {:user_id => '4'}
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
assert Issue.find(2).watched_by?(User.find(4))
|
||||
end
|
||||
|
||||
def test_create_with_mutiple_users
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', 2) do
|
||||
post :create, :params => {
|
||||
:object_type => 'issue', :object_id => '2',
|
||||
:watcher => {:user_ids => ['4', '7']}
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
assert Issue.find(2).watched_by?(User.find(4))
|
||||
assert Issue.find(2).watched_by?(User.find(7))
|
||||
end
|
||||
|
||||
def test_create_with_mutiple_objects
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', 4) do
|
||||
post :create, :params => {
|
||||
:object_type => 'issue', :object_id => ['1', '2'],
|
||||
:watcher => {:user_ids => ['4', '7']}
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
assert Issue.find(1).watched_by?(User.find(4))
|
||||
assert Issue.find(2).watched_by?(User.find(4))
|
||||
assert Issue.find(1).watched_by?(User.find(7))
|
||||
assert Issue.find(2).watched_by?(User.find(7))
|
||||
end
|
||||
|
||||
def test_autocomplete_on_watchable_creation
|
||||
@request.session[:user_id] = 2
|
||||
get :autocomplete_for_user, :params => {:q => 'mi', :project_id => 'ecookbook'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_select 'input', :count => 4
|
||||
assert_select 'input[name=?][value="1"]', 'watcher[user_ids][]'
|
||||
assert_select 'input[name=?][value="2"]', 'watcher[user_ids][]'
|
||||
assert_select 'input[name=?][value="8"]', 'watcher[user_ids][]'
|
||||
assert_select 'input[name=?][value="9"]', 'watcher[user_ids][]'
|
||||
end
|
||||
|
||||
def test_search_non_member_on_create
|
||||
@request.session[:user_id] = 2
|
||||
project = Project.find_by_name("ecookbook")
|
||||
user = User.generate!(:firstname => 'issue15622')
|
||||
membership = user.membership(project)
|
||||
assert_nil membership
|
||||
get :autocomplete_for_user, :params => {:q => 'issue15622', :project_id => 'ecookbook'}, :xhr => true
|
||||
assert_response :success
|
||||
assert_select 'input', :count => 1
|
||||
end
|
||||
|
||||
def test_autocomplete_on_watchable_update
|
||||
@request.session[:user_id] = 2
|
||||
get :autocomplete_for_user, :params => {
|
||||
:object_type => 'issue', :object_id => '2',
|
||||
:project_id => 'ecookbook', :q => 'mi'
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_select 'input', :count => 3
|
||||
assert_select 'input[name=?][value="2"]', 'watcher[user_ids][]'
|
||||
assert_select 'input[name=?][value="8"]', 'watcher[user_ids][]'
|
||||
assert_select 'input[name=?][value="9"]', 'watcher[user_ids][]'
|
||||
end
|
||||
|
||||
def test_search_and_add_non_member_on_update
|
||||
@request.session[:user_id] = 2
|
||||
project = Project.find_by_name("ecookbook")
|
||||
user = User.generate!(:firstname => 'issue15622')
|
||||
membership = user.membership(project)
|
||||
assert_nil membership
|
||||
|
||||
get :autocomplete_for_user, :params => {
|
||||
:object_type => 'issue', :object_id => '2',
|
||||
:project_id => 'ecookbook', :q => 'issue15622'
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_select 'input', :count => 1
|
||||
|
||||
assert_difference('Watcher.count', 1) do
|
||||
post :create, :params => {
|
||||
:object_type => 'issue', :object_id => '2',
|
||||
:watcher => {:user_ids => ["#{user.id}"]}
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
assert Issue.find(2).watched_by?(user)
|
||||
end
|
||||
|
||||
def test_autocomplete_for_user_should_return_visible_users
|
||||
Role.update_all :users_visibility => 'members_of_visible_projects'
|
||||
|
||||
hidden = User.generate!(:lastname => 'autocomplete_hidden')
|
||||
visible = User.generate!(:lastname => 'autocomplete_visible')
|
||||
User.add_to_project(visible, Project.find(1))
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
get :autocomplete_for_user, :params => {:q => 'autocomp', :project_id => 'ecookbook'}, :xhr => true
|
||||
assert_response :success
|
||||
|
||||
assert_include visible.name, response.body
|
||||
assert_not_include hidden.name, response.body
|
||||
end
|
||||
|
||||
def test_append
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Watcher.count' do
|
||||
post :append, :params => {
|
||||
:watcher => {:user_ids => ['4', '7']}, :project_id => 'ecookbook'
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_include 'watchers_inputs', response.body
|
||||
assert_include 'issue[watcher_user_ids][]', response.body
|
||||
end
|
||||
end
|
||||
|
||||
def test_append_without_user_should_render_nothing
|
||||
@request.session[:user_id] = 2
|
||||
post :append, :params => {:project_id => 'ecookbook'}, :xhr => true
|
||||
assert_response :success
|
||||
assert response.body.blank?
|
||||
end
|
||||
|
||||
def test_destroy_as_html
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', -1) do
|
||||
delete :destroy, :params => {
|
||||
:object_type => 'issue', :object_id => '2', :user_id => '3'
|
||||
}
|
||||
assert_response :success
|
||||
assert_include 'Watcher removed', response.body
|
||||
end
|
||||
assert !Issue.find(2).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', -1) do
|
||||
delete :destroy, :params => {
|
||||
:object_type => 'issue', :object_id => '2', :user_id => '3'
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
end
|
||||
assert !Issue.find(2).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_destroy_locked_user
|
||||
user = User.find(3)
|
||||
user.lock!
|
||||
assert user.reload.locked?
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', -1) do
|
||||
delete :destroy, :params => {
|
||||
:object_type => 'issue', :object_id => '2', :user_id => '3'
|
||||
}, :xhr => true
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
end
|
||||
assert !Issue.find(2).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_destroy_invalid_user_should_respond_with_404
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference('Watcher.count') do
|
||||
delete :destroy, :params => {
|
||||
:object_type => 'issue', :object_id => '2', :user_id => '999'
|
||||
}
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
end
|
||||
192
test/functional/welcome_controller_test.rb
Normal file
192
test/functional/welcome_controller_test.rb
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
# 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 WelcomeControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :news, :users, :members
|
||||
|
||||
def setup
|
||||
Setting.default_language = 'en'
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_select 'h3', :text => 'Latest news'
|
||||
end
|
||||
|
||||
def test_browser_language
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
get :index
|
||||
assert_select 'html[lang=fr]'
|
||||
end
|
||||
|
||||
def test_browser_language_alternate
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'zh-TW'
|
||||
get :index
|
||||
assert_select 'html[lang=zh-TW]'
|
||||
end
|
||||
|
||||
def test_browser_language_alternate_not_valid
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr-CA'
|
||||
get :index
|
||||
assert_select 'html[lang=fr]'
|
||||
end
|
||||
|
||||
def test_browser_language_should_be_ignored_with_force_default_language_for_anonymous
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
with_settings :force_default_language_for_anonymous => '1' do
|
||||
get :index
|
||||
assert_select 'html[lang=en]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_language_should_be_used
|
||||
user = User.find(2).update_attribute :language, 'it'
|
||||
@request.session[:user_id] = 2
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
with_settings :default_language => 'fi' do
|
||||
get :index
|
||||
assert_select 'html[lang=it]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_language_should_be_ignored_if_force_default_language_for_loggedin
|
||||
user = User.find(2).update_attribute :language, 'it'
|
||||
@request.session[:user_id] = 2
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
with_settings :force_default_language_for_loggedin => '1', :default_language => 'fi' do
|
||||
get :index
|
||||
assert_select 'html[lang=fi]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_robots
|
||||
get :robots
|
||||
assert_response :success
|
||||
assert_equal 'text/plain', @response.content_type
|
||||
assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$})
|
||||
end
|
||||
|
||||
def test_warn_on_leaving_unsaved_turn_on
|
||||
user = User.find(2)
|
||||
user.pref.warn_on_leaving_unsaved = '1'
|
||||
user.pref.save!
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_select 'script', :text => %r{warnLeavingUnsaved}
|
||||
end
|
||||
|
||||
def test_warn_on_leaving_unsaved_turn_off
|
||||
user = User.find(2)
|
||||
user.pref.warn_on_leaving_unsaved = '0'
|
||||
user.pref.save!
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_select 'script', :text => %r{warnLeavingUnsaved}, :count => 0
|
||||
end
|
||||
|
||||
def test_textarea_font_set_to_monospace
|
||||
user = User.find(1)
|
||||
user.pref.textarea_font = 'monospace'
|
||||
user.pref.save!
|
||||
@request.session[:user_id] = 1
|
||||
get :index
|
||||
assert_select 'body.textarea-monospace'
|
||||
end
|
||||
|
||||
def test_textarea_font_set_to_proportional
|
||||
user = User.find(1)
|
||||
user.pref.textarea_font = 'proportional'
|
||||
user.pref.save!
|
||||
@request.session[:user_id] = 1
|
||||
get :index
|
||||
assert_select 'body.textarea-proportional'
|
||||
end
|
||||
|
||||
def test_logout_link_should_post
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_select 'a[href="/logout"][data-method=post]', :text => 'Sign out'
|
||||
end
|
||||
|
||||
def test_call_hook_mixed_in
|
||||
assert @controller.respond_to?(:call_hook)
|
||||
end
|
||||
|
||||
def test_project_jump_box_should_escape_names_once
|
||||
Project.find(1).update_attribute :name, 'Foo & Bar'
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_select "#header #project-jump" do
|
||||
assert_select "a", :text => 'Foo & Bar'
|
||||
end
|
||||
end
|
||||
|
||||
def test_api_offset_and_limit_without_params
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({})
|
||||
end
|
||||
|
||||
def test_api_offset_and_limit_with_limit
|
||||
assert_equal [0, 30], @controller.api_offset_and_limit({:limit => 30})
|
||||
assert_equal [0, 100], @controller.api_offset_and_limit({:limit => 120})
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:limit => -10})
|
||||
end
|
||||
|
||||
def test_api_offset_and_limit_with_offset
|
||||
assert_equal [10, 25], @controller.api_offset_and_limit({:offset => 10})
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:offset => -10})
|
||||
end
|
||||
|
||||
def test_api_offset_and_limit_with_offset_and_limit
|
||||
assert_equal [10, 50], @controller.api_offset_and_limit({:offset => 10, :limit => 50})
|
||||
end
|
||||
|
||||
def test_api_offset_and_limit_with_page
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:page => 1})
|
||||
assert_equal [50, 25], @controller.api_offset_and_limit({:page => 3})
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:page => 0})
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:page => -2})
|
||||
end
|
||||
|
||||
def test_api_offset_and_limit_with_page_and_limit
|
||||
assert_equal [0, 100], @controller.api_offset_and_limit({:page => 1, :limit => 100})
|
||||
assert_equal [200, 100], @controller.api_offset_and_limit({:page => 3, :limit => 100})
|
||||
end
|
||||
|
||||
def test_unhautorized_exception_with_anonymous_should_redirect_to_login
|
||||
WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
|
||||
|
||||
get :index
|
||||
assert_response 302
|
||||
assert_redirected_to('/login?back_url='+CGI.escape('http://test.host/'))
|
||||
end
|
||||
|
||||
def test_unhautorized_exception_with_anonymous_and_xmlhttprequest_should_respond_with_401_to_anonymous
|
||||
WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
|
||||
|
||||
@request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
|
||||
get :index
|
||||
assert_response 401
|
||||
end
|
||||
end
|
||||
1125
test/functional/wiki_controller_test.rb
Normal file
1125
test/functional/wiki_controller_test.rb
Normal file
File diff suppressed because it is too large
Load diff
89
test/functional/wikis_controller_test.rb
Normal file
89
test/functional/wikis_controller_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 WikisControllerTest < Redmine::ControllerTest
|
||||
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 1
|
||||
assert_nil Project.find(3).wiki
|
||||
|
||||
assert_difference 'Wiki.count' do
|
||||
post :edit, :params => {:id => 3, :wiki => { :start_page => 'Start page' }}, :xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
wiki = Project.find(3).wiki
|
||||
assert_not_nil wiki
|
||||
assert_equal 'Start page', wiki.start_page
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
assert_no_difference 'Wiki.count' do
|
||||
post :edit, :params => {:id => 3, :wiki => { :start_page => '' }}, :xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
assert_include 'errorExplanation', response.body
|
||||
assert_include "Start page cannot be blank", response.body
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
assert_no_difference 'Wiki.count' do
|
||||
post :edit, :params => {:id => 1, :wiki => { :start_page => 'Other start page' }}, :xhr => true
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
wiki = Project.find(1).wiki
|
||||
assert_equal 'Other start page', wiki.start_page
|
||||
end
|
||||
|
||||
def test_get_destroy_should_ask_confirmation
|
||||
@request.session[:user_id] = 1
|
||||
assert_no_difference 'Wiki.count' do
|
||||
get :destroy, :params => {:id => 1}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_destroy_should_delete_wiki
|
||||
@request.session[:user_id] = 1
|
||||
post :destroy, :params => {:id => 1, :confirm => 1}
|
||||
assert_redirected_to :controller => 'projects',
|
||||
:action => 'settings', :id => 'ecookbook', :tab => 'wiki'
|
||||
assert_nil Project.find(1).wiki
|
||||
end
|
||||
|
||||
def test_not_found
|
||||
@request.session[:user_id] = 1
|
||||
post :destroy, :params => {:id => 999, :confirm => 1}
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
438
test/functional/workflows_controller_test.rb
Normal file
438
test/functional/workflows_controller_test.rb
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
# 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 WorkflowsControllerTest < Redmine::ControllerTest
|
||||
fixtures :roles, :trackers, :workflows, :users, :issue_statuses
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
count = WorkflowTransition.where(:role_id => 1, :tracker_id => 2).count
|
||||
assert_select 'a[href=?]', '/workflows/edit?role_id=1&tracker_id=2', :content => count.to_s
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
get :edit
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_get_edit_with_role_and_tracker
|
||||
WorkflowTransition.delete_all
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 2, :new_status_id => 3)
|
||||
WorkflowTransition.create!(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 5)
|
||||
|
||||
get :edit, :params => {:role_id => 2, :tracker_id => 1}
|
||||
assert_response :success
|
||||
|
||||
# used status only
|
||||
statuses = IssueStatus.where(:id => [2, 3, 5]).sorted.pluck(:name)
|
||||
assert_equal ["New issue"] + statuses,
|
||||
css_select('table.workflows.transitions-always tbody tr td:first').map(&:text).map(&:strip)
|
||||
|
||||
# allowed transitions
|
||||
assert_select 'input[type=checkbox][name=?][value="1"][checked=checked]', 'transitions[3][5][always]'
|
||||
# not allowed
|
||||
assert_select 'input[type=checkbox][name=?][value="1"]:not([checked=checked])', 'transitions[3][2][always]'
|
||||
# unused
|
||||
assert_select 'input[type=checkbox][name=?]', 'transitions[1][1][always]', 0
|
||||
end
|
||||
|
||||
def test_get_edit_with_role_and_tracker_should_not_include_statuses_from_roles_without_workflow_permissions
|
||||
WorkflowTransition.delete_all
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 2, :new_status_id => 3)
|
||||
|
||||
reporter = Role.find(3)
|
||||
reporter.remove_permission! :edit_issues
|
||||
reporter.remove_permission! :add_issues
|
||||
assert !reporter.consider_workflow?
|
||||
WorkflowTransition.create!(:role_id => 3, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5)
|
||||
|
||||
get :edit, :params => {:role_id => 2, :tracker_id => 1}
|
||||
assert_response :success
|
||||
|
||||
# statuses 1 and 5 not displayed
|
||||
statuses = IssueStatus.where(:id => [2, 3]).sorted.pluck(:name)
|
||||
assert_equal ["New issue"] + statuses,
|
||||
css_select('table.workflows.transitions-always tbody tr td:first').map(&:text).map(&:strip)
|
||||
end
|
||||
|
||||
def test_get_edit_should_include_allowed_statuses_for_new_issues
|
||||
WorkflowTransition.delete_all
|
||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 1)
|
||||
|
||||
get :edit, :params => {:role_id => 1, :tracker_id => 1}
|
||||
assert_response :success
|
||||
assert_select 'td', 'New issue'
|
||||
assert_select 'input[type=checkbox][name=?][value="1"][checked=checked]', 'transitions[0][1][always]'
|
||||
end
|
||||
|
||||
def test_get_edit_with_all_roles_and_all_trackers
|
||||
get :edit, :params => {:role_id => 'all', :tracker_id => 'all'}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?][multiple=multiple]', 'role_id[]' do
|
||||
assert_select 'option[selected=selected]', Role.all.select(&:consider_workflow?).count
|
||||
end
|
||||
assert_select 'select[name=?]', 'tracker_id[]' do
|
||||
assert_select 'option[selected=selected][value=all]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_edit_with_role_and_tracker_and_all_statuses
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
get :edit, :params => {:role_id => 2, :tracker_id => 1, :used_statuses_only => '0'}
|
||||
assert_response :success
|
||||
|
||||
statuses = IssueStatus.all.sorted.pluck(:name)
|
||||
assert_equal ["New issue"] + statuses,
|
||||
css_select('table.workflows.transitions-always tbody tr td:first').map(&:text).map(&:strip)
|
||||
|
||||
assert_select 'input[type=checkbox][name=?]', 'transitions[1][1][always]'
|
||||
end
|
||||
|
||||
def test_post_edit
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
post :edit, :params => {
|
||||
:role_id => 2,
|
||||
:tracker_id => 1,
|
||||
:transitions => {
|
||||
'4' => {'5' => {'always' => '1'}},
|
||||
'3' => {'1' => {'always' => '1'}, '2' => {'always' => '1'}}
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
|
||||
assert_equal 3, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
|
||||
assert_not_nil WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
|
||||
assert_nil WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4).first
|
||||
end
|
||||
|
||||
def test_post_edit_with_allowed_statuses_for_new_issues
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
post :edit, :params => {
|
||||
:role_id => 2,
|
||||
:tracker_id => 1,
|
||||
:transitions => {
|
||||
'0' => {'1' => {'always' => '1'}, '2' => {'always' => '1'}}
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
|
||||
assert WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 0, :new_status_id => 1).any?
|
||||
assert WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 0, :new_status_id => 2).any?
|
||||
assert_equal 2, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
|
||||
end
|
||||
|
||||
def test_post_edit_with_additional_transitions
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
post :edit, :params => {
|
||||
:role_id => 2,
|
||||
:tracker_id => 1,
|
||||
:transitions => {
|
||||
'4' => {'5' => {'always' => '1', 'author' => '0', 'assignee' => '0'}},
|
||||
'3' => {'1' => {'always' => '0', 'author' => '1', 'assignee' => '0'},
|
||||
'2' => {'always' => '0', 'author' => '0', 'assignee' => '1'},
|
||||
'4' => {'always' => '0', 'author' => '1', 'assignee' => '1'}}
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
|
||||
assert_equal 4, WorkflowTransition.where(:tracker_id => 1, :role_id => 2).count
|
||||
|
||||
w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 4, :new_status_id => 5).first
|
||||
assert ! w.author
|
||||
assert ! w.assignee
|
||||
w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 1).first
|
||||
assert w.author
|
||||
assert ! w.assignee
|
||||
w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 2).first
|
||||
assert ! w.author
|
||||
assert w.assignee
|
||||
w = WorkflowTransition.where(:role_id => 2, :tracker_id => 1, :old_status_id => 3, :new_status_id => 4).first
|
||||
assert w.author
|
||||
assert w.assignee
|
||||
end
|
||||
|
||||
def test_get_permissions
|
||||
get :permissions
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_get_permissions_with_role_and_tracker
|
||||
WorkflowPermission.delete_all
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'assigned_to_id', :rule => 'required')
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 3, :field_name => 'fixed_version_id', :rule => 'readonly')
|
||||
|
||||
get :permissions, :params => {:role_id => 1, :tracker_id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'input[name=?][value="1"]', 'role_id[]'
|
||||
assert_select 'input[name=?][value="2"]', 'tracker_id[]'
|
||||
|
||||
# Required field
|
||||
assert_select 'select[name=?]', 'permissions[2][assigned_to_id]' do
|
||||
assert_select 'option[value=""]'
|
||||
assert_select 'option[value=""][selected=selected]', 0
|
||||
assert_select 'option[value=readonly]', :text => 'Read-only'
|
||||
assert_select 'option[value=readonly][selected=selected]', 0
|
||||
assert_select 'option[value=required]', :text => 'Required'
|
||||
assert_select 'option[value=required][selected=selected]'
|
||||
end
|
||||
|
||||
# Read-only field
|
||||
assert_select 'select[name=?]', 'permissions[3][fixed_version_id]' do
|
||||
assert_select 'option[value=""]'
|
||||
assert_select 'option[value=""][selected=selected]', 0
|
||||
assert_select 'option[value=readonly]', :text => 'Read-only'
|
||||
assert_select 'option[value=readonly][selected=selected]'
|
||||
assert_select 'option[value=required]', :text => 'Required'
|
||||
assert_select 'option[value=required][selected=selected]', 0
|
||||
end
|
||||
|
||||
# Other field
|
||||
assert_select 'select[name=?]', 'permissions[3][due_date]' do
|
||||
assert_select 'option[value=""]'
|
||||
assert_select 'option[value=""][selected=selected]', 0
|
||||
assert_select 'option[value=readonly]', :text => 'Read-only'
|
||||
assert_select 'option[value=readonly][selected=selected]', 0
|
||||
assert_select 'option[value=required]', :text => 'Required'
|
||||
assert_select 'option[value=required][selected=selected]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_permissions_with_required_custom_field_should_not_show_required_option
|
||||
cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :tracker_ids => [1], :is_required => true)
|
||||
|
||||
get :permissions, :params => {:role_id => 1, :tracker_id => 1}
|
||||
assert_response :success
|
||||
|
||||
# Custom field that is always required
|
||||
# The default option is "(Required)"
|
||||
assert_select 'select[name=?]', "permissions[3][#{cf.id}]" do
|
||||
assert_select 'option[value=""]'
|
||||
assert_select 'option[value=readonly]', :text => 'Read-only'
|
||||
assert_select 'option[value=required]', 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_permissions_should_disable_hidden_custom_fields
|
||||
cf1 = IssueCustomField.generate!(:tracker_ids => [1], :visible => true)
|
||||
cf2 = IssueCustomField.generate!(:tracker_ids => [1], :visible => false, :role_ids => [1])
|
||||
cf3 = IssueCustomField.generate!(:tracker_ids => [1], :visible => false, :role_ids => [1, 2])
|
||||
|
||||
get :permissions, :params => {:role_id => 2, :tracker_id => 1}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]:not(.disabled)', "permissions[1][#{cf1.id}]"
|
||||
assert_select 'select[name=?]:not(.disabled)', "permissions[1][#{cf3.id}]"
|
||||
|
||||
assert_select 'select[name=?][disabled=disabled]', "permissions[1][#{cf2.id}]" do
|
||||
assert_select 'option[value=""][selected=selected]', :text => 'Hidden'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_permissions_with_missing_permissions_for_roles_should_default_to_no_change
|
||||
WorkflowPermission.delete_all
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
|
||||
|
||||
get :permissions, :params => {:role_id => [1, 2], :tracker_id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
|
||||
assert_select 'option[selected]', 1
|
||||
assert_select 'option[selected][value=no_change]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_permissions_with_different_permissions_for_roles_should_default_to_no_change
|
||||
WorkflowPermission.delete_all
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
|
||||
WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'readonly')
|
||||
|
||||
get :permissions, :params => {:role_id => [1, 2], :tracker_id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
|
||||
assert_select 'option[selected]', 1
|
||||
assert_select 'option[selected][value=no_change]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_permissions_with_same_permissions_for_roles_should_default_to_permission
|
||||
WorkflowPermission.delete_all
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
|
||||
WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
|
||||
|
||||
get :permissions, :params => {:role_id => [1, 2], :tracker_id => 2}
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=?]', 'permissions[1][assigned_to_id]' do
|
||||
assert_select 'option[selected]', 1
|
||||
assert_select 'option[selected][value=required]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_permissions_with_role_and_tracker_and_all_statuses_should_show_all_statuses
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
get :permissions, :params => {:role_id => 1, :tracker_id => 2, :used_statuses_only => '0'}
|
||||
assert_response :success
|
||||
|
||||
statuses = IssueStatus.all.sorted.pluck(:name)
|
||||
assert_equal statuses,
|
||||
css_select('table.workflows.fields_permissions thead tr:nth-child(2) td:not(:first-child)').map(&:text).map(&:strip)
|
||||
end
|
||||
|
||||
def test_get_permissions_should_set_css_class
|
||||
WorkflowPermission.delete_all
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => 'assigned_to_id', :rule => 'required')
|
||||
cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :tracker_ids => [2])
|
||||
WorkflowPermission.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 1, :field_name => cf.id, :rule => 'required')
|
||||
|
||||
get :permissions, :params => {:role_id => 1, :tracker_id => 2}
|
||||
assert_response :success
|
||||
assert_select 'td.required > select[name=?]', 'permissions[1][assigned_to_id]'
|
||||
assert_select 'td.required > select[name=?]', "permissions[1][#{cf.id}]"
|
||||
end
|
||||
|
||||
def test_post_permissions
|
||||
WorkflowPermission.delete_all
|
||||
|
||||
post :permissions, :params => {
|
||||
:role_id => 1,
|
||||
:tracker_id => 2,
|
||||
:permissions => {
|
||||
'1' => {'assigned_to_id' => '', 'fixed_version_id' => 'required', 'due_date' => ''},
|
||||
'2' => {'assigned_to_id' => 'readonly', 'fixed_version_id' => 'readonly', 'due_date' => ''},
|
||||
'3' => {'assigned_to_id' => '', 'fixed_version_id' => '', 'due_date' => ''}
|
||||
}
|
||||
}
|
||||
assert_response 302
|
||||
|
||||
workflows = WorkflowPermission.all
|
||||
assert_equal 3, workflows.size
|
||||
workflows.each do |workflow|
|
||||
assert_equal 1, workflow.role_id
|
||||
assert_equal 2, workflow.tracker_id
|
||||
end
|
||||
assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'assigned_to_id' && wf.rule == 'readonly'}
|
||||
assert workflows.detect {|wf| wf.old_status_id == 1 && wf.field_name == 'fixed_version_id' && wf.rule == 'required'}
|
||||
assert workflows.detect {|wf| wf.old_status_id == 2 && wf.field_name == 'fixed_version_id' && wf.rule == 'readonly'}
|
||||
end
|
||||
|
||||
def test_get_copy
|
||||
get :copy
|
||||
assert_response :success
|
||||
|
||||
assert_select 'select[name=source_tracker_id]' do
|
||||
assert_select 'option[value="1"]', :text => 'Bug'
|
||||
end
|
||||
assert_select 'select[name=source_role_id]' do
|
||||
assert_select 'option[value="2"]', :text => 'Developer'
|
||||
end
|
||||
assert_select 'select[name=?]', 'target_tracker_ids[]' do
|
||||
assert_select 'option[value="3"]', :text => 'Support request'
|
||||
end
|
||||
assert_select 'select[name=?]', 'target_role_ids[]' do
|
||||
assert_select 'option[value="1"]', :text => 'Manager'
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_copy_one_to_one
|
||||
source_transitions = status_transitions(:tracker_id => 1, :role_id => 2)
|
||||
|
||||
post :copy, :params => {
|
||||
:source_tracker_id => '1', :source_role_id => '2',
|
||||
:target_tracker_ids => ['3'], :target_role_ids => ['1']
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1)
|
||||
end
|
||||
|
||||
def test_post_copy_one_to_many
|
||||
source_transitions = status_transitions(:tracker_id => 1, :role_id => 2)
|
||||
|
||||
post :copy, :params => {
|
||||
:source_tracker_id => '1', :source_role_id => '2',
|
||||
:target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 1)
|
||||
assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 1)
|
||||
assert_equal source_transitions, status_transitions(:tracker_id => 2, :role_id => 3)
|
||||
assert_equal source_transitions, status_transitions(:tracker_id => 3, :role_id => 3)
|
||||
end
|
||||
|
||||
def test_post_copy_many_to_many
|
||||
source_t2 = status_transitions(:tracker_id => 2, :role_id => 2)
|
||||
source_t3 = status_transitions(:tracker_id => 3, :role_id => 2)
|
||||
|
||||
post :copy, :params => {
|
||||
:source_tracker_id => 'any', :source_role_id => '2',
|
||||
:target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
|
||||
}
|
||||
assert_response 302
|
||||
assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 1)
|
||||
assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 1)
|
||||
assert_equal source_t2, status_transitions(:tracker_id => 2, :role_id => 3)
|
||||
assert_equal source_t3, status_transitions(:tracker_id => 3, :role_id => 3)
|
||||
end
|
||||
|
||||
def test_post_copy_with_incomplete_source_specification_should_fail
|
||||
assert_no_difference 'WorkflowRule.count' do
|
||||
post :copy, :params => {
|
||||
:source_tracker_id => '', :source_role_id => '2',
|
||||
:target_tracker_ids => ['2', '3'], :target_role_ids => ['1', '3']
|
||||
}
|
||||
assert_response 200
|
||||
assert_select 'div.flash.error', :text => 'Please select a source tracker or role'
|
||||
end
|
||||
end
|
||||
|
||||
def test_post_copy_with_incomplete_target_specification_should_fail
|
||||
assert_no_difference 'WorkflowRule.count' do
|
||||
post :copy, :params => {
|
||||
:source_tracker_id => '1', :source_role_id => '2',
|
||||
:target_tracker_ids => ['2', '3']
|
||||
}
|
||||
assert_response 200
|
||||
assert_select 'div.flash.error', :text => 'Please select target tracker(s) and role(s)'
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an array of status transitions that can be compared
|
||||
def status_transitions(conditions)
|
||||
WorkflowTransition.
|
||||
where(conditions).
|
||||
order('tracker_id, role_id, old_status_id, new_status_id').
|
||||
collect {|w| [w.old_status, w.new_status_id]}
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue