添加测试用例
This commit is contained in:
parent
dec77da33c
commit
801025d967
|
@ -0,0 +1,165 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :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, :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, :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, :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, :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, :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, :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, :openid_url => 'http://openid.example.com/good_user'
|
||||
assert_response :success
|
||||
assert_template 'register'
|
||||
assert assigns(:user)
|
||||
assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
|
||||
end
|
||||
|
||||
def test_login_with_openid_with_new_user_with_missing_information_should_register
|
||||
Setting.self_registration = '3'
|
||||
|
||||
post :login, :openid_url => 'http://openid.example.com/good_blank_user'
|
||||
assert_response :success
|
||||
assert_template 'register'
|
||||
assert assigns(:user)
|
||||
assert_equal 'http://openid.example.com/good_blank_user', assigns(:user)[:identity_url]
|
||||
|
||||
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_register_after_login_failure_should_not_require_user_to_enter_a_password
|
||||
Setting.self_registration = '3'
|
||||
|
||||
assert_difference 'User.count' do
|
||||
post :register, :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.first(:order => 'id DESC')
|
||||
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
|
|
@ -0,0 +1,277 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :users, :roles
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_get_login
|
||||
get :login
|
||||
assert_response :success
|
||||
assert_template 'login'
|
||||
|
||||
assert_select 'input[name=username]'
|
||||
assert_select 'input[name=password]'
|
||||
end
|
||||
|
||||
def test_get_login_while_logged_in_should_redirect_to_home
|
||||
@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
|
||||
post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http://test.host/issues/show/1'
|
||||
assert_redirected_to '/issues/show/1'
|
||||
end
|
||||
|
||||
def test_login_should_not_redirect_to_another_host
|
||||
post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http://test.foo/fake'
|
||||
assert_redirected_to '/my/page'
|
||||
end
|
||||
|
||||
def test_login_with_wrong_password
|
||||
post :login, :username => 'admin', :password => 'bad'
|
||||
assert_response :success
|
||||
assert_template 'login'
|
||||
|
||||
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_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, :username => 'jsmith', :password => 'jsmith'
|
||||
assert_response 500
|
||||
assert_error_tag :content => /Something wrong/
|
||||
end
|
||||
|
||||
def test_login_should_reset_session
|
||||
@controller.expects(:reset_session).once
|
||||
|
||||
post :login, :username => 'jsmith', :password => 'jsmith'
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_get_logout_should_not_logout
|
||||
@request.session[:user_id] = 2
|
||||
get :logout
|
||||
assert_response :success
|
||||
assert_template 'logout'
|
||||
|
||||
assert_equal 2, @request.session[:user_id]
|
||||
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_template 'register'
|
||||
assert_not_nil assigns(:user)
|
||||
|
||||
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_not_nil assigns(:user)
|
||||
assert_equal 'fr', assigns(:user).language
|
||||
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
|
||||
|
||||
# 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, :user => {
|
||||
:login => 'register',
|
||||
:password => 'secret123',
|
||||
:password_confirmation => 'secret123',
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:mail => 'register@example.com'
|
||||
}
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
user = User.first(:order => 'id DESC')
|
||||
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, :user => {
|
||||
:login => 'register',
|
||||
:password => 'test',
|
||||
:password_confirmation => 'test',
|
||||
:firstname => 'John',
|
||||
:lastname => 'Doe',
|
||||
:mail => 'register@example.com'
|
||||
}
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
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
|
||||
with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
|
||||
post :lost_password, :mail => 'JSmith@somenet.foo'
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
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://mydomain.foo/account/lost_password?token=#{token.value}"
|
||||
end
|
||||
end
|
||||
|
||||
def test_lost_password_for_unknown_user_should_fail
|
||||
Token.delete_all
|
||||
assert_no_difference 'Token.count' do
|
||||
post :lost_password, :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, :mail => 'JSmith@somenet.foo'
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_lost_password_with_token_should_display_the_password_recovery_form
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
get :lost_password, :token => token.value
|
||||
assert_response :success
|
||||
assert_template 'password_recovery'
|
||||
|
||||
assert_select 'input[type=hidden][name=token][value=?]', token.value
|
||||
end
|
||||
|
||||
def test_get_lost_password_with_invalid_token_should_redirect
|
||||
get :lost_password, :token => "abcdef"
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
|
||||
def test_post_lost_password_with_token_should_change_the_user_password
|
||||
user = User.find(2)
|
||||
token = Token.create!(:action => 'recovery', :user => user)
|
||||
|
||||
post :lost_password, :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"
|
||||
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, :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, :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'wrongpass'
|
||||
assert_response :success
|
||||
assert_template 'password_recovery'
|
||||
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_invalid_token_should_redirect
|
||||
post :lost_password, :token => "abcdef", :new_password => 'newpass', :new_password_confirmation => 'newpass'
|
||||
assert_redirected_to '/'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,150 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :id => 1, :with_subprojects => 0
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:events_by_day)
|
||||
|
||||
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, :id => 299
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_previous_project_index
|
||||
get :index, :id => 1, :from => 2.days.ago.to_date
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:events_by_day)
|
||||
|
||||
assert_select 'h3', :text => /#{3.days.ago.to_date.day}/
|
||||
assert_select 'dl dt.issue a', :text => /Can't print recipes/
|
||||
end
|
||||
|
||||
def test_global_index
|
||||
@request.session[:user_id] = 1
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:events_by_day)
|
||||
|
||||
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, :user_id => 2
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:events_by_day)
|
||||
|
||||
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 => /Can't print recipes/
|
||||
end
|
||||
|
||||
def test_user_index_with_invalid_user_id_should_respond_404
|
||||
get :index, :user_id => 299
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_index_atom_feed
|
||||
get :index, :format => 'atom', :with_subprojects => 0
|
||||
assert_response :success
|
||||
assert_template 'common/feed'
|
||||
|
||||
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, :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_template 'common/feed'
|
||||
|
||||
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
|
||||
get :index, :format => 'atom', :show_issues => '1'
|
||||
assert_response :success
|
||||
assert_template 'common/feed'
|
||||
|
||||
assert_select 'title', :text => /Issues/
|
||||
end
|
||||
|
||||
def test_index_should_show_private_notes_with_permission_only
|
||||
journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Private notes with searchkeyword', :private_notes => true)
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_include journal, assigns(:events_by_day).values.flatten
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_not_include journal, assigns(:events_by_day).values.flatten
|
||||
end
|
||||
end
|
|
@ -0,0 +1,167 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :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_template 'projects'
|
||||
assert_not_nil assigns(:projects)
|
||||
# active projects only
|
||||
assert_nil assigns(:projects).detect {|u| !u.active?}
|
||||
end
|
||||
|
||||
def test_projects_with_status_filter
|
||||
get :projects, :status => 1
|
||||
assert_response :success
|
||||
assert_template 'projects'
|
||||
assert_not_nil assigns(:projects)
|
||||
# active projects only
|
||||
assert_nil assigns(:projects).detect {|u| !u.active?}
|
||||
end
|
||||
|
||||
def test_projects_with_name_filter
|
||||
get :projects, :name => 'store', :status => ''
|
||||
assert_response :success
|
||||
assert_template 'projects'
|
||||
projects = assigns(:projects)
|
||||
assert_not_nil projects
|
||||
assert_equal 1, projects.size
|
||||
assert_equal 'OnlineStore', projects.first.name
|
||||
end
|
||||
|
||||
def test_load_default_configuration_data
|
||||
delete_configuration_data
|
||||
post :default_configuration, :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, :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
|
||||
|
||||
get :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')
|
||||
get :test_email
|
||||
assert_redirected_to '/settings?tab=notifications'
|
||||
assert_match /Some error message/, flash[:error]
|
||||
end
|
||||
|
||||
def test_no_plugins
|
||||
Redmine::Plugin.clear
|
||||
|
||||
get :plugins
|
||||
assert_response :success
|
||||
assert_template 'plugins'
|
||||
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_template 'plugins'
|
||||
|
||||
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
|
||||
assert_template 'info'
|
||||
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.delete_all('builtin = 0')
|
||||
Tracker.delete_all
|
||||
IssueStatus.delete_all
|
||||
Enumeration.delete_all
|
||||
end
|
||||
end
|
|
@ -0,0 +1,385 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :id => 14, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_tag 'th',
|
||||
:attributes => {:class => /filename/},
|
||||
:content => /issues_controller.rb\t\(révision 1484\)/
|
||||
assert_tag 'td',
|
||||
:attributes => {:class => /line-code/},
|
||||
:content => /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, :id => 5, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_tag 'th',
|
||||
:attributes => {:class => "filename"},
|
||||
:content => /issues_controller.rb\t\(r\?vision 1484\)/
|
||||
assert_tag 'td',
|
||||
:attributes => {:class => /line-code/},
|
||||
:content => /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, :id => 5, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_tag 'th',
|
||||
:attributes => {:class => "filename"},
|
||||
:content => /issues_controller.rb\t\(révision 1484\)/
|
||||
assert_tag 'td',
|
||||
:attributes => {:class => /line-code/},
|
||||
:content => /Demande créée avec succès/
|
||||
end
|
||||
end
|
||||
set_tmp_attachments_directory
|
||||
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 :show, :id => 5
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
user.reload
|
||||
assert_equal "inline", user.pref[:diff_type]
|
||||
get :show, :id => 5, :type => 'sbs'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
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, :id => a.id, :type => 'inline'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_select 'th.filename', :text => 'test1.txt'
|
||||
end
|
||||
|
||||
def test_show_text_file
|
||||
get :show, :id => 4
|
||||
assert_response :success
|
||||
assert_template 'file'
|
||||
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"
|
||||
str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
|
||||
|
||||
get :show, :id => a.id
|
||||
assert_response :success
|
||||
assert_template 'file'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /#{str_japanese}/ }
|
||||
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, :id => a.id
|
||||
assert_response :success
|
||||
assert_template 'file'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_tag :tag => 'th',
|
||||
:content => '7',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /Demande cr\?\?e avec succ\?s/ }
|
||||
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, :id => a.id
|
||||
assert_response :success
|
||||
assert_template 'file'
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_tag :tag => 'th',
|
||||
:content => '7',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /Demande créée avec succès/ }
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_text_file_should_send_if_too_big
|
||||
Setting.file_max_size_displayed = 512
|
||||
Attachment.find(4).update_attribute :filesize, 754.kilobyte
|
||||
|
||||
get :show, :id => 4
|
||||
assert_response :success
|
||||
assert_equal 'application/x-ruby', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_other
|
||||
get :show, :id => 6
|
||||
assert_response :success
|
||||
assert_equal 'application/octet-stream', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_show_file_from_private_issue_without_permission
|
||||
get :show, :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, :id => 15
|
||||
assert_response :success
|
||||
assert_tag 'h2', :content => /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, :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, :id => attachment.id
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_show_invalid_should_respond_with_404
|
||||
get :show, :id => 999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_download_text_file
|
||||
get :download, :id => 4
|
||||
assert_response :success
|
||||
assert_equal 'application/x-ruby', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_download_version_file_with_issue_tracking_disabled
|
||||
Project.find(1).disable_module! :issue_tracking
|
||||
get :download, :id => 9
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_download_should_assign_content_type_if_blank
|
||||
Attachment.find(4).update_attribute(:content_type, '')
|
||||
|
||||
get :download, :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, :id => 2
|
||||
assert_response 404
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_download_should_be_denied_without_permission
|
||||
get :download, :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, :id => 16
|
||||
assert_response :success
|
||||
assert_equal 'image/png', response.content_type
|
||||
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, :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, :id => 16, :size => 260
|
||||
end
|
||||
|
||||
def test_thumbnail_should_return_404_for_non_image_attachment
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :thumbnail, :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, :id => 16
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_thumbnail_should_be_denied_without_permission
|
||||
get :thumbnail, :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_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, :id => 1
|
||||
assert_redirected_to '/projects/ecookbook'
|
||||
end
|
||||
end
|
||||
assert_nil Attachment.find_by_id(1)
|
||||
j = Journal.first(:order => 'id DESC')
|
||||
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, :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, :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, :id => 9
|
||||
assert_response 302
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_without_permission
|
||||
set_tmp_attachments_directory
|
||||
assert_no_difference 'Attachment.count' do
|
||||
delete :destroy, :id => 3
|
||||
end
|
||||
assert_response 302
|
||||
assert Attachment.find_by_id(3)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,168 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :users, :auth_sources
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:auth_sources)
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
|
||||
source = assigns(:auth_source)
|
||||
assert_equal AuthSourceLdap, source.class
|
||||
assert source.new_record?
|
||||
|
||||
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, :type => 'foo'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'AuthSourceLdap.count' do
|
||||
post :create, :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, :type => 'AuthSourceLdap', :auth_source => {:name => 'Test', :host => '', :port => '389', :attr_login => 'cn'}
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
assert_error_tag :content => /host can't be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :id => 1
|
||||
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
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, :id => 1
|
||||
assert_response :success
|
||||
assert_select 'input[value=secret]', 0
|
||||
assert_select 'input[name=dummy_password][value=?]', /x+/
|
||||
end
|
||||
|
||||
def test_edit_invalid_should_respond_with_404
|
||||
get :edit, :id => 99
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :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, :id => 1, :auth_source => {:name => 'Renamed', :host => '', :port => '389', :attr_login => 'uid'}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_error_tag :content => /host can't be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'AuthSourceLdap.count', -1 do
|
||||
delete :destroy, :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, :id => 1
|
||||
assert_redirected_to '/auth_sources'
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_connection
|
||||
AuthSourceLdap.any_instance.stubs(:test_connection).returns(true)
|
||||
|
||||
get :test_connection, :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, :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, :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
|
|
@ -0,0 +1,217 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:boards)
|
||||
assert_not_nil assigns(:project)
|
||||
end
|
||||
|
||||
def test_index_not_found
|
||||
get :index, :project_id => 97
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_index_should_show_messages_if_only_one_board
|
||||
Project.find(1).boards.slice(1..-1).each(&:destroy)
|
||||
|
||||
get :index, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:topics)
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :project_id => 1, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:board)
|
||||
assert_not_nil assigns(:project)
|
||||
assert_not_nil assigns(:topics)
|
||||
end
|
||||
|
||||
def test_show_should_display_sticky_messages_first
|
||||
Message.update_all(:sticky => 0)
|
||||
Message.update_all({:sticky => 1}, {:id => 1})
|
||||
|
||||
get :show, :project_id => 1, :id => 1
|
||||
assert_response :success
|
||||
|
||||
topics = assigns(:topics)
|
||||
assert_not_nil topics
|
||||
assert topics.size > 1, "topics size was #{topics.size}"
|
||||
assert topics.first.sticky?
|
||||
assert topics.first.updated_on < topics.second.updated_on
|
||||
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, :project_id => 1, :id => 1
|
||||
assert_response :success
|
||||
topics = assigns(:topics)
|
||||
assert_not_nil topics
|
||||
assert_equal old_topic, topics.first
|
||||
end
|
||||
|
||||
def test_show_with_permission_should_display_the_new_message_form
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
|
||||
assert_select 'form#message-form' do
|
||||
assert_select 'input[name=?]', 'message[subject]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_atom
|
||||
get :show, :project_id => 1, :id => 1, :format => 'atom'
|
||||
assert_response :success
|
||||
assert_template 'common/feed'
|
||||
assert_not_nil assigns(:board)
|
||||
assert_not_nil assigns(:project)
|
||||
assert_not_nil assigns(:messages)
|
||||
end
|
||||
|
||||
def test_show_not_found
|
||||
get :index, :project_id => 1, :id => 97
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
|
||||
assert_select 'select[name=?]', 'board[parent_id]' do
|
||||
assert_select 'option', (Project.find(1).boards.size + 1)
|
||||
assert_select 'option[value=]', :text => ''
|
||||
assert_select 'option[value=1]', :text => 'Help'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_without_project_boards
|
||||
Project.find(1).boards.delete_all
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
|
||||
assert_select 'select[name=?]', 'board[parent_id]', 0
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Board.count' do
|
||||
post :create, :project_id => 1, :board => { :name => 'Testing', :description => 'Testing board creation'}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
board = Board.first(:order => 'id DESC')
|
||||
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, :project_id => 1, :board => { :name => 'Testing', :description => 'Testing', :parent_id => 2}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
board = Board.first(:order => 'id DESC')
|
||||
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, :project_id => 1, :board => { :name => '', :description => 'Testing board creation'}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :project_id => 1, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_edit_with_parent
|
||||
board = Board.generate!(:project_id => 1, :parent_id => 2)
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :project_id => 1, :id => board.id
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
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, :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, :project_id => 1, :id => 2, :board => { :move_to => 'highest'}
|
||||
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, :project_id => 1, :id => 2, :board => { :name => '', :description => 'Testing board update'}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Board.count', -1 do
|
||||
delete :destroy, :project_id => 1, :id => 2
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/boards'
|
||||
assert_nil Board.find_by_id(2)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,84 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def test_show
|
||||
get :show, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'calendar'
|
||||
assert_not_nil assigns(:calendar)
|
||||
end
|
||||
|
||||
def test_show_should_run_custom_queries
|
||||
@query = IssueQuery.create!(:name => 'Calendar', :is_public => true)
|
||||
|
||||
get :show, :query_id => @query.id
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_cross_project_calendar
|
||||
get :show
|
||||
assert_response :success
|
||||
assert_template 'calendar'
|
||||
assert_not_nil assigns(:calendar)
|
||||
end
|
||||
|
||||
def test_week_number_calculation
|
||||
Setting.start_of_week = 7
|
||||
|
||||
get :show, :month => '1', :year => '2010'
|
||||
assert_response :success
|
||||
|
||||
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
|
||||
|
||||
Setting.start_of_week = 1
|
||||
get :show, :month => '1', :year => '2010'
|
||||
assert_response :success
|
||||
|
||||
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
|
||||
end
|
|
@ -0,0 +1,64 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :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, :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, :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, :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, :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
|
|
@ -0,0 +1,252 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :ids => [1]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
|
||||
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
|
||||
get :issues, :ids => [1]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
assert_tag :tag => 'a', :content => 'Delete',
|
||||
:attributes => { :href => '#',
|
||||
:class => 'icon-del disabled' }
|
||||
end
|
||||
|
||||
def test_context_menu_multiple_issues_of_same_project
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :ids => [1, 2]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
assert_not_nil assigns(:issues)
|
||||
assert_equal [1, 2], assigns(:issues).map(&:id).sort
|
||||
|
||||
ids = assigns(:issues).map(&:id).sort.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, :ids => [1, 2, 6]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
assert_not_nil assigns(:issues)
|
||||
assert_equal [1, 2, 6], assigns(:issues).map(&:id).sort
|
||||
|
||||
ids = assigns(:issues).map(&:id).sort.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, :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, :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, :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, :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, :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, :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_by_assignable_user_should_include_assigned_to_me_link
|
||||
@request.session[:user_id] = 2
|
||||
get :issues, :ids => [1]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
|
||||
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, :ids => [1, 4]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
|
||||
assert_include version, assigns(:versions)
|
||||
assert_select 'a', :text => 'eCookbook - Shared'
|
||||
end
|
||||
|
||||
def test_context_menu_issue_visibility
|
||||
get :issues, :ids => [1, 4]
|
||||
assert_response :success
|
||||
assert_template 'context_menu'
|
||||
assert_equal [1], assigns(:issues).collect(&:id)
|
||||
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, :ids => [1, 2]
|
||||
assert_response :success
|
||||
assert_template 'time_entries'
|
||||
|
||||
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, :ids => [1, 2]
|
||||
assert_response :success
|
||||
assert_template 'time_entries'
|
||||
assert_select 'a.disabled', :text => 'Edit'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,176 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :custom_fields, :custom_values, :trackers, :users
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
end
|
||||
|
||||
def test_new
|
||||
custom_field_classes.each do |klass|
|
||||
get :new, :type => klass.name
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of klass, assigns(:custom_field)
|
||||
assert_select 'form#custom_field_form' do
|
||||
assert_select 'select#custom_field_field_format[name=?]', 'custom_field[field_format]'
|
||||
assert_select 'input[type=hidden][name=type][value=?]', klass.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_issue_custom_field
|
||||
get :new, :type => 'IssueCustomField'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
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=hidden][name=type][value=IssueCustomField]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_default_value_should_be_an_input_for_string_custom_field
|
||||
get :new, :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, :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, :type => 'IssueCustomField', :custom_field => {:field_format => 'bool'}
|
||||
assert_response :success
|
||||
assert_select 'input[name=?][type=checkbox]', 'custom_field[default_value]'
|
||||
end
|
||||
|
||||
def test_default_value_should_not_be_present_for_user_custom_field
|
||||
get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'user'}
|
||||
assert_response :success
|
||||
assert_select '[name=?]', 'custom_field[default_value]', 0
|
||||
end
|
||||
|
||||
def test_new_js
|
||||
get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
|
||||
field = assigns(:custom_field)
|
||||
assert_equal 'list', field.field_format
|
||||
end
|
||||
|
||||
def test_new_with_invalid_custom_field_class_should_render_404
|
||||
get :new, :type => 'UnknownCustomField'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_create_list_custom_field
|
||||
assert_difference 'CustomField.count' do
|
||||
post :create, :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?tab=IssueCustomField'
|
||||
field = IssueCustomField.find_by_name('test_post_new_list')
|
||||
assert_not_nil field
|
||||
assert_equal ["0.1", "0.2"], field.possible_values
|
||||
assert_equal 1, field.trackers.size
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'CustomField.count' do
|
||||
post :create, :type => "IssueCustomField", :custom_field => {:name => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag 'input', :attributes => {:name => 'custom_field[name]', :value => 'Database'}
|
||||
end
|
||||
|
||||
def test_edit_invalid_custom_field_should_render_404
|
||||
get :edit, :id => 99
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :id => 1, :custom_field => {:name => 'New name'}
|
||||
assert_redirected_to '/custom_fields?tab=IssueCustomField'
|
||||
|
||||
field = CustomField.find(1)
|
||||
assert_equal 'New name', field.name
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
put :update, :id => 1, :custom_field => {:name => ''}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
custom_values_count = CustomValue.count(:conditions => {:custom_field_id => 1})
|
||||
assert custom_values_count > 0
|
||||
|
||||
assert_difference 'CustomField.count', -1 do
|
||||
assert_difference 'CustomValue.count', - custom_values_count do
|
||||
delete :destroy, :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
|
|
@ -0,0 +1,186 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :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, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:grouped)
|
||||
|
||||
# Default category selected in the new document form
|
||||
assert_tag :select, :attributes => {:name => 'document[category_id]'},
|
||||
:child => {:tag => 'option', :attributes => {:selected => 'selected'},
|
||||
:content => 'Technical documentation'}
|
||||
|
||||
assert ! DocumentCategory.find(16).active?
|
||||
assert_no_tag :option, :attributes => {:value => '16'},
|
||||
:parent => {:tag => 'select', :attributes => {:id => 'document_category_id'} }
|
||||
end
|
||||
|
||||
def test_index_grouped_by_date
|
||||
get :index, :project_id => 'ecookbook', :sort_by => 'date'
|
||||
assert_response :success
|
||||
assert_tag 'h3', :content => '2007-02-12'
|
||||
end
|
||||
|
||||
def test_index_grouped_by_title
|
||||
get :index, :project_id => 'ecookbook', :sort_by => 'title'
|
||||
assert_response :success
|
||||
assert_tag 'h3', :content => 'T'
|
||||
end
|
||||
|
||||
def test_index_grouped_by_author
|
||||
get :index, :project_id => 'ecookbook', :sort_by => 'author'
|
||||
assert_response :success
|
||||
assert_tag 'h3', :content => '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, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
|
||||
# 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, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
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, :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, :project_id => 'ecookbook', :document => { :title => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
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,
|
||||
: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, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :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, :id => 1, :document => {:title => ''}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Document.count', -1 do
|
||||
delete :destroy, :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, :id => 1,
|
||||
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
|
||||
end
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_equal Document.find(1), attachment.container
|
||||
end
|
||||
end
|
|
@ -0,0 +1,136 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :enumerations, :issues, :users
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
end
|
||||
|
||||
def test_index_should_require_admin
|
||||
@request.session[:user_id] = nil
|
||||
get :index
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new, :type => 'IssuePriority'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of IssuePriority, assigns(:enumeration)
|
||||
assert_tag 'input', :attributes => {:name => 'enumeration[type]', :value => 'IssuePriority'}
|
||||
assert_tag 'input', :attributes => {:name => 'enumeration[name]'}
|
||||
end
|
||||
|
||||
def test_new_with_invalid_type_should_respond_with_404
|
||||
get :new, :type => 'UnknownType'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'IssuePriority.count' do
|
||||
post :create, :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, :enumeration => {:type => 'IssuePriority', :name => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :id => 6
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag 'input', :attributes => {:name => 'enumeration[name]', :value => 'High'}
|
||||
end
|
||||
|
||||
def test_edit_invalid_should_respond_with_404
|
||||
get :edit, :id => 999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
assert_no_difference 'IssuePriority.count' do
|
||||
put :update, :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, :id => 6, :enumeration => {:type => 'IssuePriority', :name => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy_enumeration_not_in_use
|
||||
assert_difference 'IssuePriority.count', -1 do
|
||||
delete :destroy, :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, :id => 4
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'destroy'
|
||||
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, :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, :id => 4, :reassign_to_id => ''
|
||||
end
|
||||
assert_response :success
|
||||
end
|
||||
end
|
|
@ -0,0 +1,109 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :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, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:containers)
|
||||
|
||||
# file attached to the project
|
||||
assert_tag :a, :content => 'project_file.zip',
|
||||
:attributes => { :href => '/attachments/download/8/project_file.zip' }
|
||||
|
||||
# file attached to a project's version
|
||||
assert_tag :a, :content => 'version_file.zip',
|
||||
:attributes => { :href => '/attachments/download/9/version_file.zip' }
|
||||
end
|
||||
|
||||
def test_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
|
||||
assert_tag 'select', :attributes => {:name => 'version_id'}
|
||||
end
|
||||
|
||||
def test_new_without_versions
|
||||
Version.delete_all
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
|
||||
assert_no_tag 'select', :attributes => {:name => 'version_id'}
|
||||
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, :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, :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
|
||||
|
||||
end
|
|
@ -0,0 +1,122 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'gantts/show'
|
||||
assert_not_nil assigns(:gantt)
|
||||
# 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_should_work_without_issue_due_dates
|
||||
Issue.update_all("due_date = NULL")
|
||||
get :show, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'gantts/show'
|
||||
assert_not_nil assigns(:gantt)
|
||||
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, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'gantts/show'
|
||||
assert_not_nil assigns(:gantt)
|
||||
end
|
||||
|
||||
def test_gantt_should_work_cross_project
|
||||
get :show
|
||||
assert_response :success
|
||||
assert_template 'gantts/show'
|
||||
assert_not_nil assigns(:gantt)
|
||||
assert_not_nil assigns(:gantt).query
|
||||
assert_nil assigns(:gantt).project
|
||||
end
|
||||
|
||||
def test_gantt_should_not_disclose_private_projects
|
||||
get :show
|
||||
assert_response :success
|
||||
assert_template 'gantts/show'
|
||||
assert_tag 'a', :content => /eCookbook/
|
||||
# Root private project
|
||||
assert_no_tag 'a', {:content => /OnlineStore/}
|
||||
# Private children of a public project
|
||||
assert_no_tag 'a', :content => /Private child of eCookbook/
|
||||
end
|
||||
|
||||
def test_gantt_should_display_relations
|
||||
IssueRelation.delete_all
|
||||
issue1 = Issue.generate!(:start_date => 1.day.from_now, :due_date => 3.day.from_now)
|
||||
issue2 = Issue.generate!(:start_date => 1.day.from_now, :due_date => 3.day.from_now)
|
||||
IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => 'precedes')
|
||||
|
||||
get :show
|
||||
assert_response :success
|
||||
|
||||
relations = assigns(:gantt).relations
|
||||
assert_kind_of Hash, relations
|
||||
assert relations.present?
|
||||
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, :project_id => 1, :format => 'pdf'
|
||||
assert_response :success
|
||||
assert_equal 'application/pdf', @response.content_type
|
||||
assert @response.body.starts_with?('%PDF')
|
||||
assert_not_nil assigns(:gantt)
|
||||
end
|
||||
|
||||
def test_gantt_should_export_to_pdf_cross_project
|
||||
get :show, :format => 'pdf'
|
||||
assert_response :success
|
||||
assert_equal 'application/pdf', @response.content_type
|
||||
assert @response.body.starts_with?('%PDF')
|
||||
assert_not_nil assigns(:gantt)
|
||||
end
|
||||
|
||||
if Object.const_defined?(:Magick)
|
||||
def test_gantt_should_export_to_png
|
||||
get :show, :project_id => 1, :format => 'png'
|
||||
assert_response :success
|
||||
assert_equal 'image/png', @response.content_type
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,202 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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_template 'index'
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :id => 10
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
end
|
||||
|
||||
def test_show_invalid_should_return_404
|
||||
get :show, :id => 99
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_select 'input[name=?]', 'group[name]'
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'Group.count' do
|
||||
post :create, :group => {:name => 'New group'}
|
||||
end
|
||||
assert_redirected_to '/groups'
|
||||
group = Group.first(:order => 'id DESC')
|
||||
assert_equal 'New group', group.name
|
||||
assert_equal [], group.users
|
||||
end
|
||||
|
||||
def test_create_and_continue
|
||||
assert_difference 'Group.count' do
|
||||
post :create, :group => {:name => 'New group'}, :continue => 'Create and continue'
|
||||
end
|
||||
assert_redirected_to '/groups/new'
|
||||
group = Group.first(:order => 'id DESC')
|
||||
assert_equal 'New group', group.name
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
assert_no_difference 'Group.count' do
|
||||
post :create, :group => {:name => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_edit
|
||||
get :edit, :id => 10
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
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, :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, :id => 10, :group => {:name => ''}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'Group.count', -1 do
|
||||
post :destroy, :id => 10
|
||||
end
|
||||
assert_redirected_to '/groups'
|
||||
end
|
||||
|
||||
def test_add_users
|
||||
assert_difference 'Group.find(10).users.count', 2 do
|
||||
post :add_users, :id => 10, :user_ids => ['2', '3']
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_add_users
|
||||
assert_difference 'Group.find(10).users.count', 2 do
|
||||
xhr :post, :add_users, :id => 10, :user_ids => ['2', '3']
|
||||
assert_response :success
|
||||
assert_template 'add_users'
|
||||
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, :id => 10, :user_id => '8'
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_remove_user
|
||||
assert_difference 'Group.find(10).users.count', -1 do
|
||||
xhr :delete, :remove_user, :id => 10, :user_id => '8'
|
||||
assert_response :success
|
||||
assert_template 'remove_user'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_membership
|
||||
assert_difference 'Group.find(10).members.count' do
|
||||
post :edit_membership, :id => 10, :membership => { :project_id => 2, :role_ids => ['1', '2']}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_new_membership
|
||||
assert_difference 'Group.find(10).members.count' do
|
||||
xhr :post, :edit_membership, :id => 10, :membership => { :project_id => 2, :role_ids => ['1', '2']}
|
||||
assert_response :success
|
||||
assert_template 'edit_membership'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /OnlineStore/, response.body
|
||||
end
|
||||
|
||||
def test_xhr_new_membership_with_failure
|
||||
assert_no_difference 'Group.find(10).members.count' do
|
||||
xhr :post, :edit_membership, :id => 10, :membership => { :project_id => 999, :role_ids => ['1', '2']}
|
||||
assert_response :success
|
||||
assert_template 'edit_membership'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /alert/, response.body, "Alert message not sent"
|
||||
end
|
||||
|
||||
def test_edit_membership
|
||||
assert_no_difference 'Group.find(10).members.count' do
|
||||
post :edit_membership, :id => 10, :membership_id => 6, :membership => { :role_ids => ['1', '3']}
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_edit_membership
|
||||
assert_no_difference 'Group.find(10).members.count' do
|
||||
xhr :post, :edit_membership, :id => 10, :membership_id => 6, :membership => { :role_ids => ['1', '3']}
|
||||
assert_response :success
|
||||
assert_template 'edit_membership'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_membership
|
||||
assert_difference 'Group.find(10).members.count', -1 do
|
||||
post :destroy_membership, :id => 10, :membership_id => 6
|
||||
end
|
||||
end
|
||||
|
||||
def test_xhr_destroy_membership
|
||||
assert_difference 'Group.find(10).members.count', -1 do
|
||||
xhr :post, :destroy_membership, :id => 10, :membership_id => 6
|
||||
assert_response :success
|
||||
assert_template 'destroy_membership'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
end
|
||||
|
||||
def test_autocomplete_for_user
|
||||
get :autocomplete_for_user, :id => 10, :q => 'smi', :format => 'js'
|
||||
assert_response :success
|
||||
assert_include 'John Smith', response.body
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,263 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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,
|
||||
: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_template 'edit'
|
||||
|
||||
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,
|
||||
: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
|
||||
assert_template 'edit'
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_tag 'input', :attributes => {:name => 'attachments[p0][token]', :value => attachment.token}
|
||||
assert_tag 'input', :attributes => {:name => 'attachments[p0][filename]', :value => '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, :id => issue.id,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => '',
|
||||
:lock_version => (issue.lock_version - 1)
|
||||
}
|
||||
|
||||
assert_tag 'div', :attributes => {:class => 'conflict'}
|
||||
assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'overwrite'}
|
||||
assert_no_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'add_notes'}
|
||||
assert_tag 'input', :attributes => {:name => 'conflict_resolution', :value => 'cancel'}
|
||||
end
|
||||
|
||||
def test_update_stale_issue_should_show_conflicting_journals
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
put :update, :id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => '',
|
||||
:lock_version => 2
|
||||
},
|
||||
:last_journal_id => 1
|
||||
|
||||
assert_not_nil assigns(:conflict_journals)
|
||||
assert_equal 1, assigns(:conflict_journals).size
|
||||
assert_equal 2, assigns(:conflict_journals).first.id
|
||||
assert_tag 'div', :attributes => {:class => 'conflict'},
|
||||
:descendant => {:content => /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, :id => 1,
|
||||
:issue => {
|
||||
:fixed_version_id => 4,
|
||||
:notes => '',
|
||||
:lock_version => 2
|
||||
},
|
||||
:last_journal_id => ''
|
||||
|
||||
assert_not_nil assigns(:conflict_journals)
|
||||
assert_equal 2, assigns(:conflict_journals).size
|
||||
assert_tag 'div', :attributes => {:class => 'conflict'},
|
||||
:descendant => {:content => /Some notes with Redmine links/}
|
||||
assert_tag 'div', :attributes => {:class => 'conflict'},
|
||||
:descendant => {:content => /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, :id => 1, :issue => {:fixed_version_id => 4, :lock_version => 2}, :last_journal_id => ''
|
||||
assert_include journal, assigns(:conflict_journals)
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
put :update, :id => 1, :issue => {:fixed_version_id => 4, :lock_version => 2}, :last_journal_id => ''
|
||||
assert_not_include journal, assigns(:conflict_journals)
|
||||
end
|
||||
|
||||
def test_update_stale_issue_with_overwrite_conflict_resolution_should_update
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_difference 'Journal.count' do
|
||||
put :update, :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.first(:order => 'id DESC')
|
||||
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, :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.first(:order => 'id DESC')
|
||||
assert_equal 'add_notes_conflict_resolution', journal.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, :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,
|
||||
: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.5'
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_should_rescue_invalid_sql_query
|
||||
IssueQuery.any_instance.stubs(:statement).returns("INVALID STATEMENT")
|
||||
|
||||
get :index
|
||||
assert_response 500
|
||||
assert_tag 'p', :content => /An error occurred/
|
||||
assert_nil session[:query]
|
||||
assert_nil session[:issues_index_sort]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,147 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :issues, :journals, :journal_details, :enabled_modules,
|
||||
:trackers, :issue_statuses, :enumerations, :custom_fields, :custom_values, :custom_fields_projects
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :project_id => 1
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:journals)
|
||||
assert_equal 'application/atom+xml', @response.content_type
|
||||
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, :project_id => 1
|
||||
assert_response :success
|
||||
assert_include journal, assigns(:journals)
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :index, :project_id => 1
|
||||
assert_response :success
|
||||
assert_not_include journal, assigns(:journals)
|
||||
end
|
||||
|
||||
def test_diff
|
||||
get :diff, :id => 3, :detail_id => 4
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
|
||||
assert_tag 'span',
|
||||
:attributes => {:class => 'diff_out'},
|
||||
:content => /removed/
|
||||
assert_tag 'span',
|
||||
:attributes => {:class => 'diff_in'},
|
||||
:content => /added/
|
||||
end
|
||||
|
||||
def test_reply_to_issue
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :new, :id => 6
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
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
|
||||
xhr :get, :new, :id => 6
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_reply_to_note
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :new, :id => 6, :journal_id => 4
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
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
|
||||
|
||||
xhr :get, :new, :id => 2, :journal_id => journal.id
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include '> Privates notes', response.body
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
xhr :get, :new, :id => 2, :journal_id => journal.id
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_edit_xhr
|
||||
@request.session[:user_id] = 1
|
||||
xhr :get, :edit, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
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
|
||||
|
||||
xhr :get, :edit, :id => journal.id
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_include 'textarea', response.body
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
xhr :get, :edit, :id => journal.id
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update_xhr
|
||||
@request.session[:user_id] = 1
|
||||
xhr :post, :edit, :id => 2, :notes => 'Updated notes'
|
||||
assert_response :success
|
||||
assert_template 'update'
|
||||
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_empty_notes_should_delete_the_journal
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Journal.count', -1 do
|
||||
xhr :post, :edit, :id => 2, :notes => ''
|
||||
assert_response :success
|
||||
assert_template 'update'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_nil Journal.find_by_id(2)
|
||||
assert_include 'change-2', response.body
|
||||
end
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :users, :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, :key => 'secret', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
end
|
||||
assert_response 201
|
||||
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, :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, :key => 'secret', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
end
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_should_not_allow_with_wrong_key
|
||||
# Disable API
|
||||
Setting.mail_handler_api_enabled = 1
|
||||
Setting.mail_handler_api_key = 'secret'
|
||||
|
||||
assert_no_difference 'Issue.count' do
|
||||
post :index, :key => 'wrong', :email => IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
|
||||
end
|
||||
assert_response 403
|
||||
end
|
||||
end
|
|
@ -0,0 +1,111 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :members, :member_roles, :roles, :users
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'Member.count' do
|
||||
post :create, :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, :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_xhr_create
|
||||
assert_difference 'Member.count', 3 do
|
||||
xhr :post, :create, :project_id => 1, :membership => {:role_ids => [1], :user_ids => [7, 8, 9]}
|
||||
assert_response :success
|
||||
assert_template 'create'
|
||||
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
|
||||
xhr :post, :create, :project_id => 1, :membership => {:role_ids => [], :user_ids => [7, 8, 9]}
|
||||
assert_response :success
|
||||
assert_template 'create'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
assert_match /alert/, response.body, "Alert message not sent"
|
||||
end
|
||||
|
||||
def test_edit
|
||||
assert_no_difference 'Member.count' do
|
||||
put :update, :id => 2, :membership => {:role_ids => [1], :user_id => 3}
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/members'
|
||||
end
|
||||
|
||||
def test_xhr_edit
|
||||
assert_no_difference 'Member.count' do
|
||||
xhr :put, :update, :id => 2, :membership => {:role_ids => [1], :user_id => 3}
|
||||
assert_response :success
|
||||
assert_template 'update'
|
||||
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, :id => 2
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/settings/members'
|
||||
assert !User.find(3).member_of?(Project.find(1))
|
||||
end
|
||||
|
||||
def test_xhr_destroy
|
||||
assert_difference 'Member.count', -1 do
|
||||
xhr :delete, :destroy, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'destroy'
|
||||
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, :project_id => 1, :q => 'mis', :format => 'js'
|
||||
assert_response :success
|
||||
assert_include 'User Misc', response.body
|
||||
end
|
||||
end
|
|
@ -0,0 +1,217 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :board_id => 1, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:board)
|
||||
assert_not_nil assigns(:project)
|
||||
assert_not_nil assigns(:topic)
|
||||
end
|
||||
|
||||
def test_show_should_contain_reply_field_tags_for_quoting
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :board_id => 1, :id => 1
|
||||
assert_response :success
|
||||
|
||||
# tags required by MessagesController#quote
|
||||
assert_tag 'input', :attributes => {:id => 'message_subject'}
|
||||
assert_tag 'textarea', :attributes => {:id => 'message_content'}
|
||||
assert_tag 'div', :attributes => {:id => '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
|
||||
get :show, :board_id => 1, :id => 1, :r => message.children.last(:order => 'id').id
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
replies = assigns(:replies)
|
||||
assert_not_nil replies
|
||||
assert !replies.include?(message.children.first(:order => 'id'))
|
||||
assert replies.include?(message.children.last(:order => 'id'))
|
||||
end
|
||||
|
||||
def test_show_with_reply_permission
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :board_id => 1, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_tag :div, :attributes => { :id => 'reply' },
|
||||
:descendant => { :tag => 'textarea', :attributes => { :id => 'message_content' } }
|
||||
end
|
||||
|
||||
def test_show_message_not_found
|
||||
get :show, :board_id => 1, :id => 99999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_show_message_from_invalid_board_should_respond_with_404
|
||||
get :show, :board_id => 999, :id => 1
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :board_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_get_new_with_invalid_board
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :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, :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, :board_id => 1, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_post_edit
|
||||
@request.session[:user_id] = 2
|
||||
post :edit, :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, :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, :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, :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, :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, :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
|
||||
xhr :get, :quote, :board_id => 1, :id => 3
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
assert_template 'quote'
|
||||
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,
|
||||
:board_id => 1,
|
||||
:message => {:subject => "", :content => "Previewed text"}
|
||||
assert_response :success
|
||||
assert_template 'common/_preview'
|
||||
end
|
||||
|
||||
def test_preview_edit
|
||||
@request.session[:user_id] = 2
|
||||
post :preview,
|
||||
:id => 4,
|
||||
:board_id => 1,
|
||||
:message => {:subject => "", :content => "Previewed text"}
|
||||
assert_response :success
|
||||
assert_template 'common/_preview'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,248 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :users, :user_preferences, :roles, :projects, :members, :member_roles,
|
||||
:issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources
|
||||
|
||||
def setup
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'page'
|
||||
end
|
||||
|
||||
def test_page
|
||||
get :page
|
||||
assert_response :success
|
||||
assert_template 'page'
|
||||
end
|
||||
|
||||
def test_page_with_timelog_block
|
||||
preferences = User.find(2).pref
|
||||
preferences[:my_page_layout] = {'top' => ['timelog']}
|
||||
preferences.save!
|
||||
TimeEntry.create!(:user => User.find(2), :spent_on => Date.yesterday, :issue_id => 1, :hours => 2.5, :activity_id => 10)
|
||||
|
||||
get :page
|
||||
assert_response :success
|
||||
assert_select 'tr.time-entry' do
|
||||
assert_select 'td.subject a[href=/issues/1]'
|
||||
assert_select 'td.hours', :text => '2.50'
|
||||
end
|
||||
end
|
||||
|
||||
def test_page_with_all_blocks
|
||||
blocks = MyController::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_template 'account'
|
||||
assert_equal User.find(2), assigns(:user)
|
||||
|
||||
assert_tag :input, :attributes => { :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_template 'account'
|
||||
assert_equal User.find(2), assigns(:user)
|
||||
|
||||
assert_no_tag :input, :attributes => { :name => 'user[custom_field_values][4]'}
|
||||
end
|
||||
|
||||
def test_update_account
|
||||
post :account,
|
||||
: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 user, assigns(:user)
|
||||
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_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_template 'destroy'
|
||||
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
|
||||
assert_template 'destroy'
|
||||
end
|
||||
|
||||
def test_post_destroy_without_confirmation_should_destroy_account
|
||||
assert_difference 'User.count', -1 do
|
||||
post :destroy, :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, :confirm => '1'
|
||||
end
|
||||
assert_redirected_to '/my/account'
|
||||
end
|
||||
|
||||
def test_change_password
|
||||
get :password
|
||||
assert_response :success
|
||||
assert_template 'password'
|
||||
|
||||
# non matching password confirmation
|
||||
post :password, :password => 'jsmith',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret1234'
|
||||
assert_response :success
|
||||
assert_template 'password'
|
||||
assert_error_tag :content => /Password doesn't match confirmation/
|
||||
|
||||
# wrong password
|
||||
post :password, :password => 'wrongpassword',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret123'
|
||||
assert_response :success
|
||||
assert_template 'password'
|
||||
assert_equal 'Wrong password', flash[:error]
|
||||
|
||||
# good password
|
||||
post :password, :password => 'jsmith',
|
||||
:new_password => 'secret123',
|
||||
:new_password_confirmation => 'secret123'
|
||||
assert_redirected_to '/my/account'
|
||||
assert User.try_to_login('jsmith', 'secret123')
|
||||
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_page_layout
|
||||
get :page_layout
|
||||
assert_response :success
|
||||
assert_template 'page_layout'
|
||||
end
|
||||
|
||||
def test_add_block
|
||||
post :add_block, :block => 'issuesreportedbyme'
|
||||
assert_redirected_to '/my/page_layout'
|
||||
assert User.find(2).pref[:my_page_layout]['top'].include?('issuesreportedbyme')
|
||||
end
|
||||
|
||||
def test_add_invalid_block_should_redirect
|
||||
post :add_block, :block => 'invalid'
|
||||
assert_redirected_to '/my/page_layout'
|
||||
end
|
||||
|
||||
def test_remove_block
|
||||
post :remove_block, :block => 'issuesassignedtome'
|
||||
assert_redirected_to '/my/page_layout'
|
||||
assert !User.find(2).pref[:my_page_layout].values.flatten.include?('issuesassignedtome')
|
||||
end
|
||||
|
||||
def test_order_blocks
|
||||
xhr :post, :order_blocks, :group => 'left', 'blocks' => ['documents', 'calendar', 'latestnews']
|
||||
assert_response :success
|
||||
assert_equal ['documents', 'calendar', 'latestnews'], User.find(2).pref[:my_page_layout]['left']
|
||||
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
|
||||
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_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
|
|
@ -0,0 +1,165 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :news, :comments
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:newss)
|
||||
assert_nil assigns(:project)
|
||||
end
|
||||
|
||||
def test_index_with_project
|
||||
get :index, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:newss)
|
||||
end
|
||||
|
||||
def test_index_with_invalid_project_should_respond_with_404
|
||||
get :index, :project_id => 999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_show
|
||||
get :show, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_tag :tag => 'h2', :content => /eCookbook first release/
|
||||
end
|
||||
|
||||
def test_show_should_show_attachments
|
||||
attachment = Attachment.first
|
||||
attachment.container = News.find(1)
|
||||
attachment.save!
|
||||
|
||||
get :show, :id => 1
|
||||
assert_response :success
|
||||
assert_tag 'a', :content => attachment.filename
|
||||
end
|
||||
|
||||
def test_show_not_found
|
||||
get :show, :id => 999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_new
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_post_create
|
||||
ActionMailer::Base.deliveries.clear
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
with_settings :notified_events => %w(news_added) do
|
||||
post :create, :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, :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.first(:order => 'id DESC')
|
||||
news = News.first(:order => 'id DESC')
|
||||
assert_equal news, attachment.container
|
||||
end
|
||||
|
||||
def test_post_create_with_validation_failure
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :project_id => 1, :news => { :title => '',
|
||||
:description => 'This is the description',
|
||||
:summary => '' }
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_not_nil assigns(:news)
|
||||
assert assigns(:news).new_record?
|
||||
assert_error_tag :content => /title can't be blank/i
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_put_update
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :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, :id => 1,
|
||||
:news => { :description => 'This is the description' },
|
||||
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
|
||||
end
|
||||
end
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_equal News.find(1), attachment.container
|
||||
end
|
||||
|
||||
def test_update_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
put :update, :id => 1, :news => { :description => '' }
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_error_tag :content => /description can't be blank/i
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :id => 1
|
||||
assert_redirected_to '/projects/ecookbook/news'
|
||||
assert_nil News.find_by_id(1)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,81 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :project_id => '1', :issue => {:description => 'Foo'}
|
||||
assert_response :success
|
||||
assert_template 'preview'
|
||||
assert_not_nil assigns(:description)
|
||||
end
|
||||
|
||||
def test_preview_issue_notes
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :project_id => '1', :id => 1,
|
||||
:issue => {:description => Issue.find(1).description, :notes => 'Foo'}
|
||||
assert_response :success
|
||||
assert_template 'preview'
|
||||
assert_not_nil assigns(:notes)
|
||||
end
|
||||
|
||||
def test_preview_journal_notes_for_update
|
||||
@request.session[:user_id] = 2
|
||||
post :issue, :project_id => '1', :id => 1, :notes => 'Foo'
|
||||
assert_response :success
|
||||
assert_template 'preview'
|
||||
assert_not_nil assigns(:notes)
|
||||
assert_tag :p, :content => 'Foo'
|
||||
end
|
||||
|
||||
def test_preview_new_news
|
||||
get :news, :project_id => 1,
|
||||
:news => {:title => '',
|
||||
:description => 'News description',
|
||||
:summary => ''}
|
||||
assert_response :success
|
||||
assert_template 'common/_preview'
|
||||
assert_tag :tag => 'fieldset', :attributes => { :class => 'preview' },
|
||||
:content => /News description/
|
||||
end
|
||||
|
||||
def test_existing_new_news
|
||||
get :news, :project_id => 1, :id => 2,
|
||||
:news => {:title => '',
|
||||
:description => 'News description',
|
||||
:summary => ''}
|
||||
assert_response :success
|
||||
assert_template 'common/_preview'
|
||||
assert_equal News.find(2), assigns(:previewed)
|
||||
assert_not_nil assigns(:attachments)
|
||||
|
||||
assert_tag :tag => 'fieldset', :attributes => { :class => 'preview' },
|
||||
:content => /News description/
|
||||
end
|
||||
end
|
|
@ -0,0 +1,217 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :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_equal 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, :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.find_all_by_activity_id_and_project_id(9, 1).size
|
||||
|
||||
@request.session[:user_id] = 2 # manager
|
||||
put :update, :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.find_all_by_activity_id_and_project_id(9, 1).size, "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.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "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})
|
||||
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.find_all_by_activity_id_and_project_id(9, 1).size
|
||||
assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
|
||||
|
||||
@request.session[:user_id] = 2 # manager
|
||||
put :update, :project_id => 1, :enumerations => {
|
||||
"9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
|
||||
"10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
|
||||
}
|
||||
assert_response :redirect
|
||||
|
||||
# TimeEntries shouldn't have been reassigned on the failed record
|
||||
assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
|
||||
# TimeEntries shouldn't have been reassigned on the saved record either
|
||||
assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "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, :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.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
|
||||
assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
|
||||
|
||||
delete :destroy, :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.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity"
|
||||
assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,290 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :members, :member_roles, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries, :enabled_modules
|
||||
|
||||
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, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query[is_public]',
|
||||
:checked => nil }
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query_is_for_all',
|
||||
:checked => nil,
|
||||
:disabled => nil }
|
||||
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_template 'new'
|
||||
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query[is_public]' }
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query_is_for_all',
|
||||
:checked => 'checked',
|
||||
:disabled => nil }
|
||||
end
|
||||
|
||||
def test_new_on_invalid_project
|
||||
@request.session[:user_id] = 2
|
||||
get :new, :project_id => 'invalid'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_create_project_public_query
|
||||
@request.session[:user_id] = 2
|
||||
post :create,
|
||||
: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", "is_public" => "1"}
|
||||
|
||||
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,
|
||||
: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", "is_public" => "1"}
|
||||
|
||||
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_global_private_query_with_custom_columns
|
||||
@request.session[:user_id] = 3
|
||||
post :create,
|
||||
: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", "is_public" => "1"},
|
||||
: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,
|
||||
: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.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,
|
||||
:default_columns => '1',
|
||||
:operators => {"status_id" => "o"},
|
||||
:values => {"status_id" => ["1"]},
|
||||
:query => {:name => "test_new_with_sort",
|
||||
:is_public => "1",
|
||||
: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, :project_id => 'ecookbook', :query => {:name => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_select 'input[name=?]', 'query[name]'
|
||||
end
|
||||
|
||||
def test_edit_global_public_query
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :id => 4
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query[is_public]',
|
||||
:checked => 'checked' }
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query_is_for_all',
|
||||
:checked => 'checked',
|
||||
:disabled => 'disabled' }
|
||||
end
|
||||
|
||||
def test_edit_global_private_query
|
||||
@request.session[:user_id] = 3
|
||||
get :edit, :id => 3
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query[is_public]' }
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query_is_for_all',
|
||||
:checked => 'checked',
|
||||
:disabled => 'disabled' }
|
||||
end
|
||||
|
||||
def test_edit_project_private_query
|
||||
@request.session[:user_id] = 3
|
||||
get :edit, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query[is_public]' }
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query_is_for_all',
|
||||
:checked => nil,
|
||||
:disabled => nil }
|
||||
end
|
||||
|
||||
def test_edit_project_public_query
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query[is_public]',
|
||||
:checked => 'checked'
|
||||
}
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'query_is_for_all',
|
||||
:checked => nil,
|
||||
:disabled => 'disabled' }
|
||||
end
|
||||
|
||||
def test_edit_sort_criteria
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :id => 5
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag :tag => 'select', :attributes => { :name => 'query[sort_criteria][0][]' },
|
||||
:child => { :tag => 'option', :attributes => { :value => 'priority',
|
||||
:selected => 'selected' } }
|
||||
assert_tag :tag => 'select', :attributes => { :name => 'query[sort_criteria][0][]' },
|
||||
:child => { :tag => 'option', :attributes => { :value => 'desc',
|
||||
:selected => 'selected' } }
|
||||
end
|
||||
|
||||
def test_edit_invalid_query
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :id => 99
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_udpate_global_private_query
|
||||
@request.session[:user_id] = 3
|
||||
put :update,
|
||||
: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", "is_public" => "1"}
|
||||
|
||||
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,
|
||||
: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", "is_public" => "1"}
|
||||
|
||||
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, :id => 4, :query => {:name => ''}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :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, :subject => 'foo/bar'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_include 'addFilter("subject", "=", ["foo\/bar"]);', response.body
|
||||
end
|
||||
end
|
|
@ -0,0 +1,67 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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, :id => 1
|
||||
|
||||
assert_response :success
|
||||
assert_template 'issue_report'
|
||||
|
||||
[:issues_by_tracker, :issues_by_version, :issues_by_category, :issues_by_assigned_to,
|
||||
:issues_by_author, :issues_by_subproject, :issues_by_priority].each do |ivar|
|
||||
assert_not_nil assigns(ivar)
|
||||
end
|
||||
|
||||
assert_equal IssuePriority.all.reverse, assigns(:priorities)
|
||||
end
|
||||
|
||||
def test_get_issue_report_details
|
||||
%w(tracker version priority category assigned_to author subproject).each do |detail|
|
||||
get :issue_report_details, :id => 1, :detail => detail
|
||||
|
||||
assert_response :success
|
||||
assert_template 'issue_report_details'
|
||||
assert_not_nil assigns(:field)
|
||||
assert_not_nil assigns(:rows)
|
||||
assert_not_nil assigns(:data)
|
||||
assert_not_nil assigns(:report_title)
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_issue_report_details_by_priority
|
||||
get :issue_report_details, :id => 1, :detail => 'priority'
|
||||
assert_equal IssuePriority.all.reverse, assigns(:rows)
|
||||
end
|
||||
|
||||
def test_get_issue_report_details_with_an_invalid_detail
|
||||
get :issue_report_details, :id => 1, :detail => 'invalid'
|
||||
|
||||
assert_redirected_to '/projects/ecookbook/issues/report'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,198 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :roles, :members, :member_roles,
|
||||
:repositories, :enabled_modules
|
||||
|
||||
REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository/trunk').to_s
|
||||
PRJ_ID = 3
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@project = Project.find(PRJ_ID)
|
||||
@repository = Repository::Bazaar.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, :project_id => 'subproject1', :repository_scm => 'Bazaar'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Bazaar, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
get :show, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 2, assigns(:entries).size
|
||||
assert assigns(:entries).detect {|e| e.name == 'directory' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'doc-mkdir.txt' && e.kind == 'file'}
|
||||
end
|
||||
|
||||
def test_browse_directory
|
||||
get :show, :id => PRJ_ID, :path => repository_path_hash(['directory'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['doc-ls.txt', 'document.txt', 'edit.png'], assigns(:entries).collect(&:name)
|
||||
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||
assert_not_nil entry
|
||||
assert_equal 'file', entry.kind
|
||||
assert_equal 'directory/edit.png', entry.path
|
||||
end
|
||||
|
||||
def test_browse_at_given_revision
|
||||
get :show, :id => PRJ_ID, :path => repository_path_hash([])[:param],
|
||||
:rev => 3
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['directory', 'doc-deleted.txt', 'doc-ls.txt', 'doc-mkdir.txt'],
|
||||
assigns(:entries).collect(&:name)
|
||||
end
|
||||
|
||||
def test_changes
|
||||
get :changes, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['doc-mkdir.txt'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'changes'
|
||||
assert_tag :tag => 'h2', :content => 'doc-mkdir.txt'
|
||||
end
|
||||
|
||||
def test_entry_show
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['directory', 'doc-ls.txt'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
# Line 19
|
||||
assert_tag :tag => 'th',
|
||||
:content => /29/,
|
||||
:attributes => { :class => /line-num/ },
|
||||
:sibling => { :tag => 'td', :content => /Show help message/ }
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
get :entry, :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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['directory'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entry)
|
||||
assert_equal 'directory', assigns(:entry).name
|
||||
end
|
||||
|
||||
def test_diff
|
||||
# Full diff of changeset 3
|
||||
['inline', 'sbs'].each do |dt|
|
||||
get :diff, :id => PRJ_ID, :rev => 3, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
# Line 11 removed
|
||||
assert_tag :tag => 'th',
|
||||
:content => '11',
|
||||
:sibling => { :tag => 'td',
|
||||
:attributes => { :class => /diff_out/ },
|
||||
:content => /Display more information/ }
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['doc-mkdir.txt'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
assert_tag :tag => 'th', :content => '2',
|
||||
:sibling => {
|
||||
:tag => 'td',
|
||||
:child => {
|
||||
:tag => 'a',
|
||||
:content => '3'
|
||||
}
|
||||
}
|
||||
assert_tag :tag => 'th', :content => '2',
|
||||
:sibling => { :tag => 'td', :content => /jsmith/ }
|
||||
assert_tag :tag => 'th', :content => '2',
|
||||
:sibling => {
|
||||
:tag => 'td',
|
||||
:child => {
|
||||
:tag => 'a',
|
||||
:content => '3'
|
||||
}
|
||||
}
|
||||
assert_tag :tag => 'th', :content => '2',
|
||||
:sibling => { :tag => 'td', :content => /Main purpose/ }
|
||||
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, :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, :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
|
|
@ -0,0 +1,264 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :users, :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, :project_id => 'subproject1'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Subversion, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
assert_tag 'input', :attributes => {:name => 'repository[url]', :disabled => nil}
|
||||
end
|
||||
|
||||
def test_new_should_propose_enabled_scm_only
|
||||
@request.session[:user_id] = 1
|
||||
with_settings :enabled_scm => ['Mercurial', 'Git'] do
|
||||
get :new, :project_id => 'subproject1'
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Mercurial, assigns(:repository)
|
||||
assert_tag 'select', :attributes => {:name => 'repository_scm'},
|
||||
:children => {:count => 3}
|
||||
assert_tag 'select', :attributes => {:name => 'repository_scm'},
|
||||
:child => {:tag => 'option', :attributes => {:value => 'Mercurial', :selected => 'selected'}}
|
||||
assert_tag 'select', :attributes => {:name => 'repository_scm'},
|
||||
:child => {:tag => 'option', :attributes => {:value => 'Git', :selected => nil}}
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Repository.count' do
|
||||
post :create, :project_id => 'subproject1',
|
||||
:repository_scm => 'Subversion',
|
||||
:repository => {:url => 'file:///test', :is_default => '1', :identifier => ''}
|
||||
end
|
||||
assert_response 302
|
||||
repository = Repository.first(:order => 'id DESC')
|
||||
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, :project_id => 'subproject1',
|
||||
:repository_scm => 'Subversion',
|
||||
:repository => {:url => 'invalid'}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Subversion, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
end
|
||||
|
||||
def test_edit
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :id => 11
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_equal Repository.find(11), assigns(:repository)
|
||||
assert_tag 'input', :attributes => {:name => 'repository[url]', :value => 'svn://localhost/test', :disabled => 'disabled'}
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 1
|
||||
put :update, :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, :id => 11, :repository => {:password => 'x'*260}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_equal Repository.find(11), assigns(:repository)
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :id => 11
|
||||
end
|
||||
assert_response 302
|
||||
assert_nil Repository.find_by_id(11)
|
||||
end
|
||||
|
||||
def test_revisions
|
||||
get :revisions, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'revisions'
|
||||
assert_equal Repository.find(10), assigns(:repository)
|
||||
assert_not_nil assigns(:changesets)
|
||||
end
|
||||
|
||||
def test_revisions_for_other_repository
|
||||
repository = Repository::Subversion.create!(:project_id => 1, :identifier => 'foo', :url => 'file:///foo')
|
||||
|
||||
get :revisions, :id => 1, :repository_id => 'foo'
|
||||
assert_response :success
|
||||
assert_template 'revisions'
|
||||
assert_equal repository, assigns(:repository)
|
||||
assert_not_nil assigns(:changesets)
|
||||
end
|
||||
|
||||
def test_revisions_for_invalid_repository
|
||||
get :revisions, :id => 1, :repository_id => 'foo'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_revision
|
||||
get :revision, :id => 1, :rev => 1
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:changeset)
|
||||
assert_equal "1", assigns(:changeset).revision
|
||||
end
|
||||
|
||||
def test_revision_should_not_change_the_project_menu_link
|
||||
get :revision, :id => 1, :rev => 1
|
||||
assert_response :success
|
||||
|
||||
assert_tag 'a', :attributes => {:href => '/projects/ecookbook/repository', :class => /repository/},
|
||||
:ancestor => {:attributes => {:id => 'main-menu'}}
|
||||
end
|
||||
|
||||
def test_revision_with_before_nil_and_afer_normal
|
||||
get :revision, {:id => 1, :rev => 1}
|
||||
assert_response :success
|
||||
assert_template 'revision'
|
||||
assert_no_tag :tag => "div", :attributes => { :class => "contextual" },
|
||||
:child => { :tag => "a", :attributes => { :href => '/projects/ecookbook/repository/revisions/0'}
|
||||
}
|
||||
assert_tag :tag => "div", :attributes => { :class => "contextual" },
|
||||
:child => { :tag => "a", :attributes => { :href => '/projects/ecookbook/repository/revisions/2'}
|
||||
}
|
||||
end
|
||||
|
||||
def test_add_related_issue
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Changeset.find(103).issues.size' do
|
||||
xhr :post, :add_related_issue, :id => 1, :rev => 4, :issue_id => 2, :format => 'js'
|
||||
assert_response :success
|
||||
assert_template 'add_related_issue'
|
||||
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_with_invalid_issue_id
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Changeset.find(103).issues.size' do
|
||||
xhr :post, :add_related_issue, :id => 1, :rev => 4, :issue_id => 9999, :format => 'js'
|
||||
assert_response :success
|
||||
assert_template 'add_related_issue'
|
||||
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
|
||||
xhr :delete, :remove_related_issue, :id => 1, :rev => 4, :issue_id => 2, :format => 'js'
|
||||
assert_response :success
|
||||
assert_template 'remove_related_issue'
|
||||
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, :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, :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, :id => 10
|
||||
assert_response :success
|
||||
assert_template 'committers'
|
||||
|
||||
assert_tag :td, :content => 'dlopper',
|
||||
:sibling => { :tag => 'td',
|
||||
:child => { :tag => 'select', :attributes => { :name => %r{^committers\[\d+\]\[\]$} },
|
||||
:child => { :tag => 'option', :content => 'Dave Lopper',
|
||||
:attributes => { :value => '3', :selected => 'selected' }}}}
|
||||
assert_tag :td, :content => 'foo',
|
||||
:sibling => { :tag => 'td',
|
||||
:child => { :tag => 'select', :attributes => { :name => %r{^committers\[\d+\]\[\]$} }}}
|
||||
assert_no_tag :td, :content => 'foo',
|
||||
:sibling => { :tag => 'td',
|
||||
:descendant => { :tag => 'option', :attributes => { :selected => 'selected' }}}
|
||||
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.count(:conditions => 'user_id = 3')" do
|
||||
post :committers, :id => 10, :committers => { '0' => ['foo', '2'], '1' => ['dlopper', '3']}
|
||||
assert_response 302
|
||||
assert_equal User.find(2), c.reload.user
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,274 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :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, :project_id => 'subproject1', :repository_scm => 'Cvs'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Cvs, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
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, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 3, assigns(:entries).size
|
||||
|
||||
entry = assigns(:entries).detect {|e| e.name == 'images'}
|
||||
assert_equal 'dir', entry.kind
|
||||
|
||||
entry = assigns(:entries).detect {|e| e.name == 'README'}
|
||||
assert_equal 'file', entry.kind
|
||||
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['add.png', 'delete.png', 'edit.png'], assigns(:entries).collect(&:name)
|
||||
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||
assert_not_nil entry
|
||||
assert_equal 'file', entry.kind
|
||||
assert_equal 'images/edit.png', entry.path
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
|
||||
:rev => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
|
||||
end
|
||||
|
||||
def test_entry
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
assert_no_tag :tag => 'td',
|
||||
:attributes => { :class => /line-code/},
|
||||
:content => /before_filter/
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:rev => 2
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
# this line was removed in r3
|
||||
assert_tag :tag => 'td',
|
||||
:attributes => { :class => /line-code/},
|
||||
:content => /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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'zzz.c'])[:param]
|
||||
assert_tag :tag => 'p',
|
||||
:attributes => { :id => /errorExplanation/ },
|
||||
:content => /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, :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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entry)
|
||||
assert_equal 'sources', assigns(:entry).name
|
||||
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, :id => PRJ_ID, :rev => 3, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_out' },
|
||||
:content => /before_filter :require_login/
|
||||
assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_in' },
|
||||
:content => /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, :id => PRJ_ID, :rev => 1, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_in' },
|
||||
:content => /watched.remove_watcher/
|
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' },
|
||||
:content => /test\/README/
|
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' },
|
||||
:content => /test\/images\/delete.png /
|
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' },
|
||||
:content => /test\/images\/edit.png/
|
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' },
|
||||
:content => /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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
|
||||
# 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, :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, :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
|
|
@ -0,0 +1,165 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :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, :project_id => 'subproject1', :repository_scm => 'Darcs'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Darcs, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
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, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 3, assigns(:entries).size
|
||||
assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
|
||||
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||
assert_not_nil entry
|
||||
assert_equal 'file', entry.kind
|
||||
assert_equal 'images/edit.png', entry.path
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
|
||||
:rev => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['delete.png'], assigns(:entries).collect(&:name)
|
||||
end
|
||||
|
||||
def test_changes
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :changes, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'changes'
|
||||
assert_tag :tag => 'h2', :content => '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, :id => PRJ_ID, :rev => 5, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
# Line 22 removed
|
||||
assert_tag :tag => 'th',
|
||||
:content => '22',
|
||||
:sibling => { :tag => 'td',
|
||||
:attributes => { :class => /diff_out/ },
|
||||
:content => /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, :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, :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
|
|
@ -0,0 +1,164 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :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 =
|
||||
(RUBY_VERSION >= '1.9' && 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, :project_id => 'subproject1', :repository_scm => 'Filesystem'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Filesystem, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
end
|
||||
|
||||
def test_browse_root
|
||||
@repository.fetch_changesets
|
||||
@repository.reload
|
||||
get :show, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert assigns(:entries).size > 0
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size == 0
|
||||
|
||||
assert_no_tag 'input', :attributes => {:name => 'rev'}
|
||||
assert_no_tag 'a', :content => 'Statistics'
|
||||
assert_no_tag 'a', :content => 'Atom'
|
||||
end
|
||||
|
||||
def test_show_no_extension
|
||||
get :entry, :id => PRJ_ID, :path => repository_path_hash(['test'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /TEST CAT/ }
|
||||
end
|
||||
|
||||
def test_entry_download_no_extension
|
||||
get :raw, :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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['japanese', 'euc-jp.txt'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
assert_tag :tag => 'th',
|
||||
:content => '2',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /japanese/ }
|
||||
if @ruby19_non_utf8_pass
|
||||
puts "TODO: show repository file contents test fails in Ruby 1.9 " +
|
||||
"and 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"
|
||||
str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
|
||||
assert_tag :tag => 'th',
|
||||
:content => '3',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /#{str_japanese}/ }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_utf16
|
||||
enc = (RUBY_VERSION == "1.9.2" ? 'UTF-16LE' : 'UTF-16')
|
||||
with_settings :repositories_encodings => enc do
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['japanese', 'utf-16.txt'])[:param]
|
||||
assert_response :success
|
||||
assert_tag :tag => 'th',
|
||||
:content => '2',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /japanese/ }
|
||||
end
|
||||
end
|
||||
|
||||
def test_show_text_file_should_send_if_too_big
|
||||
with_settings :file_max_size_displayed => 1 do
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['japanese', 'big-file.txt'])[:param]
|
||||
assert_response :success
|
||||
assert_equal 'text/plain', @response.content_type
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_valid_repository
|
||||
@request.session[:user_id] = 1 # admin
|
||||
|
||||
assert_difference 'Repository.count', -1 do
|
||||
delete :destroy, :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, :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
|
|
@ -0,0 +1,638 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :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"
|
||||
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 =
|
||||
(RUBY_VERSION >= '1.9' && 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
|
||||
@char_1 = CHAR_1_HEX.dup
|
||||
if @char_1.respond_to?(:force_encoding)
|
||||
@char_1.force_encoding('UTF-8')
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_and_update
|
||||
@request.session[:user_id] = 1
|
||||
assert_difference 'Repository.count' do
|
||||
post :create, :project_id => 'subproject1',
|
||||
:repository_scm => 'Git',
|
||||
:repository => {
|
||||
:url => '/test',
|
||||
:is_default => '0',
|
||||
:identifier => 'test-create',
|
||||
:extra_report_last_commit => '1',
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
repository = Repository.first(:order => 'id DESC')
|
||||
assert_kind_of Repository::Git, repository
|
||||
assert_equal '/test', repository.url
|
||||
assert_equal true, repository.extra_report_last_commit
|
||||
|
||||
put :update, :id => repository.id,
|
||||
:repository => {
|
||||
:extra_report_last_commit => '0'
|
||||
}
|
||||
assert_response 302
|
||||
repo2 = Repository.find(repository.id)
|
||||
assert_equal false, repo2.extra_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, :project_id => 'subproject1', :repository_scm => 'Git'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Git, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
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, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 9, assigns(:entries).size
|
||||
assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'this_is_a_really_long_and_verbose_directory_name' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'copied_README' && e.kind == 'file'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'new_file.txt' && e.kind == 'file'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'renamed_test.txt' && e.kind == 'file'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'filemane with spaces.txt' && e.kind == 'file'}
|
||||
assert assigns(:entries).detect {|e| e.name == ' filename with a leading space.txt ' && e.kind == 'file'}
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :rev => 'test_branch'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 4, assigns(:entries).size
|
||||
assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'test.txt' && e.kind == 'file'}
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :rev => t1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert assigns(:entries).size > 0
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['edit.png'], assigns(:entries).collect(&:name)
|
||||
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||
assert_not_nil entry
|
||||
assert_equal 'file', entry.kind
|
||||
assert_equal 'images/edit.png', entry.path
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
|
||||
:rev => '7234cb2750b63f47bff735edc50a1c0a433c2518'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['delete.png'], assigns(:entries).collect(&:name)
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
end
|
||||
|
||||
def test_changes
|
||||
get :changes, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'changes'
|
||||
assert_tag :tag => 'h2', :content => 'edit.png'
|
||||
end
|
||||
|
||||
def test_entry_show
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
# Line 19
|
||||
assert_tag :tag => 'th',
|
||||
:content => '11',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td',
|
||||
:content => /test-#{@char_1}.txt/ }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
get :entry, :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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entry)
|
||||
assert_equal 'sources', assigns(:entry).name
|
||||
end
|
||||
|
||||
def test_diff
|
||||
assert_equal true, @repository.is_default
|
||||
assert_nil @repository.identifier
|
||||
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,
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
# Line 22 removed
|
||||
assert_tag :tag => 'th',
|
||||
:content => /22/,
|
||||
:sibling => { :tag => 'td',
|
||||
:attributes => { :class => /diff_out/ },
|
||||
:content => /def remove/ }
|
||||
assert_tag :tag => 'h2', :content => /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,
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
# Line 22 removed
|
||||
assert_tag :tag => 'th',
|
||||
:content => '22',
|
||||
:sibling => { :tag => 'td',
|
||||
:attributes => { :class => /diff_out/ },
|
||||
:content => /def remove/ }
|
||||
assert_tag :tag => 'h2', :content => /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, :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, :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,
|
||||
:id => PRJ_ID,
|
||||
:rev => '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
|
||||
:rev_to => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
diff = assigns(:diff)
|
||||
assert_not_nil diff
|
||||
assert_tag :tag => 'h2', :content => /2f9c0091:61b685fb/
|
||||
assert_tag :tag => "form",
|
||||
:attributes => {
|
||||
:action => "/projects/subproject1/repository/revisions/" +
|
||||
"61b685fbe55ab05b5ac68402d5720c1a6ac973d1/diff"
|
||||
}
|
||||
assert_tag :tag => 'input',
|
||||
:attributes => {
|
||||
:id => "rev_to",
|
||||
:name => "rev_to",
|
||||
:type => "hidden",
|
||||
: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,
|
||||
:id => PRJ_ID,
|
||||
:repository_id => 'test-diff-path',
|
||||
:rev => '61b685fbe55ab05b',
|
||||
:rev_to => '2f9c0091c754a91a',
|
||||
:type => 'inline'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
diff = assigns(:diff)
|
||||
assert_not_nil diff
|
||||
assert_tag :tag => "form",
|
||||
:attributes => {
|
||||
:action => "/projects/subproject1/repository/test-diff-path/" +
|
||||
"revisions/61b685fbe55ab05b/diff"
|
||||
}
|
||||
assert_tag :tag => 'input',
|
||||
:attributes => {
|
||||
:id => "rev_to",
|
||||
:name => "rev_to",
|
||||
:type => "hidden",
|
||||
: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, :id => PRJ_ID, :rev => r1, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_tag :tag => 'thead',
|
||||
:descendant => {
|
||||
:tag => 'th',
|
||||
:attributes => { :class => 'filename' } ,
|
||||
:content => /latin-1-dir\/test-#{@char_1}.txt/ ,
|
||||
},
|
||||
:sibling => {
|
||||
:tag => 'tbody',
|
||||
:descendant => {
|
||||
:tag => 'td',
|
||||
:attributes => { :class => /diff_in/ },
|
||||
:content => /test-#{@char_1}.txt/
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_should_show_filenames
|
||||
get :diff, :id => PRJ_ID, :rev => 'deff712f05a90d96edbd70facc47d944be5897e3', :type => 'inline'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
# 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,
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
user.reload
|
||||
assert_equal "inline", user.pref[:diff_type]
|
||||
get :diff,
|
||||
:id => PRJ_ID,
|
||||
:rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7',
|
||||
:type => 'sbs'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
user.reload
|
||||
assert_equal "sbs", user.pref[:diff_type]
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
|
||||
# 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, :id => PRJ_ID, :rev => 'deff7',
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
assert_tag :tag => 'h2', :content => /@ deff712f/
|
||||
end
|
||||
|
||||
def test_annotate_binary_file
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
assert_response 500
|
||||
assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
|
||||
:content => /cannot be annotated/
|
||||
end
|
||||
|
||||
def test_annotate_error_when_too_big
|
||||
with_settings :file_max_size_displayed => 1 do
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
|
||||
:rev => 'deff712f'
|
||||
assert_response 500
|
||||
assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
|
||||
:content => /exceeds the maximum text file size/
|
||||
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['README'])[:param],
|
||||
:rev => '7234cb2'
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||
:rev => r1
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td',
|
||||
:content => /test-#{@char_1}.txt/ }
|
||||
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, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'revisions'
|
||||
assert_tag :tag => 'form',
|
||||
:attributes => {
|
||||
: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, :id => PRJ_ID, :rev => r
|
||||
assert_response :success
|
||||
assert_template 'revision'
|
||||
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, :id => PRJ_ID, :rev => r
|
||||
assert_response 404
|
||||
assert_error_tag :content => /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, :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, :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 in Ruby 1.9 " +
|
||||
"and 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
|
|
@ -0,0 +1,525 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :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 = 32
|
||||
|
||||
ruby19_non_utf8_pass =
|
||||
(RUBY_VERSION >= '1.9' && 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
|
||||
@tag_char_1 = "tag-#{CHAR_1_HEX}-00"
|
||||
@branch_char_0 = "branch-#{CHAR_1_HEX}-00"
|
||||
@branch_char_1 = "branch-#{CHAR_1_HEX}-01"
|
||||
if @char_1.respond_to?(:force_encoding)
|
||||
@char_1.force_encoding('UTF-8')
|
||||
@tag_char_1.force_encoding('UTF-8')
|
||||
@branch_char_0.force_encoding('UTF-8')
|
||||
@branch_char_1.force_encoding('UTF-8')
|
||||
end
|
||||
end
|
||||
|
||||
if ruby19_non_utf8_pass
|
||||
puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
|
||||
"and 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, :project_id => 'subproject1', :repository_scm => 'Mercurial'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Mercurial, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
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, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 4, assigns(:entries).size
|
||||
assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
|
||||
assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
|
||||
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||
assert_not_nil entry
|
||||
assert_equal 'file', entry.kind
|
||||
assert_equal 'images/edit.png', entry.path
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['delete.png'], assigns(:entries).collect(&:name)
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sql_escape', 'percent%dir'])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['percent%file1.txt', 'percentfile1.txt'],
|
||||
assigns(:entries).collect(&:name)
|
||||
changesets = assigns(:changesets)
|
||||
assert_not_nil changesets
|
||||
assert assigns(:changesets).size > 0
|
||||
assert_equal %w(13 11 10 9), changesets.collect(&:revision)
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir'])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ["make-latin-1-file.rb",
|
||||
"test-#{@char_1}-1.txt",
|
||||
"test-#{@char_1}-2.txt",
|
||||
"test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
|
||||
changesets = assigns(:changesets)
|
||||
assert_not_nil changesets
|
||||
assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
|
||||
end
|
||||
end
|
||||
|
||||
def show_should_show_branch_selection_form
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
get :show, :id => PRJ_ID
|
||||
assert_tag 'form', :attributes => {:id => 'revision_selector', :action => '/projects/subproject1/repository/show'}
|
||||
assert_tag 'select', :attributes => {:name => 'branch'},
|
||||
:child => {:tag => 'option', :attributes => {:value => 'test-branch-01'}},
|
||||
:parent => {:tag => 'form', :attributes => {:id => 'revision_selector'}}
|
||||
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, :id => PRJ_ID, :rev => bra
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert assigns(:entries).size > 0
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
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, :id => PRJ_ID, :rev => tag
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert assigns(:entries).size > 0
|
||||
assert_not_nil assigns(:changesets)
|
||||
assert assigns(:changesets).size > 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_changes
|
||||
get :changes, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'changes'
|
||||
assert_tag :tag => 'h2', :content => 'edit.png'
|
||||
end
|
||||
|
||||
def test_entry_show
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
# Line 10
|
||||
assert_tag :tag => 'th',
|
||||
:content => '10',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
|
||||
end
|
||||
|
||||
def test_entry_show_latin_1_path
|
||||
[21, '21', 'adf805632193'].each do |r1|
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td',
|
||||
:content => /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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td',
|
||||
:content => /test-#{@char_1}.txt/ }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_entry_download
|
||||
get :entry, :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
|
||||
get :entry, :id => PRJ_ID, :rev => 1,
|
||||
:path => repository_path_hash(['images', 'edit.png'])[:param]
|
||||
assert_response :success
|
||||
assert_equal 'image/png', @response.content_type
|
||||
end
|
||||
|
||||
def test_directory_entry
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entry)
|
||||
assert_equal 'sources', assigns(:entry).name
|
||||
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, :id => PRJ_ID, :rev => r1, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
if @diff_c_support
|
||||
# Line 22 removed
|
||||
assert_tag :tag => 'th',
|
||||
:content => '22',
|
||||
:sibling => { :tag => 'td',
|
||||
:attributes => { :class => /diff_out/ },
|
||||
:content => /def remove/ }
|
||||
assert_tag :tag => 'h2', :content => /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,
|
||||
:id => PRJ_ID,
|
||||
:rev => r1,
|
||||
:rev_to => r2,
|
||||
:type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
diff = assigns(:diff)
|
||||
assert_not_nil diff
|
||||
assert_tag :tag => 'h2',
|
||||
:content => /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, :id => PRJ_ID, :rev => r1, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_tag :tag => 'thead',
|
||||
:descendant => {
|
||||
:tag => 'th',
|
||||
:attributes => { :class => 'filename' } ,
|
||||
:content => /latin-1-dir\/test-#{@char_1}-2.txt/ ,
|
||||
},
|
||||
:sibling => {
|
||||
:tag => 'tbody',
|
||||
:descendant => {
|
||||
:tag => 'td',
|
||||
:attributes => { :class => /diff_in/ },
|
||||
:content => /It is written in Python/
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff_should_show_modified_filenames
|
||||
get :diff, :id => PRJ_ID, :rev => '400bb8672109', :type => 'inline'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
|
||||
end
|
||||
|
||||
def test_diff_should_show_deleted_filenames
|
||||
get :diff, :id => PRJ_ID, :rev => 'b3a615152df8', :type => 'inline'
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_select 'th.filename', :text => 'sources/welcome_controller.rb'
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
|
||||
# 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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param]
|
||||
assert_response 404
|
||||
assert_error_tag :content => /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, :id => PRJ_ID, :rev => r1,
|
||||
:path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
|
||||
end
|
||||
end
|
||||
|
||||
def test_annotate_latin_1_path
|
||||
[21, '21', 'adf805632193'].each do |r1|
|
||||
get :annotate, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
|
||||
:rev => r1
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling =>
|
||||
{
|
||||
:tag => 'td',
|
||||
:attributes => { :class => 'revision' },
|
||||
:child => { :tag => 'a', :content => '20:709858aafd1b' }
|
||||
}
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling =>
|
||||
{
|
||||
:tag => 'td' ,
|
||||
:content => 'jsmith' ,
|
||||
:attributes => { :class => 'author' },
|
||||
}
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td',
|
||||
:content => /Mercurial is a distributed version control system/ }
|
||||
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||
:rev => r1
|
||||
assert_tag :tag => 'th',
|
||||
:content => '1',
|
||||
:attributes => { :class => 'line-num' },
|
||||
:sibling => { :tag => 'td',
|
||||
:content => /test-#{@char_1}.txt/ }
|
||||
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, :id => PRJ_ID, :rev => r
|
||||
assert_response 404
|
||||
assert_error_tag :content => /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, :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, :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
|
|
@ -0,0 +1,425 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests RepositoriesController
|
||||
|
||||
fixtures :projects, :users, :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, :project_id => 'subproject1', :repository_scm => 'Subversion'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_kind_of Repository::Subversion, assigns(:repository)
|
||||
assert assigns(:repository).new_record?
|
||||
end
|
||||
|
||||
def test_show
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :show, :id => PRJ_ID
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_not_nil assigns(:changesets)
|
||||
|
||||
entry = assigns(:entries).detect {|e| e.name == 'subversion_test'}
|
||||
assert_not_nil entry
|
||||
assert_equal 'dir', entry.kind
|
||||
assert_select 'tr.dir a[href=/projects/subproject1/repository/show/subversion_test]'
|
||||
|
||||
assert_tag 'input', :attributes => {:name => 'rev'}
|
||||
assert_tag 'a', :content => 'Statistics'
|
||||
assert_tag 'a', :content => 'Atom'
|
||||
assert_tag :tag => 'a',
|
||||
:attributes => {:href => '/projects/subproject1/repository'},
|
||||
:content => '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, :id => PRJ_ID, :repository_id => 'svn'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
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, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal [
|
||||
'[folder_with_brackets]', 'folder', '.project',
|
||||
'helloworld.c', 'textfile.txt'
|
||||
],
|
||||
assigns(:entries).collect(&:name)
|
||||
entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
|
||||
assert_equal 'file', entry.kind
|
||||
assert_equal 'subversion_test/helloworld.c', entry.path
|
||||
assert_tag :a, :content => 'helloworld.c', :attributes => { :class => /text\-x\-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, :id => PRJ_ID, :path => repository_path_hash(['subversion_test'])[:param],
|
||||
:rev => 4
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal ['folder', '.project', 'helloworld.c', 'helloworld.rb', 'textfile.txt'],
|
||||
assigns(:entries).collect(&:name)
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder', 'helloworld.rb'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'changes'
|
||||
|
||||
changesets = assigns(:changesets)
|
||||
assert_not_nil changesets
|
||||
assert_equal %w(6 3 2), changesets.collect(&:revision)
|
||||
|
||||
# svn properties displayed with svn >= 1.5 only
|
||||
if Redmine::Scm::Adapters::SubversionAdapter.client_version_above?([1, 5, 0])
|
||||
assert_not_nil assigns(:properties)
|
||||
assert_equal 'native', assigns(:properties)['svn:eol-style']
|
||||
assert_tag :ul,
|
||||
:child => { :tag => 'li',
|
||||
:child => { :tag => 'b', :content => 'svn:eol-style' },
|
||||
:child => { :tag => 'span', :content => 'native' } }
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'changes'
|
||||
|
||||
changesets = assigns(:changesets)
|
||||
assert_not_nil changesets
|
||||
assert_equal %w(10 9 7 6 5 2), changesets.collect(&:revision)
|
||||
end
|
||||
|
||||
def test_entry
|
||||
assert_equal 0, @repository.changesets.count
|
||||
@repository.fetch_changesets
|
||||
@project.reload
|
||||
assert_equal NUM_REV, @repository.changesets.count
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
end
|
||||
|
||||
def test_entry_should_send_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, :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
|
||||
end
|
||||
|
||||
def test_entry_should_send_images_inline
|
||||
get :entry, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder', 'subfolder', 'rubylogo.gif'])[:param]
|
||||
assert_response :success
|
||||
assert_equal 'inline; filename="rubylogo.gif"', response.headers['Content-Disposition']
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.rb'])[:param],
|
||||
:rev => 2
|
||||
assert_response :success
|
||||
assert_template 'entry'
|
||||
# this line was removed in r3 and file was moved in r6
|
||||
assert_tag :tag => 'td', :attributes => { :class => /line-code/},
|
||||
:content => /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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'zzz.c'])[:param]
|
||||
assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ },
|
||||
:content => /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, :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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'folder'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:entry)
|
||||
assert_equal 'folder', assigns(:entry).name
|
||||
end
|
||||
|
||||
# TODO: this test needs fixtures.
|
||||
def test_revision
|
||||
get :revision, :id => 1, :rev => 2
|
||||
assert_response :success
|
||||
assert_template 'revision'
|
||||
|
||||
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, :id => PRJ_ID, :rev => 'something_weird'
|
||||
assert_response 404
|
||||
assert_error_tag :content => /was not found/
|
||||
end
|
||||
|
||||
def test_invalid_revision_diff
|
||||
get :diff, :id => PRJ_ID, :rev => '1', :rev_to => 'something_weird'
|
||||
assert_response 404
|
||||
assert_error_tag :content => /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, :id => PRJ_ID, :rev => r
|
||||
assert_response 404
|
||||
assert_error_tag :content => /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, :id => 1, :rev => 2
|
||||
assert_response :success
|
||||
assert_template 'revision'
|
||||
|
||||
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, :id => PRJ_ID, :rev => 3, :type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
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, :id => PRJ_ID, :rev => 3, :format => 'diff'
|
||||
assert_response :success
|
||||
assert_equal 'text/x-patch', @response.content_type
|
||||
assert_equal 'Index: subversion_test/textfile.txt', @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, :id => PRJ_ID, :rev => 6, :rev_to => 2,
|
||||
:path => repository_path_hash(['subversion_test', 'folder'])[:param],
|
||||
:type => dt
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
|
||||
diff = assigns(:diff)
|
||||
assert_not_nil diff
|
||||
# 2 files modified
|
||||
assert_equal 2, Redmine::UnifiedDiff.new(diff).size
|
||||
assert_tag :tag => 'h2', :content => /2:6/
|
||||
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, :id => PRJ_ID,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
|
||||
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, :id => PRJ_ID, :rev => 8,
|
||||
:path => repository_path_hash(['subversion_test', 'helloworld.c'])[:param]
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
assert_tag :tag => 'h2', :content => /@ 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, :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, :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
|
|
@ -0,0 +1,216 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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_template 'index'
|
||||
|
||||
assert_not_nil assigns(:roles)
|
||||
assert_equal Role.order('builtin, position').all, assigns(:roles)
|
||||
|
||||
assert_tag :tag => 'a', :attributes => { :href => '/roles/1/edit' },
|
||||
:content => 'Manager'
|
||||
end
|
||||
|
||||
def test_new
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_new_with_copy
|
||||
copy_from = Role.find(2)
|
||||
|
||||
get :new, :copy => copy_from.id.to_s
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
|
||||
role = assigns(:role)
|
||||
assert_equal copy_from.permissions, role.permissions
|
||||
|
||||
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, :role => {:name => '',
|
||||
:permissions => ['add_issues', 'edit_issues', 'log_time', ''],
|
||||
:assignable => '0'}
|
||||
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_tag :tag => 'div', :attributes => { :id => 'errorExplanation' }
|
||||
end
|
||||
|
||||
def test_create_without_workflow_copy
|
||||
post :create, :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, :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_edit
|
||||
get :edit, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_equal Role.find(1), assigns(:role)
|
||||
assert_select 'select[name=?]', 'role[issues_visibility]'
|
||||
end
|
||||
|
||||
def test_edit_anonymous
|
||||
get :edit, :id => Role.anonymous.id
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_select 'select[name=?]', 'role[issues_visibility]', 0
|
||||
end
|
||||
|
||||
def test_edit_invalid_should_respond_with_404
|
||||
get :edit, :id => 999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update
|
||||
put :update, :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_with_failure
|
||||
put :update, :id => 1, :role => {:name => ''}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
r = Role.create!(:name => 'ToBeDestroyed', :permissions => [:view_wiki_pages])
|
||||
|
||||
delete :destroy, :id => r
|
||||
assert_redirected_to '/roles'
|
||||
assert_nil Role.find_by_id(r.id)
|
||||
end
|
||||
|
||||
def test_destroy_role_in_use
|
||||
delete :destroy, :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_template 'permissions'
|
||||
|
||||
assert_not_nil assigns(:roles)
|
||||
assert_equal Role.order('builtin, position').all, assigns(:roles)
|
||||
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'permissions[3][]',
|
||||
:value => 'add_issues',
|
||||
:checked => 'checked' }
|
||||
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'permissions[3][]',
|
||||
:value => 'delete_issues',
|
||||
:checked => nil }
|
||||
end
|
||||
|
||||
def test_post_permissions
|
||||
post :permissions, :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, :permissions => { '0' => '' }
|
||||
assert_redirected_to '/roles'
|
||||
assert Role.find(1).permissions.empty?
|
||||
end
|
||||
|
||||
def test_move_highest
|
||||
put :update, :id => 3, :role => {:move_to => 'highest'}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal 1, Role.find(3).position
|
||||
end
|
||||
|
||||
def test_move_higher
|
||||
position = Role.find(3).position
|
||||
put :update, :id => 3, :role => {:move_to => 'higher'}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal position - 1, Role.find(3).position
|
||||
end
|
||||
|
||||
def test_move_lower
|
||||
position = Role.find(2).position
|
||||
put :update, :id => 2, :role => {:move_to => 'lower'}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal position + 1, Role.find(2).position
|
||||
end
|
||||
|
||||
def test_move_lowest
|
||||
put :update, :id => 2, :role => {:move_to => 'lowest'}
|
||||
assert_redirected_to '/roles'
|
||||
assert_equal Role.count, Role.find(2).position
|
||||
end
|
||||
end
|
|
@ -0,0 +1,265 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :enabled_modules, :roles, :users, :members, :member_roles,
|
||||
:issues, :trackers, :issue_statuses, :enumerations,
|
||||
:custom_fields, :custom_values,
|
||||
:repositories, :changesets
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_search_for_projects
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
|
||||
get :index, :q => "cook"
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert assigns(:results).include?(Project.find(1))
|
||||
end
|
||||
|
||||
def test_search_all_projects
|
||||
get :index, :q => 'recipe subproject commit', :all_words => ''
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
|
||||
assert assigns(:results).include?(Issue.find(2))
|
||||
assert assigns(:results).include?(Issue.find(5))
|
||||
assert assigns(:results).include?(Changeset.find(101))
|
||||
assert_tag :dt, :attributes => { :class => /issue/ },
|
||||
:child => { :tag => 'a', :content => /Add ingredients categories/ },
|
||||
:sibling => { :tag => 'dd', :content => /should be classified by categories/ }
|
||||
|
||||
assert assigns(:results_by_type).is_a?(Hash)
|
||||
assert_equal 5, assigns(:results_by_type)['changesets']
|
||||
assert_tag :a, :content => 'Changesets (5)'
|
||||
end
|
||||
|
||||
def test_search_issues
|
||||
get :index, :q => 'issue', :issues => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
|
||||
assert_equal true, assigns(:all_words)
|
||||
assert_equal false, assigns(:titles_only)
|
||||
assert assigns(:results).include?(Issue.find(8))
|
||||
assert assigns(:results).include?(Issue.find(5))
|
||||
assert_tag :dt, :attributes => { :class => /issue closed/ },
|
||||
:child => { :tag => 'a', :content => /Closed/ }
|
||||
end
|
||||
|
||||
def test_search_issues_should_search_notes
|
||||
Journal.create!(:journalized => Issue.find(2), :notes => 'Issue notes with searchkeyword')
|
||||
|
||||
get :index, :q => 'searchkeyword', :issues => 1
|
||||
assert_response :success
|
||||
assert_include Issue.find(2), assigns(:results)
|
||||
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, :q => 'searchkeyword', :issues => 1
|
||||
assert_response :success
|
||||
assert_include Issue.find(2), assigns(:results)
|
||||
assert_equal 1, assigns(:results).size
|
||||
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, :q => 'searchkeyword', :issues => 1
|
||||
assert_response :success
|
||||
assert_include Issue.find(2), assigns(:results)
|
||||
|
||||
Role.find(1).remove_permission! :view_private_notes
|
||||
get :index, :q => 'searchkeyword', :issues => 1
|
||||
assert_response :success
|
||||
assert_not_include Issue.find(2), assigns(:results)
|
||||
end
|
||||
|
||||
def test_search_all_projects_with_scope_param
|
||||
get :index, :q => 'issue', :scope => 'all'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert assigns(:results).present?
|
||||
end
|
||||
|
||||
def test_search_my_projects
|
||||
@request.session[:user_id] = 2
|
||||
get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => ''
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert assigns(:results).include?(Issue.find(1))
|
||||
assert !assigns(:results).include?(Issue.find(5))
|
||||
end
|
||||
|
||||
def test_search_my_projects_without_memberships
|
||||
# anonymous user has no memberships
|
||||
get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => ''
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert assigns(:results).empty?
|
||||
end
|
||||
|
||||
def test_search_project_and_subprojects
|
||||
get :index, :id => 1, :q => 'recipe subproject', :scope => 'subprojects', :all_words => ''
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert assigns(:results).include?(Issue.find(1))
|
||||
assert assigns(:results).include?(Issue.find(5))
|
||||
end
|
||||
|
||||
def test_search_without_searchable_custom_fields
|
||||
CustomField.update_all "searchable = #{ActiveRecord::Base.connection.quoted_false}"
|
||||
|
||||
get :index, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:project)
|
||||
|
||||
get :index, :id => 1, :q => "can"
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
end
|
||||
|
||||
def test_search_with_searchable_custom_fields
|
||||
get :index, :id => 1, :q => "stringforcustomfield"
|
||||
assert_response :success
|
||||
results = assigns(:results)
|
||||
assert_not_nil results
|
||||
assert_equal 1, results.size
|
||||
assert results.include?(Issue.find(7))
|
||||
end
|
||||
|
||||
def test_search_all_words
|
||||
# 'all words' is on by default
|
||||
get :index, :id => 1, :q => 'recipe updating saving', :all_words => '1'
|
||||
assert_equal true, assigns(:all_words)
|
||||
results = assigns(:results)
|
||||
assert_not_nil results
|
||||
assert_equal 1, results.size
|
||||
assert results.include?(Issue.find(3))
|
||||
end
|
||||
|
||||
def test_search_one_of_the_words
|
||||
get :index, :id => 1, :q => 'recipe updating saving', :all_words => ''
|
||||
assert_equal false, assigns(:all_words)
|
||||
results = assigns(:results)
|
||||
assert_not_nil results
|
||||
assert_equal 3, results.size
|
||||
assert results.include?(Issue.find(3))
|
||||
end
|
||||
|
||||
def test_search_titles_only_without_result
|
||||
get :index, :id => 1, :q => 'recipe updating saving', :titles_only => '1'
|
||||
results = assigns(:results)
|
||||
assert_not_nil results
|
||||
assert_equal 0, results.size
|
||||
end
|
||||
|
||||
def test_search_titles_only
|
||||
get :index, :id => 1, :q => 'recipe', :titles_only => '1'
|
||||
assert_equal true, assigns(:titles_only)
|
||||
results = assigns(:results)
|
||||
assert_not_nil results
|
||||
assert_equal 2, results.size
|
||||
end
|
||||
|
||||
def test_search_content
|
||||
Issue.update_all("description = 'This is a searchkeywordinthecontent'", "id=1")
|
||||
|
||||
get :index, :id => 1, :q => 'searchkeywordinthecontent', :titles_only => ''
|
||||
assert_equal false, assigns(:titles_only)
|
||||
results = assigns(:results)
|
||||
assert_not_nil results
|
||||
assert_equal 1, results.size
|
||||
end
|
||||
|
||||
def test_search_with_offset
|
||||
get :index, :q => 'coo', :offset => '20080806073000'
|
||||
assert_response :success
|
||||
results = assigns(:results)
|
||||
assert results.any?
|
||||
assert results.map(&:event_datetime).max < '20080806T073000'.to_time
|
||||
end
|
||||
|
||||
def test_search_previous_with_offset
|
||||
get :index, :q => 'coo', :offset => '20080806073000', :previous => '1'
|
||||
assert_response :success
|
||||
results = assigns(:results)
|
||||
assert results.any?
|
||||
assert results.map(&:event_datetime).min >= '20080806T073000'.to_time
|
||||
end
|
||||
|
||||
def test_search_with_invalid_project_id
|
||||
get :index, :id => 195, :q => 'recipe'
|
||||
assert_response 404
|
||||
assert_nil assigns(:results)
|
||||
end
|
||||
|
||||
def test_quick_jump_to_issue
|
||||
# issue of a public project
|
||||
get :index, :q => "3"
|
||||
assert_redirected_to '/issues/3'
|
||||
|
||||
# issue of a private project
|
||||
get :index, :q => "4"
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
end
|
||||
|
||||
def test_large_integer
|
||||
get :index, :q => '4615713488'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
end
|
||||
|
||||
def test_tokens_with_quotes
|
||||
get :index, :id => 1, :q => '"good bye" hello "bye bye"'
|
||||
assert_equal ["good bye", "hello", "bye bye"], assigns(:tokens)
|
||||
end
|
||||
|
||||
def test_results_should_be_escaped_once
|
||||
assert Issue.find(1).update_attributes(:subject => '<subject> escaped_once', :description => '<description> escaped_once')
|
||||
get :index, :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, :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
|
|
@ -0,0 +1,117 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 SessionStartTest < ActionController::TestCase
|
||||
tests AccountController
|
||||
|
||||
fixtures :users
|
||||
|
||||
def test_login_should_set_session_timestamps
|
||||
post :login, :username => 'jsmith', :password => 'jsmith'
|
||||
assert_response 302
|
||||
assert_equal 2, session[:user_id]
|
||||
assert_not_nil session[:ctime]
|
||||
assert_not_nil session[:atime]
|
||||
end
|
||||
end
|
||||
|
||||
class SessionsTest < ActionController::TestCase
|
||||
tests WelcomeController
|
||||
|
||||
fixtures :users
|
||||
|
||||
def test_atime_from_user_session_should_be_updated
|
||||
created = 2.hours.ago.utc.to_i
|
||||
get :index, {}, {:user_id => 2, :ctime => created, :atime => created}
|
||||
assert_response :success
|
||||
assert_equal created, session[:ctime]
|
||||
assert_not_equal created, session[:atime]
|
||||
assert session[:atime] > created
|
||||
end
|
||||
|
||||
def test_user_session_should_not_be_reset_if_lifetime_and_timeout_disabled
|
||||
with_settings :session_lifetime => '0', :session_timeout => '0' do
|
||||
get :index, {}, {:user_id => 2}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_without_ctime_should_be_reset_if_lifetime_enabled
|
||||
with_settings :session_lifetime => '720' do
|
||||
get :index, {}, {:user_id => 2}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_with_expired_ctime_should_be_reset_if_lifetime_enabled
|
||||
with_settings :session_timeout => '720' do
|
||||
get :index, {}, {:user_id => 2, :atime => 2.days.ago.utc.to_i}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_with_valid_ctime_should_not_be_reset_if_lifetime_enabled
|
||||
with_settings :session_timeout => '720' do
|
||||
get :index, {}, {:user_id => 2, :atime => 3.hours.ago.utc.to_i}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_without_atime_should_be_reset_if_timeout_enabled
|
||||
with_settings :session_timeout => '60' do
|
||||
get :index, {}, {:user_id => 2}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_with_expired_atime_should_be_reset_if_timeout_enabled
|
||||
with_settings :session_timeout => '60' do
|
||||
get :index, {}, {:user_id => 2, :atime => 4.hours.ago.utc.to_i}
|
||||
assert_redirected_to '/login'
|
||||
end
|
||||
end
|
||||
|
||||
def test_user_session_with_valid_atime_should_not_be_reset_if_timeout_enabled
|
||||
with_settings :session_timeout => '60' do
|
||||
get :index, {}, {:user_id => 2, :atime => 10.minutes.ago.utc.to_i}
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
def test_expired_user_session_should_be_restarted_if_autologin
|
||||
with_settings :session_lifetime => '720', :session_timeout => '60', :autologin => 7 do
|
||||
token = Token.create!(:user_id => 2, :action => 'autologin', :created_on => 1.day.ago)
|
||||
@request.cookies['autologin'] = token.value
|
||||
created = 2.hours.ago.utc.to_i
|
||||
|
||||
get :index, {}, {:user_id => 2, :ctime => created, :atime => created}
|
||||
assert_equal 2, session[:user_id]
|
||||
assert_response :success
|
||||
assert_not_equal created, session[:ctime]
|
||||
assert session[:ctime] >= created
|
||||
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
|
|
@ -0,0 +1,131 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :users
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
get :edit
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
assert_tag 'input', :attributes => {:name => 'settings[enabled_scm][]', :value => ''}
|
||||
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[id=selected_columns][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[id=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, :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
|
||||
Setting.clear_cache
|
||||
end
|
||||
|
||||
def test_get_plugin_settings
|
||||
Setting.stubs(:plugin_foo).returns({'sample_setting' => 'Plugin setting value'})
|
||||
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
|
||||
|
||||
get :plugin, :id => 'foo'
|
||||
assert_response :success
|
||||
assert_template 'plugin'
|
||||
assert_tag 'form', :attributes => {:action => '/settings/plugin/foo'},
|
||||
:descendant => {:tag => 'input', :attributes => {:name => 'settings[sample_setting]', :value => 'Plugin setting value'}}
|
||||
|
||||
Redmine::Plugin.clear
|
||||
end
|
||||
|
||||
def test_get_invalid_plugin_settings
|
||||
get :plugin, :id => 'none'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_non_configurable_plugin_settings
|
||||
Redmine::Plugin.register(:foo) {}
|
||||
|
||||
get :plugin, :id => 'foo'
|
||||
assert_response 404
|
||||
|
||||
Redmine::Plugin.clear
|
||||
end
|
||||
|
||||
def test_post_plugin_settings
|
||||
Setting.expects(:plugin_foo=).with({'sample_setting' => 'Value'}).returns(true)
|
||||
Redmine::Plugin.register(:foo) do
|
||||
settings :partial => 'not blank' # so that configurable? is true
|
||||
end
|
||||
|
||||
post :plugin, :id => 'foo', :settings => {'sample_setting' => 'Value'}
|
||||
assert_redirected_to '/settings/plugin/foo'
|
||||
end
|
||||
|
||||
def test_post_non_configurable_plugin_settings
|
||||
Redmine::Plugin.register(:foo) {}
|
||||
|
||||
post :plugin, :id => 'foo', :settings => {'sample_setting' => 'Value'}
|
||||
assert_response 404
|
||||
|
||||
Redmine::Plugin.clear
|
||||
end
|
||||
end
|
|
@ -0,0 +1,125 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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/xml', @response.content_type
|
||||
with_options :tag => 'projects' do |test|
|
||||
test.assert_tag :children => { :count => Project.active.has_module(:repository).count }
|
||||
test.assert_tag 'project', :child => {:tag => 'identifier', :sibling => {:tag => 'is-public'}}
|
||||
end
|
||||
assert_no_tag 'extra-info'
|
||||
assert_no_tag 'extra_info'
|
||||
end
|
||||
|
||||
def test_create_project_repository
|
||||
assert_nil Project.find(4).repository
|
||||
|
||||
post :create_project_repository, :id => 4,
|
||||
:vendor => 'Subversion',
|
||||
:repository => { :url => 'file:///create/project/repository/subproject2'}
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
r = Project.find(4).repository
|
||||
assert r.is_a?(Repository::Subversion)
|
||||
assert_equal 'file:///create/project/repository/subproject2', r.url
|
||||
|
||||
assert_tag 'repository-subversion',
|
||||
:child => {
|
||||
:tag => 'id', :content => r.id.to_s,
|
||||
:sibling => {:tag => 'url', :content => r.url}
|
||||
}
|
||||
assert_no_tag 'extra-info'
|
||||
assert_no_tag 'extra_info'
|
||||
end
|
||||
|
||||
def test_create_already_existing
|
||||
post :create_project_repository, :id => 1,
|
||||
:vendor => 'Subversion',
|
||||
:repository => { :url => 'file:///create/project/repository/subproject2'}
|
||||
|
||||
assert_response :conflict
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
post :create_project_repository, :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, :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, :id => '1'
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_fetch_changesets_unknown_project
|
||||
get :fetch_changesets, :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
|
||||
end
|
||||
end
|
||||
|
||||
def test_api_key
|
||||
with_settings :sys_api_key => 'my_secret_key' do
|
||||
get :projects, :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, :key => 'wrong_key'
|
||||
assert_response 403
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,372 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
tests TimelogController
|
||||
|
||||
fixtures :projects, :enabled_modules, :roles, :members, :member_roles,
|
||||
:issues, :time_entries, :users, :trackers, :enumerations,
|
||||
:issue_statuses, :custom_fields, :custom_values
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def setup
|
||||
Setting.default_language = "en"
|
||||
end
|
||||
|
||||
def test_report_at_project_level
|
||||
get :report, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/time_entries/report", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_report_all_projects
|
||||
get :report
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/time_entries/report", :id => 'query_form'}
|
||||
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, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "8.65", "%.2f" % assigns(:report).total_hours
|
||||
end
|
||||
|
||||
def test_report_all_time
|
||||
get :report, :project_id => 1, :criteria => ['project', 'issue']
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "162.90", "%.2f" % assigns(:report).total_hours
|
||||
end
|
||||
|
||||
def test_report_all_time_by_day
|
||||
get :report, :project_id => 1, :criteria => ['project', 'issue'], :columns => 'day'
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "162.90", "%.2f" % assigns(:report).total_hours
|
||||
assert_tag :tag => 'th', :content => '2007-03-12'
|
||||
end
|
||||
|
||||
def test_report_one_criteria
|
||||
get :report, :project_id => 1, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criteria => ['project']
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "8.65", "%.2f" % assigns(:report).total_hours
|
||||
end
|
||||
|
||||
def test_report_two_criteria
|
||||
get :report, :project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "162.90", "%.2f" % assigns(:report).total_hours
|
||||
end
|
||||
|
||||
def test_report_custom_field_criteria_with_multiple_values
|
||||
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, :project_id => 1, :columns => 'day', :criteria => ["cf_#{field.id}"]
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_report_one_day
|
||||
get :report, :project_id => 1, :columns => 'day', :from => "2007-03-23", :to => "2007-03-23", :criteria => ["user", "activity"]
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "4.25", "%.2f" % assigns(:report).total_hours
|
||||
end
|
||||
|
||||
def test_report_at_issue_level
|
||||
get :report, :project_id => 1, :issue_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criteria => ["user", "activity"]
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "154.25", "%.2f" % assigns(:report).total_hours
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/issues/1/time_entries/report", :id => 'query_form'}
|
||||
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, :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_template 'report'
|
||||
|
||||
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, :criteria => ['cf_1', 'cf_3', 'cf_7']
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal 3, assigns(:report).criteria.size
|
||||
assert_equal "162.90", "%.2f" % assigns(:report).total_hours
|
||||
|
||||
# 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, :project_id => 1, :columns => 'week', :from => "1998-04-01", :to => "1998-04-30", :criteria => ['project']
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_not_nil assigns(:report)
|
||||
assert_equal "0.00", "%.2f" % assigns(:report).total_hours
|
||||
end
|
||||
|
||||
def test_report_status_criterion
|
||||
get :report, :project_id => 1, :criteria => ['status']
|
||||
assert_response :success
|
||||
assert_template 'report'
|
||||
assert_tag :tag => 'th', :content => 'Status'
|
||||
assert_tag :tag => 'td', :content => 'New'
|
||||
end
|
||||
|
||||
def test_report_all_projects_csv_export
|
||||
get :report, :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, :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
|
||||
Setting.default_language = "zh-TW"
|
||||
str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
|
||||
str_big5 = "\xa4@\xa4\xeb"
|
||||
if str_utf8.respond_to?(:force_encoding)
|
||||
str_utf8.force_encoding('UTF-8')
|
||||
str_big5.force_encoding('Big5')
|
||||
end
|
||||
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
|
||||
|
||||
get :report, :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 = "\xa5\xce\xa4\xe1,2011-11-11,\xc1`\xadp"
|
||||
s2 = "\xc1`\xadp"
|
||||
if s1.respond_to?(:force_encoding)
|
||||
s1.force_encoding('Big5')
|
||||
s2.force_encoding('Big5')
|
||||
end
|
||||
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)"
|
||||
if str_tw.respond_to?(:force_encoding)
|
||||
str_tw.force_encoding('UTF-8')
|
||||
end
|
||||
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
|
||||
Setting.default_language = "zh-TW"
|
||||
str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
|
||||
if str_utf8.respond_to?(:force_encoding)
|
||||
str_utf8.force_encoding('UTF-8')
|
||||
end
|
||||
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
|
||||
|
||||
get :report, :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 = "\xa5\xce\xa4\xe1,2011-11-11,\xc1`\xadp"
|
||||
if s1.respond_to?(:force_encoding)
|
||||
s1.force_encoding('Big5')
|
||||
end
|
||||
assert_equal s1, lines.first
|
||||
# Total row
|
||||
s2 = ""
|
||||
if s2.respond_to?(:force_encoding)
|
||||
s2 = "\xa5H?"
|
||||
s2.force_encoding('Big5')
|
||||
elsif RUBY_PLATFORM == 'java'
|
||||
s2 = "??"
|
||||
else
|
||||
s2 = "\xa5H???"
|
||||
end
|
||||
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, :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"
|
||||
s2 = "Temps total"
|
||||
if s1.respond_to?(:force_encoding)
|
||||
s1.force_encoding('ISO-8859-1')
|
||||
s2.force_encoding('ISO-8859-1')
|
||||
end
|
||||
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 = "Fran\xc3\xa7ais"
|
||||
if str_fr.respond_to?(:force_encoding)
|
||||
str_fr.force_encoding('UTF-8')
|
||||
end
|
||||
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
|
|
@ -0,0 +1,604 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 TimelogControllerTest < ActionController::TestCase
|
||||
fixtures :projects, :enabled_modules, :roles, :members,
|
||||
:member_roles, :issues, :time_entries, :users,
|
||||
:trackers, :enumerations, :issue_statuses,
|
||||
:custom_fields, :custom_values,
|
||||
:projects_trackers, :custom_fields_trackers,
|
||||
:custom_fields_projects
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def test_new_with_project_id
|
||||
@request.session[:user_id] = 3
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_select 'select[name=?]', 'time_entry[project_id]', 0
|
||||
assert_select 'input[name=?][value=1][type=hidden]', 'time_entry[project_id]'
|
||||
end
|
||||
|
||||
def test_new_with_issue_id
|
||||
@request.session[:user_id] = 3
|
||||
get :new, :issue_id => 2
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_select 'select[name=?]', 'time_entry[project_id]', 0
|
||||
assert_select 'input[name=?][value=1][type=hidden]', 'time_entry[project_id]'
|
||||
end
|
||||
|
||||
def test_new_without_project
|
||||
@request.session[:user_id] = 3
|
||||
get :new
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_select 'select[name=?]', 'time_entry[project_id]'
|
||||
assert_select 'input[name=?]', 'time_entry[project_id]', 0
|
||||
end
|
||||
|
||||
def test_new_without_project_should_prefill_the_form
|
||||
@request.session[:user_id] = 3
|
||||
get :new, :time_entry => {:project_id => '1'}
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_select 'select[name=?]', 'time_entry[project_id]' do
|
||||
assert_select 'option[value=1][selected=selected]'
|
||||
end
|
||||
assert_select 'input[name=?]', 'time_entry[project_id]', 0
|
||||
end
|
||||
|
||||
def test_new_without_project_should_deny_without_permission
|
||||
Role.all.each {|role| role.remove_permission! :log_time}
|
||||
@request.session[:user_id] = 3
|
||||
|
||||
get :new
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_new_should_select_default_activity
|
||||
@request.session[:user_id] = 3
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_select 'select[name=?]', 'time_entry[activity_id]' do
|
||||
assert_select 'option[selected=selected]', :text => 'Development'
|
||||
end
|
||||
end
|
||||
|
||||
def test_new_should_only_show_active_time_entry_activities
|
||||
@request.session[:user_id] = 3
|
||||
get :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_no_tag 'option', :content => 'Inactive Activity'
|
||||
end
|
||||
|
||||
def test_get_edit_existing_time
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :id => 2, :project_id => nil
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
# Default activity selected
|
||||
assert_tag :tag => 'form', :attributes => { :action => '/projects/ecookbook/time_entries/2' }
|
||||
end
|
||||
|
||||
def test_get_edit_with_an_existing_time_entry_with_inactive_activity
|
||||
te = TimeEntry.find(1)
|
||||
te.activity = TimeEntryActivity.find_by_name("Inactive Activity")
|
||||
te.save!
|
||||
|
||||
@request.session[:user_id] = 1
|
||||
get :edit, :project_id => 1, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
# Blank option since nothing is pre-selected
|
||||
assert_tag :tag => 'option', :content => '--- Please select ---'
|
||||
end
|
||||
|
||||
def test_post_create
|
||||
# TODO: should POST to issues’ time log instead of project. change form
|
||||
# and routing
|
||||
@request.session[:user_id] = 3
|
||||
post :create, :project_id => 1,
|
||||
:time_entry => {:comments => 'Some work on TimelogControllerTest',
|
||||
# Not the default activity
|
||||
:activity_id => '11',
|
||||
:spent_on => '2008-03-14',
|
||||
:issue_id => '1',
|
||||
:hours => '7.3'}
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
|
||||
i = Issue.find(1)
|
||||
t = TimeEntry.find_by_comments('Some work on TimelogControllerTest')
|
||||
assert_not_nil t
|
||||
assert_equal 11, t.activity_id
|
||||
assert_equal 7.3, t.hours
|
||||
assert_equal 3, t.user_id
|
||||
assert_equal i, t.issue
|
||||
assert_equal i.project, t.project
|
||||
end
|
||||
|
||||
def test_post_create_with_blank_issue
|
||||
# TODO: should POST to issues’ time log instead of project. change form
|
||||
# and routing
|
||||
@request.session[:user_id] = 3
|
||||
post :create, :project_id => 1,
|
||||
:time_entry => {:comments => 'Some work on TimelogControllerTest',
|
||||
# Not the default activity
|
||||
:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'}
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
|
||||
t = TimeEntry.find_by_comments('Some work on TimelogControllerTest')
|
||||
assert_not_nil t
|
||||
assert_equal 11, t.activity_id
|
||||
assert_equal 7.3, t.hours
|
||||
assert_equal 3, t.user_id
|
||||
end
|
||||
|
||||
def test_create_and_continue
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :project_id => 1,
|
||||
:time_entry => {:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'},
|
||||
:continue => '1'
|
||||
assert_redirected_to '/projects/ecookbook/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D='
|
||||
end
|
||||
|
||||
def test_create_and_continue_with_issue_id
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :project_id => 1,
|
||||
:time_entry => {:activity_id => '11',
|
||||
:issue_id => '1',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'},
|
||||
:continue => '1'
|
||||
assert_redirected_to '/projects/ecookbook/issues/1/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=1'
|
||||
end
|
||||
|
||||
def test_create_and_continue_without_project
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :time_entry => {:project_id => '1',
|
||||
:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'},
|
||||
:continue => '1'
|
||||
|
||||
assert_redirected_to '/time_entries/new?time_entry%5Bactivity_id%5D=11&time_entry%5Bissue_id%5D=&time_entry%5Bproject_id%5D=1'
|
||||
end
|
||||
|
||||
def test_create_without_log_time_permission_should_be_denied
|
||||
@request.session[:user_id] = 2
|
||||
Role.find_by_name('Manager').remove_permission! :log_time
|
||||
post :create, :project_id => 1,
|
||||
:time_entry => {:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'}
|
||||
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_create_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
post :create, :project_id => 1,
|
||||
:time_entry => {:activity_id => '',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'}
|
||||
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_create_without_project
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'TimeEntry.count' do
|
||||
post :create, :time_entry => {:project_id => '1',
|
||||
:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'}
|
||||
end
|
||||
|
||||
assert_redirected_to '/projects/ecookbook/time_entries'
|
||||
time_entry = TimeEntry.first(:order => 'id DESC')
|
||||
assert_equal 1, time_entry.project_id
|
||||
end
|
||||
|
||||
def test_create_without_project_should_fail_with_issue_not_inside_project
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
post :create, :time_entry => {:project_id => '1',
|
||||
:activity_id => '11',
|
||||
:issue_id => '5',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'}
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert assigns(:time_entry).errors[:issue_id].present?
|
||||
end
|
||||
|
||||
def test_create_without_project_should_deny_without_permission
|
||||
@request.session[:user_id] = 2
|
||||
Project.find(3).disable_module!(:time_tracking)
|
||||
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
post :create, :time_entry => {:project_id => '3',
|
||||
:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => '7.3'}
|
||||
end
|
||||
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_create_without_project_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
post :create, :time_entry => {:project_id => '1',
|
||||
:activity_id => '11',
|
||||
:issue_id => '',
|
||||
:spent_on => '2008-03-14',
|
||||
:hours => ''}
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_tag 'select', :attributes => {:name => 'time_entry[project_id]'},
|
||||
:child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
|
||||
end
|
||||
|
||||
def test_update
|
||||
entry = TimeEntry.find(1)
|
||||
assert_equal 1, entry.issue_id
|
||||
assert_equal 2, entry.user_id
|
||||
|
||||
@request.session[:user_id] = 1
|
||||
put :update, :id => 1,
|
||||
:time_entry => {:issue_id => '2',
|
||||
:hours => '8'}
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
entry.reload
|
||||
|
||||
assert_equal 8, entry.hours
|
||||
assert_equal 2, entry.issue_id
|
||||
assert_equal 2, entry.user_id
|
||||
end
|
||||
|
||||
def test_get_bulk_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :bulk_edit, :ids => [1, 2]
|
||||
assert_response :success
|
||||
assert_template 'bulk_edit'
|
||||
|
||||
assert_select 'ul#bulk-selection' do
|
||||
assert_select 'li', 2
|
||||
assert_select 'li a', :text => '03/23/2007 - eCookbook: 4.25 hours'
|
||||
end
|
||||
|
||||
assert_select 'form#bulk_edit_form[action=?]', '/time_entries/bulk_update' do
|
||||
# System wide custom field
|
||||
assert_select 'select[name=?]', 'time_entry[custom_field_values][10]'
|
||||
|
||||
# Activities
|
||||
assert_select 'select[name=?]', 'time_entry[activity_id]' do
|
||||
assert_select 'option[value=]', :text => '(No change)'
|
||||
assert_select 'option[value=9]', :text => 'Design'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_bulk_edit_on_different_projects
|
||||
@request.session[:user_id] = 2
|
||||
get :bulk_edit, :ids => [1, 2, 6]
|
||||
assert_response :success
|
||||
assert_template 'bulk_edit'
|
||||
end
|
||||
|
||||
def test_bulk_update
|
||||
@request.session[:user_id] = 2
|
||||
# update time entry activity
|
||||
post :bulk_update, :ids => [1, 2], :time_entry => { :activity_id => 9}
|
||||
|
||||
assert_response 302
|
||||
# check that the issues were updated
|
||||
assert_equal [9, 9], TimeEntry.find_all_by_id([1, 2]).collect {|i| i.activity_id}
|
||||
end
|
||||
|
||||
def test_bulk_update_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
post :bulk_update, :ids => [1, 2], :time_entry => { :hours => 'A'}
|
||||
|
||||
assert_response 302
|
||||
assert_match /Failed to save 2 time entrie/, flash[:error]
|
||||
end
|
||||
|
||||
def test_bulk_update_on_different_projects
|
||||
@request.session[:user_id] = 2
|
||||
# makes user a manager on the other project
|
||||
Member.create!(:user_id => 2, :project_id => 3, :role_ids => [1])
|
||||
|
||||
# update time entry activity
|
||||
post :bulk_update, :ids => [1, 2, 4], :time_entry => { :activity_id => 9 }
|
||||
|
||||
assert_response 302
|
||||
# check that the issues were updated
|
||||
assert_equal [9, 9, 9], TimeEntry.find_all_by_id([1, 2, 4]).collect {|i| i.activity_id}
|
||||
end
|
||||
|
||||
def test_bulk_update_on_different_projects_without_rights
|
||||
@request.session[:user_id] = 3
|
||||
user = User.find(3)
|
||||
action = { :controller => "timelog", :action => "bulk_update" }
|
||||
assert user.allowed_to?(action, TimeEntry.find(1).project)
|
||||
assert ! user.allowed_to?(action, TimeEntry.find(5).project)
|
||||
post :bulk_update, :ids => [1, 5], :time_entry => { :activity_id => 9 }
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_bulk_update_custom_field
|
||||
@request.session[:user_id] = 2
|
||||
post :bulk_update, :ids => [1, 2], :time_entry => { :custom_field_values => {'10' => '0'} }
|
||||
|
||||
assert_response 302
|
||||
assert_equal ["0", "0"], TimeEntry.find_all_by_id([1, 2]).collect {|i| i.custom_value_for(10).value}
|
||||
end
|
||||
|
||||
def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
|
||||
@request.session[:user_id] = 2
|
||||
post :bulk_update, :ids => [1,2], :back_url => '/time_entries'
|
||||
|
||||
assert_response :redirect
|
||||
assert_redirected_to '/time_entries'
|
||||
end
|
||||
|
||||
def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
|
||||
@request.session[:user_id] = 2
|
||||
post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
|
||||
|
||||
assert_response :redirect
|
||||
assert_redirected_to :controller => 'timelog', :action => 'index', :project_id => Project.find(1).identifier
|
||||
end
|
||||
|
||||
def test_post_bulk_update_without_edit_permission_should_be_denied
|
||||
@request.session[:user_id] = 2
|
||||
Role.find_by_name('Manager').remove_permission! :edit_time_entries
|
||||
post :bulk_update, :ids => [1,2]
|
||||
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :id => 1
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
assert_equal I18n.t(:notice_successful_delete), flash[:notice]
|
||||
assert_nil TimeEntry.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_destroy_should_fail
|
||||
# simulate that this fails (e.g. due to a plugin), see #5700
|
||||
TimeEntry.any_instance.expects(:destroy).returns(false)
|
||||
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :id => 1
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
assert_equal I18n.t(:notice_unable_delete_time_entry), flash[:error]
|
||||
assert_not_nil TimeEntry.find_by_id(1)
|
||||
end
|
||||
|
||||
def test_index_all_projects
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:total_hours)
|
||||
assert_equal "162.90", "%.2f" % assigns(:total_hours)
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/time_entries", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_index_all_projects_should_show_log_time_link
|
||||
@request.session[:user_id] = 2
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_tag 'a', :attributes => {:href => '/time_entries/new'}, :content => /Log time/
|
||||
end
|
||||
|
||||
def test_index_at_project_level
|
||||
get :index, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 4, assigns(:entries).size
|
||||
# project and subproject
|
||||
assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
|
||||
assert_not_nil assigns(:total_hours)
|
||||
assert_equal "162.90", "%.2f" % assigns(:total_hours)
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_index_at_project_level_with_date_range
|
||||
get :index, :project_id => 'ecookbook',
|
||||
:f => ['spent_on'],
|
||||
:op => {'spent_on' => '><'},
|
||||
:v => {'spent_on' => ['2007-03-20', '2007-04-30']}
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 3, assigns(:entries).size
|
||||
assert_not_nil assigns(:total_hours)
|
||||
assert_equal "12.90", "%.2f" % assigns(:total_hours)
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_index_at_project_level_with_date_range_using_from_and_to_params
|
||||
get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 3, assigns(:entries).size
|
||||
assert_not_nil assigns(:total_hours)
|
||||
assert_equal "12.90", "%.2f" % assigns(:total_hours)
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_index_at_project_level_with_period
|
||||
get :index, :project_id => 'ecookbook',
|
||||
:f => ['spent_on'],
|
||||
:op => {'spent_on' => '>t-'},
|
||||
:v => {'spent_on' => ['7']}
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_not_nil assigns(:total_hours)
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_index_at_issue_level
|
||||
get :index, :issue_id => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:entries)
|
||||
assert_equal 2, assigns(:entries).size
|
||||
assert_not_nil assigns(:total_hours)
|
||||
assert_equal 154.25, assigns(:total_hours)
|
||||
# display all time
|
||||
assert_nil assigns(:from)
|
||||
assert_nil assigns(:to)
|
||||
# TODO: remove /projects/:project_id/issues/:issue_id/time_entries routes
|
||||
# to use /issues/:issue_id/time_entries
|
||||
assert_tag :form,
|
||||
:attributes => {:action => "/projects/ecookbook/issues/1/time_entries", :id => 'query_form'}
|
||||
end
|
||||
|
||||
def test_index_should_sort_by_spent_on_and_created_on
|
||||
t1 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:00:00', :activity_id => 10)
|
||||
t2 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:05:00', :activity_id => 10)
|
||||
t3 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-15', :created_on => '2012-06-16 20:10:00', :activity_id => 10)
|
||||
|
||||
get :index, :project_id => 1,
|
||||
:f => ['spent_on'],
|
||||
:op => {'spent_on' => '><'},
|
||||
:v => {'spent_on' => ['2012-06-15', '2012-06-16']}
|
||||
assert_response :success
|
||||
assert_equal [t2, t1, t3], assigns(:entries)
|
||||
|
||||
get :index, :project_id => 1,
|
||||
:f => ['spent_on'],
|
||||
:op => {'spent_on' => '><'},
|
||||
:v => {'spent_on' => ['2012-06-15', '2012-06-16']},
|
||||
:sort => 'spent_on'
|
||||
assert_response :success
|
||||
assert_equal [t3, t1, t2], assigns(:entries)
|
||||
end
|
||||
|
||||
def test_index_with_filter_on_issue_custom_field
|
||||
issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
|
||||
entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
|
||||
|
||||
get :index, :f => ['issue.cf_2'], :op => {'issue.cf_2' => '='}, :v => {'issue.cf_2' => ['filter_on_issue_custom_field']}
|
||||
assert_response :success
|
||||
assert_equal [entry], assigns(:entries)
|
||||
end
|
||||
|
||||
def test_index_with_issue_custom_field_column
|
||||
issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {2 => 'filter_on_issue_custom_field'})
|
||||
entry = TimeEntry.generate!(:issue => issue, :hours => 2.5)
|
||||
|
||||
get :index, :c => %w(project spent_on issue comments hours issue.cf_2)
|
||||
assert_response :success
|
||||
assert_include :'issue.cf_2', assigns(:query).column_names
|
||||
assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
|
||||
end
|
||||
|
||||
def test_index_atom_feed
|
||||
get :index, :project_id => 1, :format => 'atom'
|
||||
assert_response :success
|
||||
assert_equal 'application/atom+xml', @response.content_type
|
||||
assert_not_nil assigns(:items)
|
||||
assert assigns(:items).first.is_a?(TimeEntry)
|
||||
end
|
||||
|
||||
def test_index_at_project_level_should_include_csv_export_dialog
|
||||
get :index, :project_id => 'ecookbook',
|
||||
:f => ['spent_on'],
|
||||
:op => {'spent_on' => '>='},
|
||||
:v => {'spent_on' => ['2007-04-01']},
|
||||
:c => ['spent_on', 'user']
|
||||
assert_response :success
|
||||
|
||||
assert_select '#csv-export-options' do
|
||||
assert_select 'form[action=?][method=get]', '/projects/ecookbook/time_entries.csv' do
|
||||
# filter
|
||||
assert_select 'input[name=?][value=?]', 'f[]', 'spent_on'
|
||||
assert_select 'input[name=?][value=?]', 'op[spent_on]', '>='
|
||||
assert_select 'input[name=?][value=?]', 'v[spent_on][]', '2007-04-01'
|
||||
# columns
|
||||
assert_select 'input[name=?][value=?]', 'c[]', 'spent_on'
|
||||
assert_select 'input[name=?][value=?]', 'c[]', 'user'
|
||||
assert_select 'input[name=?]', 'c[]', 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_cross_project_should_include_csv_export_dialog
|
||||
get :index
|
||||
assert_response :success
|
||||
|
||||
assert_select '#csv-export-options' do
|
||||
assert_select 'form[action=?][method=get]', '/time_entries.csv'
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_at_issue_level_should_include_csv_export_dialog
|
||||
get :index, :project_id => 'ecookbook', :issue_id => 3
|
||||
assert_response :success
|
||||
|
||||
assert_select '#csv-export-options' do
|
||||
assert_select 'form[action=?][method=get]', '/projects/ecookbook/issues/3/time_entries.csv'
|
||||
end
|
||||
end
|
||||
|
||||
def test_index_csv_all_projects
|
||||
Setting.date_format = '%m/%d/%Y'
|
||||
get :index, :format => 'csv'
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', response.content_type
|
||||
end
|
||||
|
||||
def test_index_csv
|
||||
Setting.date_format = '%m/%d/%Y'
|
||||
get :index, :project_id => 1, :format => 'csv'
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', response.content_type
|
||||
end
|
||||
end
|
|
@ -0,0 +1,211 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :trackers, :projects, :projects_trackers, :users, :issues, :custom_fields
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
@request.session[:user_id] = 1 # admin
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
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_template 'new'
|
||||
end
|
||||
|
||||
def test_create
|
||||
assert_difference 'Tracker.count' do
|
||||
post :create, :tracker => { :name => 'New tracker', :project_ids => ['1', '', ''], :custom_field_ids => ['1', '6', ''] }
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
tracker = Tracker.first(:order => 'id DESC')
|
||||
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 create_with_disabled_core_fields
|
||||
assert_difference 'Tracker.count' do
|
||||
post :create, :tracker => { :name => 'New tracker', :core_fields => ['assigned_to_id', 'fixed_version_id', ''] }
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
tracker = Tracker.first(:order => 'id DESC')
|
||||
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, :tracker => { :name => 'New tracker' }, :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, :tracker => { :name => '', :project_ids => ['1', '', ''], :custom_field_ids => ['1', '6', ''] }
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_error_tag :content => /name can't be blank/i
|
||||
end
|
||||
|
||||
def test_edit
|
||||
Tracker.find(1).project_ids = [1, 3]
|
||||
|
||||
get :edit, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
assert_tag :input, :attributes => { :name => 'tracker[project_ids][]',
|
||||
:value => '1',
|
||||
:checked => 'checked' }
|
||||
|
||||
assert_tag :input, :attributes => { :name => 'tracker[project_ids][]',
|
||||
:value => '2',
|
||||
:checked => nil }
|
||||
|
||||
assert_tag :input, :attributes => { :name => 'tracker[project_ids][]',
|
||||
:value => '',
|
||||
:type => 'hidden'}
|
||||
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, :id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
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, :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, :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, :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, :id => 1, :tracker => { :name => '' }
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_error_tag :content => /name can't be blank/i
|
||||
end
|
||||
|
||||
def test_move_lower
|
||||
tracker = Tracker.find_by_position(1)
|
||||
put :update, :id => 1, :tracker => { :move_to => 'lower' }
|
||||
assert_equal 2, tracker.reload.position
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
tracker = Tracker.create!(:name => 'Destroyable')
|
||||
assert_difference 'Tracker.count', -1 do
|
||||
delete :destroy, :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, :id => 1
|
||||
end
|
||||
assert_redirected_to :action => 'index'
|
||||
assert_not_nil flash[:error]
|
||||
end
|
||||
|
||||
def test_get_fields
|
||||
get :fields
|
||||
assert_response :success
|
||||
assert_template 'fields'
|
||||
|
||||
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, :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
|
|
@ -0,0 +1,232 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :versions, :issues, :users, :roles, :members, :member_roles, :enabled_modules, :issue_statuses, :issue_categories
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:versions)
|
||||
# Version with no date set appears
|
||||
assert assigns(:versions).include?(Version.find(3))
|
||||
# Completed version doesn't appear
|
||||
assert !assigns(:versions).include?(Version.find(1))
|
||||
# Context menu on issues
|
||||
assert_select "script", :text => Regexp.new(Regexp.escape("contextMenuInit('/issues/context_menu')"))
|
||||
# Links to versions anchors
|
||||
assert_tag 'a', :attributes => {:href => '#2.0'},
|
||||
:ancestor => {:tag => 'div', :attributes => {:id => 'sidebar'}}
|
||||
# Links to completed versions in the sidebar
|
||||
assert_tag 'a', :attributes => {:href => '/versions/1'},
|
||||
:ancestor => {:tag => 'div', :attributes => {:id => 'sidebar'}}
|
||||
end
|
||||
|
||||
def test_index_with_completed_versions
|
||||
get :index, :project_id => 1, :completed => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:versions)
|
||||
# Version with no date set appears
|
||||
assert assigns(:versions).include?(Version.find(3))
|
||||
# Completed version appears
|
||||
assert assigns(:versions).include?(Version.find(1))
|
||||
end
|
||||
|
||||
def test_index_with_tracker_ids
|
||||
get :index, :project_id => 1, :tracker_ids => [1, 3]
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:issues_by_version)
|
||||
assert_nil assigns(:issues_by_version).values.flatten.detect {|issue| issue.tracker_id == 2}
|
||||
end
|
||||
|
||||
def test_index_showing_subprojects_versions
|
||||
@subproject_version = Version.create!(:project => Project.find(3), :name => "Subproject version")
|
||||
get :index, :project_id => 1, :with_subprojects => 1
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:versions)
|
||||
|
||||
assert assigns(:versions).include?(Version.find(4)), "Shared version not found"
|
||||
assert assigns(:versions).include?(@subproject_version), "Subproject version not found"
|
||||
end
|
||||
|
||||
def test_index_should_prepend_shared_versions
|
||||
get :index, :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, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_not_nil assigns(:version)
|
||||
|
||||
assert_tag :tag => 'h2', :content => /1.0/
|
||||
end
|
||||
|
||||
def test_show_should_display_nil_counts
|
||||
with_settings :default_language => 'en' do
|
||||
get :show, :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, :project_id => '1'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
end
|
||||
|
||||
def test_new_from_issue_form
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :new, :project_id => '1'
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2 # manager
|
||||
assert_difference 'Version.count' do
|
||||
post :create, :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
|
||||
xhr :post, :create, :project_id => '1', :version => {:name => 'test_add_version_from_issue_form'}
|
||||
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_template 'create'
|
||||
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
|
||||
xhr :post, :create, :project_id => '1', :version => {:name => ''}
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'new'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_close_completed
|
||||
Version.update_all("status = 'open'")
|
||||
@request.session[:user_id] = 2
|
||||
put :close_completed, :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, :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, :id => 2,
|
||||
:version => { :name => '',
|
||||
:effective_date => Date.today.strftime("%Y-%m-%d")}
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Version.count', -1 do
|
||||
delete :destroy, :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, :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
|
||||
xhr :get, :status_by, :id => 2
|
||||
assert_response :success
|
||||
assert_template 'status_by'
|
||||
assert_template '_issue_counts'
|
||||
end
|
||||
|
||||
def test_issue_status_by_status
|
||||
xhr :get, :status_by, :id => 2, :status_by => 'status'
|
||||
assert_response :success
|
||||
assert_template 'status_by'
|
||||
assert_template '_issue_counts'
|
||||
assert_include 'Assigned', response.body
|
||||
assert_include 'Closed', response.body
|
||||
end
|
||||
end
|
|
@ -0,0 +1,195 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count') do
|
||||
xhr :post, :watch, :object_type => 'issue', :object_id => '1'
|
||||
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
|
||||
xhr :post, :watch, :object_type => 'issue', :object_id => ['1']
|
||||
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
|
||||
xhr :post, :watch, :object_type => 'issue', :object_id => ['1', '3']
|
||||
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_should_be_denied_without_permission
|
||||
Role.find(2).remove_permission! :view_issues
|
||||
@request.session[:user_id] = 3
|
||||
assert_no_difference('Watcher.count') do
|
||||
xhr :post, :watch, :object_type => 'issue', :object_id => '1'
|
||||
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
|
||||
xhr :post, :watch, :object_type => 'foo', :object_id => '1'
|
||||
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
|
||||
xhr :post, :watch, :object_type => 'issue', :object_id => '999'
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
|
||||
def test_unwatch
|
||||
@request.session[:user_id] = 3
|
||||
assert_difference('Watcher.count', -1) do
|
||||
xhr :delete, :unwatch, :object_type => 'issue', :object_id => '2'
|
||||
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
|
||||
xhr :delete, :unwatch, :object_type => 'issue', :object_id => ['1', '3']
|
||||
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
|
||||
xhr :get, :new, :object_type => 'issue', :object_id => '2'
|
||||
assert_response :success
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_new_for_new_record_with_project_id
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :new, :project_id => 1
|
||||
assert_response :success
|
||||
assert_equal Project.find(1), assigns(:project)
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_new_for_new_record_with_project_identifier
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :new, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_equal Project.find(1), assigns(:project)
|
||||
assert_match /ajax-modal/, response.body
|
||||
end
|
||||
|
||||
def test_create
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count') do
|
||||
xhr :post, :create, :object_type => 'issue', :object_id => '2', :watcher => {:user_id => '4'}
|
||||
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_multiple
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', 2) do
|
||||
xhr :post, :create, :object_type => 'issue', :object_id => '2', :watcher => {:user_ids => ['4', '7']}
|
||||
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_autocomplete_on_watchable_creation
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :autocomplete_for_user, :q => 'mi', :project_id => 'ecookbook'
|
||||
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_autocomplete_on_watchable_update
|
||||
@request.session[:user_id] = 2
|
||||
xhr :get, :autocomplete_for_user, :q => 'mi', :object_id => '2' , :object_type => 'issue', :project_id => 'ecookbook'
|
||||
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_append
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'Watcher.count' do
|
||||
xhr :post, :append, :watcher => {:user_ids => ['4', '7']}, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_include 'watchers_inputs', response.body
|
||||
assert_include 'issue[watcher_user_ids][]', response.body
|
||||
end
|
||||
end
|
||||
|
||||
def test_remove_watcher
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('Watcher.count', -1) do
|
||||
xhr :delete, :destroy, :object_type => 'issue', :object_id => '2', :user_id => '3'
|
||||
assert_response :success
|
||||
assert_match /watchers/, response.body
|
||||
end
|
||||
assert !Issue.find(2).watched_by?(User.find(3))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,165 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
fixtures :projects, :news, :users, :members
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
assert_not_nil assigns(:news)
|
||||
assert_not_nil assigns(:projects)
|
||||
assert !assigns(:projects).include?(Project.where(:is_public => false).first)
|
||||
end
|
||||
|
||||
def test_browser_language
|
||||
Setting.default_language = 'en'
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
get :index
|
||||
assert_equal :fr, @controller.current_language
|
||||
end
|
||||
|
||||
def test_browser_language_alternate
|
||||
Setting.default_language = 'en'
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'zh-TW'
|
||||
get :index
|
||||
assert_equal :"zh-TW", @controller.current_language
|
||||
end
|
||||
|
||||
def test_browser_language_alternate_not_valid
|
||||
Setting.default_language = 'en'
|
||||
@request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr-CA'
|
||||
get :index
|
||||
assert_equal :fr, @controller.current_language
|
||||
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_tag 'script',
|
||||
:attributes => {:type => "text/javascript"},
|
||||
:content => %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_no_tag 'script',
|
||||
:attributes => {:type => "text/javascript"},
|
||||
:content => %r{warnLeavingUnsaved}
|
||||
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 select" do
|
||||
assert_select "option", :text => 'Foo & Bar'
|
||||
end
|
||||
end
|
||||
|
||||
context "test_api_offset_and_limit" do
|
||||
context "without params" do
|
||||
should "return 0, 25" do
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({})
|
||||
end
|
||||
end
|
||||
|
||||
context "with limit" do
|
||||
should "return 0, limit" do
|
||||
assert_equal [0, 30], @controller.api_offset_and_limit({:limit => 30})
|
||||
end
|
||||
|
||||
should "not exceed 100" do
|
||||
assert_equal [0, 100], @controller.api_offset_and_limit({:limit => 120})
|
||||
end
|
||||
|
||||
should "not be negative" do
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:limit => -10})
|
||||
end
|
||||
end
|
||||
|
||||
context "with offset" do
|
||||
should "return offset, 25" do
|
||||
assert_equal [10, 25], @controller.api_offset_and_limit({:offset => 10})
|
||||
end
|
||||
|
||||
should "not be negative" do
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:offset => -10})
|
||||
end
|
||||
|
||||
context "and limit" do
|
||||
should "return offset, limit" do
|
||||
assert_equal [10, 50], @controller.api_offset_and_limit({:offset => 10, :limit => 50})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with page" do
|
||||
should "return offset, 25" do
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:page => 1})
|
||||
assert_equal [50, 25], @controller.api_offset_and_limit({:page => 3})
|
||||
end
|
||||
|
||||
should "not be negative" do
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:page => 0})
|
||||
assert_equal [0, 25], @controller.api_offset_and_limit({:page => -2})
|
||||
end
|
||||
|
||||
context "and limit" do
|
||||
should "return offset, limit" do
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,933 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 WikiControllerTest < ActionController::TestCase
|
||||
fixtures :projects, :users, :roles, :members, :member_roles,
|
||||
:enabled_modules, :wikis, :wiki_pages, :wiki_contents,
|
||||
:wiki_content_versions, :attachments
|
||||
|
||||
def setup
|
||||
User.current = nil
|
||||
end
|
||||
|
||||
def test_show_start_page
|
||||
get :show, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_tag :tag => 'h1', :content => /CookBook documentation/
|
||||
|
||||
# child_pages macro
|
||||
assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
|
||||
:child => { :tag => 'li',
|
||||
:child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
|
||||
:content => 'Page with an inline image' } }
|
||||
end
|
||||
|
||||
def test_export_link
|
||||
Role.anonymous.add_permission! :export_wiki_pages
|
||||
get :show, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_tag 'a', :attributes => {:href => '/projects/ecookbook/wiki/CookBook_documentation.txt'}
|
||||
end
|
||||
|
||||
def test_show_page_with_name
|
||||
get :show, :project_id => 1, :id => 'Another_page'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_tag :tag => 'h1', :content => /Another page/
|
||||
# Included page with an inline image
|
||||
assert_tag :tag => 'p', :content => /This is an inline image/
|
||||
assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3/logo.gif',
|
||||
:alt => 'This is a logo' }
|
||||
end
|
||||
|
||||
def test_show_old_version
|
||||
get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/1', :text => /Previous/
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/diff', :text => /diff/
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/3', :text => /Next/
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
|
||||
end
|
||||
|
||||
def test_show_old_version_with_attachments
|
||||
page = WikiPage.find(4)
|
||||
assert page.attachments.any?
|
||||
content = page.content
|
||||
content.text = "update"
|
||||
content.save!
|
||||
|
||||
get :show, :project_id => 'ecookbook', :id => page.title, :version => '1'
|
||||
assert_kind_of WikiContent::Version, assigns(:content)
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
end
|
||||
|
||||
def test_show_old_version_without_permission_should_be_denied
|
||||
Role.anonymous.remove_permission! :view_wiki_edits
|
||||
|
||||
get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
|
||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fprojects%2Fecookbook%2Fwiki%2FCookBook_documentation%2F2'
|
||||
end
|
||||
|
||||
def test_show_first_version
|
||||
get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1'
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
|
||||
assert_select 'a', :text => /Previous/, :count => 0
|
||||
assert_select 'a', :text => /diff/, :count => 0
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => /Next/
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
|
||||
end
|
||||
|
||||
def test_show_redirected_page
|
||||
WikiRedirect.create!(:wiki_id => 1, :title => 'Old_title', :redirects_to => 'Another_page')
|
||||
|
||||
get :show, :project_id => 'ecookbook', :id => 'Old_title'
|
||||
assert_redirected_to '/projects/ecookbook/wiki/Another_page'
|
||||
end
|
||||
|
||||
def test_show_with_sidebar
|
||||
page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
|
||||
page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
|
||||
page.save!
|
||||
|
||||
get :show, :project_id => 1, :id => 'Another_page'
|
||||
assert_response :success
|
||||
assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
|
||||
:content => /Side bar content for test_show_with_sidebar/
|
||||
end
|
||||
|
||||
def test_show_should_display_section_edit_links
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :id => 'Page with sections'
|
||||
assert_no_tag 'a', :attributes => {
|
||||
:href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=1'
|
||||
}
|
||||
assert_tag 'a', :attributes => {
|
||||
:href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
|
||||
}
|
||||
assert_tag 'a', :attributes => {
|
||||
:href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=3'
|
||||
}
|
||||
end
|
||||
|
||||
def test_show_current_version_should_display_section_edit_links
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :id => 'Page with sections', :version => 3
|
||||
|
||||
assert_tag 'a', :attributes => {
|
||||
:href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
|
||||
}
|
||||
end
|
||||
|
||||
def test_show_old_version_should_not_display_section_edit_links
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :id => 'Page with sections', :version => 2
|
||||
|
||||
assert_no_tag 'a', :attributes => {
|
||||
:href => '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
|
||||
}
|
||||
end
|
||||
|
||||
def test_show_unexistent_page_without_edit_right
|
||||
get :show, :project_id => 1, :id => 'Unexistent page'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_show_unexistent_page_with_edit_right
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :id => 'Unexistent page'
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_show_unexistent_page_with_parent_should_preselect_parent
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :id => 'Unexistent page', :parent => 'Another_page'
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag 'select', :attributes => {:name => 'wiki_page[parent_id]'},
|
||||
:child => {:tag => 'option', :attributes => {:value => '2', :selected => 'selected'}}
|
||||
end
|
||||
|
||||
def test_show_should_not_show_history_without_permission
|
||||
Role.anonymous.remove_permission! :view_wiki_edits
|
||||
get :show, :project_id => 1, :id => 'Page with sections', :version => 2
|
||||
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
def test_create_page
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'WikiPage.count' do
|
||||
assert_difference 'WikiContent.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'New page',
|
||||
:content => {:comments => 'Created the page',
|
||||
:text => "h1. New page\n\nThis is a new page",
|
||||
:version => 0}
|
||||
end
|
||||
end
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
|
||||
page = Project.find(1).wiki.find_page('New page')
|
||||
assert !page.new_record?
|
||||
assert_not_nil page.content
|
||||
assert_nil page.parent
|
||||
assert_equal 'Created the page', page.content.comments
|
||||
end
|
||||
|
||||
def test_create_page_with_attachments
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'WikiPage.count' do
|
||||
assert_difference 'Attachment.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'New page',
|
||||
:content => {:comments => 'Created the page',
|
||||
:text => "h1. New page\n\nThis is a new page",
|
||||
:version => 0},
|
||||
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
|
||||
end
|
||||
end
|
||||
page = Project.find(1).wiki.find_page('New page')
|
||||
assert_equal 1, page.attachments.count
|
||||
assert_equal 'testfile.txt', page.attachments.first.filename
|
||||
end
|
||||
|
||||
def test_create_page_with_parent
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'WikiPage.count' do
|
||||
put :update, :project_id => 1, :id => 'New page',
|
||||
:content => {:text => "h1. New page\n\nThis is a new page", :version => 0},
|
||||
:wiki_page => {:parent_id => 2}
|
||||
end
|
||||
page = Project.find(1).wiki.find_page('New page')
|
||||
assert_equal WikiPage.find(2), page.parent
|
||||
end
|
||||
|
||||
def test_edit_page
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :project_id => 'ecookbook', :id => 'Another_page'
|
||||
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
assert_tag 'textarea',
|
||||
:attributes => { :name => 'content[text]' },
|
||||
:content => "\n"+WikiPage.find_by_title('Another_page').content.text
|
||||
end
|
||||
|
||||
def test_edit_section
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 2
|
||||
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
page = WikiPage.find_by_title('Page_with_sections')
|
||||
section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
|
||||
|
||||
assert_tag 'textarea',
|
||||
:attributes => { :name => 'content[text]' },
|
||||
:content => "\n"+section
|
||||
assert_tag 'input',
|
||||
:attributes => { :name => 'section', :type => 'hidden', :value => '2' }
|
||||
assert_tag 'input',
|
||||
:attributes => { :name => 'section_hash', :type => 'hidden', :value => hash }
|
||||
end
|
||||
|
||||
def test_edit_invalid_section_should_respond_with_404
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 10
|
||||
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_update_page
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'Another_page',
|
||||
:content => {
|
||||
:comments => "my comments",
|
||||
:text => "edited",
|
||||
:version => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/wiki/Another_page'
|
||||
|
||||
page = Wiki.find(1).pages.find_by_title('Another_page')
|
||||
assert_equal "edited", page.content.text
|
||||
assert_equal 2, page.content.version
|
||||
assert_equal "my comments", page.content.comments
|
||||
end
|
||||
|
||||
def test_update_page_with_parent
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'Another_page',
|
||||
:content => {
|
||||
:comments => "my comments",
|
||||
:text => "edited",
|
||||
:version => 1
|
||||
},
|
||||
:wiki_page => {:parent_id => '1'}
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/wiki/Another_page'
|
||||
|
||||
page = Wiki.find(1).pages.find_by_title('Another_page')
|
||||
assert_equal "edited", page.content.text
|
||||
assert_equal 2, page.content.version
|
||||
assert_equal "my comments", page.content.comments
|
||||
assert_equal WikiPage.find(1), page.parent
|
||||
end
|
||||
|
||||
def test_update_page_with_failure
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_no_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'Another_page',
|
||||
:content => {
|
||||
:comments => 'a' * 300, # failure here, comment is too long
|
||||
:text => 'edited',
|
||||
:version => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
assert_error_tag :descendant => {:content => /Comment is too long/}
|
||||
assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => "\nedited"
|
||||
assert_tag :tag => 'input', :attributes => {:id => 'content_version', :value => '1'}
|
||||
end
|
||||
|
||||
def test_update_page_with_parent_change_only_should_not_create_content_version
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_no_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'Another_page',
|
||||
:content => {
|
||||
:comments => '',
|
||||
:text => Wiki.find(1).find_page('Another_page').content.text,
|
||||
:version => 1
|
||||
},
|
||||
:wiki_page => {:parent_id => '1'}
|
||||
end
|
||||
end
|
||||
end
|
||||
page = Wiki.find(1).pages.find_by_title('Another_page')
|
||||
assert_equal 1, page.content.version
|
||||
assert_equal WikiPage.find(1), page.parent
|
||||
end
|
||||
|
||||
def test_update_page_with_attachments_only_should_not_create_content_version
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_no_difference 'WikiContent::Version.count' do
|
||||
assert_difference 'Attachment.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'Another_page',
|
||||
:content => {
|
||||
:comments => '',
|
||||
:text => Wiki.find(1).find_page('Another_page').content.text,
|
||||
:version => 1
|
||||
},
|
||||
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
page = Wiki.find(1).pages.find_by_title('Another_page')
|
||||
assert_equal 1, page.content.version
|
||||
end
|
||||
|
||||
def test_update_stale_page_should_not_raise_an_error
|
||||
@request.session[:user_id] = 2
|
||||
c = Wiki.find(1).find_page('Another_page').content
|
||||
c.text = 'Previous text'
|
||||
c.save!
|
||||
assert_equal 2, c.version
|
||||
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_no_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1,
|
||||
:id => 'Another_page',
|
||||
:content => {
|
||||
:comments => 'My comments',
|
||||
:text => 'Text should not be lost',
|
||||
:version => 1
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag :div,
|
||||
:attributes => { :class => /error/ },
|
||||
:content => /Data has been updated by another user/
|
||||
assert_tag 'textarea',
|
||||
:attributes => { :name => 'content[text]' },
|
||||
:content => /Text should not be lost/
|
||||
assert_tag 'input',
|
||||
:attributes => { :name => 'content[comments]', :value => 'My comments' }
|
||||
|
||||
c.reload
|
||||
assert_equal 'Previous text', c.text
|
||||
assert_equal 2, c.version
|
||||
end
|
||||
|
||||
def test_update_section
|
||||
@request.session[:user_id] = 2
|
||||
page = WikiPage.find_by_title('Page_with_sections')
|
||||
section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
|
||||
text = page.content.text
|
||||
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1, :id => 'Page_with_sections',
|
||||
:content => {
|
||||
:text => "New section content",
|
||||
:version => 3
|
||||
},
|
||||
:section => 2,
|
||||
:section_hash => hash
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections'
|
||||
assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.reload.content.text
|
||||
end
|
||||
|
||||
def test_update_section_should_allow_stale_page_update
|
||||
@request.session[:user_id] = 2
|
||||
page = WikiPage.find_by_title('Page_with_sections')
|
||||
section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
|
||||
text = page.content.text
|
||||
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1, :id => 'Page_with_sections',
|
||||
:content => {
|
||||
:text => "New section content",
|
||||
:version => 2 # Current version is 3
|
||||
},
|
||||
:section => 2,
|
||||
:section_hash => hash
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections'
|
||||
page.reload
|
||||
assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.content.text
|
||||
assert_equal 4, page.content.version
|
||||
end
|
||||
|
||||
def test_update_section_should_not_allow_stale_section_update
|
||||
@request.session[:user_id] = 2
|
||||
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_no_difference 'WikiContent::Version.count' do
|
||||
put :update, :project_id => 1, :id => 'Page_with_sections',
|
||||
:content => {
|
||||
:comments => 'My comments',
|
||||
:text => "Text should not be lost",
|
||||
:version => 3
|
||||
},
|
||||
:section => 2,
|
||||
:section_hash => Digest::MD5.hexdigest("wrong hash")
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_tag :div,
|
||||
:attributes => { :class => /error/ },
|
||||
:content => /Data has been updated by another user/
|
||||
assert_tag 'textarea',
|
||||
:attributes => { :name => 'content[text]' },
|
||||
:content => /Text should not be lost/
|
||||
assert_tag 'input',
|
||||
:attributes => { :name => 'content[comments]', :value => 'My comments' }
|
||||
end
|
||||
|
||||
def test_preview
|
||||
@request.session[:user_id] = 2
|
||||
xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
|
||||
:content => { :comments => '',
|
||||
:text => 'this is a *previewed text*',
|
||||
:version => 3 }
|
||||
assert_response :success
|
||||
assert_template 'common/_preview'
|
||||
assert_tag :tag => 'strong', :content => /previewed text/
|
||||
end
|
||||
|
||||
def test_preview_new_page
|
||||
@request.session[:user_id] = 2
|
||||
xhr :post, :preview, :project_id => 1, :id => 'New page',
|
||||
:content => { :text => 'h1. New page',
|
||||
:comments => '',
|
||||
:version => 0 }
|
||||
assert_response :success
|
||||
assert_template 'common/_preview'
|
||||
assert_tag :tag => 'h1', :content => /New page/
|
||||
end
|
||||
|
||||
def test_history
|
||||
@request.session[:user_id] = 2
|
||||
get :history, :project_id => 'ecookbook', :id => 'CookBook_documentation'
|
||||
assert_response :success
|
||||
assert_template 'history'
|
||||
assert_not_nil assigns(:versions)
|
||||
assert_equal 3, assigns(:versions).size
|
||||
|
||||
assert_select "input[type=submit][name=commit]"
|
||||
assert_select 'td' do
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => '2'
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/annotate', :text => 'Annotate'
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => 'Delete'
|
||||
end
|
||||
end
|
||||
|
||||
def test_history_with_one_version
|
||||
@request.session[:user_id] = 2
|
||||
get :history, :project_id => 'ecookbook', :id => 'Another_page'
|
||||
assert_response :success
|
||||
assert_template 'history'
|
||||
assert_not_nil assigns(:versions)
|
||||
assert_equal 1, assigns(:versions).size
|
||||
assert_select "input[type=submit][name=commit]", false
|
||||
assert_select 'td' do
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => '1'
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1/annotate', :text => 'Annotate'
|
||||
assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => 'Delete', :count => 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_diff
|
||||
content = WikiPage.find(1).content
|
||||
assert_difference 'WikiContent::Version.count', 2 do
|
||||
content.text = "Line removed\nThis is a sample text for testing diffs"
|
||||
content.save!
|
||||
content.text = "This is a sample text for testing diffs\nLine added"
|
||||
content.save!
|
||||
end
|
||||
|
||||
get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => content.version, :version_from => (content.version - 1)
|
||||
assert_response :success
|
||||
assert_template 'diff'
|
||||
assert_select 'span.diff_out', :text => 'Line removed'
|
||||
assert_select 'span.diff_in', :text => 'Line added'
|
||||
end
|
||||
|
||||
def test_diff_with_invalid_version_should_respond_with_404
|
||||
get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_diff_with_invalid_version_from_should_respond_with_404
|
||||
get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99', :version_from => '98'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_annotate
|
||||
get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => 2
|
||||
assert_response :success
|
||||
assert_template 'annotate'
|
||||
|
||||
# Line 1
|
||||
assert_tag :tag => 'tr', :child => {
|
||||
:tag => 'th', :attributes => {:class => 'line-num'}, :content => '1', :sibling => {
|
||||
:tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/, :sibling => {
|
||||
:tag => 'td', :content => /h1\. CookBook documentation/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Line 5
|
||||
assert_tag :tag => 'tr', :child => {
|
||||
:tag => 'th', :attributes => {:class => 'line-num'}, :content => '5', :sibling => {
|
||||
:tag => 'td', :attributes => {:class => 'author'}, :content => /Redmine Admin/, :sibling => {
|
||||
:tag => 'td', :content => /Some updated \[\[documentation\]\] here/
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_annotate_with_invalid_version_should_respond_with_404
|
||||
get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_get_rename
|
||||
@request.session[:user_id] = 2
|
||||
get :rename, :project_id => 1, :id => 'Another_page'
|
||||
assert_response :success
|
||||
assert_template 'rename'
|
||||
assert_tag 'option',
|
||||
:attributes => {:value => ''},
|
||||
:content => '',
|
||||
:parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
|
||||
assert_no_tag 'option',
|
||||
:attributes => {:selected => 'selected'},
|
||||
:parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
|
||||
end
|
||||
|
||||
def test_get_rename_child_page
|
||||
@request.session[:user_id] = 2
|
||||
get :rename, :project_id => 1, :id => 'Child_1'
|
||||
assert_response :success
|
||||
assert_template 'rename'
|
||||
assert_tag 'option',
|
||||
:attributes => {:value => ''},
|
||||
:content => '',
|
||||
:parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
|
||||
assert_tag 'option',
|
||||
:attributes => {:value => '2', :selected => 'selected'},
|
||||
:content => /Another page/,
|
||||
:parent => {
|
||||
:tag => 'select',
|
||||
:attributes => {:name => 'wiki_page[parent_id]'}
|
||||
}
|
||||
end
|
||||
|
||||
def test_rename_with_redirect
|
||||
@request.session[:user_id] = 2
|
||||
post :rename, :project_id => 1, :id => 'Another_page',
|
||||
:wiki_page => { :title => 'Another renamed page',
|
||||
:redirect_existing_links => 1 }
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
|
||||
wiki = Project.find(1).wiki
|
||||
# Check redirects
|
||||
assert_not_nil wiki.find_page('Another page')
|
||||
assert_nil wiki.find_page('Another page', :with_redirect => false)
|
||||
end
|
||||
|
||||
def test_rename_without_redirect
|
||||
@request.session[:user_id] = 2
|
||||
post :rename, :project_id => 1, :id => 'Another_page',
|
||||
:wiki_page => { :title => 'Another renamed page',
|
||||
:redirect_existing_links => "0" }
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
|
||||
wiki = Project.find(1).wiki
|
||||
# Check that there's no redirects
|
||||
assert_nil wiki.find_page('Another page')
|
||||
end
|
||||
|
||||
def test_rename_with_parent_assignment
|
||||
@request.session[:user_id] = 2
|
||||
post :rename, :project_id => 1, :id => 'Another_page',
|
||||
:wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
|
||||
assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
|
||||
end
|
||||
|
||||
def test_rename_with_parent_unassignment
|
||||
@request.session[:user_id] = 2
|
||||
post :rename, :project_id => 1, :id => 'Child_1',
|
||||
:wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
|
||||
assert_nil WikiPage.find_by_title('Child_1').parent
|
||||
end
|
||||
|
||||
def test_destroy_a_page_without_children_should_not_ask_confirmation
|
||||
@request.session[:user_id] = 2
|
||||
delete :destroy, :project_id => 1, :id => 'Child_2'
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
end
|
||||
|
||||
def test_destroy_parent_should_ask_confirmation
|
||||
@request.session[:user_id] = 2
|
||||
assert_no_difference('WikiPage.count') do
|
||||
delete :destroy, :project_id => 1, :id => 'Another_page'
|
||||
end
|
||||
assert_response :success
|
||||
assert_template 'destroy'
|
||||
assert_select 'form' do
|
||||
assert_select 'input[name=todo][value=nullify]'
|
||||
assert_select 'input[name=todo][value=destroy]'
|
||||
assert_select 'input[name=todo][value=reassign]'
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy_parent_with_nullify_should_delete_parent_only
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('WikiPage.count', -1) do
|
||||
delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
|
||||
end
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
assert_nil WikiPage.find_by_id(2)
|
||||
end
|
||||
|
||||
def test_destroy_parent_with_cascade_should_delete_descendants
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('WikiPage.count', -4) do
|
||||
delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
|
||||
end
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
assert_nil WikiPage.find_by_id(2)
|
||||
assert_nil WikiPage.find_by_id(5)
|
||||
end
|
||||
|
||||
def test_destroy_parent_with_reassign
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference('WikiPage.count', -1) do
|
||||
delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
|
||||
end
|
||||
assert_redirected_to :action => 'index', :project_id => 'ecookbook'
|
||||
assert_nil WikiPage.find_by_id(2)
|
||||
assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
|
||||
end
|
||||
|
||||
def test_destroy_version
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'WikiContent::Version.count', -1 do
|
||||
assert_no_difference 'WikiContent.count' do
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
delete :destroy_version, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => 2
|
||||
assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation/history'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_index
|
||||
get :index, :project_id => 'ecookbook'
|
||||
assert_response :success
|
||||
assert_template 'index'
|
||||
pages = assigns(:pages)
|
||||
assert_not_nil pages
|
||||
assert_equal Project.find(1).wiki.pages.size, pages.size
|
||||
assert_equal pages.first.content.updated_on, pages.first.updated_on
|
||||
|
||||
assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
|
||||
:child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
|
||||
:content => 'CookBook documentation' },
|
||||
:child => { :tag => 'ul',
|
||||
:child => { :tag => 'li',
|
||||
:child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
|
||||
:content => 'Page with an inline image' } } } },
|
||||
:child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
|
||||
:content => 'Another page' } }
|
||||
end
|
||||
|
||||
def test_index_should_include_atom_link
|
||||
get :index, :project_id => 'ecookbook'
|
||||
assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
|
||||
end
|
||||
|
||||
def test_export_to_html
|
||||
@request.session[:user_id] = 2
|
||||
get :export, :project_id => 'ecookbook'
|
||||
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:pages)
|
||||
assert assigns(:pages).any?
|
||||
assert_equal "text/html", @response.content_type
|
||||
|
||||
assert_select "a[name=?]", "CookBook_documentation"
|
||||
assert_select "a[name=?]", "Another_page"
|
||||
assert_select "a[name=?]", "Page_with_an_inline_image"
|
||||
end
|
||||
|
||||
def test_export_to_pdf
|
||||
@request.session[:user_id] = 2
|
||||
get :export, :project_id => 'ecookbook', :format => 'pdf'
|
||||
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:pages)
|
||||
assert assigns(:pages).any?
|
||||
assert_equal 'application/pdf', @response.content_type
|
||||
assert_equal 'attachment; filename="ecookbook.pdf"', @response.headers['Content-Disposition']
|
||||
assert @response.body.starts_with?('%PDF')
|
||||
end
|
||||
|
||||
def test_export_without_permission_should_be_denied
|
||||
@request.session[:user_id] = 2
|
||||
Role.find_by_name('Manager').remove_permission! :export_wiki_pages
|
||||
get :export, :project_id => 'ecookbook'
|
||||
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_date_index
|
||||
get :date_index, :project_id => 'ecookbook'
|
||||
|
||||
assert_response :success
|
||||
assert_template 'date_index'
|
||||
assert_not_nil assigns(:pages)
|
||||
assert_not_nil assigns(:pages_by_date)
|
||||
|
||||
assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
|
||||
end
|
||||
|
||||
def test_not_found
|
||||
get :show, :project_id => 999
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_protect_page
|
||||
page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
|
||||
assert !page.protected?
|
||||
@request.session[:user_id] = 2
|
||||
post :protect, :project_id => 1, :id => page.title, :protected => '1'
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
|
||||
assert page.reload.protected?
|
||||
end
|
||||
|
||||
def test_unprotect_page
|
||||
page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
|
||||
assert page.protected?
|
||||
@request.session[:user_id] = 2
|
||||
post :protect, :project_id => 1, :id => page.title, :protected => '0'
|
||||
assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
|
||||
assert !page.reload.protected?
|
||||
end
|
||||
|
||||
def test_show_page_with_edit_link
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
|
||||
end
|
||||
|
||||
def test_show_page_without_edit_link
|
||||
@request.session[:user_id] = 4
|
||||
get :show, :project_id => 1
|
||||
assert_response :success
|
||||
assert_template 'show'
|
||||
assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
|
||||
end
|
||||
|
||||
def test_show_pdf
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :format => 'pdf'
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:page)
|
||||
assert_equal 'application/pdf', @response.content_type
|
||||
assert_equal 'attachment; filename="CookBook_documentation.pdf"',
|
||||
@response.headers['Content-Disposition']
|
||||
end
|
||||
|
||||
def test_show_html
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :format => 'html'
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:page)
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_equal 'attachment; filename="CookBook_documentation.html"',
|
||||
@response.headers['Content-Disposition']
|
||||
assert_tag 'h1', :content => 'CookBook documentation'
|
||||
end
|
||||
|
||||
def test_show_versioned_html
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :format => 'html', :version => 2
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:content)
|
||||
assert_equal 2, assigns(:content).version
|
||||
assert_equal 'text/html', @response.content_type
|
||||
assert_equal 'attachment; filename="CookBook_documentation.html"',
|
||||
@response.headers['Content-Disposition']
|
||||
assert_tag 'h1', :content => 'CookBook documentation'
|
||||
end
|
||||
|
||||
def test_show_txt
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :format => 'txt'
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:page)
|
||||
assert_equal 'text/plain', @response.content_type
|
||||
assert_equal 'attachment; filename="CookBook_documentation.txt"',
|
||||
@response.headers['Content-Disposition']
|
||||
assert_include 'h1. CookBook documentation', @response.body
|
||||
end
|
||||
|
||||
def test_show_versioned_txt
|
||||
@request.session[:user_id] = 2
|
||||
get :show, :project_id => 1, :format => 'txt', :version => 2
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:content)
|
||||
assert_equal 2, assigns(:content).version
|
||||
assert_equal 'text/plain', @response.content_type
|
||||
assert_equal 'attachment; filename="CookBook_documentation.txt"',
|
||||
@response.headers['Content-Disposition']
|
||||
assert_include 'h1. CookBook documentation', @response.body
|
||||
end
|
||||
|
||||
def test_edit_unprotected_page
|
||||
# Non members can edit unprotected wiki pages
|
||||
@request.session[:user_id] = 4
|
||||
get :edit, :project_id => 1, :id => 'Another_page'
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_edit_protected_page_by_nonmember
|
||||
# Non members can't edit protected wiki pages
|
||||
@request.session[:user_id] = 4
|
||||
get :edit, :project_id => 1, :id => 'CookBook_documentation'
|
||||
assert_response 403
|
||||
end
|
||||
|
||||
def test_edit_protected_page_by_member
|
||||
@request.session[:user_id] = 2
|
||||
get :edit, :project_id => 1, :id => 'CookBook_documentation'
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
end
|
||||
|
||||
def test_history_of_non_existing_page_should_return_404
|
||||
get :history, :project_id => 1, :id => 'Unknown_page'
|
||||
assert_response 404
|
||||
end
|
||||
|
||||
def test_add_attachment
|
||||
@request.session[:user_id] = 2
|
||||
assert_difference 'Attachment.count' do
|
||||
post :add_attachment, :project_id => 1, :id => 'CookBook_documentation',
|
||||
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
|
||||
end
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_equal Wiki.find(1).find_page('CookBook_documentation'), attachment.container
|
||||
end
|
||||
end
|
|
@ -0,0 +1,83 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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
|
||||
xhr :post, :edit, :id => 3, :wiki => { :start_page => 'Start page' }
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
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
|
||||
xhr :post, :edit, :id => 3, :wiki => { :start_page => '' }
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
assert_include 'errorExplanation', response.body
|
||||
assert_include 'Start page can't be blank', response.body
|
||||
end
|
||||
|
||||
def test_update
|
||||
@request.session[:user_id] = 1
|
||||
|
||||
assert_no_difference 'Wiki.count' do
|
||||
xhr :post, :edit, :id => 1, :wiki => { :start_page => 'Other start page' }
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
wiki = Project.find(1).wiki
|
||||
assert_equal 'Other start page', wiki.start_page
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
@request.session[:user_id] = 1
|
||||
post :destroy, :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, :id => 999, :confirm => 1
|
||||
assert_response 404
|
||||
end
|
||||
end
|
|
@ -0,0 +1,328 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 < ActionController::TestCase
|
||||
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
|
||||
assert_template 'index'
|
||||
|
||||
count = WorkflowTransition.count(:all, :conditions => 'role_id = 1 AND tracker_id = 2')
|
||||
assert_tag :tag => 'a', :content => count.to_s,
|
||||
:attributes => { :href => '/workflows/edit?role_id=1&tracker_id=2' }
|
||||
end
|
||||
|
||||
def test_get_edit
|
||||
get :edit
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
assert_not_nil assigns(:roles)
|
||||
assert_not_nil assigns(:trackers)
|
||||
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, :role_id => 2, :tracker_id => 1
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
# used status only
|
||||
assert_not_nil assigns(:statuses)
|
||||
assert_equal [2, 3, 5], assigns(:statuses).collect(&:id)
|
||||
|
||||
# allowed transitions
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'issue_status[3][5][]',
|
||||
:value => 'always',
|
||||
:checked => 'checked' }
|
||||
# not allowed
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'issue_status[3][2][]',
|
||||
:value => 'always',
|
||||
:checked => nil }
|
||||
# unused
|
||||
assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'issue_status[1][1][]' }
|
||||
end
|
||||
|
||||
def test_get_edit_with_role_and_tracker_and_all_statuses
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
get :edit, :role_id => 2, :tracker_id => 1, :used_statuses_only => '0'
|
||||
assert_response :success
|
||||
assert_template 'edit'
|
||||
|
||||
assert_not_nil assigns(:statuses)
|
||||
assert_equal IssueStatus.count, assigns(:statuses).size
|
||||
|
||||
assert_tag :tag => 'input', :attributes => { :type => 'checkbox',
|
||||
:name => 'issue_status[1][1][]',
|
||||
:value => 'always',
|
||||
:checked => nil }
|
||||
end
|
||||
|
||||
def test_post_edit
|
||||
post :edit, :role_id => 2, :tracker_id => 1,
|
||||
:issue_status => {
|
||||
'4' => {'5' => ['always']},
|
||||
'3' => {'1' => ['always'], '2' => ['always']}
|
||||
}
|
||||
assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1'
|
||||
|
||||
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_additional_transitions
|
||||
post :edit, :role_id => 2, :tracker_id => 1,
|
||||
:issue_status => {
|
||||
'4' => {'5' => ['always']},
|
||||
'3' => {'1' => ['author'], '2' => ['assignee'], '4' => ['author', 'assignee']}
|
||||
}
|
||||
assert_redirected_to '/workflows/edit?role_id=2&tracker_id=1'
|
||||
|
||||
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_clear_workflow
|
||||
assert WorkflowTransition.count(:conditions => {:tracker_id => 1, :role_id => 2}) > 0
|
||||
|
||||
post :edit, :role_id => 2, :tracker_id => 1
|
||||
assert_equal 0, WorkflowTransition.count(:conditions => {:tracker_id => 1, :role_id => 2})
|
||||
end
|
||||
|
||||
def test_get_permissions
|
||||
get :permissions
|
||||
|
||||
assert_response :success
|
||||
assert_template 'permissions'
|
||||
assert_not_nil assigns(:roles)
|
||||
assert_not_nil assigns(:trackers)
|
||||
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, :role_id => 1, :tracker_id => 2
|
||||
assert_response :success
|
||||
assert_template 'permissions'
|
||||
|
||||
assert_select 'input[name=role_id][value=1]'
|
||||
assert_select 'input[name=tracker_id][value=2]'
|
||||
|
||||
# Required field
|
||||
assert_select 'select[name=?]', 'permissions[assigned_to_id][2]' 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[fixed_version_id][3]' 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[due_date][3]' 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, :role_id => 1, :tracker_id => 1
|
||||
assert_response :success
|
||||
assert_template 'permissions'
|
||||
|
||||
# Custom field that is always required
|
||||
# The default option is "(Required)"
|
||||
assert_select 'select[name=?]', "permissions[#{cf.id}][3]" 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_with_role_and_tracker_and_all_statuses
|
||||
WorkflowTransition.delete_all
|
||||
|
||||
get :permissions, :role_id => 1, :tracker_id => 2, :used_statuses_only => '0'
|
||||
assert_response :success
|
||||
assert_equal IssueStatus.sorted.all, assigns(:statuses)
|
||||
end
|
||||
|
||||
def test_post_permissions
|
||||
WorkflowPermission.delete_all
|
||||
|
||||
post :permissions, :role_id => 1, :tracker_id => 2, :permissions => {
|
||||
'assigned_to_id' => {'1' => '', '2' => 'readonly', '3' => ''},
|
||||
'fixed_version_id' => {'1' => 'required', '2' => 'readonly', '3' => ''},
|
||||
'due_date' => {'1' => '', '2' => '', '3' => ''},
|
||||
}
|
||||
assert_redirected_to '/workflows/permissions?role_id=1&tracker_id=2'
|
||||
|
||||
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_post_permissions_should_clear_permissions
|
||||
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')
|
||||
wf1 = WorkflowPermission.create!(:role_id => 1, :tracker_id => 3, :old_status_id => 2, :field_name => 'fixed_version_id', :rule => 'required')
|
||||
wf2 = WorkflowPermission.create!(:role_id => 2, :tracker_id => 2, :old_status_id => 3, :field_name => 'fixed_version_id', :rule => 'readonly')
|
||||
|
||||
post :permissions, :role_id => 1, :tracker_id => 2
|
||||
assert_redirected_to '/workflows/permissions?role_id=1&tracker_id=2'
|
||||
|
||||
workflows = WorkflowPermission.all
|
||||
assert_equal 2, workflows.size
|
||||
assert wf1.reload
|
||||
assert wf2.reload
|
||||
end
|
||||
|
||||
def test_get_copy
|
||||
get :copy
|
||||
assert_response :success
|
||||
assert_template 'copy'
|
||||
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, :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, :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, :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,
|
||||
: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,
|
||||
: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').
|
||||
all.
|
||||
collect {|w| [w.old_status, w.new_status_id]}
|
||||
end
|
||||
end
|
|
@ -0,0 +1,212 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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__)
|
||||
|
||||
begin
|
||||
require 'mocha'
|
||||
rescue
|
||||
# Won't run some tests
|
||||
end
|
||||
|
||||
class AccountTest < ActionController::IntegrationTest
|
||||
fixtures :users, :roles
|
||||
|
||||
# Replace this with your real tests.
|
||||
def test_login
|
||||
get "my/page"
|
||||
assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fmy%2Fpage"
|
||||
log_user('jsmith', 'jsmith')
|
||||
|
||||
get "my/account"
|
||||
assert_response :success
|
||||
assert_template "my/account"
|
||||
end
|
||||
|
||||
def test_autologin
|
||||
user = User.find(1)
|
||||
Setting.autologin = "7"
|
||||
Token.delete_all
|
||||
|
||||
# User logs in with 'autologin' checked
|
||||
post '/login', :username => user.login, :password => 'admin', :autologin => 1
|
||||
assert_redirected_to '/my/page'
|
||||
token = Token.first
|
||||
assert_not_nil token
|
||||
assert_equal user, token.user
|
||||
assert_equal 'autologin', token.action
|
||||
assert_equal user.id, session[:user_id]
|
||||
assert_equal token.value, cookies['autologin']
|
||||
|
||||
# Session is cleared
|
||||
reset!
|
||||
User.current = nil
|
||||
# Clears user's last login timestamp
|
||||
user.update_attribute :last_login_on, nil
|
||||
assert_nil user.reload.last_login_on
|
||||
|
||||
# User comes back with his autologin cookie
|
||||
cookies[:autologin] = token.value
|
||||
get '/my/page'
|
||||
assert_response :success
|
||||
assert_template 'my/page'
|
||||
assert_equal user.id, session[:user_id]
|
||||
assert_not_nil user.reload.last_login_on
|
||||
end
|
||||
|
||||
def test_autologin_should_use_autologin_cookie_name
|
||||
Token.delete_all
|
||||
Redmine::Configuration.stubs(:[]).with('autologin_cookie_name').returns('custom_autologin')
|
||||
Redmine::Configuration.stubs(:[]).with('autologin_cookie_path').returns('/')
|
||||
Redmine::Configuration.stubs(:[]).with('autologin_cookie_secure').returns(false)
|
||||
|
||||
with_settings :autologin => '7' do
|
||||
assert_difference 'Token.count' do
|
||||
post '/login', :username => 'admin', :password => 'admin', :autologin => 1
|
||||
end
|
||||
assert_response 302
|
||||
assert cookies['custom_autologin'].present?
|
||||
token = cookies['custom_autologin']
|
||||
|
||||
# Session is cleared
|
||||
reset!
|
||||
cookies['custom_autologin'] = token
|
||||
get '/my/page'
|
||||
assert_response :success
|
||||
|
||||
assert_difference 'Token.count', -1 do
|
||||
post '/logout'
|
||||
end
|
||||
assert cookies['custom_autologin'].blank?
|
||||
end
|
||||
end
|
||||
|
||||
def test_lost_password
|
||||
Token.delete_all
|
||||
|
||||
get "account/lost_password"
|
||||
assert_response :success
|
||||
assert_template "account/lost_password"
|
||||
assert_select 'input[name=mail]'
|
||||
|
||||
post "account/lost_password", :mail => 'jSmith@somenet.foo'
|
||||
assert_redirected_to "/login"
|
||||
|
||||
token = Token.first
|
||||
assert_equal 'recovery', token.action
|
||||
assert_equal 'jsmith@somenet.foo', token.user.mail
|
||||
assert !token.expired?
|
||||
|
||||
get "account/lost_password", :token => token.value
|
||||
assert_response :success
|
||||
assert_template "account/password_recovery"
|
||||
assert_select 'input[type=hidden][name=token][value=?]', token.value
|
||||
assert_select 'input[name=new_password]'
|
||||
assert_select 'input[name=new_password_confirmation]'
|
||||
|
||||
post "account/lost_password", :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
|
||||
assert_redirected_to "/login"
|
||||
assert_equal 'Password was successfully updated.', flash[:notice]
|
||||
|
||||
log_user('jsmith', 'newpass123')
|
||||
assert_equal 0, Token.count
|
||||
end
|
||||
|
||||
def test_register_with_automatic_activation
|
||||
Setting.self_registration = '3'
|
||||
|
||||
get 'account/register'
|
||||
assert_response :success
|
||||
assert_template 'account/register'
|
||||
|
||||
post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
|
||||
:password => "newpass123", :password_confirmation => "newpass123"}
|
||||
assert_redirected_to '/my/account'
|
||||
follow_redirect!
|
||||
assert_response :success
|
||||
assert_template 'my/account'
|
||||
|
||||
user = User.find_by_login('newuser')
|
||||
assert_not_nil user
|
||||
assert user.active?
|
||||
assert_not_nil user.last_login_on
|
||||
end
|
||||
|
||||
def test_register_with_manual_activation
|
||||
Setting.self_registration = '2'
|
||||
|
||||
post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
|
||||
:password => "newpass123", :password_confirmation => "newpass123"}
|
||||
assert_redirected_to '/login'
|
||||
assert !User.find_by_login('newuser').active?
|
||||
end
|
||||
|
||||
def test_register_with_email_activation
|
||||
Setting.self_registration = '1'
|
||||
Token.delete_all
|
||||
|
||||
post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
|
||||
:password => "newpass123", :password_confirmation => "newpass123"}
|
||||
assert_redirected_to '/login'
|
||||
assert !User.find_by_login('newuser').active?
|
||||
|
||||
token = Token.first
|
||||
assert_equal 'register', token.action
|
||||
assert_equal 'newuser@foo.bar', token.user.mail
|
||||
assert !token.expired?
|
||||
|
||||
get 'account/activate', :token => token.value
|
||||
assert_redirected_to '/login'
|
||||
log_user('newuser', 'newpass123')
|
||||
end
|
||||
|
||||
def test_onthefly_registration
|
||||
# disable registration
|
||||
Setting.self_registration = '0'
|
||||
AuthSource.expects(:authenticate).returns({:login => 'foo', :firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com', :auth_source_id => 66})
|
||||
|
||||
post '/login', :username => 'foo', :password => 'bar'
|
||||
assert_redirected_to '/my/page'
|
||||
|
||||
user = User.find_by_login('foo')
|
||||
assert user.is_a?(User)
|
||||
assert_equal 66, user.auth_source_id
|
||||
assert user.hashed_password.blank?
|
||||
end
|
||||
|
||||
def test_onthefly_registration_with_invalid_attributes
|
||||
# disable registration
|
||||
Setting.self_registration = '0'
|
||||
AuthSource.expects(:authenticate).returns({:login => 'foo', :lastname => 'Smith', :auth_source_id => 66})
|
||||
|
||||
post '/login', :username => 'foo', :password => 'bar'
|
||||
assert_response :success
|
||||
assert_template 'account/register'
|
||||
assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
|
||||
assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
|
||||
assert_no_tag :input, :attributes => { :name => 'user[login]' }
|
||||
assert_no_tag :input, :attributes => { :name => 'user[password]' }
|
||||
|
||||
post 'account/register', :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
|
||||
assert_redirected_to '/my/account'
|
||||
|
||||
user = User.find_by_login('foo')
|
||||
assert user.is_a?(User)
|
||||
assert_equal 66, user.auth_source_id
|
||||
assert user.hashed_password.blank?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 AdminTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def test_add_user
|
||||
log_user("admin", "admin")
|
||||
get "/users/new"
|
||||
assert_response :success
|
||||
assert_template "users/new"
|
||||
post "/users",
|
||||
:user => { :login => "psmith", :firstname => "Paul",
|
||||
:lastname => "Smith", :mail => "psmith@somenet.foo",
|
||||
:language => "en", :password => "psmith09",
|
||||
:password_confirmation => "psmith09" }
|
||||
|
||||
user = User.find_by_login("psmith")
|
||||
assert_kind_of User, user
|
||||
assert_redirected_to "/users/#{ user.id }/edit"
|
||||
|
||||
logged_user = User.try_to_login("psmith", "psmith09")
|
||||
assert_kind_of User, logged_user
|
||||
assert_equal "Paul", logged_user.firstname
|
||||
|
||||
put "users/#{user.id}", :id => user.id, :user => { :status => User::STATUS_LOCKED }
|
||||
assert_redirected_to "/users/#{ user.id }/edit"
|
||||
locked_user = User.try_to_login("psmith", "psmith09")
|
||||
assert_equal nil, locked_user
|
||||
end
|
||||
|
||||
test "Add a user as an anonymous user should fail" do
|
||||
post '/users',
|
||||
:user => { :login => 'psmith', :firstname => 'Paul'},
|
||||
:password => "psmith09", :password_confirmation => "psmith09"
|
||||
assert_response :redirect
|
||||
assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fusers"
|
||||
end
|
||||
end
|
|
@ -0,0 +1,149 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::AttachmentsTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:attachments
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
set_fixtures_attachments_directory
|
||||
end
|
||||
|
||||
def teardown
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
test "GET /attachments/:id.xml should return the attachment" do
|
||||
get '/attachments/7.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'attachment',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '7',
|
||||
:sibling => {
|
||||
:tag => 'filename',
|
||||
:content => 'archive.zip',
|
||||
:sibling => {
|
||||
:tag => 'content_url',
|
||||
:content => 'http://www.example.com/attachments/download/7/archive.zip'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
test "GET /attachments/:id.xml should deny access without credentials" do
|
||||
get '/attachments/7.xml'
|
||||
assert_response 401
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
test "GET /attachments/download/:id/:filename should return the attachment content" do
|
||||
get '/attachments/download/7/archive.zip', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/octet-stream', @response.content_type
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
test "GET /attachments/download/:id/:filename should deny access without credentials" do
|
||||
get '/attachments/download/7/archive.zip'
|
||||
assert_response 302
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
test "POST /uploads.xml should return the token" do
|
||||
set_tmp_attachments_directory
|
||||
assert_difference 'Attachment.count' do
|
||||
post '/uploads.xml', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', response.content_type
|
||||
end
|
||||
|
||||
xml = Hash.from_xml(response.body)
|
||||
assert_kind_of Hash, xml['upload']
|
||||
token = xml['upload']['token']
|
||||
assert_not_nil token
|
||||
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_equal token, attachment.token
|
||||
assert_nil attachment.container
|
||||
assert_equal 2, attachment.author_id
|
||||
assert_equal 'File content'.size, attachment.filesize
|
||||
assert attachment.content_type.blank?
|
||||
assert attachment.filename.present?
|
||||
assert_match /\d+_[0-9a-z]+/, attachment.diskfile
|
||||
assert File.exist?(attachment.diskfile)
|
||||
assert_equal 'File content', File.read(attachment.diskfile)
|
||||
end
|
||||
|
||||
test "POST /uploads.json should return the token" do
|
||||
set_tmp_attachments_directory
|
||||
assert_difference 'Attachment.count' do
|
||||
post '/uploads.json', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
|
||||
assert_response :created
|
||||
assert_equal 'application/json', response.content_type
|
||||
end
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json['upload']
|
||||
token = json['upload']['token']
|
||||
assert_not_nil token
|
||||
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_equal token, attachment.token
|
||||
end
|
||||
|
||||
test "POST /uploads.xml should accept :filename param as the attachment filename" do
|
||||
set_tmp_attachments_directory
|
||||
assert_difference 'Attachment.count' do
|
||||
post '/uploads.xml?filename=test.txt', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
|
||||
assert_response :created
|
||||
end
|
||||
|
||||
attachment = Attachment.order('id DESC').first
|
||||
assert_equal 'test.txt', attachment.filename
|
||||
assert_match /_test\.txt$/, attachment.diskfile
|
||||
end
|
||||
|
||||
test "POST /uploads.xml should not accept other content types" do
|
||||
set_tmp_attachments_directory
|
||||
assert_no_difference 'Attachment.count' do
|
||||
post '/uploads.xml', 'PNG DATA', {"CONTENT_TYPE" => 'image/png'}.merge(credentials('jsmith'))
|
||||
assert_response 406
|
||||
end
|
||||
end
|
||||
|
||||
test "POST /uploads.xml should return errors if file is too big" do
|
||||
set_tmp_attachments_directory
|
||||
with_settings :attachment_max_size => 1 do
|
||||
assert_no_difference 'Attachment.count' do
|
||||
post '/uploads.xml', ('x' * 2048), {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
|
||||
assert_response 422
|
||||
assert_tag 'error', :content => /exceeds the maximum allowed file size/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::AuthenticationTest < Redmine::ApiTest::Base
|
||||
fixtures :users
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.rest_api_enabled = '0'
|
||||
end
|
||||
|
||||
def test_api_request_should_not_use_user_session
|
||||
log_user('jsmith', 'jsmith')
|
||||
|
||||
get '/users/current'
|
||||
assert_response :success
|
||||
|
||||
get '/users/current.json'
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
def test_api_should_accept_switch_user_header_for_admin_user
|
||||
user = User.find(1)
|
||||
su = User.find(4)
|
||||
|
||||
get '/users/current', {}, {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login}
|
||||
assert_response :success
|
||||
assert_equal su, assigns(:user)
|
||||
assert_equal su, User.current
|
||||
end
|
||||
|
||||
def test_api_should_respond_with_412_when_trying_to_switch_to_a_invalid_user
|
||||
get '/users/current', {}, {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => 'foobar'}
|
||||
assert_response 412
|
||||
end
|
||||
|
||||
def test_api_should_respond_with_412_when_trying_to_switch_to_a_locked_user
|
||||
user = User.find(5)
|
||||
assert user.locked?
|
||||
|
||||
get '/users/current', {}, {'X-Redmine-API-Key' => User.find(1).api_key, 'X-Redmine-Switch-User' => user.login}
|
||||
assert_response 412
|
||||
end
|
||||
|
||||
def test_api_should_not_accept_switch_user_header_for_non_admin_user
|
||||
user = User.find(2)
|
||||
su = User.find(4)
|
||||
|
||||
get '/users/current', {}, {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login}
|
||||
assert_response :success
|
||||
assert_equal user, assigns(:user)
|
||||
assert_equal user, User.current
|
||||
end
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::DisabledRestApiTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '0'
|
||||
Setting.login_required = '1'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.rest_api_enabled = '1'
|
||||
Setting.login_required = '0'
|
||||
end
|
||||
|
||||
def test_with_a_valid_api_token
|
||||
@user = User.generate!
|
||||
@token = Token.create!(:user => @user, :action => 'api')
|
||||
|
||||
get "/news.xml?key=#{@token.value}"
|
||||
assert_response :unauthorized
|
||||
assert_equal User.anonymous, User.current
|
||||
|
||||
get "/news.json?key=#{@token.value}"
|
||||
assert_response :unauthorized
|
||||
assert_equal User.anonymous, User.current
|
||||
end
|
||||
|
||||
def test_with_valid_username_password_http_authentication
|
||||
@user = User.generate! do |user|
|
||||
user.password = 'my_password'
|
||||
end
|
||||
|
||||
get "/news.xml", nil, credentials(@user.login, 'my_password')
|
||||
assert_response :unauthorized
|
||||
assert_equal User.anonymous, User.current
|
||||
|
||||
get "/news.json", nil, credentials(@user.login, 'my_password')
|
||||
assert_response :unauthorized
|
||||
assert_equal User.anonymous, User.current
|
||||
end
|
||||
|
||||
def test_with_valid_token_http_authentication
|
||||
@user = User.generate!
|
||||
@token = Token.create!(:user => @user, :action => 'api')
|
||||
|
||||
get "/news.xml", nil, credentials(@token.value, 'X')
|
||||
assert_response :unauthorized
|
||||
assert_equal User.anonymous, User.current
|
||||
|
||||
get "/news.json", nil, credentials(@token.value, 'X')
|
||||
assert_response :unauthorized
|
||||
assert_equal User.anonymous, User.current
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::EnumerationsTest < Redmine::ApiTest::Base
|
||||
fixtures :enumerations
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/enumerations/issue_priorities" do
|
||||
context "GET" do
|
||||
|
||||
should "return priorities" do
|
||||
get '/enumerations/issue_priorities.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', response.content_type
|
||||
assert_select 'issue_priorities[type=array]' do
|
||||
assert_select 'issue_priority' do
|
||||
assert_select 'id', :text => '6'
|
||||
assert_select 'name', :text => 'High'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,212 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base
|
||||
fixtures :users, :groups_users
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "GET /groups" do
|
||||
context ".xml" do
|
||||
should "require authentication" do
|
||||
get '/groups.xml'
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
should "return groups" do
|
||||
get '/groups.xml', {}, credentials('admin')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', response.content_type
|
||||
|
||||
assert_select 'groups' do
|
||||
assert_select 'group' do
|
||||
assert_select 'name', :text => 'A Team'
|
||||
assert_select 'id', :text => '10'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "require authentication" do
|
||||
get '/groups.json'
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
should "return groups" do
|
||||
get '/groups.json', {}, credentials('admin')
|
||||
assert_response :success
|
||||
assert_equal 'application/json', response.content_type
|
||||
|
||||
json = MultiJson.load(response.body)
|
||||
groups = json['groups']
|
||||
assert_kind_of Array, groups
|
||||
group = groups.detect {|g| g['name'] == 'A Team'}
|
||||
assert_not_nil group
|
||||
assert_equal({'id' => 10, 'name' => 'A Team'}, group)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "GET /groups/:id" do
|
||||
context ".xml" do
|
||||
should "return the group with its users" do
|
||||
get '/groups/10.xml', {}, credentials('admin')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', response.content_type
|
||||
|
||||
assert_select 'group' do
|
||||
assert_select 'name', :text => 'A Team'
|
||||
assert_select 'id', :text => '10'
|
||||
end
|
||||
end
|
||||
|
||||
should "include users if requested" do
|
||||
get '/groups/10.xml?include=users', {}, credentials('admin')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', response.content_type
|
||||
|
||||
assert_select 'group' do
|
||||
assert_select 'users' do
|
||||
assert_select 'user', Group.find(10).users.count
|
||||
assert_select 'user[id=8]'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "include memberships if requested" do
|
||||
get '/groups/10.xml?include=memberships', {}, credentials('admin')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', response.content_type
|
||||
|
||||
assert_select 'group' do
|
||||
assert_select 'memberships'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /groups" do
|
||||
context "with valid parameters" do
|
||||
context ".xml" do
|
||||
should "create groups" do
|
||||
assert_difference('Group.count') do
|
||||
post '/groups.xml', {:group => {:name => 'Test', :user_ids => [2, 3]}}, credentials('admin')
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', response.content_type
|
||||
end
|
||||
|
||||
group = Group.order('id DESC').first
|
||||
assert_equal 'Test', group.name
|
||||
assert_equal [2, 3], group.users.map(&:id).sort
|
||||
|
||||
assert_select 'group' do
|
||||
assert_select 'name', :text => 'Test'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
context ".xml" do
|
||||
should "return errors" do
|
||||
assert_no_difference('Group.count') do
|
||||
post '/groups.xml', {:group => {:name => ''}}, credentials('admin')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', response.content_type
|
||||
|
||||
assert_select 'errors' do
|
||||
assert_select 'error', :text => /Name can't be blank/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /groups/:id" do
|
||||
context "with valid parameters" do
|
||||
context ".xml" do
|
||||
should "update the group" do
|
||||
put '/groups/10.xml', {:group => {:name => 'New name', :user_ids => [2, 3]}}, credentials('admin')
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
|
||||
group = Group.find(10)
|
||||
assert_equal 'New name', group.name
|
||||
assert_equal [2, 3], group.users.map(&:id).sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
context ".xml" do
|
||||
should "return errors" do
|
||||
put '/groups/10.xml', {:group => {:name => ''}}, credentials('admin')
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', response.content_type
|
||||
|
||||
assert_select 'errors' do
|
||||
assert_select 'error', :text => /Name can't be blank/
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /groups/:id" do
|
||||
context ".xml" do
|
||||
should "delete the group" do
|
||||
assert_difference 'Group.count', -1 do
|
||||
delete '/groups/10.xml', {}, credentials('admin')
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /groups/:id/users" do
|
||||
context ".xml" do
|
||||
should "add user to the group" do
|
||||
assert_difference 'Group.find(10).users.count' do
|
||||
post '/groups/10/users.xml', {:user_id => 5}, credentials('admin')
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
assert_include User.find(5), Group.find(10).users
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /groups/:id/users/:user_id" do
|
||||
context ".xml" do
|
||||
should "remove user from the group" do
|
||||
assert_difference 'Group.find(10).users.count', -1 do
|
||||
delete '/groups/10/users/8.xml', {}, credentials('admin')
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
assert_not_include User.find(8), Group.find(10).users
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,54 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::HttpBasicLoginTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
Setting.login_required = '1'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.rest_api_enabled = '0'
|
||||
Setting.login_required = '0'
|
||||
end
|
||||
|
||||
# Using the NewsController because it's a simple API.
|
||||
context "get /news" do
|
||||
setup do
|
||||
project = Project.find('onlinestore')
|
||||
EnabledModule.create(:project => project, :name => 'news')
|
||||
end
|
||||
|
||||
context "in :xml format" do
|
||||
should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.xml")
|
||||
end
|
||||
|
||||
context "in :json format" do
|
||||
should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.json")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::HttpBasicLoginWithApiTokenTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
Setting.login_required = '1'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.rest_api_enabled = '0'
|
||||
Setting.login_required = '0'
|
||||
end
|
||||
|
||||
# Using the NewsController because it's a simple API.
|
||||
context "get /news" do
|
||||
|
||||
context "in :xml format" do
|
||||
should_allow_http_basic_auth_with_key(:get, "/news.xml")
|
||||
end
|
||||
|
||||
context "in :json format" do
|
||||
should_allow_http_basic_auth_with_key(:get, "/news.json")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,126 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::IssueCategoriesTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :users, :issue_categories, :issues,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "GET /projects/:project_id/issue_categories.xml" do
|
||||
should "return issue categories" do
|
||||
get '/projects/1/issue_categories.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'issue_categories',
|
||||
:child => {:tag => 'issue_category', :child => {:tag => 'id', :content => '2'}}
|
||||
end
|
||||
end
|
||||
|
||||
context "GET /issue_categories/2.xml" do
|
||||
should "return requested issue category" do
|
||||
get '/issue_categories/2.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'issue_category',
|
||||
:child => {:tag => 'id', :content => '2'}
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /projects/:project_id/issue_categories.xml" do
|
||||
should "return create issue category" do
|
||||
assert_difference 'IssueCategory.count' do
|
||||
post '/projects/1/issue_categories.xml', {:issue_category => {:name => 'API'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
category = IssueCategory.first(:order => 'id DESC')
|
||||
assert_equal 'API', category.name
|
||||
assert_equal 1, category.project_id
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
should "return errors" do
|
||||
assert_no_difference 'IssueCategory.count' do
|
||||
post '/projects/1/issue_categories.xml', {:issue_category => {:name => ''}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /issue_categories/2.xml" do
|
||||
context "with valid parameters" do
|
||||
should "update issue category" do
|
||||
assert_no_difference 'IssueCategory.count' do
|
||||
put '/issue_categories/2.xml', {:issue_category => {:name => 'API Update'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_equal 'API Update', IssueCategory.find(2).name
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
should "return errors" do
|
||||
assert_no_difference 'IssueCategory.count' do
|
||||
put '/issue_categories/2.xml', {:issue_category => {:name => ''}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /issue_categories/1.xml" do
|
||||
should "destroy issue categories" do
|
||||
assert_difference 'IssueCategory.count', -1 do
|
||||
delete '/issue_categories/1.xml', {}, credentials('jsmith')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_nil IssueCategory.find_by_id(1)
|
||||
end
|
||||
|
||||
should "reassign issues with :reassign_to_id param" do
|
||||
issue_count = Issue.count(:conditions => {:category_id => 1})
|
||||
assert issue_count > 0
|
||||
|
||||
assert_difference 'IssueCategory.count', -1 do
|
||||
assert_difference 'Issue.count(:conditions => {:category_id => 2})', 3 do
|
||||
delete '/issue_categories/1.xml', {:reassign_to_id => 2}, credentials('jsmith')
|
||||
end
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_nil IssueCategory.find_by_id(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,106 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::IssueRelationsTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:issue_relations
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/issues/:issue_id/relations" do
|
||||
context "GET" do
|
||||
should "return issue relations" do
|
||||
get '/issues/9/relations.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag :tag => 'relations',
|
||||
:attributes => { :type => 'array' },
|
||||
:child => {
|
||||
:tag => 'relation',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '1'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "POST" do
|
||||
should "create a relation" do
|
||||
assert_difference('IssueRelation.count') do
|
||||
post '/issues/2/relations.xml', {:relation => {:issue_to_id => 7, :relation_type => 'relates'}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
relation = IssueRelation.first(:order => 'id DESC')
|
||||
assert_equal 2, relation.issue_from_id
|
||||
assert_equal 7, relation.issue_to_id
|
||||
assert_equal 'relates', relation.relation_type
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'relation', :child => {:tag => 'id', :content => relation.id.to_s}
|
||||
end
|
||||
|
||||
context "with failure" do
|
||||
should "return the errors" do
|
||||
assert_no_difference('IssueRelation.count') do
|
||||
post '/issues/2/relations.xml', {:relation => {:issue_to_id => 7, :relation_type => 'foo'}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_tag :errors, :child => {:tag => 'error', :content => /relation_type is not included in the list/}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "/relations/:id" do
|
||||
context "GET" do
|
||||
should "return the relation" do
|
||||
get '/relations/2.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'relation', :child => {:tag => 'id', :content => '2'}
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE" do
|
||||
should "delete the relation" do
|
||||
assert_difference('IssueRelation.count', -1) do
|
||||
delete '/relations/2.xml', {}, credentials('jsmith')
|
||||
end
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_nil IssueRelation.find_by_id(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,51 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::IssueStatusesTest < Redmine::ApiTest::Base
|
||||
fixtures :issue_statuses
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/issue_statuses" do
|
||||
context "GET" do
|
||||
|
||||
should "return issue statuses" do
|
||||
get '/issue_statuses.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'issue_statuses',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'issue_status',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2',
|
||||
:sibling => {
|
||||
:tag => 'name',
|
||||
:content => 'Assigned'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,846 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:issues,
|
||||
:issue_statuses,
|
||||
:issue_relations,
|
||||
: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,
|
||||
:attachments
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/issues" do
|
||||
# Use a private project to make sure auth is really working and not just
|
||||
# only showing public issues.
|
||||
should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
|
||||
|
||||
should "contain metadata" do
|
||||
get '/issues.xml'
|
||||
|
||||
assert_tag :tag => 'issues',
|
||||
:attributes => {
|
||||
:type => 'array',
|
||||
:total_count => assigns(:issue_count),
|
||||
:limit => 25,
|
||||
:offset => 0
|
||||
}
|
||||
end
|
||||
|
||||
context "with offset and limit" do
|
||||
should "use the params" do
|
||||
get '/issues.xml?offset=2&limit=3'
|
||||
|
||||
assert_equal 3, assigns(:limit)
|
||||
assert_equal 2, assigns(:offset)
|
||||
assert_tag :tag => 'issues', :children => {:count => 3, :only => {:tag => 'issue'}}
|
||||
end
|
||||
end
|
||||
|
||||
context "with nometa param" do
|
||||
should "not contain metadata" do
|
||||
get '/issues.xml?nometa=1'
|
||||
|
||||
assert_tag :tag => 'issues',
|
||||
:attributes => {
|
||||
:type => 'array',
|
||||
:total_count => nil,
|
||||
:limit => nil,
|
||||
:offset => nil
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "with nometa header" do
|
||||
should "not contain metadata" do
|
||||
get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
|
||||
|
||||
assert_tag :tag => 'issues',
|
||||
:attributes => {
|
||||
:type => 'array',
|
||||
:total_count => nil,
|
||||
:limit => nil,
|
||||
:offset => nil
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "with relations" do
|
||||
should "display relations" do
|
||||
get '/issues.xml?include=relations'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'relations',
|
||||
:parent => {:tag => 'issue', :child => {:tag => 'id', :content => '3'}},
|
||||
:children => {:count => 1},
|
||||
:child => {
|
||||
:tag => 'relation',
|
||||
:attributes => {:id => '2', :issue_id => '2', :issue_to_id => '3',
|
||||
:relation_type => 'relates'}
|
||||
}
|
||||
assert_tag 'relations',
|
||||
:parent => {:tag => 'issue', :child => {:tag => 'id', :content => '1'}},
|
||||
:children => {:count => 0}
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid query params" do
|
||||
should "return errors" do
|
||||
get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Start date can't be blank"}
|
||||
end
|
||||
end
|
||||
|
||||
context "with custom field filter" do
|
||||
should "show only issues with the custom field value" do
|
||||
get '/issues.xml',
|
||||
{:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='},
|
||||
:v => {:cf_1 => ['MySQL']}}
|
||||
expected_ids = Issue.visible.all(
|
||||
:include => :custom_values,
|
||||
:conditions => {:custom_values => {:custom_field_id => 1, :value => 'MySQL'}}).map(&:id)
|
||||
assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
|
||||
ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with custom field filter (shorthand method)" do
|
||||
should "show only issues with the custom field value" do
|
||||
get '/issues.xml', { :cf_1 => 'MySQL' }
|
||||
|
||||
expected_ids = Issue.visible.all(
|
||||
:include => :custom_values,
|
||||
:conditions => {:custom_values => {:custom_field_id => 1, :value => 'MySQL'}}).map(&:id)
|
||||
|
||||
assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
|
||||
ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "/index.json" do
|
||||
should_allow_api_authentication(:get, "/projects/private-child/issues.json")
|
||||
end
|
||||
|
||||
context "/index.xml with filter" do
|
||||
should "show only issues with the status_id" do
|
||||
get '/issues.xml?status_id=5'
|
||||
|
||||
expected_ids = Issue.visible.all(:conditions => {:status_id => 5}).map(&:id)
|
||||
|
||||
assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
|
||||
ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "/index.json with filter" do
|
||||
should "show only issues with the status_id" do
|
||||
get '/issues.json?status_id=5'
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
status_ids_used = json['issues'].collect {|j| j['status']['id'] }
|
||||
assert_equal 3, status_ids_used.length
|
||||
assert status_ids_used.all? {|id| id == 5 }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Issue 6 is on a private project
|
||||
context "/issues/6.xml" do
|
||||
should_allow_api_authentication(:get, "/issues/6.xml")
|
||||
end
|
||||
|
||||
context "/issues/6.json" do
|
||||
should_allow_api_authentication(:get, "/issues/6.json")
|
||||
end
|
||||
|
||||
context "GET /issues/:id" do
|
||||
context "with journals" do
|
||||
context ".xml" do
|
||||
should "display journals" do
|
||||
get '/issues/1.xml?include=journals'
|
||||
|
||||
assert_tag :tag => 'issue',
|
||||
:child => {
|
||||
:tag => 'journals',
|
||||
:attributes => { :type => 'array' },
|
||||
:child => {
|
||||
:tag => 'journal',
|
||||
:attributes => { :id => '1'},
|
||||
:child => {
|
||||
:tag => 'details',
|
||||
:attributes => { :type => 'array' },
|
||||
:child => {
|
||||
:tag => 'detail',
|
||||
:attributes => { :name => 'status_id' },
|
||||
:child => {
|
||||
:tag => 'old_value',
|
||||
:content => '1',
|
||||
:sibling => {
|
||||
:tag => 'new_value',
|
||||
:content => '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with custom fields" do
|
||||
context ".xml" do
|
||||
should "display custom fields" do
|
||||
get '/issues/3.xml'
|
||||
|
||||
assert_tag :tag => 'issue',
|
||||
:child => {
|
||||
:tag => 'custom_fields',
|
||||
:attributes => { :type => 'array' },
|
||||
:child => {
|
||||
:tag => 'custom_field',
|
||||
:attributes => { :id => '1'},
|
||||
:child => {
|
||||
:tag => 'value',
|
||||
:content => 'MySQL'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_nothing_raised do
|
||||
Hash.from_xml(response.body).to_xml
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with multi custom fields" do
|
||||
setup do
|
||||
field = CustomField.find(1)
|
||||
field.update_attribute :multiple, true
|
||||
issue = Issue.find(3)
|
||||
issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
|
||||
issue.save!
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "display custom fields" do
|
||||
get '/issues/3.xml'
|
||||
assert_response :success
|
||||
assert_tag :tag => 'issue',
|
||||
:child => {
|
||||
:tag => 'custom_fields',
|
||||
:attributes => { :type => 'array' },
|
||||
:child => {
|
||||
:tag => 'custom_field',
|
||||
:attributes => { :id => '1'},
|
||||
:child => {
|
||||
:tag => 'value',
|
||||
:attributes => { :type => 'array' },
|
||||
:children => { :count => 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml = Hash.from_xml(response.body)
|
||||
custom_fields = xml['issue']['custom_fields']
|
||||
assert_kind_of Array, custom_fields
|
||||
field = custom_fields.detect {|f| f['id'] == '1'}
|
||||
assert_kind_of Hash, field
|
||||
assert_equal ['MySQL', 'Oracle'], field['value'].sort
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "display custom fields" do
|
||||
get '/issues/3.json'
|
||||
assert_response :success
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
custom_fields = json['issue']['custom_fields']
|
||||
assert_kind_of Array, custom_fields
|
||||
field = custom_fields.detect {|f| f['id'] == 1}
|
||||
assert_kind_of Hash, field
|
||||
assert_equal ['MySQL', 'Oracle'], field['value'].sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with empty value for multi custom field" do
|
||||
setup do
|
||||
field = CustomField.find(1)
|
||||
field.update_attribute :multiple, true
|
||||
issue = Issue.find(3)
|
||||
issue.custom_field_values = {1 => ['']}
|
||||
issue.save!
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "display custom fields" do
|
||||
get '/issues/3.xml'
|
||||
assert_response :success
|
||||
assert_tag :tag => 'issue',
|
||||
:child => {
|
||||
:tag => 'custom_fields',
|
||||
:attributes => { :type => 'array' },
|
||||
:child => {
|
||||
:tag => 'custom_field',
|
||||
:attributes => { :id => '1'},
|
||||
:child => {
|
||||
:tag => 'value',
|
||||
:attributes => { :type => 'array' },
|
||||
:children => { :count => 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml = Hash.from_xml(response.body)
|
||||
custom_fields = xml['issue']['custom_fields']
|
||||
assert_kind_of Array, custom_fields
|
||||
field = custom_fields.detect {|f| f['id'] == '1'}
|
||||
assert_kind_of Hash, field
|
||||
assert_equal [], field['value']
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "display custom fields" do
|
||||
get '/issues/3.json'
|
||||
assert_response :success
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
custom_fields = json['issue']['custom_fields']
|
||||
assert_kind_of Array, custom_fields
|
||||
field = custom_fields.detect {|f| f['id'] == 1}
|
||||
assert_kind_of Hash, field
|
||||
assert_equal [], field['value'].sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with attachments" do
|
||||
context ".xml" do
|
||||
should "display attachments" do
|
||||
get '/issues/3.xml?include=attachments'
|
||||
|
||||
assert_tag :tag => 'issue',
|
||||
:child => {
|
||||
:tag => 'attachments',
|
||||
:children => {:count => 5},
|
||||
:child => {
|
||||
:tag => 'attachment',
|
||||
:child => {
|
||||
:tag => 'filename',
|
||||
:content => 'source.rb',
|
||||
:sibling => {
|
||||
:tag => 'content_url',
|
||||
:content => 'http://www.example.com/attachments/download/4/source.rb'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with subtasks" do
|
||||
setup do
|
||||
@c1 = Issue.create!(
|
||||
:status_id => 1, :subject => "child c1",
|
||||
:tracker_id => 1, :project_id => 1, :author_id => 1,
|
||||
:parent_issue_id => 1
|
||||
)
|
||||
@c2 = Issue.create!(
|
||||
:status_id => 1, :subject => "child c2",
|
||||
:tracker_id => 1, :project_id => 1, :author_id => 1,
|
||||
:parent_issue_id => 1
|
||||
)
|
||||
@c3 = Issue.create!(
|
||||
:status_id => 1, :subject => "child c3",
|
||||
:tracker_id => 1, :project_id => 1, :author_id => 1,
|
||||
:parent_issue_id => @c1.id
|
||||
)
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "display children" do
|
||||
get '/issues/1.xml?include=children'
|
||||
|
||||
assert_tag :tag => 'issue',
|
||||
:child => {
|
||||
:tag => 'children',
|
||||
:children => {:count => 2},
|
||||
:child => {
|
||||
:tag => 'issue',
|
||||
:attributes => {:id => @c1.id.to_s},
|
||||
:child => {
|
||||
:tag => 'subject',
|
||||
:content => 'child c1',
|
||||
:sibling => {
|
||||
:tag => 'children',
|
||||
:children => {:count => 1},
|
||||
:child => {
|
||||
:tag => 'issue',
|
||||
:attributes => {:id => @c3.id.to_s}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "display children" do
|
||||
get '/issues/1.json?include=children'
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_equal([
|
||||
{
|
||||
'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
|
||||
'children' => [{'id' => @c3.id, 'subject' => 'child c3',
|
||||
'tracker' => {'id' => 1, 'name' => 'Bug'} }]
|
||||
},
|
||||
{ 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
|
||||
],
|
||||
json['issue']['children'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /issues/:id.xml?include=watchers should include watchers" do
|
||||
Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
|
||||
|
||||
get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal 'application/xml', response.content_type
|
||||
assert_select 'issue' do
|
||||
assert_select 'watchers', Issue.find(1).watchers.count
|
||||
assert_select 'watchers' do
|
||||
assert_select 'user[id=3]'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /issues.xml" do
|
||||
should_allow_api_authentication(
|
||||
:post,
|
||||
'/issues.xml',
|
||||
{:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
|
||||
{:success_code => :created}
|
||||
)
|
||||
should "create an issue with the attributes" do
|
||||
assert_difference('Issue.count') do
|
||||
post '/issues.xml',
|
||||
{:issue => {:project_id => 1, :subject => 'API test',
|
||||
:tracker_id => 2, :status_id => 3}}, credentials('jsmith')
|
||||
end
|
||||
issue = Issue.first(:order => 'id DESC')
|
||||
assert_equal 1, issue.project_id
|
||||
assert_equal 2, issue.tracker_id
|
||||
assert_equal 3, issue.status_id
|
||||
assert_equal 'API test', issue.subject
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'issue', :child => {:tag => 'id', :content => issue.id.to_s}
|
||||
end
|
||||
end
|
||||
|
||||
test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
|
||||
assert_difference('Issue.count') do
|
||||
post '/issues.xml',
|
||||
{:issue => {:project_id => 1, :subject => 'Watchers',
|
||||
:tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
|
||||
assert_response :created
|
||||
end
|
||||
issue = Issue.order('id desc').first
|
||||
assert_equal 2, issue.watchers.size
|
||||
assert_equal [1, 3], issue.watcher_user_ids.sort
|
||||
end
|
||||
|
||||
context "POST /issues.xml with failure" do
|
||||
should "have an errors tag" do
|
||||
assert_no_difference('Issue.count') do
|
||||
post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /issues.json" do
|
||||
should_allow_api_authentication(:post,
|
||||
'/issues.json',
|
||||
{:issue => {:project_id => 1, :subject => 'API test',
|
||||
:tracker_id => 2, :status_id => 3}},
|
||||
{:success_code => :created})
|
||||
|
||||
should "create an issue with the attributes" do
|
||||
assert_difference('Issue.count') do
|
||||
post '/issues.json',
|
||||
{:issue => {:project_id => 1, :subject => 'API test',
|
||||
:tracker_id => 2, :status_id => 3}},
|
||||
credentials('jsmith')
|
||||
end
|
||||
|
||||
issue = Issue.first(:order => 'id DESC')
|
||||
assert_equal 1, issue.project_id
|
||||
assert_equal 2, issue.tracker_id
|
||||
assert_equal 3, issue.status_id
|
||||
assert_equal 'API test', issue.subject
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "POST /issues.json with failure" do
|
||||
should "have an errors element" do
|
||||
assert_no_difference('Issue.count') do
|
||||
post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert json['errors'].include?("Subject can't be blank")
|
||||
end
|
||||
end
|
||||
|
||||
# Issue 6 is on a private project
|
||||
context "PUT /issues/6.xml" do
|
||||
setup do
|
||||
@parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
|
||||
end
|
||||
|
||||
should_allow_api_authentication(:put,
|
||||
'/issues/6.xml',
|
||||
{:issue => {:subject => 'API update', :notes => 'A new note'}},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "not create a new issue" do
|
||||
assert_no_difference('Issue.count') do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
end
|
||||
|
||||
should "create a new journal" do
|
||||
assert_difference('Journal.count') do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
end
|
||||
|
||||
should "add the note to the journal" do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
|
||||
journal = Journal.last
|
||||
assert_equal "A new note", journal.notes
|
||||
end
|
||||
|
||||
should "update the issue" do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
|
||||
issue = Issue.find(6)
|
||||
assert_equal "API update", issue.subject
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "PUT /issues/3.xml with custom fields" do
|
||||
setup do
|
||||
@parameters = {
|
||||
:issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' },
|
||||
{'id' => '2', 'value' => '150'}]}
|
||||
}
|
||||
end
|
||||
|
||||
should "update custom fields" do
|
||||
assert_no_difference('Issue.count') do
|
||||
put '/issues/3.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
|
||||
issue = Issue.find(3)
|
||||
assert_equal '150', issue.custom_value_for(2).value
|
||||
assert_equal 'PostgreSQL', issue.custom_value_for(1).value
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /issues/3.xml with multi custom fields" do
|
||||
setup do
|
||||
field = CustomField.find(1)
|
||||
field.update_attribute :multiple, true
|
||||
@parameters = {
|
||||
:issue => {:custom_fields => [{'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
|
||||
{'id' => '2', 'value' => '150'}]}
|
||||
}
|
||||
end
|
||||
|
||||
should "update custom fields" do
|
||||
assert_no_difference('Issue.count') do
|
||||
put '/issues/3.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
|
||||
issue = Issue.find(3)
|
||||
assert_equal '150', issue.custom_value_for(2).value
|
||||
assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /issues/3.xml with project change" do
|
||||
setup do
|
||||
@parameters = {:issue => {:project_id => 2, :subject => 'Project changed'}}
|
||||
end
|
||||
|
||||
should "update project" do
|
||||
assert_no_difference('Issue.count') do
|
||||
put '/issues/3.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
|
||||
issue = Issue.find(3)
|
||||
assert_equal 2, issue.project_id
|
||||
assert_equal 'Project changed', issue.subject
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /issues/6.xml with failed update" do
|
||||
setup do
|
||||
@parameters = {:issue => {:subject => ''}}
|
||||
end
|
||||
|
||||
should "not create a new issue" do
|
||||
assert_no_difference('Issue.count') do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
end
|
||||
|
||||
should "not create a new journal" do
|
||||
assert_no_difference('Journal.count') do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
end
|
||||
|
||||
should "have an errors tag" do
|
||||
put '/issues/6.xml', @parameters, credentials('jsmith')
|
||||
|
||||
assert_tag :errors, :child => {:tag => 'error', :content => "Subject can't be blank"}
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /issues/6.json" do
|
||||
setup do
|
||||
@parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
|
||||
end
|
||||
|
||||
should_allow_api_authentication(:put,
|
||||
'/issues/6.json',
|
||||
{:issue => {:subject => 'API update', :notes => 'A new note'}},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "update the issue" do
|
||||
assert_no_difference('Issue.count') do
|
||||
assert_difference('Journal.count') do
|
||||
put '/issues/6.json', @parameters, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', response.body
|
||||
end
|
||||
end
|
||||
|
||||
issue = Issue.find(6)
|
||||
assert_equal "API update", issue.subject
|
||||
journal = Journal.last
|
||||
assert_equal "A new note", journal.notes
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /issues/6.json with failed update" do
|
||||
should "return errors" do
|
||||
assert_no_difference('Issue.count') do
|
||||
assert_no_difference('Journal.count') do
|
||||
put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert json['errors'].include?("Subject can't be blank")
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /issues/1.xml" do
|
||||
should_allow_api_authentication(:delete,
|
||||
'/issues/6.xml',
|
||||
{},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "delete the issue" do
|
||||
assert_difference('Issue.count', -1) do
|
||||
delete '/issues/6.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', response.body
|
||||
end
|
||||
|
||||
assert_nil Issue.find_by_id(6)
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /issues/1.json" do
|
||||
should_allow_api_authentication(:delete,
|
||||
'/issues/6.json',
|
||||
{},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "delete the issue" do
|
||||
assert_difference('Issue.count', -1) do
|
||||
delete '/issues/6.json', {}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', response.body
|
||||
end
|
||||
|
||||
assert_nil Issue.find_by_id(6)
|
||||
end
|
||||
end
|
||||
|
||||
test "POST /issues/:id/watchers.xml should add watcher" do
|
||||
assert_difference 'Watcher.count' do
|
||||
post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', response.body
|
||||
end
|
||||
watcher = Watcher.order('id desc').first
|
||||
assert_equal Issue.find(1), watcher.watchable
|
||||
assert_equal User.find(3), watcher.user
|
||||
end
|
||||
|
||||
test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
|
||||
Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
|
||||
|
||||
assert_difference 'Watcher.count', -1 do
|
||||
delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', response.body
|
||||
end
|
||||
assert_equal false, Issue.find(1).watched_by?(User.find(3))
|
||||
end
|
||||
|
||||
def test_create_issue_with_uploaded_file
|
||||
set_tmp_attachments_directory
|
||||
# upload the file
|
||||
assert_difference 'Attachment.count' do
|
||||
post '/uploads.xml', 'test_create_with_upload',
|
||||
{"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
|
||||
assert_response :created
|
||||
end
|
||||
xml = Hash.from_xml(response.body)
|
||||
token = xml['upload']['token']
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
|
||||
# create the issue with the upload's token
|
||||
assert_difference 'Issue.count' do
|
||||
post '/issues.xml',
|
||||
{:issue => {:project_id => 1, :subject => 'Uploaded file',
|
||||
:uploads => [{:token => token, :filename => 'test.txt',
|
||||
:content_type => 'text/plain'}]}},
|
||||
credentials('jsmith')
|
||||
assert_response :created
|
||||
end
|
||||
issue = Issue.first(:order => 'id DESC')
|
||||
assert_equal 1, issue.attachments.count
|
||||
assert_equal attachment, issue.attachments.first
|
||||
|
||||
attachment.reload
|
||||
assert_equal 'test.txt', attachment.filename
|
||||
assert_equal 'text/plain', attachment.content_type
|
||||
assert_equal 'test_create_with_upload'.size, attachment.filesize
|
||||
assert_equal 2, attachment.author_id
|
||||
|
||||
# get the issue with its attachments
|
||||
get "/issues/#{issue.id}.xml", :include => 'attachments'
|
||||
assert_response :success
|
||||
xml = Hash.from_xml(response.body)
|
||||
attachments = xml['issue']['attachments']
|
||||
assert_kind_of Array, attachments
|
||||
assert_equal 1, attachments.size
|
||||
url = attachments.first['content_url']
|
||||
assert_not_nil url
|
||||
|
||||
# download the attachment
|
||||
get url
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_update_issue_with_uploaded_file
|
||||
set_tmp_attachments_directory
|
||||
# upload the file
|
||||
assert_difference 'Attachment.count' do
|
||||
post '/uploads.xml', 'test_upload_with_upload',
|
||||
{"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
|
||||
assert_response :created
|
||||
end
|
||||
xml = Hash.from_xml(response.body)
|
||||
token = xml['upload']['token']
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
|
||||
# update the issue with the upload's token
|
||||
assert_difference 'Journal.count' do
|
||||
put '/issues/1.xml',
|
||||
{:issue => {:notes => 'Attachment added',
|
||||
:uploads => [{:token => token, :filename => 'test.txt',
|
||||
:content_type => 'text/plain'}]}},
|
||||
credentials('jsmith')
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
|
||||
issue = Issue.find(1)
|
||||
assert_include attachment, issue.attachments
|
||||
end
|
||||
end
|
|
@ -0,0 +1,72 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::JsonpTest < Redmine::ApiTest::Base
|
||||
fixtures :trackers
|
||||
|
||||
def test_should_ignore_jsonp_callback_with_jsonp_disabled
|
||||
with_settings :jsonp_enabled => '0' do
|
||||
get '/trackers.json?jsonp=handler'
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_match %r{^\{"trackers":.+\}$}, response.body
|
||||
assert_equal 'application/json; charset=utf-8', response.headers['Content-Type']
|
||||
end
|
||||
|
||||
def test_jsonp_should_accept_callback_param
|
||||
with_settings :jsonp_enabled => '1' do
|
||||
get '/trackers.json?callback=handler'
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_match %r{^handler\(\{"trackers":.+\}\)$}, response.body
|
||||
assert_equal 'application/javascript; charset=utf-8', response.headers['Content-Type']
|
||||
end
|
||||
|
||||
def test_jsonp_should_accept_jsonp_param
|
||||
with_settings :jsonp_enabled => '1' do
|
||||
get '/trackers.json?jsonp=handler'
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_match %r{^handler\(\{"trackers":.+\}\)$}, response.body
|
||||
assert_equal 'application/javascript; charset=utf-8', response.headers['Content-Type']
|
||||
end
|
||||
|
||||
def test_jsonp_should_strip_invalid_characters_from_callback
|
||||
with_settings :jsonp_enabled => '1' do
|
||||
get '/trackers.json?callback=+-aA$1_'
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_match %r{^aA1_\(\{"trackers":.+\}\)$}, response.body
|
||||
assert_equal 'application/javascript; charset=utf-8', response.headers['Content-Type']
|
||||
end
|
||||
|
||||
def test_jsonp_without_callback_should_return_json
|
||||
with_settings :jsonp_enabled => '1' do
|
||||
get '/trackers.json?callback='
|
||||
end
|
||||
|
||||
assert_response :success
|
||||
assert_match %r{^\{"trackers":.+\}$}, response.body
|
||||
assert_equal 'application/json; charset=utf-8', response.headers['Content-Type']
|
||||
end
|
||||
end
|
|
@ -0,0 +1,200 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :users, :roles, :members, :member_roles
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/projects/:project_id/memberships" do
|
||||
context "GET" do
|
||||
context "xml" do
|
||||
should "return memberships" do
|
||||
get '/projects/1/memberships.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'memberships',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'membership',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2',
|
||||
:sibling => {
|
||||
:tag => 'user',
|
||||
:attributes => {:id => '3', :name => 'Dave Lopper'},
|
||||
:sibling => {
|
||||
:tag => 'roles',
|
||||
:child => {
|
||||
:tag => 'role',
|
||||
:attributes => {:id => '2', :name => 'Developer'}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "json" do
|
||||
should "return memberships" do
|
||||
get '/projects/1/memberships.json', {}, credentials('jsmith')
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', @response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_equal({
|
||||
"memberships" =>
|
||||
[{"id"=>1,
|
||||
"project" => {"name"=>"eCookbook", "id"=>1},
|
||||
"roles" => [{"name"=>"Manager", "id"=>1}],
|
||||
"user" => {"name"=>"John Smith", "id"=>2}},
|
||||
{"id"=>2,
|
||||
"project" => {"name"=>"eCookbook", "id"=>1},
|
||||
"roles" => [{"name"=>"Developer", "id"=>2}],
|
||||
"user" => {"name"=>"Dave Lopper", "id"=>3}}],
|
||||
"limit" => 25,
|
||||
"total_count" => 2,
|
||||
"offset" => 0},
|
||||
json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "POST" do
|
||||
context "xml" do
|
||||
should "create membership" do
|
||||
assert_difference 'Member.count' do
|
||||
post '/projects/1/memberships.xml', {:membership => {:user_id => 7, :role_ids => [2,3]}}, credentials('jsmith')
|
||||
|
||||
assert_response :created
|
||||
end
|
||||
end
|
||||
|
||||
should "return errors on failure" do
|
||||
assert_no_difference 'Member.count' do
|
||||
post '/projects/1/memberships.xml', {:membership => {:role_ids => [2,3]}}, credentials('jsmith')
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Principal can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "/memberships/:id" do
|
||||
context "GET" do
|
||||
context "xml" do
|
||||
should "return the membership" do
|
||||
get '/memberships/2.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'membership',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2',
|
||||
:sibling => {
|
||||
:tag => 'user',
|
||||
:attributes => {:id => '3', :name => 'Dave Lopper'},
|
||||
:sibling => {
|
||||
:tag => 'roles',
|
||||
:child => {
|
||||
:tag => 'role',
|
||||
:attributes => {:id => '2', :name => 'Developer'}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "json" do
|
||||
should "return the membership" do
|
||||
get '/memberships/2.json', {}, credentials('jsmith')
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', @response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_equal(
|
||||
{"membership" => {
|
||||
"id" => 2,
|
||||
"project" => {"name"=>"eCookbook", "id"=>1},
|
||||
"roles" => [{"name"=>"Developer", "id"=>2}],
|
||||
"user" => {"name"=>"Dave Lopper", "id"=>3}}
|
||||
},
|
||||
json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT" do
|
||||
context "xml" do
|
||||
should "update membership" do
|
||||
assert_not_equal [1,2], Member.find(2).role_ids.sort
|
||||
assert_no_difference 'Member.count' do
|
||||
put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [1,2]}}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
member = Member.find(2)
|
||||
assert_equal [1,2], member.role_ids.sort
|
||||
end
|
||||
|
||||
should "return errors on failure" do
|
||||
put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [99]}}, credentials('jsmith')
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => /member_roles is invalid/}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE" do
|
||||
context "xml" do
|
||||
should "destroy membership" do
|
||||
assert_difference 'Member.count', -1 do
|
||||
delete '/memberships/2.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
assert_nil Member.find_by_id(2)
|
||||
end
|
||||
|
||||
should "respond with 422 on failure" do
|
||||
assert_no_difference 'Member.count' do
|
||||
# A membership with an inherited role can't be deleted
|
||||
Member.find(2).member_roles.first.update_attribute :inherited_from, 99
|
||||
delete '/memberships/2.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,97 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:news
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "GET /news" do
|
||||
context ".xml" do
|
||||
should "return news" do
|
||||
get '/news.xml'
|
||||
|
||||
assert_tag :tag => 'news',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'news',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "return news" do
|
||||
get '/news.json'
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Array, json['news']
|
||||
assert_kind_of Hash, json['news'].first
|
||||
assert_equal 2, json['news'].first['id']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "GET /projects/:project_id/news" do
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:get, "/projects/onlinestore/news.xml")
|
||||
|
||||
should "return news" do
|
||||
get '/projects/ecookbook/news.xml'
|
||||
|
||||
assert_tag :tag => 'news',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'news',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should_allow_api_authentication(:get, "/projects/onlinestore/news.json")
|
||||
|
||||
should "return news" do
|
||||
get '/projects/ecookbook/news.json'
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Array, json['news']
|
||||
assert_kind_of Hash, json['news'].first
|
||||
assert_equal 2, json['news'].first['id']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,297 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::ProjectsTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :versions, :users, :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, :issue_categories
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
context "GET /projects" do
|
||||
context ".xml" do
|
||||
should "return projects" do
|
||||
get '/projects.xml'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag :tag => 'projects',
|
||||
:child => {:tag => 'project', :child => {:tag => 'id', :content => '1'}}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "return projects" do
|
||||
get '/projects.json'
|
||||
assert_response :success
|
||||
assert_equal 'application/json', @response.content_type
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Array, json['projects']
|
||||
assert_kind_of Hash, json['projects'].first
|
||||
assert json['projects'].first.has_key?('id')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "GET /projects/:id" do
|
||||
context ".xml" do
|
||||
# TODO: A private project is needed because should_allow_api_authentication
|
||||
# actually tests that authentication is *required*, not just allowed
|
||||
should_allow_api_authentication(:get, "/projects/2.xml")
|
||||
|
||||
should "return requested project" do
|
||||
get '/projects/1.xml'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag :tag => 'project',
|
||||
:child => {:tag => 'id', :content => '1'}
|
||||
assert_tag :tag => 'custom_field',
|
||||
:attributes => {:name => 'Development status'}, :content => 'Stable'
|
||||
|
||||
assert_no_tag 'trackers'
|
||||
assert_no_tag 'issue_categories'
|
||||
end
|
||||
|
||||
context "with hidden custom fields" do
|
||||
setup do
|
||||
ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
|
||||
end
|
||||
|
||||
should "not display hidden custom fields" do
|
||||
get '/projects/1.xml'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_no_tag 'custom_field',
|
||||
:attributes => {:name => 'Development status'}
|
||||
end
|
||||
end
|
||||
|
||||
should "return categories with include=issue_categories" do
|
||||
get '/projects/1.xml?include=issue_categories'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag 'issue_categories',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'issue_category',
|
||||
:attributes => {
|
||||
:id => '2',
|
||||
:name => 'Recipes'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
should "return trackers with include=trackers" do
|
||||
get '/projects/1.xml?include=trackers'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag 'trackers',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'tracker',
|
||||
:attributes => {
|
||||
:id => '2',
|
||||
:name => 'Feature request'
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should_allow_api_authentication(:get, "/projects/2.json")
|
||||
|
||||
should "return requested project" do
|
||||
get '/projects/1.json'
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Hash, json['project']
|
||||
assert_equal 1, json['project']['id']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /projects" do
|
||||
context "with valid parameters" do
|
||||
setup do
|
||||
Setting.default_projects_modules = ['issue_tracking', 'repository']
|
||||
@parameters = {:project => {:name => 'API test', :identifier => 'api-test'}}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:post,
|
||||
'/projects.xml',
|
||||
{:project => {:name => 'API test', :identifier => 'api-test'}},
|
||||
{:success_code => :created})
|
||||
|
||||
|
||||
should "create a project with the attributes" do
|
||||
assert_difference('Project.count') do
|
||||
post '/projects.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
project = Project.first(:order => 'id DESC')
|
||||
assert_equal 'API test', project.name
|
||||
assert_equal 'api-test', project.identifier
|
||||
assert_equal ['issue_tracking', 'repository'], project.enabled_module_names.sort
|
||||
assert_equal Tracker.all.size, project.trackers.size
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'project', :child => {:tag => 'id', :content => project.id.to_s}
|
||||
end
|
||||
|
||||
should "accept enabled_module_names attribute" do
|
||||
@parameters[:project].merge!({:enabled_module_names => ['issue_tracking', 'news', 'time_tracking']})
|
||||
|
||||
assert_difference('Project.count') do
|
||||
post '/projects.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
project = Project.first(:order => 'id DESC')
|
||||
assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort
|
||||
end
|
||||
|
||||
should "accept tracker_ids attribute" do
|
||||
@parameters[:project].merge!({:tracker_ids => [1, 3]})
|
||||
|
||||
assert_difference('Project.count') do
|
||||
post '/projects.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
project = Project.first(:order => 'id DESC')
|
||||
assert_equal [1, 3], project.trackers.map(&:id).sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
setup do
|
||||
@parameters = {:project => {:name => 'API test'}}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "return errors" do
|
||||
assert_no_difference('Project.count') do
|
||||
post '/projects.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Identifier can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /projects/:id" do
|
||||
context "with valid parameters" do
|
||||
setup do
|
||||
@parameters = {:project => {:name => 'API update'}}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:put,
|
||||
'/projects/2.xml',
|
||||
{:project => {:name => 'API update'}},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "update the project" do
|
||||
assert_no_difference 'Project.count' do
|
||||
put '/projects/2.xml', @parameters, credentials('jsmith')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
project = Project.find(2)
|
||||
assert_equal 'API update', project.name
|
||||
end
|
||||
|
||||
should "accept enabled_module_names attribute" do
|
||||
@parameters[:project].merge!({:enabled_module_names => ['issue_tracking', 'news', 'time_tracking']})
|
||||
|
||||
assert_no_difference 'Project.count' do
|
||||
put '/projects/2.xml', @parameters, credentials('admin')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
project = Project.find(2)
|
||||
assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort
|
||||
end
|
||||
|
||||
should "accept tracker_ids attribute" do
|
||||
@parameters[:project].merge!({:tracker_ids => [1, 3]})
|
||||
|
||||
assert_no_difference 'Project.count' do
|
||||
put '/projects/2.xml', @parameters, credentials('admin')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
project = Project.find(2)
|
||||
assert_equal [1, 3], project.trackers.map(&:id).sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
setup do
|
||||
@parameters = {:project => {:name => ''}}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "return errors" do
|
||||
assert_no_difference('Project.count') do
|
||||
put '/projects/2.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Name can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /projects/:id" do
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:delete,
|
||||
'/projects/2.xml',
|
||||
{},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "delete the project" do
|
||||
assert_difference('Project.count',-1) do
|
||||
delete '/projects/2.xml', {}, credentials('admin')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_nil Project.find_by_id(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::QueriesTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:queries
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/queries" do
|
||||
context "GET" do
|
||||
|
||||
should "return queries" do
|
||||
get '/queries.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'queries',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'query',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '4',
|
||||
:sibling => {
|
||||
:tag => 'name',
|
||||
:content => 'Public query for all projects'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,90 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::RolesTest < Redmine::ApiTest::Base
|
||||
fixtures :roles
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/roles" do
|
||||
context "GET" do
|
||||
context "xml" do
|
||||
should "return the roles" do
|
||||
get '/roles.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_equal 3, assigns(:roles).size
|
||||
|
||||
assert_tag :tag => 'roles',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'role',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2',
|
||||
:sibling => {
|
||||
:tag => 'name',
|
||||
:content => 'Developer'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "json" do
|
||||
should "return the roles" do
|
||||
get '/roles.json'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/json', @response.content_type
|
||||
assert_equal 3, assigns(:roles).size
|
||||
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Array, json['roles']
|
||||
assert_include({'id' => 2, 'name' => 'Developer'}, json['roles'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "/roles/:id" do
|
||||
context "GET" do
|
||||
context "xml" do
|
||||
should "return the role" do
|
||||
get '/roles/1.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_select 'role' do
|
||||
assert_select 'name', :text => 'Manager'
|
||||
assert_select 'role permissions[type=array]' do
|
||||
assert_select 'permission', Role.find(1).permissions.size
|
||||
assert_select 'permission', :text => 'view_issues'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,164 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::TimeEntriesTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:time_entries
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "GET /time_entries.xml" do
|
||||
should "return time entries" do
|
||||
get '/time_entries.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'time_entries',
|
||||
:child => {:tag => 'time_entry', :child => {:tag => 'id', :content => '2'}}
|
||||
end
|
||||
|
||||
context "with limit" do
|
||||
should "return limited results" do
|
||||
get '/time_entries.xml?limit=2', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'time_entries',
|
||||
:children => {:count => 2}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "GET /time_entries/2.xml" do
|
||||
should "return requested time entry" do
|
||||
get '/time_entries/2.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'time_entry',
|
||||
:child => {:tag => 'id', :content => '2'}
|
||||
end
|
||||
end
|
||||
|
||||
context "POST /time_entries.xml" do
|
||||
context "with issue_id" do
|
||||
should "return create time entry" do
|
||||
assert_difference 'TimeEntry.count' do
|
||||
post '/time_entries.xml', {:time_entry => {:issue_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
entry = TimeEntry.first(:order => 'id DESC')
|
||||
assert_equal 'jsmith', entry.user.login
|
||||
assert_equal Issue.find(1), entry.issue
|
||||
assert_equal Project.find(1), entry.project
|
||||
assert_equal Date.parse('2010-12-02'), entry.spent_on
|
||||
assert_equal 3.5, entry.hours
|
||||
assert_equal TimeEntryActivity.find(11), entry.activity
|
||||
end
|
||||
|
||||
should "accept custom fields" do
|
||||
field = TimeEntryCustomField.create!(:name => 'Test', :field_format => 'string')
|
||||
|
||||
assert_difference 'TimeEntry.count' do
|
||||
post '/time_entries.xml', {:time_entry => {
|
||||
:issue_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11', :custom_fields => [{:id => field.id.to_s, :value => 'accepted'}]
|
||||
}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
entry = TimeEntry.first(:order => 'id DESC')
|
||||
assert_equal 'accepted', entry.custom_field_value(field)
|
||||
end
|
||||
end
|
||||
|
||||
context "with project_id" do
|
||||
should "return create time entry" do
|
||||
assert_difference 'TimeEntry.count' do
|
||||
post '/time_entries.xml', {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
entry = TimeEntry.first(:order => 'id DESC')
|
||||
assert_equal 'jsmith', entry.user.login
|
||||
assert_nil entry.issue
|
||||
assert_equal Project.find(1), entry.project
|
||||
assert_equal Date.parse('2010-12-02'), entry.spent_on
|
||||
assert_equal 3.5, entry.hours
|
||||
assert_equal TimeEntryActivity.find(11), entry.activity
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
should "return errors" do
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
post '/time_entries.xml', {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :activity_id => '11'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Hours can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /time_entries/2.xml" do
|
||||
context "with valid parameters" do
|
||||
should "update time entry" do
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
put '/time_entries/2.xml', {:time_entry => {:comments => 'API Update'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_equal 'API Update', TimeEntry.find(2).comments
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
should "return errors" do
|
||||
assert_no_difference 'TimeEntry.count' do
|
||||
put '/time_entries/2.xml', {:time_entry => {:hours => '', :comments => 'API Update'}}, credentials('jsmith')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
|
||||
assert_tag 'errors', :child => {:tag => 'error', :content => "Hours can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /time_entries/2.xml" do
|
||||
should "destroy time entry" do
|
||||
assert_difference 'TimeEntry.count', -1 do
|
||||
delete '/time_entries/2.xml', {}, credentials('jsmith')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_nil TimeEntry.find_by_id(2)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::TokenAuthenticationTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
Setting.login_required = '1'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.rest_api_enabled = '0'
|
||||
Setting.login_required = '0'
|
||||
end
|
||||
|
||||
# Using the NewsController because it's a simple API.
|
||||
context "get /news" do
|
||||
context "in :xml format" do
|
||||
should_allow_key_based_auth(:get, "/news.xml")
|
||||
end
|
||||
|
||||
context "in :json format" do
|
||||
should_allow_key_based_auth(:get, "/news.json")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,51 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::TrackersTest < Redmine::ApiTest::Base
|
||||
fixtures :trackers
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/trackers" do
|
||||
context "GET" do
|
||||
|
||||
should "return trackers" do
|
||||
get '/trackers.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'trackers',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'tracker',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2',
|
||||
:sibling => {
|
||||
:tag => 'name',
|
||||
:content => 'Feature request'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,371 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base
|
||||
fixtures :users, :members, :member_roles, :roles, :projects
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "GET /users" do
|
||||
should_allow_api_authentication(:get, "/users.xml")
|
||||
should_allow_api_authentication(:get, "/users.json")
|
||||
end
|
||||
|
||||
context "GET /users/2" do
|
||||
context ".xml" do
|
||||
should "return requested user" do
|
||||
get '/users/2.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_tag :tag => 'user',
|
||||
:child => {:tag => 'id', :content => '2'}
|
||||
end
|
||||
|
||||
context "with include=memberships" do
|
||||
should "include memberships" do
|
||||
get '/users/2.xml?include=memberships'
|
||||
|
||||
assert_response :success
|
||||
assert_tag :tag => 'memberships',
|
||||
:parent => {:tag => 'user'},
|
||||
:children => {:count => 1}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "return requested user" do
|
||||
get '/users/2.json'
|
||||
|
||||
assert_response :success
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Hash, json['user']
|
||||
assert_equal 2, json['user']['id']
|
||||
end
|
||||
|
||||
context "with include=memberships" do
|
||||
should "include memberships" do
|
||||
get '/users/2.json?include=memberships'
|
||||
|
||||
assert_response :success
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Array, json['user']['memberships']
|
||||
assert_equal [{
|
||||
"id"=>1,
|
||||
"project"=>{"name"=>"eCookbook", "id"=>1},
|
||||
"roles"=>[{"name"=>"Manager", "id"=>1}]
|
||||
}], json['user']['memberships']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "GET /users/current" do
|
||||
context ".xml" do
|
||||
should "require authentication" do
|
||||
get '/users/current.xml'
|
||||
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
should "return current user" do
|
||||
get '/users/current.xml', {}, credentials('jsmith')
|
||||
|
||||
assert_tag :tag => 'user',
|
||||
:child => {:tag => 'id', :content => '2'}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /users/:id should not return login for other user" do
|
||||
get '/users/3.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_no_tag 'user', :child => {:tag => 'login'}
|
||||
end
|
||||
|
||||
test "GET /users/:id should return login for current user" do
|
||||
get '/users/2.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_tag 'user', :child => {:tag => 'login', :content => 'jsmith'}
|
||||
end
|
||||
|
||||
test "GET /users/:id should not return api_key for other user" do
|
||||
get '/users/3.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_no_tag 'user', :child => {:tag => 'api_key'}
|
||||
end
|
||||
|
||||
test "GET /users/:id should return api_key for current user" do
|
||||
get '/users/2.xml', {}, credentials('jsmith')
|
||||
assert_response :success
|
||||
assert_tag 'user', :child => {:tag => 'api_key', :content => User.find(2).api_key}
|
||||
end
|
||||
|
||||
context "POST /users" do
|
||||
context "with valid parameters" do
|
||||
setup do
|
||||
@parameters = {
|
||||
:user => {
|
||||
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
|
||||
:mail => 'foo@example.net', :password => 'secret123',
|
||||
:mail_notification => 'only_assigned'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:post,
|
||||
'/users.xml',
|
||||
{:user => {
|
||||
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
|
||||
:mail => 'foo@example.net', :password => 'secret123'
|
||||
}},
|
||||
{:success_code => :created})
|
||||
|
||||
should "create a user with the attributes" do
|
||||
assert_difference('User.count') do
|
||||
post '/users.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
user = User.first(:order => 'id DESC')
|
||||
assert_equal 'foo', user.login
|
||||
assert_equal 'Firstname', user.firstname
|
||||
assert_equal 'Lastname', user.lastname
|
||||
assert_equal 'foo@example.net', user.mail
|
||||
assert_equal 'only_assigned', user.mail_notification
|
||||
assert !user.admin?
|
||||
assert user.check_password?('secret123')
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'user', :child => {:tag => 'id', :content => user.id.to_s}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should_allow_api_authentication(:post,
|
||||
'/users.json',
|
||||
{:user => {
|
||||
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
|
||||
:mail => 'foo@example.net'
|
||||
}},
|
||||
{:success_code => :created})
|
||||
|
||||
should "create a user with the attributes" do
|
||||
assert_difference('User.count') do
|
||||
post '/users.json', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
user = User.first(:order => 'id DESC')
|
||||
assert_equal 'foo', user.login
|
||||
assert_equal 'Firstname', user.firstname
|
||||
assert_equal 'Lastname', user.lastname
|
||||
assert_equal 'foo@example.net', user.mail
|
||||
assert !user.admin?
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/json', @response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert_kind_of Hash, json['user']
|
||||
assert_equal user.id, json['user']['id']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
setup do
|
||||
@parameters = {:user => {:login => 'foo', :lastname => 'Lastname', :mail => 'foo'}}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "return errors" do
|
||||
assert_no_difference('User.count') do
|
||||
post '/users.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {
|
||||
:tag => 'error',
|
||||
:content => "First name can't be blank"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "return errors" do
|
||||
assert_no_difference('User.count') do
|
||||
post '/users.json', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/json', @response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert json.has_key?('errors')
|
||||
assert_kind_of Array, json['errors']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT /users/2" do
|
||||
context "with valid parameters" do
|
||||
setup do
|
||||
@parameters = {
|
||||
:user => {
|
||||
:login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
|
||||
:mail => 'jsmith@somenet.foo'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:put,
|
||||
'/users/2.xml',
|
||||
{:user => {
|
||||
:login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
|
||||
:mail => 'jsmith@somenet.foo'
|
||||
}},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "update user with the attributes" do
|
||||
assert_no_difference('User.count') do
|
||||
put '/users/2.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
user = User.find(2)
|
||||
assert_equal 'jsmith', user.login
|
||||
assert_equal 'John', user.firstname
|
||||
assert_equal 'Renamed', user.lastname
|
||||
assert_equal 'jsmith@somenet.foo', user.mail
|
||||
assert !user.admin?
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should_allow_api_authentication(:put,
|
||||
'/users/2.json',
|
||||
{:user => {
|
||||
:login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
|
||||
:mail => 'jsmith@somenet.foo'
|
||||
}},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "update user with the attributes" do
|
||||
assert_no_difference('User.count') do
|
||||
put '/users/2.json', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
user = User.find(2)
|
||||
assert_equal 'jsmith', user.login
|
||||
assert_equal 'John', user.firstname
|
||||
assert_equal 'Renamed', user.lastname
|
||||
assert_equal 'jsmith@somenet.foo', user.mail
|
||||
assert !user.admin?
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
setup do
|
||||
@parameters = {
|
||||
:user => {
|
||||
:login => 'jsmith', :firstname => '', :lastname => 'Lastname',
|
||||
:mail => 'foo'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context ".xml" do
|
||||
should "return errors" do
|
||||
assert_no_difference('User.count') do
|
||||
put '/users/2.xml', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'errors', :child => {
|
||||
:tag => 'error',
|
||||
:content => "First name can't be blank"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should "return errors" do
|
||||
assert_no_difference('User.count') do
|
||||
put '/users/2.json', @parameters, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/json', @response.content_type
|
||||
json = ActiveSupport::JSON.decode(response.body)
|
||||
assert_kind_of Hash, json
|
||||
assert json.has_key?('errors')
|
||||
assert_kind_of Array, json['errors']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE /users/2" do
|
||||
context ".xml" do
|
||||
should_allow_api_authentication(:delete,
|
||||
'/users/2.xml',
|
||||
{},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "delete user" do
|
||||
assert_difference('User.count', -1) do
|
||||
delete '/users/2.xml', {}, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
end
|
||||
|
||||
context ".json" do
|
||||
should_allow_api_authentication(:delete,
|
||||
'/users/2.xml',
|
||||
{},
|
||||
{:success_code => :ok})
|
||||
|
||||
should "delete user" do
|
||||
assert_difference('User.count', -1) do
|
||||
delete '/users/2.json', {}, credentials('admin')
|
||||
end
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,158 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::VersionsTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules,
|
||||
:versions
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
context "/projects/:project_id/versions" do
|
||||
context "GET" do
|
||||
should "return project versions" do
|
||||
get '/projects/1/versions.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :tag => 'versions',
|
||||
:attributes => {:type => 'array'},
|
||||
:child => {
|
||||
:tag => 'version',
|
||||
:child => {
|
||||
:tag => 'id',
|
||||
:content => '2',
|
||||
:sibling => {
|
||||
:tag => 'name',
|
||||
:content => '1.0'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
context "POST" do
|
||||
should "create the version" do
|
||||
assert_difference 'Version.count' do
|
||||
post '/projects/1/versions.xml', {:version => {:name => 'API test'}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
version = Version.first(:order => 'id DESC')
|
||||
assert_equal 'API test', version.name
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'version', :child => {:tag => 'id', :content => version.id.to_s}
|
||||
end
|
||||
|
||||
should "create the version with due date" do
|
||||
assert_difference 'Version.count' do
|
||||
post '/projects/1/versions.xml', {:version => {:name => 'API test', :due_date => '2012-01-24'}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
version = Version.first(:order => 'id DESC')
|
||||
assert_equal 'API test', version.name
|
||||
assert_equal Date.parse('2012-01-24'), version.due_date
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag 'version', :child => {:tag => 'id', :content => version.id.to_s}
|
||||
end
|
||||
|
||||
should "create the version with custom fields" do
|
||||
field = VersionCustomField.generate!
|
||||
|
||||
assert_difference 'Version.count' do
|
||||
post '/projects/1/versions.xml', {
|
||||
:version => {
|
||||
:name => 'API test',
|
||||
:custom_fields => [
|
||||
{'id' => field.id.to_s, 'value' => 'Some value'}
|
||||
]
|
||||
}
|
||||
}, credentials('jsmith')
|
||||
end
|
||||
|
||||
version = Version.first(:order => 'id DESC')
|
||||
assert_equal 'API test', version.name
|
||||
assert_equal 'Some value', version.custom_field_value(field)
|
||||
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_select 'version>custom_fields>custom_field[id=?]>value', field.id.to_s, 'Some value'
|
||||
end
|
||||
|
||||
context "with failure" do
|
||||
should "return the errors" do
|
||||
assert_no_difference('Version.count') do
|
||||
post '/projects/1/versions.xml', {:version => {:name => ''}}, credentials('jsmith')
|
||||
end
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
assert_tag :errors, :child => {:tag => 'error', :content => "Name can't be blank"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "/versions/:id" do
|
||||
context "GET" do
|
||||
should "return the version" do
|
||||
get '/versions/2.xml'
|
||||
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_select 'version' do
|
||||
assert_select 'id', :text => '2'
|
||||
assert_select 'name', :text => '1.0'
|
||||
assert_select 'sharing', :text => 'none'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "PUT" do
|
||||
should "update the version" do
|
||||
put '/versions/2.xml', {:version => {:name => 'API update'}}, credentials('jsmith')
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_equal 'API update', Version.find(2).name
|
||||
end
|
||||
end
|
||||
|
||||
context "DELETE" do
|
||||
should "destroy the version" do
|
||||
assert_difference 'Version.count', -1 do
|
||||
delete '/versions/3.xml', {}, credentials('jsmith')
|
||||
end
|
||||
|
||||
assert_response :ok
|
||||
assert_equal '', @response.body
|
||||
assert_nil Version.find_by_id(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,193 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../../test_helper', __FILE__)
|
||||
|
||||
class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base
|
||||
fixtures :projects, :users, :roles, :members, :member_roles,
|
||||
:enabled_modules, :wikis, :wiki_pages, :wiki_contents,
|
||||
:wiki_content_versions, :attachments
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
test "GET /projects/:project_id/wiki/index.xml should return wiki pages" do
|
||||
get '/projects/ecookbook/wiki/index.xml'
|
||||
assert_response 200
|
||||
assert_equal 'application/xml', response.content_type
|
||||
assert_select 'wiki_pages[type=array]' do
|
||||
assert_select 'wiki_page', :count => Wiki.find(1).pages.count
|
||||
assert_select 'wiki_page' do
|
||||
assert_select 'title', :text => 'CookBook_documentation'
|
||||
assert_select 'version', :text => '3'
|
||||
assert_select 'created_on'
|
||||
assert_select 'updated_on'
|
||||
end
|
||||
assert_select 'wiki_page' do
|
||||
assert_select 'title', :text => 'Page_with_an_inline_image'
|
||||
assert_select 'parent[title=?]', 'CookBook_documentation'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /projects/:project_id/wiki/:title.xml should return wiki page" do
|
||||
get '/projects/ecookbook/wiki/CookBook_documentation.xml'
|
||||
assert_response 200
|
||||
assert_equal 'application/xml', response.content_type
|
||||
assert_select 'wiki_page' do
|
||||
assert_select 'title', :text => 'CookBook_documentation'
|
||||
assert_select 'version', :text => '3'
|
||||
assert_select 'text'
|
||||
assert_select 'author'
|
||||
assert_select 'comments'
|
||||
assert_select 'created_on'
|
||||
assert_select 'updated_on'
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /projects/:project_id/wiki/:title.xml?include=attachments should include attachments" do
|
||||
get '/projects/ecookbook/wiki/Page_with_an_inline_image.xml?include=attachments'
|
||||
assert_response 200
|
||||
assert_equal 'application/xml', response.content_type
|
||||
assert_select 'wiki_page' do
|
||||
assert_select 'title', :text => 'Page_with_an_inline_image'
|
||||
assert_select 'attachments[type=array]' do
|
||||
assert_select 'attachment' do
|
||||
assert_select 'id', :text => '3'
|
||||
assert_select 'filename', :text => 'logo.gif'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /projects/:project_id/wiki/:title.xml with unknown title and edit permission should respond with 404" do
|
||||
get '/projects/ecookbook/wiki/Invalid_Page.xml', {}, credentials('jsmith')
|
||||
assert_response 404
|
||||
assert_equal 'application/xml', response.content_type
|
||||
end
|
||||
|
||||
test "GET /projects/:project_id/wiki/:title/:version.xml should return wiki page version" do
|
||||
get '/projects/ecookbook/wiki/CookBook_documentation/2.xml'
|
||||
assert_response 200
|
||||
assert_equal 'application/xml', response.content_type
|
||||
assert_select 'wiki_page' do
|
||||
assert_select 'title', :text => 'CookBook_documentation'
|
||||
assert_select 'version', :text => '2'
|
||||
assert_select 'text'
|
||||
assert_select 'author'
|
||||
assert_select 'created_on'
|
||||
assert_select 'updated_on'
|
||||
end
|
||||
end
|
||||
|
||||
test "GET /projects/:project_id/wiki/:title/:version.xml without permission should be denied" do
|
||||
Role.anonymous.remove_permission! :view_wiki_edits
|
||||
|
||||
get '/projects/ecookbook/wiki/CookBook_documentation/2.xml'
|
||||
assert_response 401
|
||||
assert_equal 'application/xml', response.content_type
|
||||
end
|
||||
|
||||
test "PUT /projects/:project_id/wiki/:title.xml should update wiki page" do
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put '/projects/ecookbook/wiki/CookBook_documentation.xml',
|
||||
{:wiki_page => {:text => 'New content from API', :comments => 'API update'}},
|
||||
credentials('jsmith')
|
||||
assert_response 200
|
||||
end
|
||||
end
|
||||
|
||||
page = WikiPage.find(1)
|
||||
assert_equal 'New content from API', page.content.text
|
||||
assert_equal 4, page.content.version
|
||||
assert_equal 'API update', page.content.comments
|
||||
assert_equal 'jsmith', page.content.author.login
|
||||
end
|
||||
|
||||
test "PUT /projects/:project_id/wiki/:title.xml with current versino should update wiki page" do
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put '/projects/ecookbook/wiki/CookBook_documentation.xml',
|
||||
{:wiki_page => {:text => 'New content from API', :comments => 'API update', :version => '3'}},
|
||||
credentials('jsmith')
|
||||
assert_response 200
|
||||
end
|
||||
end
|
||||
|
||||
page = WikiPage.find(1)
|
||||
assert_equal 'New content from API', page.content.text
|
||||
assert_equal 4, page.content.version
|
||||
assert_equal 'API update', page.content.comments
|
||||
assert_equal 'jsmith', page.content.author.login
|
||||
end
|
||||
|
||||
test "PUT /projects/:project_id/wiki/:title.xml with stale version should respond with 409" do
|
||||
assert_no_difference 'WikiPage.count' do
|
||||
assert_no_difference 'WikiContent::Version.count' do
|
||||
put '/projects/ecookbook/wiki/CookBook_documentation.xml',
|
||||
{:wiki_page => {:text => 'New content from API', :comments => 'API update', :version => '2'}},
|
||||
credentials('jsmith')
|
||||
assert_response 409
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "PUT /projects/:project_id/wiki/:title.xml should create the page if it does not exist" do
|
||||
assert_difference 'WikiPage.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put '/projects/ecookbook/wiki/New_page_from_API.xml',
|
||||
{:wiki_page => {:text => 'New content from API', :comments => 'API create'}},
|
||||
credentials('jsmith')
|
||||
assert_response 201
|
||||
end
|
||||
end
|
||||
|
||||
page = WikiPage.order('id DESC').first
|
||||
assert_equal 'New_page_from_API', page.title
|
||||
assert_equal 'New content from API', page.content.text
|
||||
assert_equal 1, page.content.version
|
||||
assert_equal 'API create', page.content.comments
|
||||
assert_equal 'jsmith', page.content.author.login
|
||||
assert_nil page.parent
|
||||
end
|
||||
|
||||
test "PUT /projects/:project_id/wiki/:title.xml with parent" do
|
||||
assert_difference 'WikiPage.count' do
|
||||
assert_difference 'WikiContent::Version.count' do
|
||||
put '/projects/ecookbook/wiki/New_subpage_from_API.xml',
|
||||
{:wiki_page => {:parent_title => 'CookBook_documentation', :text => 'New content from API', :comments => 'API create'}},
|
||||
credentials('jsmith')
|
||||
assert_response 201
|
||||
end
|
||||
end
|
||||
|
||||
page = WikiPage.order('id DESC').first
|
||||
assert_equal 'New_subpage_from_API', page.title
|
||||
assert_equal WikiPage.find(1), page.parent
|
||||
end
|
||||
|
||||
test "DELETE /projects/:project_id/wiki/:title.xml should destroy the page" do
|
||||
assert_difference 'WikiPage.count', -1 do
|
||||
delete '/projects/ecookbook/wiki/CookBook_documentation.xml', {}, credentials('jsmith')
|
||||
assert_response 200
|
||||
end
|
||||
|
||||
assert_nil WikiPage.find_by_id(1)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,67 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 ApplicationTest < ActionController::IntegrationTest
|
||||
include Redmine::I18n
|
||||
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def test_set_localization
|
||||
Setting.default_language = 'en'
|
||||
|
||||
# a french user
|
||||
get 'projects', { }, 'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
assert_response :success
|
||||
assert_tag :tag => 'h2', :content => 'Projets'
|
||||
assert_equal :fr, current_language
|
||||
|
||||
# then an italien user
|
||||
get 'projects', { }, 'HTTP_ACCEPT_LANGUAGE' => 'it;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
assert_response :success
|
||||
assert_tag :tag => 'h2', :content => 'Progetti'
|
||||
assert_equal :it, current_language
|
||||
|
||||
# not a supported language: default language should be used
|
||||
get 'projects', { }, 'HTTP_ACCEPT_LANGUAGE' => 'zz'
|
||||
assert_response :success
|
||||
assert_tag :tag => 'h2', :content => 'Projects'
|
||||
end
|
||||
|
||||
def test_token_based_access_should_not_start_session
|
||||
# issue of a private project
|
||||
get 'issues/4.atom'
|
||||
assert_response 302
|
||||
|
||||
rss_key = User.find(2).rss_key
|
||||
get "issues/4.atom?key=#{rss_key}"
|
||||
assert_response 200
|
||||
assert_nil session[:user_id]
|
||||
end
|
||||
|
||||
def test_missing_template_should_respond_with_404
|
||||
get '/login.png'
|
||||
assert_response 404
|
||||
end
|
||||
end
|
|
@ -0,0 +1,132 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 AttachmentsTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :enabled_modules,
|
||||
:users, :roles, :members, :member_roles,
|
||||
:trackers, :projects_trackers,
|
||||
:issue_statuses, :enumerations
|
||||
|
||||
def test_upload_as_js_and_attach_to_an_issue
|
||||
log_user('jsmith', 'jsmith')
|
||||
|
||||
token = ajax_upload('myupload.txt', 'File content')
|
||||
|
||||
assert_difference 'Issue.count' do
|
||||
post '/projects/ecookbook/issues', {
|
||||
:issue => {:tracker_id => 1, :subject => 'Issue with upload'},
|
||||
:attachments => {'1' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
issue = Issue.order('id DESC').first
|
||||
assert_equal 'Issue with upload', issue.subject
|
||||
assert_equal 1, issue.attachments.count
|
||||
|
||||
attachment = issue.attachments.first
|
||||
assert_equal 'myupload.txt', attachment.filename
|
||||
assert_equal 'My uploaded file', attachment.description
|
||||
assert_equal 'File content'.length, attachment.filesize
|
||||
end
|
||||
|
||||
def test_upload_as_js_and_preview_as_inline_attachment
|
||||
log_user('jsmith', 'jsmith')
|
||||
|
||||
token = ajax_upload('myupload.jpg', 'JPEG content')
|
||||
|
||||
post '/issues/preview/new/ecookbook', {
|
||||
:issue => {:tracker_id => 1, :description => 'Inline upload: !myupload.jpg!'},
|
||||
:attachments => {'1' => {:filename => 'myupload.jpg', :description => 'My uploaded file', :token => token}}
|
||||
}
|
||||
assert_response :success
|
||||
|
||||
attachment_path = response.body.match(%r{<img src="(/attachments/download/\d+/myupload.jpg)"})[1]
|
||||
assert_not_nil token, "No attachment path found in response:\n#{response.body}"
|
||||
|
||||
get attachment_path
|
||||
assert_response :success
|
||||
assert_equal 'JPEG content', response.body
|
||||
end
|
||||
|
||||
def test_upload_and_resubmit_after_validation_failure
|
||||
log_user('jsmith', 'jsmith')
|
||||
|
||||
token = ajax_upload('myupload.txt', 'File content')
|
||||
|
||||
assert_no_difference 'Issue.count' do
|
||||
post '/projects/ecookbook/issues', {
|
||||
:issue => {:tracker_id => 1, :subject => ''},
|
||||
:attachments => {'1' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
|
||||
}
|
||||
assert_response :success
|
||||
end
|
||||
assert_select 'input[type=hidden][name=?][value=?]', 'attachments[p0][token]', token
|
||||
assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'myupload.txt'
|
||||
assert_select 'input[name=?][value=?]', 'attachments[p0][description]', 'My uploaded file'
|
||||
|
||||
assert_difference 'Issue.count' do
|
||||
post '/projects/ecookbook/issues', {
|
||||
:issue => {:tracker_id => 1, :subject => 'Issue with upload'},
|
||||
:attachments => {'p0' => {:filename => 'myupload.txt', :description => 'My uploaded file', :token => token}}
|
||||
}
|
||||
assert_response 302
|
||||
end
|
||||
|
||||
issue = Issue.order('id DESC').first
|
||||
assert_equal 'Issue with upload', issue.subject
|
||||
assert_equal 1, issue.attachments.count
|
||||
|
||||
attachment = issue.attachments.first
|
||||
assert_equal 'myupload.txt', attachment.filename
|
||||
assert_equal 'My uploaded file', attachment.description
|
||||
assert_equal 'File content'.length, attachment.filesize
|
||||
end
|
||||
|
||||
def test_upload_as_js_and_destroy
|
||||
log_user('jsmith', 'jsmith')
|
||||
|
||||
token = ajax_upload('myupload.txt', 'File content')
|
||||
|
||||
attachment = Attachment.order('id DESC').first
|
||||
attachment_path = "/attachments/#{attachment.id}.js?attachment_id=1"
|
||||
assert_include "href: '#{attachment_path}'", response.body, "Path to attachment: #{attachment_path} not found in response:\n#{response.body}"
|
||||
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
delete attachment_path
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
assert_include "$('#attachments_1').remove();", response.body
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ajax_upload(filename, content, attachment_id=1)
|
||||
assert_difference 'Attachment.count' do
|
||||
post "/uploads.js?attachment_id=#{attachment_id}&filename=#{filename}", content, {"CONTENT_TYPE" => 'application/octet-stream'}
|
||||
assert_response :success
|
||||
assert_equal 'text/javascript', response.content_type
|
||||
end
|
||||
|
||||
token = response.body.match(/\.val\('(\d+\.[0-9a-f]+)'\)/)[1]
|
||||
assert_not_nil token, "No upload token found in response:\n#{response.body}"
|
||||
token
|
||||
end
|
||||
end
|
|
@ -0,0 +1,220 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 IssuesTest < ActionController::IntegrationTest
|
||||
fixtures :projects,
|
||||
:users,
|
||||
:roles,
|
||||
:members,
|
||||
:member_roles,
|
||||
:trackers,
|
||||
:projects_trackers,
|
||||
:enabled_modules,
|
||||
:issue_statuses,
|
||||
:issues,
|
||||
:enumerations,
|
||||
:custom_fields,
|
||||
:custom_values,
|
||||
:custom_fields_trackers
|
||||
|
||||
# create an issue
|
||||
def test_add_issue
|
||||
log_user('jsmith', 'jsmith')
|
||||
get 'projects/1/issues/new', :tracker_id => '1'
|
||||
assert_response :success
|
||||
assert_template 'issues/new'
|
||||
|
||||
post 'projects/1/issues', :tracker_id => "1",
|
||||
:issue => { :start_date => "2006-12-26",
|
||||
:priority_id => "4",
|
||||
:subject => "new test issue",
|
||||
:category_id => "",
|
||||
:description => "new issue",
|
||||
:done_ratio => "0",
|
||||
:due_date => "",
|
||||
:assigned_to_id => "" },
|
||||
:custom_fields => {'2' => 'Value for field 2'}
|
||||
# find created issue
|
||||
issue = Issue.find_by_subject("new test issue")
|
||||
assert_kind_of Issue, issue
|
||||
|
||||
# check redirection
|
||||
assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
|
||||
follow_redirect!
|
||||
assert_equal issue, assigns(:issue)
|
||||
|
||||
# check issue attributes
|
||||
assert_equal 'jsmith', issue.author.login
|
||||
assert_equal 1, issue.project.id
|
||||
assert_equal 1, issue.status.id
|
||||
end
|
||||
|
||||
# add then remove 2 attachments to an issue
|
||||
def test_issue_attachments
|
||||
log_user('jsmith', 'jsmith')
|
||||
set_tmp_attachments_directory
|
||||
|
||||
put 'issues/1',
|
||||
:notes => 'Some notes',
|
||||
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'This is an attachment'}}
|
||||
assert_redirected_to "/issues/1"
|
||||
|
||||
# make sure attachment was saved
|
||||
attachment = Issue.find(1).attachments.find_by_filename("testfile.txt")
|
||||
assert_kind_of Attachment, attachment
|
||||
assert_equal Issue.find(1), attachment.container
|
||||
assert_equal 'This is an attachment', attachment.description
|
||||
# verify the size of the attachment stored in db
|
||||
#assert_equal file_data_1.length, attachment.filesize
|
||||
# verify that the attachment was written to disk
|
||||
assert File.exist?(attachment.diskfile)
|
||||
|
||||
# remove the attachments
|
||||
Issue.find(1).attachments.each(&:destroy)
|
||||
assert_equal 0, Issue.find(1).attachments.length
|
||||
end
|
||||
|
||||
def test_other_formats_links_on_index
|
||||
get '/projects/ecookbook/issues'
|
||||
|
||||
%w(Atom PDF CSV).each do |format|
|
||||
assert_tag :a, :content => format,
|
||||
:attributes => { :href => "/projects/ecookbook/issues.#{format.downcase}",
|
||||
:rel => 'nofollow' }
|
||||
end
|
||||
end
|
||||
|
||||
def test_other_formats_links_on_index_without_project_id_in_url
|
||||
get '/issues', :project_id => 'ecookbook'
|
||||
|
||||
%w(Atom PDF CSV).each do |format|
|
||||
assert_tag :a, :content => format,
|
||||
:attributes => { :href => "/projects/ecookbook/issues.#{format.downcase}",
|
||||
:rel => 'nofollow' }
|
||||
end
|
||||
end
|
||||
|
||||
def test_pagination_links_on_index
|
||||
Setting.per_page_options = '2'
|
||||
get '/projects/ecookbook/issues'
|
||||
|
||||
assert_tag :a, :content => '2',
|
||||
:attributes => { :href => '/projects/ecookbook/issues?page=2' }
|
||||
|
||||
end
|
||||
|
||||
def test_pagination_links_on_index_without_project_id_in_url
|
||||
Setting.per_page_options = '2'
|
||||
get '/issues', :project_id => 'ecookbook'
|
||||
|
||||
assert_tag :a, :content => '2',
|
||||
:attributes => { :href => '/projects/ecookbook/issues?page=2' }
|
||||
|
||||
end
|
||||
|
||||
def test_issue_with_user_custom_field
|
||||
@field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true, :trackers => Tracker.all)
|
||||
Role.anonymous.add_permission! :add_issues, :edit_issues
|
||||
users = Project.find(1).users
|
||||
tester = users.first
|
||||
|
||||
# Issue form
|
||||
get '/projects/ecookbook/issues/new'
|
||||
assert_response :success
|
||||
assert_tag :select,
|
||||
:attributes => {:name => "issue[custom_field_values][#{@field.id}]"},
|
||||
:children => {:count => (users.size + 1)}, # +1 for blank value
|
||||
:child => {
|
||||
:tag => 'option',
|
||||
:attributes => {:value => tester.id.to_s},
|
||||
:content => tester.name
|
||||
}
|
||||
|
||||
# Create issue
|
||||
assert_difference 'Issue.count' do
|
||||
post '/projects/ecookbook/issues',
|
||||
:issue => {
|
||||
:tracker_id => '1',
|
||||
:priority_id => '4',
|
||||
:subject => 'Issue with user custom field',
|
||||
:custom_field_values => {@field.id.to_s => users.first.id.to_s}
|
||||
}
|
||||
end
|
||||
issue = Issue.first(:order => 'id DESC')
|
||||
assert_response 302
|
||||
|
||||
# Issue view
|
||||
follow_redirect!
|
||||
assert_tag :th,
|
||||
:content => /Tester/,
|
||||
:sibling => {
|
||||
:tag => 'td',
|
||||
:content => tester.name
|
||||
}
|
||||
assert_tag :select,
|
||||
:attributes => {:name => "issue[custom_field_values][#{@field.id}]"},
|
||||
:children => {:count => (users.size + 1)}, # +1 for blank value
|
||||
:child => {
|
||||
:tag => 'option',
|
||||
:attributes => {:value => tester.id.to_s, :selected => 'selected'},
|
||||
:content => tester.name
|
||||
}
|
||||
|
||||
# Update issue
|
||||
new_tester = users[1]
|
||||
assert_difference 'Journal.count' do
|
||||
put "/issues/#{issue.id}",
|
||||
:notes => 'Updating custom field',
|
||||
:issue => {
|
||||
:custom_field_values => {@field.id.to_s => new_tester.id.to_s}
|
||||
}
|
||||
end
|
||||
assert_response 302
|
||||
|
||||
# Issue view
|
||||
follow_redirect!
|
||||
assert_tag :content => 'Tester',
|
||||
:ancestor => {:tag => 'ul', :attributes => {:class => /details/}},
|
||||
:sibling => {
|
||||
:content => tester.name,
|
||||
:sibling => {
|
||||
:content => new_tester.name
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_update_using_invalid_http_verbs
|
||||
subject = 'Updated by an invalid http verb'
|
||||
|
||||
get '/issues/update/1', {:issue => {:subject => subject}}, credentials('jsmith')
|
||||
assert_response 404
|
||||
assert_not_equal subject, Issue.find(1).subject
|
||||
|
||||
post '/issues/1', {:issue => {:subject => subject}}, credentials('jsmith')
|
||||
assert_response 404
|
||||
assert_not_equal subject, Issue.find(1).subject
|
||||
end
|
||||
|
||||
def test_get_watch_should_be_invalid
|
||||
assert_no_difference 'Watcher.count' do
|
||||
get '/watchers/watch?object_type=issue&object_id=1', {}, credentials('jsmith')
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,119 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 LayoutTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
test "browsing to a missing page should render the base layout" do
|
||||
get "/users/100000000"
|
||||
|
||||
assert_response :not_found
|
||||
|
||||
# UsersController uses the admin layout by default
|
||||
assert_select "#admin-menu", :count => 0
|
||||
end
|
||||
|
||||
test "browsing to an unauthorized page should render the base layout" do
|
||||
change_user_password('miscuser9', 'test1234')
|
||||
|
||||
log_user('miscuser9','test1234')
|
||||
|
||||
get "/admin"
|
||||
assert_response :forbidden
|
||||
assert_select "#admin-menu", :count => 0
|
||||
end
|
||||
|
||||
def test_top_menu_and_search_not_visible_when_login_required
|
||||
with_settings :login_required => '1' do
|
||||
get '/'
|
||||
assert_select "#top-menu > ul", 0
|
||||
assert_select "#quick-search", 0
|
||||
end
|
||||
end
|
||||
|
||||
def test_top_menu_and_search_visible_when_login_not_required
|
||||
with_settings :login_required => '0' do
|
||||
get '/'
|
||||
assert_select "#top-menu > ul"
|
||||
assert_select "#quick-search"
|
||||
end
|
||||
end
|
||||
|
||||
def test_wiki_formatter_header_tags
|
||||
Role.anonymous.add_permission! :add_issues
|
||||
|
||||
get '/projects/ecookbook/issues/new'
|
||||
assert_tag :script,
|
||||
:attributes => {:src => %r{^/javascripts/jstoolbar/jstoolbar-textile.min.js}},
|
||||
:parent => {:tag => 'head'}
|
||||
end
|
||||
|
||||
def test_calendar_header_tags
|
||||
with_settings :default_language => 'fr' do
|
||||
get '/issues'
|
||||
assert_include "/javascripts/i18n/jquery.ui.datepicker-fr.js", response.body
|
||||
end
|
||||
|
||||
with_settings :default_language => 'en-GB' do
|
||||
get '/issues'
|
||||
assert_include "/javascripts/i18n/jquery.ui.datepicker-en-GB.js", response.body
|
||||
end
|
||||
|
||||
with_settings :default_language => 'en' do
|
||||
get '/issues'
|
||||
assert_not_include "/javascripts/i18n/jquery.ui.datepicker", response.body
|
||||
end
|
||||
|
||||
with_settings :default_language => 'zh' do
|
||||
get '/issues'
|
||||
assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-CN.js", response.body
|
||||
end
|
||||
|
||||
with_settings :default_language => 'zh-TW' do
|
||||
get '/issues'
|
||||
assert_include "/javascripts/i18n/jquery.ui.datepicker-zh-TW.js", response.body
|
||||
end
|
||||
|
||||
with_settings :default_language => 'pt' do
|
||||
get '/issues'
|
||||
assert_include "/javascripts/i18n/jquery.ui.datepicker-pt.js", response.body
|
||||
end
|
||||
|
||||
with_settings :default_language => 'pt-BR' do
|
||||
get '/issues'
|
||||
assert_include "/javascripts/i18n/jquery.ui.datepicker-pt-BR.js", response.body
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_field_outside_project_should_link_to_global_search
|
||||
get '/'
|
||||
assert_select 'div#quick-search form[action=/search]'
|
||||
end
|
||||
|
||||
def test_search_field_inside_project_should_link_to_project_search
|
||||
get '/projects/ecookbook'
|
||||
assert_select 'div#quick-search form[action=/projects/ecookbook/search]'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,89 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 HookTest < ActionController::IntegrationTest
|
||||
fixtures :users, :roles, :projects, :members, :member_roles
|
||||
|
||||
# Hooks that are manually registered later
|
||||
class ProjectBasedTemplate < Redmine::Hook::ViewListener
|
||||
def view_layouts_base_html_head(context)
|
||||
# Adds a project stylesheet
|
||||
stylesheet_link_tag(context[:project].identifier) if context[:project]
|
||||
end
|
||||
end
|
||||
|
||||
class SidebarContent < Redmine::Hook::ViewListener
|
||||
def view_layouts_base_sidebar(context)
|
||||
content_tag('p', 'Sidebar hook')
|
||||
end
|
||||
end
|
||||
|
||||
class ContentForInsideHook < Redmine::Hook::ViewListener
|
||||
render_on :view_welcome_index_left, :inline => <<-VIEW
|
||||
<% content_for :header_tags do %>
|
||||
<%= javascript_include_tag 'test_plugin.js', :plugin => 'test_plugin' %>
|
||||
<%= stylesheet_link_tag 'test_plugin.css', :plugin => 'test_plugin' %>
|
||||
<% end %>
|
||||
|
||||
<p>ContentForInsideHook content</p>
|
||||
VIEW
|
||||
end
|
||||
|
||||
def setup
|
||||
Redmine::Hook.clear_listeners
|
||||
end
|
||||
|
||||
def teardown
|
||||
Redmine::Hook.clear_listeners
|
||||
end
|
||||
|
||||
def test_html_head_hook_response
|
||||
Redmine::Hook.add_listener(ProjectBasedTemplate)
|
||||
|
||||
get '/projects/ecookbook'
|
||||
assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
|
||||
:parent => {:tag => 'head'}
|
||||
end
|
||||
|
||||
def test_empty_sidebar_should_be_hidden
|
||||
get '/'
|
||||
assert_select 'div#main.nosidebar'
|
||||
end
|
||||
|
||||
def test_sidebar_with_hook_content_should_not_be_hidden
|
||||
Redmine::Hook.add_listener(SidebarContent)
|
||||
|
||||
get '/'
|
||||
assert_select 'div#sidebar p', :text => 'Sidebar hook'
|
||||
assert_select 'div#main'
|
||||
assert_select 'div#main.nosidebar', 0
|
||||
end
|
||||
|
||||
def test_hook_with_content_for_should_append_content
|
||||
Redmine::Hook.add_listener(ContentForInsideHook)
|
||||
|
||||
get '/'
|
||||
assert_response :success
|
||||
assert_select 'p', :text => 'ContentForInsideHook content'
|
||||
assert_select 'head' do
|
||||
assert_select 'script[src=/plugin_assets/test_plugin/javascripts/test_plugin.js]'
|
||||
assert_select 'link[href=/plugin_assets/test_plugin/stylesheets/test_plugin.css]'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 MenuManagerTest < ActionController::IntegrationTest
|
||||
include Redmine::I18n
|
||||
|
||||
fixtures :projects, :trackers, :issue_statuses, :issues,
|
||||
:enumerations, :users, :issue_categories,
|
||||
:projects_trackers,
|
||||
:roles,
|
||||
:member_roles,
|
||||
:members,
|
||||
:enabled_modules
|
||||
|
||||
def test_project_menu_with_specific_locale
|
||||
get 'projects/ecookbook/issues', { }, 'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
|
||||
|
||||
assert_tag :div, :attributes => { :id => 'main-menu' },
|
||||
:descendant => { :tag => 'li', :child => { :tag => 'a', :content => ll('fr', :label_activity),
|
||||
:attributes => { :href => '/projects/ecookbook/activity',
|
||||
:class => 'activity' } } }
|
||||
assert_tag :div, :attributes => { :id => 'main-menu' },
|
||||
:descendant => { :tag => 'li', :child => { :tag => 'a', :content => ll('fr', :label_issue_plural),
|
||||
:attributes => { :href => '/projects/ecookbook/issues',
|
||||
:class => 'issues selected' } } }
|
||||
end
|
||||
|
||||
def test_project_menu_with_additional_menu_items
|
||||
Setting.default_language = 'en'
|
||||
assert_no_difference 'Redmine::MenuManager.items(:project_menu).size' do
|
||||
Redmine::MenuManager.map :project_menu do |menu|
|
||||
menu.push :foo, { :controller => 'projects', :action => 'show' }, :caption => 'Foo'
|
||||
menu.push :bar, { :controller => 'projects', :action => 'show' }, :before => :activity
|
||||
menu.push :hello, { :controller => 'projects', :action => 'show' }, :caption => Proc.new {|p| p.name.upcase }, :after => :bar
|
||||
end
|
||||
|
||||
get 'projects/ecookbook'
|
||||
assert_tag :div, :attributes => { :id => 'main-menu' },
|
||||
:descendant => { :tag => 'li', :child => { :tag => 'a', :content => 'Foo',
|
||||
:attributes => { :class => 'foo' } } }
|
||||
|
||||
assert_tag :div, :attributes => { :id => 'main-menu' },
|
||||
:descendant => { :tag => 'li', :child => { :tag => 'a', :content => 'Bar',
|
||||
:attributes => { :class => 'bar' } },
|
||||
:before => { :tag => 'li', :child => { :tag => 'a', :content => 'ECOOKBOOK' } } }
|
||||
|
||||
assert_tag :div, :attributes => { :id => 'main-menu' },
|
||||
:descendant => { :tag => 'li', :child => { :tag => 'a', :content => 'ECOOKBOOK',
|
||||
:attributes => { :class => 'hello' } },
|
||||
:before => { :tag => 'li', :child => { :tag => 'a', :content => 'Activity' } } }
|
||||
|
||||
# Remove the menu items
|
||||
Redmine::MenuManager.map :project_menu do |menu|
|
||||
menu.delete :foo
|
||||
menu.delete :bar
|
||||
menu.delete :hello
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,74 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 ThemesTest < ActionController::IntegrationTest
|
||||
|
||||
def setup
|
||||
@theme = Redmine::Themes.themes.last
|
||||
Setting.ui_theme = @theme.id
|
||||
end
|
||||
|
||||
def teardown
|
||||
Setting.ui_theme = ''
|
||||
end
|
||||
|
||||
def test_application_css
|
||||
get '/'
|
||||
|
||||
assert_response :success
|
||||
assert_tag :tag => 'link',
|
||||
:attributes => {:href => %r{^/themes/#{@theme.dir}/stylesheets/application.css}}
|
||||
end
|
||||
|
||||
def test_without_theme_js
|
||||
get '/'
|
||||
|
||||
assert_response :success
|
||||
assert_no_tag :tag => 'script',
|
||||
:attributes => {:src => %r{^/themes/#{@theme.dir}/javascripts/theme.js}}
|
||||
end
|
||||
|
||||
def test_with_theme_js
|
||||
# Simulates a theme.js
|
||||
@theme.javascripts << 'theme'
|
||||
get '/'
|
||||
|
||||
assert_response :success
|
||||
assert_tag :tag => 'script',
|
||||
:attributes => {:src => %r{^/themes/#{@theme.dir}/javascripts/theme.js}}
|
||||
|
||||
ensure
|
||||
@theme.javascripts.delete 'theme'
|
||||
end
|
||||
|
||||
def test_with_sub_uri
|
||||
Redmine::Utils.relative_url_root = '/foo'
|
||||
@theme.javascripts << 'theme'
|
||||
get '/'
|
||||
|
||||
assert_response :success
|
||||
assert_tag :tag => 'link',
|
||||
:attributes => {:href => %r{^/foo/themes/#{@theme.dir}/stylesheets/application.css}}
|
||||
assert_tag :tag => 'script',
|
||||
:attributes => {:src => %r{^/foo/themes/#{@theme.dir}/javascripts/theme.js}}
|
||||
|
||||
ensure
|
||||
Redmine::Utils.relative_url_root = ''
|
||||
end
|
||||
end
|
|
@ -0,0 +1,51 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 ProjectsTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :users, :members, :enabled_modules
|
||||
|
||||
def test_archive_project
|
||||
subproject = Project.find(1).children.first
|
||||
log_user("admin", "admin")
|
||||
get "admin/projects"
|
||||
assert_response :success
|
||||
assert_template "admin/projects"
|
||||
post "projects/1/archive"
|
||||
assert_redirected_to "/admin/projects"
|
||||
assert !Project.find(1).active?
|
||||
|
||||
get 'projects/1'
|
||||
assert_response 403
|
||||
get "projects/#{subproject.id}"
|
||||
assert_response 403
|
||||
|
||||
post "projects/1/unarchive"
|
||||
assert_redirected_to "/admin/projects"
|
||||
assert Project.find(1).active?
|
||||
get "projects/1"
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_modules_should_not_allow_get
|
||||
assert_no_difference 'EnabledModule.count' do
|
||||
get '/projects/1/modules', {:enabled_module_names => ['']}, credentials('jsmith')
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 RepositoriesGitTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :users, :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
|
||||
|
||||
def setup
|
||||
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
|
||||
|
||||
if File.directory?(REPOSITORY_PATH)
|
||||
def test_index
|
||||
get '/projects/subproject1/repository/'
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
def test_diff_two_revs
|
||||
get '/projects/subproject1/repository/diff?rev=61b685fbe&rev_to=2f9c0091'
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 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 UsersTest < ActionController::IntegrationTest
|
||||
fixtures :users
|
||||
|
||||
def test_destroy_should_not_accept_get_requests
|
||||
assert_no_difference 'User.count' do
|
||||
get '/users/destroy/2', {}, credentials('admin')
|
||||
assert_response 404
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,129 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class ActivityTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :versions, :attachments, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
|
||||
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages, :time_entries,
|
||||
:wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
|
||||
|
||||
def setup
|
||||
@project = Project.find(1)
|
||||
end
|
||||
|
||||
def test_activity_without_subprojects
|
||||
events = find_events(User.anonymous, :project => @project)
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
assert !events.include?(Issue.find(4))
|
||||
# subproject issue
|
||||
assert !events.include?(Issue.find(5))
|
||||
end
|
||||
|
||||
def test_activity_with_subprojects
|
||||
events = find_events(User.anonymous, :project => @project, :with_subprojects => 1)
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
# subproject issue
|
||||
assert events.include?(Issue.find(5))
|
||||
end
|
||||
|
||||
def test_global_activity_anonymous
|
||||
events = find_events(User.anonymous)
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
assert events.include?(Message.find(5))
|
||||
# Issue of a private project
|
||||
assert !events.include?(Issue.find(4))
|
||||
# Private issue and comment
|
||||
assert !events.include?(Issue.find(14))
|
||||
assert !events.include?(Journal.find(5))
|
||||
end
|
||||
|
||||
def test_global_activity_logged_user
|
||||
events = find_events(User.find(2)) # manager
|
||||
assert_not_nil events
|
||||
|
||||
assert events.include?(Issue.find(1))
|
||||
# Issue of a private project the user belongs to
|
||||
assert events.include?(Issue.find(4))
|
||||
end
|
||||
|
||||
def test_user_activity
|
||||
user = User.find(2)
|
||||
events = Redmine::Activity::Fetcher.new(User.anonymous, :author => user).events(nil, nil, :limit => 10)
|
||||
|
||||
assert(events.size > 0)
|
||||
assert(events.size <= 10)
|
||||
assert_nil(events.detect {|e| e.event_author != user})
|
||||
end
|
||||
|
||||
def test_files_activity
|
||||
f = Redmine::Activity::Fetcher.new(User.anonymous, :project => Project.find(1))
|
||||
f.scope = ['files']
|
||||
events = f.events
|
||||
|
||||
assert_kind_of Array, events
|
||||
assert events.include?(Attachment.find_by_container_type_and_container_id('Project', 1))
|
||||
assert events.include?(Attachment.find_by_container_type_and_container_id('Version', 1))
|
||||
assert_equal [Attachment], events.collect(&:class).uniq
|
||||
assert_equal %w(Project Version), events.collect(&:container_type).uniq.sort
|
||||
end
|
||||
|
||||
def test_event_group_for_issue
|
||||
issue = Issue.find(1)
|
||||
assert_equal issue, issue.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_journal
|
||||
issue = Issue.find(1)
|
||||
journal = issue.journals.first
|
||||
assert_equal issue, journal.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_issue_time_entry
|
||||
time = TimeEntry.where(:issue_id => 1).first
|
||||
assert_equal time.issue, time.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_project_time_entry
|
||||
time = TimeEntry.where(:issue_id => nil).first
|
||||
assert_equal time, time.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_message
|
||||
message = Message.find(1)
|
||||
reply = message.children.first
|
||||
assert_equal message, message.event_group
|
||||
assert_equal message, reply.event_group
|
||||
end
|
||||
|
||||
def test_event_group_for_wiki_content_version
|
||||
content = WikiContent::Version.find(1)
|
||||
assert_equal content.page, content.event_group
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_events(user, options={})
|
||||
Redmine::Activity::Fetcher.new(user, options).events(Date.today - 30, Date.today + 1)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,283 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class AttachmentTest < ActiveSupport::TestCase
|
||||
fixtures :users, :projects, :roles, :members, :member_roles,
|
||||
:enabled_modules, :issues, :trackers, :attachments
|
||||
|
||||
class MockFile
|
||||
attr_reader :original_filename, :content_type, :content, :size
|
||||
|
||||
def initialize(attributes)
|
||||
@original_filename = attributes[:original_filename]
|
||||
@content_type = attributes[:content_type]
|
||||
@content = attributes[:content] || "Content"
|
||||
@size = content.size
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_container_for_new_attachment_should_be_nil
|
||||
assert_nil Attachment.new.container
|
||||
end
|
||||
|
||||
def test_create
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'testfile.txt', a.filename
|
||||
assert_equal 59, a.filesize
|
||||
assert_equal 'text/plain', a.content_type
|
||||
assert_equal 0, a.downloads
|
||||
assert_equal '1478adae0d4eb06d35897518540e25d6', a.digest
|
||||
|
||||
assert a.disk_directory
|
||||
assert_match %r{\A\d{4}/\d{2}\z}, a.disk_directory
|
||||
|
||||
assert File.exist?(a.diskfile)
|
||||
assert_equal 59, File.size(a.diskfile)
|
||||
end
|
||||
|
||||
def test_copy_should_preserve_attributes
|
||||
a = Attachment.find(1)
|
||||
copy = a.copy
|
||||
|
||||
assert_save copy
|
||||
copy = Attachment.order('id DESC').first
|
||||
%w(filename filesize content_type author_id created_on description digest disk_filename disk_directory diskfile).each do |attribute|
|
||||
assert_equal a.send(attribute), copy.send(attribute), "#{attribute} was different"
|
||||
end
|
||||
end
|
||||
|
||||
def test_size_should_be_validated_for_new_file
|
||||
with_settings :attachment_max_size => 0 do
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert !a.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_size_should_not_be_validated_when_copying
|
||||
a = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
with_settings :attachment_max_size => 0 do
|
||||
copy = a.copy
|
||||
assert copy.save
|
||||
end
|
||||
end
|
||||
|
||||
def test_description_length_should_be_validated
|
||||
a = Attachment.new(:description => 'a' * 300)
|
||||
assert !a.save
|
||||
assert_not_nil a.errors[:description]
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'testfile.txt', a.filename
|
||||
assert_equal 59, a.filesize
|
||||
assert_equal 'text/plain', a.content_type
|
||||
assert_equal 0, a.downloads
|
||||
assert_equal '1478adae0d4eb06d35897518540e25d6', a.digest
|
||||
diskfile = a.diskfile
|
||||
assert File.exist?(diskfile)
|
||||
assert_equal 59, File.size(a.diskfile)
|
||||
assert a.destroy
|
||||
assert !File.exist?(diskfile)
|
||||
end
|
||||
|
||||
def test_destroy_should_not_delete_file_referenced_by_other_attachment
|
||||
a = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", "text/plain"),
|
||||
:author => User.find(1))
|
||||
diskfile = a.diskfile
|
||||
|
||||
copy = a.copy
|
||||
copy.save!
|
||||
|
||||
assert File.exists?(diskfile)
|
||||
a.destroy
|
||||
assert File.exists?(diskfile)
|
||||
copy.destroy
|
||||
assert !File.exists?(diskfile)
|
||||
end
|
||||
|
||||
def test_create_should_auto_assign_content_type
|
||||
a = Attachment.new(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", ""),
|
||||
:author => User.find(1))
|
||||
assert a.save
|
||||
assert_equal 'text/plain', a.content_type
|
||||
end
|
||||
|
||||
def test_identical_attachments_at_the_same_time_should_not_overwrite
|
||||
a1 = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", ""),
|
||||
:author => User.find(1))
|
||||
a2 = Attachment.create!(:container => Issue.find(1),
|
||||
:file => uploaded_test_file("testfile.txt", ""),
|
||||
:author => User.find(1))
|
||||
assert a1.disk_filename != a2.disk_filename
|
||||
end
|
||||
|
||||
def test_filename_should_be_basenamed
|
||||
a = Attachment.new(:file => MockFile.new(:original_filename => "path/to/the/file"))
|
||||
assert_equal 'file', a.filename
|
||||
end
|
||||
|
||||
def test_filename_should_be_sanitized
|
||||
a = Attachment.new(:file => MockFile.new(:original_filename => "valid:[] invalid:?%*|\"'<>chars"))
|
||||
assert_equal 'valid_[] invalid_chars', a.filename
|
||||
end
|
||||
|
||||
def test_diskfilename
|
||||
assert Attachment.disk_filename("test_file.txt") =~ /^\d{12}_test_file.txt$/
|
||||
assert_equal 'test_file.txt', Attachment.disk_filename("test_file.txt")[13..-1]
|
||||
assert_equal '770c509475505f37c2b8fb6030434d6b.txt', Attachment.disk_filename("test_accentué.txt")[13..-1]
|
||||
assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1]
|
||||
assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1]
|
||||
end
|
||||
|
||||
def test_title
|
||||
a = Attachment.new(:filename => "test.png")
|
||||
assert_equal "test.png", a.title
|
||||
|
||||
a = Attachment.new(:filename => "test.png", :description => "Cool image")
|
||||
assert_equal "test.png (Cool image)", a.title
|
||||
end
|
||||
|
||||
def test_prune_should_destroy_old_unattached_attachments
|
||||
Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
|
||||
Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1, :created_on => 2.days.ago)
|
||||
Attachment.create!(:file => uploaded_test_file("testfile.txt", ""), :author_id => 1)
|
||||
|
||||
assert_difference 'Attachment.count', -2 do
|
||||
Attachment.prune
|
||||
end
|
||||
end
|
||||
|
||||
def test_move_from_root_to_target_directory_should_move_root_files
|
||||
a = Attachment.find(20)
|
||||
assert a.disk_directory.blank?
|
||||
# Create a real file for this fixture
|
||||
File.open(a.diskfile, "w") do |f|
|
||||
f.write "test file at the root of files directory"
|
||||
end
|
||||
assert a.readable?
|
||||
Attachment.move_from_root_to_target_directory
|
||||
|
||||
a.reload
|
||||
assert_equal '2012/05', a.disk_directory
|
||||
assert a.readable?
|
||||
end
|
||||
|
||||
test "Attachmnet.attach_files should attach the file" do
|
||||
issue = Issue.first
|
||||
assert_difference 'Attachment.count' do
|
||||
Attachment.attach_files(issue,
|
||||
'1' => {
|
||||
'file' => uploaded_test_file('testfile.txt', 'text/plain'),
|
||||
'description' => 'test'
|
||||
})
|
||||
end
|
||||
|
||||
attachment = Attachment.first(:order => 'id DESC')
|
||||
assert_equal issue, attachment.container
|
||||
assert_equal 'testfile.txt', attachment.filename
|
||||
assert_equal 59, attachment.filesize
|
||||
assert_equal 'test', attachment.description
|
||||
assert_equal 'text/plain', attachment.content_type
|
||||
assert File.exists?(attachment.diskfile)
|
||||
assert_equal 59, File.size(attachment.diskfile)
|
||||
end
|
||||
|
||||
test "Attachmnet.attach_files should add unsaved files to the object as unsaved attachments" do
|
||||
# Max size of 0 to force Attachment creation failures
|
||||
with_settings(:attachment_max_size => 0) do
|
||||
@project = Project.find(1)
|
||||
response = Attachment.attach_files(@project, {
|
||||
'1' => {'file' => mock_file, 'description' => 'test'},
|
||||
'2' => {'file' => mock_file, 'description' => 'test'}
|
||||
})
|
||||
|
||||
assert response[:unsaved].present?
|
||||
assert_equal 2, response[:unsaved].length
|
||||
assert response[:unsaved].first.new_record?
|
||||
assert response[:unsaved].second.new_record?
|
||||
assert_equal response[:unsaved], @project.unsaved_attachments
|
||||
end
|
||||
end
|
||||
|
||||
def test_latest_attach
|
||||
set_fixtures_attachments_directory
|
||||
a1 = Attachment.find(16)
|
||||
assert_equal "testfile.png", a1.filename
|
||||
assert a1.readable?
|
||||
assert (! a1.visible?(User.anonymous))
|
||||
assert a1.visible?(User.find(2))
|
||||
a2 = Attachment.find(17)
|
||||
assert_equal "testfile.PNG", a2.filename
|
||||
assert a2.readable?
|
||||
assert (! a2.visible?(User.anonymous))
|
||||
assert a2.visible?(User.find(2))
|
||||
assert a1.created_on < a2.created_on
|
||||
|
||||
la1 = Attachment.latest_attach([a1, a2], "testfile.png")
|
||||
assert_equal 17, la1.id
|
||||
la2 = Attachment.latest_attach([a1, a2], "Testfile.PNG")
|
||||
assert_equal 17, la2.id
|
||||
|
||||
set_tmp_attachments_directory
|
||||
end
|
||||
|
||||
def test_thumbnailable_should_be_true_for_images
|
||||
assert_equal true, Attachment.new(:filename => 'test.jpg').thumbnailable?
|
||||
end
|
||||
|
||||
def test_thumbnailable_should_be_true_for_non_images
|
||||
assert_equal false, Attachment.new(:filename => 'test.txt').thumbnailable?
|
||||
end
|
||||
|
||||
if convert_installed?
|
||||
def test_thumbnail_should_generate_the_thumbnail
|
||||
set_fixtures_attachments_directory
|
||||
attachment = Attachment.find(16)
|
||||
Attachment.clear_thumbnails
|
||||
|
||||
assert_difference "Dir.glob(File.join(Attachment.thumbnails_storage_path, '*.thumb')).size" do
|
||||
thumbnail = attachment.thumbnail
|
||||
assert_equal "16_8e0294de2441577c529f170b6fb8f638_100.thumb", File.basename(thumbnail)
|
||||
assert File.exists?(thumbnail)
|
||||
end
|
||||
end
|
||||
else
|
||||
puts '(ImageMagick convert not available)'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,141 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class AuthSourceLdapTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
fixtures :auth_sources
|
||||
|
||||
def setup
|
||||
end
|
||||
|
||||
def test_create
|
||||
a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName')
|
||||
assert a.save
|
||||
end
|
||||
|
||||
def test_should_strip_ldap_attributes
|
||||
a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
|
||||
:attr_firstname => 'givenName ')
|
||||
assert a.save
|
||||
assert_equal 'givenName', a.reload.attr_firstname
|
||||
end
|
||||
|
||||
def test_replace_port_zero_to_389
|
||||
a = AuthSourceLdap.new(
|
||||
:name => 'My LDAP', :host => 'ldap.example.net', :port => 0,
|
||||
:base_dn => 'dc=example,dc=net', :attr_login => 'sAMAccountName',
|
||||
:attr_firstname => 'givenName ')
|
||||
assert a.save
|
||||
assert_equal 389, a.port
|
||||
end
|
||||
|
||||
def test_filter_should_be_validated
|
||||
set_language_if_valid 'en'
|
||||
|
||||
a = AuthSourceLdap.new(:name => 'My LDAP', :host => 'ldap.example.net', :port => 389, :attr_login => 'sn')
|
||||
a.filter = "(mail=*@redmine.org"
|
||||
assert !a.valid?
|
||||
assert_include "LDAP filter is invalid", a.errors.full_messages
|
||||
|
||||
a.filter = "(mail=*@redmine.org)"
|
||||
assert a.valid?
|
||||
end
|
||||
|
||||
if ldap_configured?
|
||||
test '#authenticate with a valid LDAP user should return the user attributes' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
auth.update_attribute :onthefly_register, true
|
||||
|
||||
attributes = auth.authenticate('example1','123456')
|
||||
assert attributes.is_a?(Hash), "An hash was not returned"
|
||||
assert_equal 'Example', attributes[:firstname]
|
||||
assert_equal 'One', attributes[:lastname]
|
||||
assert_equal 'example1@redmine.org', attributes[:mail]
|
||||
assert_equal auth.id, attributes[:auth_source_id]
|
||||
attributes.keys.each do |attribute|
|
||||
assert User.new.respond_to?("#{attribute}="), "Unexpected :#{attribute} attribute returned"
|
||||
end
|
||||
end
|
||||
|
||||
test '#authenticate with an invalid LDAP user should return nil' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert_equal nil, auth.authenticate('nouser','123456')
|
||||
end
|
||||
|
||||
test '#authenticate without a login should return nil' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert_equal nil, auth.authenticate('','123456')
|
||||
end
|
||||
|
||||
test '#authenticate without a password should return nil' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert_equal nil, auth.authenticate('edavis','')
|
||||
end
|
||||
|
||||
test '#authenticate without filter should return any user' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
assert auth.authenticate('example1','123456')
|
||||
assert auth.authenticate('edavis', '123456')
|
||||
end
|
||||
|
||||
test '#authenticate with filter should return user who matches the filter only' do
|
||||
auth = AuthSourceLdap.find(1)
|
||||
auth.filter = "(mail=*@redmine.org)"
|
||||
|
||||
assert auth.authenticate('example1','123456')
|
||||
assert_nil auth.authenticate('edavis', '123456')
|
||||
end
|
||||
|
||||
def test_authenticate_should_timeout
|
||||
auth_source = AuthSourceLdap.find(1)
|
||||
auth_source.timeout = 1
|
||||
def auth_source.initialize_ldap_con(*args); sleep(5); end
|
||||
|
||||
assert_raise AuthSourceTimeoutException do
|
||||
auth_source.authenticate 'example1', '123456'
|
||||
end
|
||||
end
|
||||
|
||||
def test_search_should_return_matching_entries
|
||||
results = AuthSource.search("exa")
|
||||
assert_equal 1, results.size
|
||||
result = results.first
|
||||
assert_kind_of Hash, result
|
||||
assert_equal "example1", result[:login]
|
||||
assert_equal "Example", result[:firstname]
|
||||
assert_equal "One", result[:lastname]
|
||||
assert_equal "example1@redmine.org", result[:mail]
|
||||
assert_equal 1, result[:auth_source_id]
|
||||
end
|
||||
|
||||
def test_search_with_no_match_should_return_an_empty_array
|
||||
results = AuthSource.search("wro")
|
||||
assert_equal [], results
|
||||
end
|
||||
|
||||
def test_search_with_exception_should_return_an_empty_array
|
||||
Net::LDAP.stubs(:new).raises(Net::LDAP::LdapError, 'Cannot connect')
|
||||
|
||||
results = AuthSource.search("exa")
|
||||
assert_equal [], results
|
||||
end
|
||||
else
|
||||
puts '(Test LDAP server not configured)'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,116 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class BoardTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :boards, :messages, :attachments, :watchers
|
||||
|
||||
include Redmine::I18n
|
||||
|
||||
def setup
|
||||
@project = Project.find(1)
|
||||
end
|
||||
|
||||
def test_create
|
||||
board = Board.new(:project => @project, :name => 'Test board', :description => 'Test board description')
|
||||
assert board.save
|
||||
board.reload
|
||||
assert_equal 'Test board', board.name
|
||||
assert_equal 'Test board description', board.description
|
||||
assert_equal @project, board.project
|
||||
assert_equal 0, board.topics_count
|
||||
assert_equal 0, board.messages_count
|
||||
assert_nil board.last_message
|
||||
# last position
|
||||
assert_equal @project.boards.size, board.position
|
||||
end
|
||||
|
||||
def test_parent_should_be_in_same_project
|
||||
set_language_if_valid 'en'
|
||||
board = Board.new(:project_id => 3, :name => 'Test', :description => 'Test', :parent_id => 1)
|
||||
assert !board.save
|
||||
assert_include "Parent forum is invalid", board.errors.full_messages
|
||||
end
|
||||
|
||||
def test_valid_parents_should_not_include_self_nor_a_descendant
|
||||
board1 = Board.generate!(:project_id => 3)
|
||||
board2 = Board.generate!(:project_id => 3, :parent => board1)
|
||||
board3 = Board.generate!(:project_id => 3, :parent => board2)
|
||||
board4 = Board.generate!(:project_id => 3)
|
||||
|
||||
assert_equal [board4], board1.reload.valid_parents.sort_by(&:id)
|
||||
assert_equal [board1, board4], board2.reload.valid_parents.sort_by(&:id)
|
||||
assert_equal [board1, board2, board4], board3.reload.valid_parents.sort_by(&:id)
|
||||
assert_equal [board1, board2, board3], board4.reload.valid_parents.sort_by(&:id)
|
||||
end
|
||||
|
||||
def test_position_should_be_assigned_with_parent_scope
|
||||
parent1 = Board.generate!(:project_id => 3)
|
||||
parent2 = Board.generate!(:project_id => 3)
|
||||
child1 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
child2 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
|
||||
assert_equal 1, parent1.reload.position
|
||||
assert_equal 1, child1.reload.position
|
||||
assert_equal 2, child2.reload.position
|
||||
assert_equal 2, parent2.reload.position
|
||||
end
|
||||
|
||||
def test_board_tree_should_yield_boards_with_level
|
||||
parent1 = Board.generate!(:project_id => 3)
|
||||
parent2 = Board.generate!(:project_id => 3)
|
||||
child1 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
child2 = Board.generate!(:project_id => 3, :parent => parent1)
|
||||
child3 = Board.generate!(:project_id => 3, :parent => child1)
|
||||
|
||||
tree = Board.board_tree(Project.find(3).boards)
|
||||
|
||||
assert_equal [
|
||||
[parent1, 0],
|
||||
[child1, 1],
|
||||
[child3, 2],
|
||||
[child2, 1],
|
||||
[parent2, 0]
|
||||
], tree
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
board = Board.find(1)
|
||||
assert_difference 'Message.count', -6 do
|
||||
assert_difference 'Attachment.count', -1 do
|
||||
assert_difference 'Watcher.count', -1 do
|
||||
assert board.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
assert_equal 0, Message.count(:conditions => {:board_id => 1})
|
||||
end
|
||||
|
||||
def test_destroy_should_nullify_children
|
||||
parent = Board.generate!(:project => @project)
|
||||
child = Board.generate!(:project => @project, :parent => parent)
|
||||
assert_equal parent, child.parent
|
||||
|
||||
assert parent.destroy
|
||||
child.reload
|
||||
assert_nil child.parent
|
||||
assert_nil child.parent_id
|
||||
end
|
||||
end
|
|
@ -0,0 +1,476 @@
|
|||
# encoding: utf-8
|
||||
#
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class ChangesetTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :repositories,
|
||||
:issues, :issue_statuses, :issue_categories,
|
||||
:changesets, :changes,
|
||||
:enumerations,
|
||||
:custom_fields, :custom_values,
|
||||
:users, :members, :member_roles, :trackers,
|
||||
:enabled_modules, :roles
|
||||
|
||||
def test_ref_keywords_any
|
||||
ActionMailer::Base.deliveries.clear
|
||||
Setting.commit_fix_status_id = IssueStatus.find(
|
||||
:first, :conditions => ["is_closed = ?", true]).id
|
||||
Setting.commit_fix_done_ratio = '90'
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_fix_keywords = 'fixes , closes'
|
||||
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'New commit (#2). Fixes #1',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
fixed = Issue.find(1)
|
||||
assert fixed.closed?
|
||||
assert_equal 90, fixed.done_ratio
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_ref_keywords
|
||||
Setting.commit_ref_keywords = 'refs'
|
||||
Setting.commit_fix_keywords = ''
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'Ignores #2. Refs #1',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_any_only
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_fix_keywords = ''
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'Ignores #2. Refs #1',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_any_with_timelog
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_logtime_enabled = '1'
|
||||
|
||||
{
|
||||
'2' => 2.0,
|
||||
'2h' => 2.0,
|
||||
'2hours' => 2.0,
|
||||
'15m' => 0.25,
|
||||
'15min' => 0.25,
|
||||
'3h15' => 3.25,
|
||||
'3h15m' => 3.25,
|
||||
'3h15min' => 3.25,
|
||||
'3:15' => 3.25,
|
||||
'3.25' => 3.25,
|
||||
'3.25h' => 3.25,
|
||||
'3,25' => 3.25,
|
||||
'3,25h' => 3.25,
|
||||
}.each do |syntax, expected_hours|
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => 24.hours.ago,
|
||||
:comments => "Worked on this issue #1 @#{syntax}",
|
||||
:revision => '520',
|
||||
:user => User.find(2))
|
||||
assert_difference 'TimeEntry.count' do
|
||||
c.scan_comment_for_issue_ids
|
||||
end
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
|
||||
time = TimeEntry.first(:order => 'id desc')
|
||||
assert_equal 1, time.issue_id
|
||||
assert_equal 1, time.project_id
|
||||
assert_equal 2, time.user_id
|
||||
assert_equal expected_hours, time.hours,
|
||||
"@#{syntax} should be logged as #{expected_hours} hours but was #{time.hours}"
|
||||
assert_equal Date.yesterday, time.spent_on
|
||||
assert time.activity.is_default?
|
||||
assert time.comments.include?('r520'),
|
||||
"r520 was expected in time_entry comments: #{time.comments}"
|
||||
end
|
||||
end
|
||||
|
||||
def test_ref_keywords_closing_with_timelog
|
||||
Setting.commit_fix_status_id = IssueStatus.find(
|
||||
:first, :conditions => ["is_closed = ?", true]).id
|
||||
Setting.commit_ref_keywords = '*'
|
||||
Setting.commit_fix_keywords = 'fixes , closes'
|
||||
Setting.commit_logtime_enabled = '1'
|
||||
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'This is a comment. Fixes #1 @4.5, #2 @1',
|
||||
:user => User.find(2))
|
||||
assert_difference 'TimeEntry.count', 2 do
|
||||
c.scan_comment_for_issue_ids
|
||||
end
|
||||
|
||||
assert_equal [1, 2], c.issue_ids.sort
|
||||
assert Issue.find(1).closed?
|
||||
assert Issue.find(2).closed?
|
||||
|
||||
times = TimeEntry.all(:order => 'id desc', :limit => 2)
|
||||
assert_equal [1, 2], times.collect(&:issue_id).sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_any_line_start
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => '#1 is the reason of this commit',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_allow_brackets_around_a_issue_number
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => '[#1] Worked on this issue',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_ref_keywords_allow_brackets_around_multiple_issue_numbers
|
||||
Setting.commit_ref_keywords = '*'
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => '[#1 #2, #3] Worked on these',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [1,2,3], c.issue_ids.sort
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_subproject_issue
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #5, a subproject issue',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [5], c.issue_ids.sort
|
||||
assert c.issues.first.project != c.project
|
||||
end
|
||||
|
||||
def test_commit_closing_a_subproject_issue
|
||||
with_settings :commit_fix_status_id => 5, :commit_fix_keywords => 'closes',
|
||||
:default_language => 'en' do
|
||||
issue = Issue.find(5)
|
||||
assert !issue.closed?
|
||||
assert_difference 'Journal.count' do
|
||||
c = Changeset.new(:repository => Project.find(1).repository,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'closes #5, a subproject issue',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
end
|
||||
assert issue.reload.closed?
|
||||
journal = Journal.first(:order => 'id DESC')
|
||||
assert_equal issue, journal.issue
|
||||
assert_include "Applied in changeset ecookbook:r12345.", journal.notes
|
||||
end
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_parent_project_issue
|
||||
# repository of child project
|
||||
r = Repository::Subversion.create!(
|
||||
:project => Project.find(3),
|
||||
:url => 'svn://localhost/test')
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #2, an issue of a parent project',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [2], c.issue_ids.sort
|
||||
assert c.issues.first.project != c.project
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_project_with_commit_cross_project_ref_disabled
|
||||
r = Repository::Subversion.create!(
|
||||
:project => Project.find(3),
|
||||
:url => 'svn://localhost/test')
|
||||
|
||||
with_settings :commit_cross_project_ref => '0' do
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #4, an issue of a different project',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [], c.issue_ids
|
||||
end
|
||||
end
|
||||
|
||||
def test_commit_referencing_a_project_with_commit_cross_project_ref_enabled
|
||||
r = Repository::Subversion.create!(
|
||||
:project => Project.find(3),
|
||||
:url => 'svn://localhost/test')
|
||||
|
||||
with_settings :commit_cross_project_ref => '1' do
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:comments => 'refs #4, an issue of a different project',
|
||||
:revision => '12345')
|
||||
assert c.save
|
||||
assert_equal [4], c.issue_ids
|
||||
end
|
||||
end
|
||||
|
||||
def test_text_tag_revision
|
||||
c = Changeset.new(:revision => '520')
|
||||
assert_equal 'r520', c.text_tag
|
||||
end
|
||||
|
||||
def test_text_tag_revision_with_same_project
|
||||
c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
|
||||
assert_equal 'r520', c.text_tag(Project.find(1))
|
||||
end
|
||||
|
||||
def test_text_tag_revision_with_different_project
|
||||
c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
|
||||
assert_equal 'ecookbook:r520', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_text_tag_revision_with_repository_identifier
|
||||
r = Repository::Subversion.create!(
|
||||
:project_id => 1,
|
||||
:url => 'svn://localhost/test',
|
||||
:identifier => 'documents')
|
||||
|
||||
c = Changeset.new(:revision => '520', :repository => r)
|
||||
assert_equal 'documents|r520', c.text_tag
|
||||
assert_equal 'ecookbook:documents|r520', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_text_tag_hash
|
||||
c = Changeset.new(
|
||||
:scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518',
|
||||
:revision => '7234cb2750b63f47bff735edc50a1c0a433c2518')
|
||||
assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
|
||||
end
|
||||
|
||||
def test_text_tag_hash_with_same_project
|
||||
c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
|
||||
assert_equal 'commit:7234cb27', c.text_tag(Project.find(1))
|
||||
end
|
||||
|
||||
def test_text_tag_hash_with_different_project
|
||||
c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
|
||||
assert_equal 'ecookbook:commit:7234cb27', c.text_tag(Project.find(2))
|
||||
end
|
||||
|
||||
def test_text_tag_hash_all_number
|
||||
c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
|
||||
assert_equal 'commit:0123456789', c.text_tag
|
||||
end
|
||||
|
||||
def test_previous
|
||||
changeset = Changeset.find_by_revision('3')
|
||||
assert_equal Changeset.find_by_revision('2'), changeset.previous
|
||||
end
|
||||
|
||||
def test_previous_nil
|
||||
changeset = Changeset.find_by_revision('1')
|
||||
assert_nil changeset.previous
|
||||
end
|
||||
|
||||
def test_next
|
||||
changeset = Changeset.find_by_revision('2')
|
||||
assert_equal Changeset.find_by_revision('3'), changeset.next
|
||||
end
|
||||
|
||||
def test_next_nil
|
||||
changeset = Changeset.find_by_revision('10')
|
||||
assert_nil changeset.next
|
||||
end
|
||||
|
||||
def test_comments_should_be_converted_to_utf8
|
||||
proj = Project.find(3)
|
||||
# str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
|
||||
str = "Texte encod\xe9 en ISO-8859-1."
|
||||
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => str)
|
||||
assert( c.save )
|
||||
str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1."
|
||||
str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding)
|
||||
assert_equal str_utf8, c.comments
|
||||
end
|
||||
|
||||
def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
|
||||
proj = Project.find(3)
|
||||
# str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
|
||||
str1 = "Texte encod\xe9 en ISO-8859-1."
|
||||
str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
|
||||
str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
|
||||
str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'UTF-8' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => str1,
|
||||
:committer => str2)
|
||||
assert( c.save )
|
||||
assert_equal "Texte encod? en ISO-8859-1.", c.comments
|
||||
assert_equal "?a?b?c?d?e test", c.committer
|
||||
end
|
||||
|
||||
def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
|
||||
proj = Project.find(3)
|
||||
str = "test\xb5\xfetest\xb5\xfe"
|
||||
if str.respond_to?(:force_encoding)
|
||||
str.force_encoding('ASCII-8BIT')
|
||||
end
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-2022-JP' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => str)
|
||||
assert( c.save )
|
||||
assert_equal "test??test??", c.comments
|
||||
end
|
||||
|
||||
def test_comments_should_be_converted_all_latin1_to_utf8
|
||||
s1 = "\xC2\x80"
|
||||
s2 = "\xc3\x82\xc2\x80"
|
||||
s4 = s2.dup
|
||||
if s1.respond_to?(:force_encoding)
|
||||
s3 = s1.dup
|
||||
s1.force_encoding('ASCII-8BIT')
|
||||
s2.force_encoding('ASCII-8BIT')
|
||||
s3.force_encoding('ISO-8859-1')
|
||||
s4.force_encoding('UTF-8')
|
||||
assert_equal s3.encode('UTF-8'), s4
|
||||
end
|
||||
proj = Project.find(3)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => s1)
|
||||
assert( c.save )
|
||||
assert_equal s4, c.comments
|
||||
end
|
||||
|
||||
def test_invalid_utf8_sequences_in_paths_should_be_replaced
|
||||
proj = Project.find(3)
|
||||
str1 = "Texte encod\xe9 en ISO-8859-1"
|
||||
str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
|
||||
str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
|
||||
str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'UTF-8' )
|
||||
assert r
|
||||
cs = Changeset.new(
|
||||
:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => "test")
|
||||
assert(cs.save)
|
||||
ch = Change.new(
|
||||
:changeset => cs,
|
||||
:action => "A",
|
||||
:path => str1,
|
||||
:from_path => str2,
|
||||
:from_revision => "345")
|
||||
assert(ch.save)
|
||||
assert_equal "Texte encod? en ISO-8859-1", ch.path
|
||||
assert_equal "?a?b?c?d?e test", ch.from_path
|
||||
end
|
||||
|
||||
def test_comments_nil
|
||||
proj = Project.find(3)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => nil,
|
||||
:committer => nil)
|
||||
assert( c.save )
|
||||
assert_equal "", c.comments
|
||||
assert_equal nil, c.committer
|
||||
if c.comments.respond_to?(:force_encoding)
|
||||
assert_equal "UTF-8", c.comments.encoding.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def test_comments_empty
|
||||
proj = Project.find(3)
|
||||
r = Repository::Bazaar.create!(
|
||||
:project => proj,
|
||||
:url => '/tmp/test/bazaar',
|
||||
:log_encoding => 'ISO-8859-1' )
|
||||
assert r
|
||||
c = Changeset.new(:repository => r,
|
||||
:committed_on => Time.now,
|
||||
:revision => '123',
|
||||
:scmid => '12345',
|
||||
:comments => "",
|
||||
:committer => "")
|
||||
assert( c.save )
|
||||
assert_equal "", c.comments
|
||||
assert_equal "", c.committer
|
||||
if c.comments.respond_to?(:force_encoding)
|
||||
assert_equal "UTF-8", c.comments.encoding.to_s
|
||||
assert_equal "UTF-8", c.committer.encoding.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def test_identifier
|
||||
c = Changeset.find_by_revision('1')
|
||||
assert_equal c.revision, c.identifier
|
||||
end
|
||||
end
|
|
@ -0,0 +1,57 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class CommentTest < ActiveSupport::TestCase
|
||||
fixtures :users, :news, :comments, :projects, :enabled_modules
|
||||
|
||||
def setup
|
||||
@jsmith = User.find(2)
|
||||
@news = News.find(1)
|
||||
end
|
||||
|
||||
def test_create
|
||||
comment = Comment.new(:commented => @news, :author => @jsmith, :comments => "my comment")
|
||||
assert comment.save
|
||||
@news.reload
|
||||
assert_equal 2, @news.comments_count
|
||||
end
|
||||
|
||||
def test_create_should_send_notification
|
||||
Watcher.create!(:watchable => @news, :user => @jsmith)
|
||||
|
||||
with_settings :notified_events => %w(news_comment_added) do
|
||||
assert_difference 'ActionMailer::Base.deliveries.size' do
|
||||
Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate
|
||||
comment = Comment.new(:commented => @news)
|
||||
assert !comment.save
|
||||
assert_equal 2, comment.errors.count
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
comment = Comment.find(1)
|
||||
assert comment.destroy
|
||||
@news.reload
|
||||
assert_equal 0, @news.comments_count
|
||||
end
|
||||
end
|
|
@ -0,0 +1,244 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class CustomFieldTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields
|
||||
|
||||
def test_create
|
||||
field = UserCustomField.new(:name => 'Money money money', :field_format => 'float')
|
||||
assert field.save
|
||||
end
|
||||
|
||||
def test_before_validation
|
||||
field = CustomField.new(:name => 'test_before_validation', :field_format => 'int')
|
||||
field.searchable = true
|
||||
assert field.save
|
||||
assert_equal false, field.searchable
|
||||
field.searchable = true
|
||||
assert field.save
|
||||
assert_equal false, field.searchable
|
||||
end
|
||||
|
||||
def test_regexp_validation
|
||||
field = IssueCustomField.new(:name => 'regexp', :field_format => 'text', :regexp => '[a-z0-9')
|
||||
assert !field.save
|
||||
assert_include I18n.t('activerecord.errors.messages.invalid'),
|
||||
field.errors[:regexp]
|
||||
field.regexp = '[a-z0-9]'
|
||||
assert field.save
|
||||
end
|
||||
|
||||
def test_default_value_should_be_validated
|
||||
field = CustomField.new(:name => 'Test', :field_format => 'int')
|
||||
field.default_value = 'abc'
|
||||
assert !field.valid?
|
||||
field.default_value = '6'
|
||||
assert field.valid?
|
||||
end
|
||||
|
||||
def test_default_value_should_not_be_validated_when_blank
|
||||
field = CustomField.new(:name => 'Test', :field_format => 'list', :possible_values => ['a', 'b'], :is_required => true, :default_value => '')
|
||||
assert field.valid?
|
||||
end
|
||||
|
||||
def test_should_not_change_field_format_of_existing_custom_field
|
||||
field = CustomField.find(1)
|
||||
field.field_format = 'int'
|
||||
assert_equal 'list', field.field_format
|
||||
end
|
||||
|
||||
def test_possible_values_should_accept_an_array
|
||||
field = CustomField.new
|
||||
field.possible_values = ["One value", ""]
|
||||
assert_equal ["One value"], field.possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_should_accept_a_string
|
||||
field = CustomField.new
|
||||
field.possible_values = "One value"
|
||||
assert_equal ["One value"], field.possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_should_accept_a_multiline_string
|
||||
field = CustomField.new
|
||||
field.possible_values = "One value\nAnd another one \r\n \n"
|
||||
assert_equal ["One value", "And another one"], field.possible_values
|
||||
end
|
||||
|
||||
if "string".respond_to?(:encoding)
|
||||
def test_possible_values_stored_as_binary_should_be_utf8_encoded
|
||||
field = CustomField.find(11)
|
||||
assert_kind_of Array, field.possible_values
|
||||
assert field.possible_values.size > 0
|
||||
field.possible_values.each do |value|
|
||||
assert_equal "UTF-8", value.encoding.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
field = CustomField.find(1)
|
||||
assert field.destroy
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_should_return_an_instance
|
||||
f = CustomField.new_subclass_instance('IssueCustomField')
|
||||
assert_kind_of IssueCustomField, f
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_should_set_attributes
|
||||
f = CustomField.new_subclass_instance('IssueCustomField', :name => 'Test')
|
||||
assert_kind_of IssueCustomField, f
|
||||
assert_equal 'Test', f.name
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_with_invalid_class_name_should_return_nil
|
||||
assert_nil CustomField.new_subclass_instance('WrongClassName')
|
||||
end
|
||||
|
||||
def test_new_subclass_instance_with_non_subclass_name_should_return_nil
|
||||
assert_nil CustomField.new_subclass_instance('Project')
|
||||
end
|
||||
|
||||
def test_string_field_validation_with_blank_value
|
||||
f = CustomField.new(:field_format => 'string')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
|
||||
f.is_required = true
|
||||
assert !f.valid_field_value?(nil)
|
||||
assert !f.valid_field_value?('')
|
||||
end
|
||||
|
||||
def test_string_field_validation_with_min_and_max_lengths
|
||||
f = CustomField.new(:field_format => 'string', :min_length => 2, :max_length => 5)
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?('a' * 2)
|
||||
assert !f.valid_field_value?('a')
|
||||
assert !f.valid_field_value?('a' * 6)
|
||||
end
|
||||
|
||||
def test_string_field_validation_with_regexp
|
||||
f = CustomField.new(:field_format => 'string', :regexp => '^[A-Z0-9]*$')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?('ABC')
|
||||
assert !f.valid_field_value?('abc')
|
||||
end
|
||||
|
||||
def test_date_field_validation
|
||||
f = CustomField.new(:field_format => 'date')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?('1975-07-14')
|
||||
assert !f.valid_field_value?('1975-07-33')
|
||||
assert !f.valid_field_value?('abc')
|
||||
end
|
||||
|
||||
def test_list_field_validation
|
||||
f = CustomField.new(:field_format => 'list', :possible_values => ['value1', 'value2'])
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?('value2')
|
||||
assert !f.valid_field_value?('abc')
|
||||
end
|
||||
|
||||
def test_int_field_validation
|
||||
f = CustomField.new(:field_format => 'int')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?('123')
|
||||
assert f.valid_field_value?('+123')
|
||||
assert f.valid_field_value?('-123')
|
||||
assert !f.valid_field_value?('6abc')
|
||||
end
|
||||
|
||||
def test_float_field_validation
|
||||
f = CustomField.new(:field_format => 'float')
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?('11.2')
|
||||
assert f.valid_field_value?('-6.250')
|
||||
assert f.valid_field_value?('5')
|
||||
assert !f.valid_field_value?('6abc')
|
||||
end
|
||||
|
||||
def test_multi_field_validation
|
||||
f = CustomField.new(:field_format => 'list', :multiple => 'true', :possible_values => ['value1', 'value2'])
|
||||
|
||||
assert f.valid_field_value?(nil)
|
||||
assert f.valid_field_value?('')
|
||||
assert f.valid_field_value?([])
|
||||
assert f.valid_field_value?([nil])
|
||||
assert f.valid_field_value?([''])
|
||||
|
||||
assert f.valid_field_value?('value2')
|
||||
assert !f.valid_field_value?('abc')
|
||||
|
||||
assert f.valid_field_value?(['value2'])
|
||||
assert !f.valid_field_value?(['abc'])
|
||||
|
||||
assert f.valid_field_value?(['', 'value2'])
|
||||
assert !f.valid_field_value?(['', 'abc'])
|
||||
|
||||
assert f.valid_field_value?(['value1', 'value2'])
|
||||
assert !f.valid_field_value?(['value1', 'abc'])
|
||||
end
|
||||
|
||||
def test_changing_multiple_to_false_should_delete_multiple_values
|
||||
field = ProjectCustomField.create!(:name => 'field', :field_format => 'list', :multiple => 'true', :possible_values => ['field1', 'field2'])
|
||||
other = ProjectCustomField.create!(:name => 'other', :field_format => 'list', :multiple => 'true', :possible_values => ['other1', 'other2'])
|
||||
|
||||
item_with_multiple_values = Project.generate!(:custom_field_values => {field.id => ['field1', 'field2'], other.id => ['other1', 'other2']})
|
||||
item_with_single_values = Project.generate!(:custom_field_values => {field.id => ['field1'], other.id => ['other2']})
|
||||
|
||||
assert_difference 'CustomValue.count', -1 do
|
||||
field.multiple = false
|
||||
field.save!
|
||||
end
|
||||
|
||||
item_with_multiple_values = Project.find(item_with_multiple_values.id)
|
||||
assert_kind_of String, item_with_multiple_values.custom_field_value(field)
|
||||
assert_kind_of Array, item_with_multiple_values.custom_field_value(other)
|
||||
assert_equal 2, item_with_multiple_values.custom_field_value(other).size
|
||||
end
|
||||
|
||||
def test_value_class_should_return_the_class_used_for_fields_values
|
||||
assert_equal User, CustomField.new(:field_format => 'user').value_class
|
||||
assert_equal Version, CustomField.new(:field_format => 'version').value_class
|
||||
end
|
||||
|
||||
def test_value_class_should_return_nil_for_other_fields
|
||||
assert_nil CustomField.new(:field_format => 'text').value_class
|
||||
assert_nil CustomField.new.value_class
|
||||
end
|
||||
|
||||
def test_value_from_keyword_for_list_custom_field
|
||||
field = CustomField.find(1)
|
||||
assert_equal 'PostgreSQL', field.value_from_keyword('postgresql', Issue.find(1))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class CustomFieldUserFormatTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues
|
||||
|
||||
def setup
|
||||
@field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user')
|
||||
end
|
||||
|
||||
def test_possible_values_with_no_arguments
|
||||
assert_equal [], @field.possible_values
|
||||
assert_equal [], @field.possible_values(nil)
|
||||
end
|
||||
|
||||
def test_possible_values_with_project_resource
|
||||
project = Project.find(1)
|
||||
possible_values = @field.possible_values(project.issues.first)
|
||||
assert possible_values.any?
|
||||
assert_equal project.users.sort.collect(&:id).map(&:to_s), possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_with_nil_project_resource
|
||||
project = Project.find(1)
|
||||
assert_equal [], @field.possible_values(Issue.new)
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_no_arguments
|
||||
assert_equal [], @field.possible_values_options
|
||||
assert_equal [], @field.possible_values_options(nil)
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_project_resource
|
||||
project = Project.find(1)
|
||||
possible_values_options = @field.possible_values_options(project.issues.first)
|
||||
assert possible_values_options.any?
|
||||
assert_equal project.users.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_array
|
||||
projects = Project.find([1, 2])
|
||||
possible_values_options = @field.possible_values_options(projects)
|
||||
assert possible_values_options.any?
|
||||
assert_equal (projects.first.users & projects.last.users).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_cast_blank_value
|
||||
assert_equal nil, @field.cast_value(nil)
|
||||
assert_equal nil, @field.cast_value("")
|
||||
end
|
||||
|
||||
def test_cast_valid_value
|
||||
user = @field.cast_value("2")
|
||||
assert_kind_of User, user
|
||||
assert_equal User.find(2), user
|
||||
end
|
||||
|
||||
def test_cast_invalid_value
|
||||
assert_equal nil, @field.cast_value("187")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class CustomFieldVersionFormatTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :projects, :members, :users, :member_roles, :trackers, :issues, :versions
|
||||
|
||||
def setup
|
||||
@field = IssueCustomField.create!(:name => 'Tester', :field_format => 'version')
|
||||
end
|
||||
|
||||
def test_possible_values_with_no_arguments
|
||||
assert_equal [], @field.possible_values
|
||||
assert_equal [], @field.possible_values(nil)
|
||||
end
|
||||
|
||||
def test_possible_values_with_project_resource
|
||||
project = Project.find(1)
|
||||
possible_values = @field.possible_values(project.issues.first)
|
||||
assert possible_values.any?
|
||||
assert_equal project.shared_versions.sort.collect(&:id).map(&:to_s), possible_values
|
||||
end
|
||||
|
||||
def test_possible_values_with_nil_project_resource
|
||||
assert_equal [], @field.possible_values(Issue.new)
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_no_arguments
|
||||
assert_equal [], @field.possible_values_options
|
||||
assert_equal [], @field.possible_values_options(nil)
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_project_resource
|
||||
project = Project.find(1)
|
||||
possible_values_options = @field.possible_values_options(project.issues.first)
|
||||
assert possible_values_options.any?
|
||||
assert_equal project.shared_versions.sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_possible_values_options_with_array
|
||||
projects = Project.find([1, 2])
|
||||
possible_values_options = @field.possible_values_options(projects)
|
||||
assert possible_values_options.any?
|
||||
assert_equal (projects.first.shared_versions & projects.last.shared_versions).sort.map {|u| [u.name, u.id.to_s]}, possible_values_options
|
||||
end
|
||||
|
||||
def test_cast_blank_value
|
||||
assert_equal nil, @field.cast_value(nil)
|
||||
assert_equal nil, @field.cast_value("")
|
||||
end
|
||||
|
||||
def test_cast_valid_value
|
||||
version = @field.cast_value("2")
|
||||
assert_kind_of Version, version
|
||||
assert_equal Version.find(2), version
|
||||
end
|
||||
|
||||
def test_cast_invalid_value
|
||||
assert_equal nil, @field.cast_value("187")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class CustomValueTest < ActiveSupport::TestCase
|
||||
fixtures :custom_fields, :custom_values, :users
|
||||
|
||||
def test_default_value
|
||||
field = CustomField.find_by_default_value('Default string')
|
||||
assert_not_nil field
|
||||
|
||||
v = CustomValue.new(:custom_field => field)
|
||||
assert_equal 'Default string', v.value
|
||||
|
||||
v = CustomValue.new(:custom_field => field, :value => 'Not empty')
|
||||
assert_equal 'Not empty', v.value
|
||||
end
|
||||
|
||||
def test_sti_polymorphic_association
|
||||
# Rails uses top level sti class for polymorphic association. See #3978.
|
||||
assert !User.find(4).custom_values.empty?
|
||||
assert !CustomValue.find(2).customized.nil?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class DefaultDataTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
fixtures :roles
|
||||
|
||||
def test_no_data
|
||||
assert !Redmine::DefaultData::Loader::no_data?
|
||||
Role.delete_all("builtin = 0")
|
||||
Tracker.delete_all
|
||||
IssueStatus.delete_all
|
||||
Enumeration.delete_all
|
||||
assert Redmine::DefaultData::Loader::no_data?
|
||||
end
|
||||
|
||||
def test_load
|
||||
valid_languages.each do |lang|
|
||||
begin
|
||||
Role.delete_all("builtin = 0")
|
||||
Tracker.delete_all
|
||||
IssueStatus.delete_all
|
||||
Enumeration.delete_all
|
||||
assert Redmine::DefaultData::Loader::load(lang)
|
||||
assert_not_nil DocumentCategory.first
|
||||
assert_not_nil IssuePriority.first
|
||||
assert_not_nil TimeEntryActivity.first
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
assert false, ":#{lang} default data is invalid (#{e.message})."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class DocumentCategoryTest < ActiveSupport::TestCase
|
||||
fixtures :enumerations, :documents, :issues
|
||||
|
||||
def test_should_be_an_enumeration
|
||||
assert DocumentCategory.ancestors.include?(Enumeration)
|
||||
end
|
||||
|
||||
def test_objects_count
|
||||
assert_equal 2, DocumentCategory.find_by_name("Uncategorized").objects_count
|
||||
assert_equal 0, DocumentCategory.find_by_name("User documentation").objects_count
|
||||
end
|
||||
|
||||
def test_option_name
|
||||
assert_equal :enumeration_doc_categories, DocumentCategory.new.option_name
|
||||
end
|
||||
|
||||
def test_default
|
||||
assert_nil DocumentCategory.where(:is_default => true).first
|
||||
e = Enumeration.find_by_name('Technical documentation')
|
||||
e.update_attributes(:is_default => true)
|
||||
assert_equal 3, DocumentCategory.default.id
|
||||
end
|
||||
|
||||
def test_force_default
|
||||
assert_nil DocumentCategory.where(:is_default => true).first
|
||||
assert_equal 1, DocumentCategory.default.id
|
||||
end
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class DocumentTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :enumerations, :documents, :attachments,
|
||||
:enabled_modules,
|
||||
:users, :members, :member_roles, :roles,
|
||||
:groups_users
|
||||
|
||||
def test_create
|
||||
doc = Document.new(:project => Project.find(1), :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
|
||||
assert doc.save
|
||||
end
|
||||
|
||||
def test_create_should_send_email_notification
|
||||
ActionMailer::Base.deliveries.clear
|
||||
|
||||
with_settings :notified_events => %w(document_added) do
|
||||
doc = Document.new(:project => Project.find(1), :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
|
||||
assert doc.save
|
||||
end
|
||||
assert_equal 1, ActionMailer::Base.deliveries.size
|
||||
end
|
||||
|
||||
def test_create_with_default_category
|
||||
# Sets a default category
|
||||
e = Enumeration.find_by_name('Technical documentation')
|
||||
e.update_attributes(:is_default => true)
|
||||
|
||||
doc = Document.new(:project => Project.find(1), :title => 'New document')
|
||||
assert_equal e, doc.category
|
||||
assert doc.save
|
||||
end
|
||||
|
||||
def test_updated_on_with_attachments
|
||||
d = Document.find(1)
|
||||
assert d.attachments.any?
|
||||
assert_equal d.attachments.map(&:created_on).max, d.updated_on
|
||||
end
|
||||
|
||||
def test_updated_on_without_attachments
|
||||
d = Document.find(2)
|
||||
assert d.attachments.empty?
|
||||
assert_equal d.created_on, d.updated_on
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class EnabledModuleTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :wikis
|
||||
|
||||
def test_enabling_wiki_should_create_a_wiki
|
||||
CustomField.delete_all
|
||||
project = Project.create!(:name => 'Project with wiki', :identifier => 'wikiproject')
|
||||
assert_nil project.wiki
|
||||
project.enabled_module_names = ['wiki']
|
||||
project.reload
|
||||
assert_not_nil project.wiki
|
||||
assert_equal 'Wiki', project.wiki.start_page
|
||||
end
|
||||
|
||||
def test_reenabling_wiki_should_not_create_another_wiki
|
||||
project = Project.find(1)
|
||||
assert_not_nil project.wiki
|
||||
project.enabled_module_names = []
|
||||
project.reload
|
||||
assert_no_difference 'Wiki.count' do
|
||||
project.enabled_module_names = ['wiki']
|
||||
end
|
||||
assert_not_nil project.wiki
|
||||
end
|
||||
end
|
|
@ -0,0 +1,130 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
class EnumerationTest < ActiveSupport::TestCase
|
||||
fixtures :enumerations, :issues, :custom_fields, :custom_values
|
||||
|
||||
def test_objects_count
|
||||
# low priority
|
||||
assert_equal 6, Enumeration.find(4).objects_count
|
||||
# urgent
|
||||
assert_equal 0, Enumeration.find(7).objects_count
|
||||
end
|
||||
|
||||
def test_in_use
|
||||
# low priority
|
||||
assert Enumeration.find(4).in_use?
|
||||
# urgent
|
||||
assert !Enumeration.find(7).in_use?
|
||||
end
|
||||
|
||||
def test_default
|
||||
e = Enumeration.default
|
||||
assert e.is_a?(Enumeration)
|
||||
assert e.is_default?
|
||||
assert e.active?
|
||||
assert_equal 'Default Enumeration', e.name
|
||||
end
|
||||
|
||||
def test_default_non_active
|
||||
e = Enumeration.find(12)
|
||||
assert e.is_a?(Enumeration)
|
||||
assert e.is_default?
|
||||
assert e.active?
|
||||
e.update_attributes(:active => false)
|
||||
assert e.is_default?
|
||||
assert !e.active?
|
||||
end
|
||||
|
||||
def test_create
|
||||
e = Enumeration.new(:name => 'Not default', :is_default => false)
|
||||
e.type = 'Enumeration'
|
||||
assert e.save
|
||||
assert_equal 'Default Enumeration', Enumeration.default.name
|
||||
end
|
||||
|
||||
def test_create_as_default
|
||||
e = Enumeration.new(:name => 'Very urgent', :is_default => true)
|
||||
e.type = 'Enumeration'
|
||||
assert e.save
|
||||
assert_equal e, Enumeration.default
|
||||
end
|
||||
|
||||
def test_update_default
|
||||
e = Enumeration.default
|
||||
e.update_attributes(:name => 'Changed', :is_default => true)
|
||||
assert_equal e, Enumeration.default
|
||||
end
|
||||
|
||||
def test_update_default_to_non_default
|
||||
e = Enumeration.default
|
||||
e.update_attributes(:name => 'Changed', :is_default => false)
|
||||
assert_nil Enumeration.default
|
||||
end
|
||||
|
||||
def test_change_default
|
||||
e = Enumeration.find_by_name('Default Enumeration')
|
||||
e.update_attributes(:name => 'Changed Enumeration', :is_default => true)
|
||||
assert_equal e, Enumeration.default
|
||||
end
|
||||
|
||||
def test_destroy_with_reassign
|
||||
Enumeration.find(4).destroy(Enumeration.find(6))
|
||||
assert_nil Issue.where(:priority_id => 4).first
|
||||
assert_equal 6, Enumeration.find(6).objects_count
|
||||
end
|
||||
|
||||
def test_should_be_customizable
|
||||
assert Enumeration.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
|
||||
end
|
||||
|
||||
def test_should_belong_to_a_project
|
||||
association = Enumeration.reflect_on_association(:project)
|
||||
assert association, "No Project association found"
|
||||
assert_equal :belongs_to, association.macro
|
||||
end
|
||||
|
||||
def test_should_act_as_tree
|
||||
enumeration = Enumeration.find(4)
|
||||
|
||||
assert enumeration.respond_to?(:parent)
|
||||
assert enumeration.respond_to?(:children)
|
||||
end
|
||||
|
||||
def test_is_override
|
||||
# Defaults to off
|
||||
enumeration = Enumeration.find(4)
|
||||
assert !enumeration.is_override?
|
||||
|
||||
# Setup as an override
|
||||
enumeration.parent = Enumeration.find(5)
|
||||
assert enumeration.is_override?
|
||||
end
|
||||
|
||||
def test_get_subclasses
|
||||
classes = Enumeration.get_subclasses
|
||||
assert_include IssuePriority, classes
|
||||
assert_include DocumentCategory, classes
|
||||
assert_include TimeEntryActivity, classes
|
||||
|
||||
classes.each do |klass|
|
||||
assert_equal Enumeration, klass.superclass
|
||||
end
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue