添加测试用例

This commit is contained in:
nwb 2014-08-29 16:56:59 +08:00
parent dec77da33c
commit 801025d967
191 changed files with 41650 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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&#x27;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&#x27;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&amp;show_documents=1&amp;show_files=1&amp;show_issues=1&amp;show_messages=1&amp;show_news=1&amp;show_time_entries=1&amp;show_wiki_edits=1&amp;with_subprojects=0'
assert_select 'link[rel=alternate][href=?]', 'http://test.host/activity?show_changesets=1&amp;show_documents=1&amp;show_files=1&amp;show_issues=1&amp;show_messages=1&amp;show_news=1&amp;show_time_entries=1&amp;show_wiki_edits=1&amp;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

View File

@ -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

View File

@ -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

View File

@ -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&#x27;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&#x27;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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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&amp;issue%5Bstatus_id%5D=5', :text => 'Closed'
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;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&amp;issue%5Bfixed_version_id%5D=3', :text => '2.0'
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4', :text => 'eCookbook Subproject 1 - 2.0'
# Assignees
assert_select 'a[href=?]', '/issues/bulk_update?ids%5B%5D=1&amp;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('&amp;')
assert_select 'a.icon-edit[href=?]', "/issues/bulk_edit?#{ids}", :text => 'Edit'
assert_select 'a.icon-copy[href=?]', "/issues/bulk_edit?copy=1&amp;#{ids}", :text => 'Copy'
assert_select 'a.icon-del[href=?]', "/issues?#{ids}", :text => 'Delete'
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bstatus_id%5D=5", :text => 'Closed'
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bpriority_id%5D=8", :text => 'Immediate'
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;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('&amp;')
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}&amp;issue%5Bstatus_id%5D=5", :text => 'Closed'
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;issue%5Bpriority_id%5D=8", :text => 'Immediate'
assert_select 'a[href=?]', "/issues/bulk_update?#{ids}&amp;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&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=Foo", :text => 'Foo'
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;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&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=0", :text => 'No'
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=1", :text => 'Yes'
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;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&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=2", :text => 'John Smith'
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;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&amp;issue%5Bcustom_field_values%5D%5B#{field.id}%5D=3", :text => '2.0'
assert_select 'a[href=?]', "/issues/bulk_update?ids%5B%5D=1&amp;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&amp;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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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&#x27;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

View File

@ -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&#x27;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&#x27;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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 => /&lt;subject&gt;/
assert_select 'dd', :text => /&lt;description&gt;/
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]', '&gt;='
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

View File

@ -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&#x27;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&#x27;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

View File

@ -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

View File

@ -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

View File

@ -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 &amp; 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

View File

@ -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

View File

@ -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&#x27;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

View File

@ -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&amp;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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

129
test/unit/activity_test.rb Normal file
View File

@ -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

View File

@ -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

View File

@ -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

116
test/unit/board_test.rb Normal file
View File

@ -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

476
test/unit/changeset_test.rb Normal file
View File

@ -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

57
test/unit/comment_test.rb Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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