Redmine 3.4.4

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

View file

@ -0,0 +1,413 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class AccountTest < Redmine::IntegrationTest
fixtures :users, :email_addresses, :roles
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
end
def test_login_should_set_session_token
assert_difference 'Token.count' do
log_user('jsmith', 'jsmith')
assert_equal 2, session[:user_id]
assert_not_nil session[:tk]
end
end
def test_autologin
user = User.find(1)
Token.delete_all
with_settings :autologin => '7' do
assert_difference 'Token.count', 2 do
# User logs in with 'autologin' checked
post '/login', :params => {
:username => user.login,
:password => 'admin',
:autologin => 1
}
assert_redirected_to '/my/page'
end
token = Token.where(:action => 'autologin').order(:id => :desc).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 user's autologin cookie
cookies[:autologin] = token.value
get '/my/page'
assert_response :success
assert_equal user.id, session[:user_id]
assert_not_nil user.reload.last_login_on
end
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)
Redmine::Configuration.stubs(:[]).with('sudo_mode_timeout').returns(15)
with_settings :autologin => '7' do
assert_difference 'Token.count', 2 do
post '/login', :params => {
:username => 'admin',
:password => 'admin',
:autologin => 1
}
assert_response 302
end
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', -2 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_select 'input[name=mail]'
post "/account/lost_password", :params => {
: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", :params => {
:token => token.value
}
assert_redirected_to '/account/lost_password'
follow_redirect!
assert_response :success
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", :params => {
: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 false, Token.exists?(token.id), "Password recovery token was not deleted"
end
def test_user_with_must_change_passwd_should_be_forced_to_change_its_password
User.find_by_login('jsmith').update_attribute :must_change_passwd, true
post '/login', :params => {
:username => 'jsmith',
:password => 'jsmith'
}
assert_redirected_to '/my/page'
follow_redirect!
assert_redirected_to '/my/password'
get '/issues'
assert_redirected_to '/my/password'
end
def test_flash_message_should_use_user_language_when_redirecting_user_for_password_change
user = User.find_by_login('jsmith')
user.must_change_passwd = true
user.language = 'it'
user.save!
post '/login', :params => {
:username => 'jsmith',
:password => 'jsmith'
}
assert_redirected_to '/my/page'
follow_redirect!
assert_redirected_to '/my/password'
follow_redirect!
assert_select 'div.error', :text => /richiesto che sia cambiata/
end
def test_user_with_must_change_passwd_should_be_able_to_change_its_password
User.find_by_login('jsmith').update_attribute :must_change_passwd, true
post '/login', :params => {
:username => 'jsmith',
:password => 'jsmith'
}
assert_redirected_to '/my/page'
follow_redirect!
assert_redirected_to '/my/password'
follow_redirect!
assert_response :success
post '/my/password', :params => {
:password => 'jsmith',
:new_password => 'newpassword',
:new_password_confirmation => 'newpassword'
}
assert_redirected_to '/my/account'
follow_redirect!
assert_response :success
assert_equal false, User.find_by_login('jsmith').must_change_passwd?
end
def test_user_with_expired_password_should_be_forced_to_change_its_password
User.find_by_login('jsmith').update_attribute :passwd_changed_on, 14.days.ago
with_settings :password_max_age => 7 do
post '/login', :params => {
:username => 'jsmith',
:password => 'jsmith'
}
assert_redirected_to '/my/page'
follow_redirect!
assert_redirected_to '/my/password'
get '/issues'
assert_redirected_to '/my/password'
end
end
def test_user_with_expired_password_should_be_able_to_change_its_password
User.find_by_login('jsmith').update_attribute :passwd_changed_on, 14.days.ago
with_settings :password_max_age => 7 do
post '/login', :params => {
:username => 'jsmith',
:password => 'jsmith'
}
assert_redirected_to '/my/page'
follow_redirect!
assert_redirected_to '/my/password'
follow_redirect!
assert_response :success
post '/my/password', :params => {
:password => 'jsmith',
:new_password => 'newpassword',
:new_password_confirmation => 'newpassword'
}
assert_redirected_to '/my/account'
follow_redirect!
assert_response :success
assert_equal false, User.find_by_login('jsmith').must_change_passwd?
end
end
def test_register_with_automatic_activation
Setting.self_registration = '3'
get '/account/register'
assert_response :success
post '/account/register', :params => {
: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
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', :params => {
: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', :params => {
: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', :params => {
: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', :params => {
: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', :params => {
:username => 'foo',
:password => 'bar'
}
assert_response :success
assert_select 'input[name=?][value=""]', 'user[firstname]'
assert_select 'input[name=?][value=Smith]', 'user[lastname]'
assert_select 'input[name=?]', 'user[login]', 0
assert_select 'input[name=?]', 'user[password]', 0
post '/account/register', :params => {
: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
def test_registered_user_should_be_able_to_get_a_new_activation_email
Token.delete_all
with_settings :self_registration => '1', :default_language => 'en' do
# register a new account
assert_difference 'User.count' do
assert_difference 'Token.count' do
post '/account/register', :params => {
:user => {
:login => "newuser", :language => "en",
:firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
:password => "newpass123", :password_confirmation => "newpass123"
}
}
end
end
user = User.order('id desc').first
assert_equal User::STATUS_REGISTERED, user.status
reset!
# try to use "lost password"
assert_no_difference 'ActionMailer::Base.deliveries.size' do
post '/account/lost_password', :params => {
:mail => 'newuser@foo.bar'
}
end
assert_redirected_to '/account/lost_password'
follow_redirect!
assert_response :success
assert_select 'div.flash', :text => /new activation email/
assert_select 'div.flash a[href="/account/activation_email"]'
# request a new action activation email
assert_difference 'ActionMailer::Base.deliveries.size' do
get '/account/activation_email'
end
assert_redirected_to '/login'
token = Token.order('id desc').first
activation_path = "/account/activate?token=#{token.value}"
assert_include activation_path, mail_body(ActionMailer::Base.deliveries.last)
# activate the account
get activation_path
assert_redirected_to '/login'
post '/login', :params => {
:username => 'newuser',
:password => 'newpass123'
}
assert_redirected_to '/my/page'
end
end
end

View file

@ -0,0 +1,72 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class AdminTest < Redmine::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
post "/users", :params => {
: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}", :params => {
:id => user.id,
:user => {
:status => User::STATUS_LOCKED
}
}
assert_redirected_to "/users/#{ user.id }/edit"
locked_user = User.try_to_login("psmith", "psmith09")
assert_nil locked_user
end
test "Add a user as an anonymous user should fail" do
post '/users', :params => {
: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,165 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::ApiRoutingTest < Redmine::ApiTest::Routing
def test_attachments
should_route 'GET /attachments/1' => 'attachments#show', :id => '1'
should_route 'PATCH /attachments/1' => 'attachments#update', :id => '1'
should_route 'DELETE /attachments/1' => 'attachments#destroy', :id => '1'
should_route 'POST /uploads' => 'attachments#upload'
end
def test_custom_fields
should_route 'GET /custom_fields' => 'custom_fields#index'
end
def test_enumerations
should_route 'GET /enumerations/issue_priorities' => 'enumerations#index', :type => 'issue_priorities'
end
def test_files
should_route 'GET /projects/foo/files' => 'files#index', :project_id => 'foo'
should_route 'POST /projects/foo/files' => 'files#create', :project_id => 'foo'
end
def test_groups
should_route 'GET /groups' => 'groups#index'
should_route 'POST /groups' => 'groups#create'
should_route 'GET /groups/1' => 'groups#show', :id => '1'
should_route 'PUT /groups/1' => 'groups#update', :id => '1'
should_route 'DELETE /groups/1' => 'groups#destroy', :id => '1'
end
def test_group_users
should_route 'POST /groups/567/users' => 'groups#add_users', :id => '567'
should_route 'DELETE /groups/567/users/12' => 'groups#remove_user', :id => '567', :user_id => '12'
end
def test_issue_categories
should_route 'GET /projects/foo/issue_categories' => 'issue_categories#index', :project_id => 'foo'
should_route 'POST /projects/foo/issue_categories' => 'issue_categories#create', :project_id => 'foo'
should_route 'GET /issue_categories/1' => 'issue_categories#show', :id => '1'
should_route 'PUT /issue_categories/1' => 'issue_categories#update', :id => '1'
should_route 'DELETE /issue_categories/1' => 'issue_categories#destroy', :id => '1'
end
def test_issue_relations
should_route 'GET /issues/1/relations' => 'issue_relations#index', :issue_id => '1'
should_route 'POST /issues/1/relations' => 'issue_relations#create', :issue_id => '1'
should_route 'GET /relations/23' => 'issue_relations#show', :id => '23'
should_route 'DELETE /relations/23' => 'issue_relations#destroy', :id => '23'
end
def test_issue_statuses
should_route 'GET /issue_statuses' => 'issue_statuses#index'
end
def test_issues
should_route 'GET /issues' => 'issues#index'
should_route 'POST /issues' => 'issues#create'
should_route 'GET /issues/64' => 'issues#show', :id => '64'
should_route 'PUT /issues/64' => 'issues#update', :id => '64'
should_route 'DELETE /issues/64' => 'issues#destroy', :id => '64'
end
def test_issue_watchers
should_route 'POST /issues/12/watchers' => 'watchers#create', :object_type => 'issue', :object_id => '12'
should_route 'DELETE /issues/12/watchers/3' => 'watchers#destroy', :object_type => 'issue', :object_id => '12', :user_id => '3'
end
def test_memberships
should_route 'GET /projects/5234/memberships' => 'members#index', :project_id => '5234'
should_route 'POST /projects/5234/memberships' => 'members#create', :project_id => '5234'
should_route 'GET /memberships/5234' => 'members#show', :id => '5234'
should_route 'PUT /memberships/5234' => 'members#update', :id => '5234'
should_route 'DELETE /memberships/5234' => 'members#destroy', :id => '5234'
end
def test_news
should_route 'GET /news' => 'news#index'
should_route 'GET /projects/567/news' => 'news#index', :project_id => '567'
end
def test_projects
should_route 'GET /projects' => 'projects#index'
should_route 'POST /projects' => 'projects#create'
should_route 'GET /projects/1' => 'projects#show', :id => '1'
should_route 'PUT /projects/1' => 'projects#update', :id => '1'
should_route 'DELETE /projects/1' => 'projects#destroy', :id => '1'
end
def test_queries
should_route 'GET /queries' => 'queries#index'
end
def test_roles
should_route 'GET /roles' => 'roles#index'
should_route 'GET /roles/2' => 'roles#show', :id => '2'
end
def test_time_entries
should_route 'GET /time_entries' => 'timelog#index'
should_route 'POST /time_entries' => 'timelog#create'
should_route 'GET /time_entries/1' => 'timelog#show', :id => '1'
should_route 'PUT /time_entries/1' => 'timelog#update', :id => '1'
should_route 'DELETE /time_entries/1' => 'timelog#destroy', :id => '1'
end
def test_trackers
should_route 'GET /trackers' => 'trackers#index'
end
def test_users
should_route 'GET /users' => 'users#index'
should_route 'POST /users' => 'users#create'
should_route 'GET /users/44' => 'users#show', :id => '44'
should_route 'GET /users/current' => 'users#show', :id => 'current'
should_route 'PUT /users/44' => 'users#update', :id => '44'
should_route 'DELETE /users/44' => 'users#destroy', :id => '44'
end
def test_versions
should_route 'GET /projects/foo/versions' => 'versions#index', :project_id => 'foo'
should_route 'POST /projects/foo/versions' => 'versions#create', :project_id => 'foo'
should_route 'GET /versions/1' => 'versions#show', :id => '1'
should_route 'PUT /versions/1' => 'versions#update', :id => '1'
should_route 'DELETE /versions/1' => 'versions#destroy', :id => '1'
end
def test_wiki
should_route 'GET /projects/567/wiki/index' => 'wiki#index', :project_id => '567'
should_route 'GET /projects/567/wiki/my_page' => 'wiki#show', :project_id => '567', :id => 'my_page'
should_route 'GET /projects/567/wiki/my_page' => 'wiki#show', :project_id => '567', :id => 'my_page'
should_route 'GET /projects/1/wiki/my_page/2' => 'wiki#show', :project_id => '1', :id => 'my_page', :version => '2'
should_route 'PUT /projects/567/wiki/my_page' => 'wiki#update', :project_id => '567', :id => 'my_page'
should_route 'DELETE /projects/567/wiki/my_page' => 'wiki#destroy', :project_id => '567', :id => 'my_page'
end
end

View file

@ -0,0 +1,55 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::ApiTest < Redmine::ApiTest::Base
fixtures :users, :email_addresses, :members, :member_roles, :roles, :projects
def test_api_should_work_with_protect_from_forgery
ActionController::Base.allow_forgery_protection = true
assert_difference('User.count') do
post '/users.xml',
:params => {
:user => {
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
:mail => 'foo@example.net', :password => 'secret123'}
},
:headers => credentials('admin')
assert_response 201
end
ensure
ActionController::Base.allow_forgery_protection = false
end
def test_json_datetime_format
get '/users/1.json', :headers => credentials('admin')
assert_include '"created_on":"2006-07-19T17:12:21Z"', response.body
end
def test_xml_datetime_format
get '/users/1.xml', :headers => credentials('admin')
assert_include '<created_on>2006-07-19T17:12:21Z</created_on>', response.body
end
def test_head_response_should_have_empty_body
put '/users/7.xml', :params => {:user => {:login => 'foo'}}, :headers => credentials('admin')
assert_response :ok
assert_equal '', response.body
end
end

View file

@ -0,0 +1,236 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::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
super
set_fixtures_attachments_directory
end
def teardown
super
set_tmp_attachments_directory
end
test "GET /attachments/:id.xml should return the attachment" do
get '/attachments/7.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'attachment id', :text => '7' do
assert_select '~ filename', :text => 'archive.zip'
assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/7/archive.zip'
end
end
test "GET /attachments/:id.xml for image should include thumbnail_url" do
get '/attachments/16.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'attachment id:contains(16)' do
assert_select '~ thumbnail_url', :text => 'http://www.example.com/attachments/thumbnail/16'
end
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', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/zip', @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 "GET /attachments/thumbnail/:id should return the thumbnail" do
skip unless convert_installed?
get '/attachments/thumbnail/16', :headers => credentials('jsmith')
assert_response :success
end
test "DELETE /attachments/:id.xml should return ok and delete Attachment" do
assert_difference 'Attachment.count', -1 do
delete '/attachments/7.xml', :headers => credentials('jsmith')
assert_response :ok
assert_equal '', response.body
end
assert_nil Attachment.find_by_id(7)
end
test "DELETE /attachments/:id.json should return ok and delete Attachment" do
assert_difference 'Attachment.count', -1 do
delete '/attachments/7.json', :headers => credentials('jsmith')
assert_response :ok
assert_equal '', response.body
end
assert_nil Attachment.find_by_id(7)
end
test "PATCH /attachments/:id.json should update the attachment" do
patch '/attachments/7.json',
:params => {:attachment => {:filename => 'renamed.zip', :description => 'updated'}},
:headers => credentials('jsmith')
assert_response :ok
assert_equal 'application/json', response.content_type
attachment = Attachment.find(7)
assert_equal 'renamed.zip', attachment.filename
assert_equal 'updated', attachment.description
end
test "PATCH /attachments/:id.json with failure should return the errors" do
patch '/attachments/7.json',
:params => {:attachment => {:filename => '', :description => 'updated'}},
:headers => credentials('jsmith')
assert_response 422
assert_equal 'application/json', response.content_type
json = ActiveSupport::JSON.decode(response.body)
assert_include "File cannot be blank", json['errors']
end
test "POST /uploads.xml should return the token" do
set_tmp_attachments_directory
assert_difference 'Attachment.count' do
post '/uploads.xml', :headers => {
"RAW_POST_DATA" => '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_id = xml['upload']['id']
assert_not_nil attachment_id
attachment = Attachment.order('id DESC').first
assert_equal token, attachment.token
assert_equal attachment_id, attachment.id.to_s
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 %r{\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', :headers => {
"RAW_POST_DATA" => '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.order('id DESC').first
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', :headers => {
"RAW_POST_DATA" => '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', :headers => {
"RAW_POST_DATA" => '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', :headers => {
"RAW_POST_DATA" => ('x' * 2048),
"CONTENT_TYPE" => 'application/octet-stream'
}.merge(credentials('jsmith'))
assert_response 422
assert_select 'error', :text => /exceeds the maximum allowed file size/
end
end
end
test "POST /uploads.json should create an empty file and return a valid token" do
set_tmp_attachments_directory
assert_difference 'Attachment.count' do
post '/uploads.json', :headers => {
"CONTENT_TYPE" => 'application/octet-stream'
}.merge(credentials('jsmith'))
assert_response :created
end
json = ActiveSupport::JSON.decode(response.body)
assert_kind_of Hash, json['upload']
token = json['upload']['token']
assert token.present?
assert attachment = Attachment.find_by_token(token)
assert_equal 0, attachment.filesize
assert attachment.digest.present?
assert File.exist? attachment.diskfile
end
end

View file

@ -0,0 +1,158 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::AuthenticationTest < Redmine::ApiTest::Base
fixtures :users
def test_api_should_deny_without_credentials
get '/users/current.xml'
assert_response 401
assert_equal User.anonymous, User.current
assert response.headers.has_key?('WWW-Authenticate')
end
def test_api_should_accept_http_basic_auth_using_username_and_password
user = User.generate! do |user|
user.password = 'my_password'
end
get '/users/current.xml', :headers => credentials(user.login, 'my_password')
assert_response 200
assert_equal user, User.current
end
def test_api_should_deny_http_basic_auth_using_username_and_wrong_password
user = User.generate! do |user|
user.password = 'my_password'
end
get '/users/current.xml', :headers => credentials(user.login, 'wrong_password')
assert_response 401
assert_equal User.anonymous, User.current
end
def test_api_should_accept_http_basic_auth_using_api_key
user = User.generate!
token = Token.create!(:user => user, :action => 'api')
get '/users/current.xml', :headers => credentials(token.value, 'X')
assert_response 200
assert_equal user, User.current
end
def test_api_should_deny_http_basic_auth_using_wrong_api_key
user = User.generate!
token = Token.create!(:user => user, :action => 'feeds') # not the API key
get '/users/current.xml', :headers => credentials(token.value, 'X')
assert_response 401
assert_equal User.anonymous, User.current
end
def test_api_should_accept_auth_using_api_key_as_parameter
user = User.generate!
token = Token.create!(:user => user, :action => 'api')
get "/users/current.xml?key=#{token.value}"
assert_response 200
assert_equal user, User.current
end
def test_api_should_deny_auth_using_wrong_api_key_as_parameter
user = User.generate!
token = Token.create!(:user => user, :action => 'feeds') # not the API key
get "/users/current.xml?key=#{token.value}"
assert_response 401
assert_equal User.anonymous, User.current
end
def test_api_should_accept_auth_using_api_key_as_request_header
user = User.generate!
token = Token.create!(:user => user, :action => 'api')
get "/users/current.xml", :headers => {'X-Redmine-API-Key' => token.value.to_s}
assert_response 200
assert_equal user, User.current
end
def test_api_should_deny_auth_using_wrong_api_key_as_request_header
user = User.generate!
token = Token.create!(:user => user, :action => 'feeds') # not the API key
get "/users/current.xml", :headers => {'X-Redmine-API-Key' => token.value.to_s}
assert_response 401
assert_equal User.anonymous, User.current
end
def test_api_should_trigger_basic_http_auth_with_basic_authorization_header
ApplicationController.any_instance.expects(:authenticate_with_http_basic).once
get '/users/current.xml', :headers => credentials('jsmith')
assert_response 401
end
def test_api_should_not_trigger_basic_http_auth_with_non_basic_authorization_header
ApplicationController.any_instance.expects(:authenticate_with_http_basic).never
get '/users/current.xml', :headers => {'HTTP_AUTHORIZATION' => 'Digest foo bar'}
assert_response 401
end
def test_invalid_utf8_credentials_should_not_trigger_an_error
invalid_utf8 = "\x82".force_encoding('UTF-8')
assert !invalid_utf8.valid_encoding?
assert_nothing_raised do
get '/users/current.xml', :headers => credentials(invalid_utf8, "foo")
end
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', :headers => {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login}
assert_response :success
assert_select 'h2', :text => su.name
assert_equal su, User.current
end
def test_api_should_respond_with_412_when_trying_to_switch_to_a_invalid_user
get '/users/current', :headers => {'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', :headers => {'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', :headers => {'X-Redmine-API-Key' => user.api_key, 'X-Redmine-Switch-User' => su.login}
assert_response :success
assert_select 'h2', :text => user.name
assert_equal user, User.current
end
end

View file

@ -0,0 +1,99 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::CustomFieldsAttributeTest < Redmine::ApiTest::Base
fixtures :users
def test_integer_custom_fields_should_accept_strings
field = GroupCustomField.generate!(:field_format => 'int')
post '/groups.json',
:params => %({"group":{"name":"Foo","custom_field_values":{"#{field.id}":"52"}}}),
:headers => {
'CONTENT_TYPE' => 'application/json'
}.merge(credentials('admin'))
assert_response :created
group = Group.order('id DESC').first
assert_equal "52", group.custom_field_value(field)
end
def test_integer_custom_fields_should_accept_integers
field = GroupCustomField.generate!(:field_format => 'int')
post '/groups.json',
:params => %({"group":{"name":"Foo","custom_field_values":{"#{field.id}":52}}}),
:headers => {
'CONTENT_TYPE' => 'application/json'
}.merge(credentials('admin'))
assert_response :created
group = Group.order('id DESC').first
assert_equal "52", group.custom_field_value(field)
end
def test_boolean_custom_fields_should_accept_strings
field = GroupCustomField.generate!(:field_format => 'bool')
post '/groups.json',
:params => %({"group":{"name":"Foo","custom_field_values":{"#{field.id}": "1"}}}),
:headers => {
'CONTENT_TYPE' => 'application/json'
}.merge(credentials('admin'))
assert_response :created
group = Group.order('id DESC').first
assert_equal "1", group.custom_field_value(field)
end
def test_boolean_custom_fields_should_accept_integers
field = GroupCustomField.generate!(:field_format => 'bool')
post '/groups.json',
:params => %({"group":{"name":"Foo","custom_field_values":{"#{field.id}": 1}}}),
:headers => {
'CONTENT_TYPE' => 'application/json'
}.merge(credentials('admin'))
assert_response :created
group = Group.order('id DESC').first
assert_equal "1", group.custom_field_value(field)
end
def test_multivalued_custom_fields_should_accept_an_array
field = GroupCustomField.generate!(
:field_format => 'list',
:multiple => true,
:possible_values => ["V1", "V2", "V3"],
:default_value => "V2"
)
payload = <<-JSON
{"group": {"name":"Foooo",
"custom_field_values":{"#{field.id}":["V1","V3"]}
}
}
JSON
post '/groups.json',
:params => payload,
:headers => {
'CONTENT_TYPE' => 'application/json'
}.merge(credentials('admin'))
assert_response :created
group = Group.order('id DESC').first
assert_equal ["V1", "V3"], group.custom_field_value(field).sort
end
end

View file

@ -0,0 +1,56 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::CustomFieldsTest < Redmine::ApiTest::Base
fixtures :users, :custom_fields
test "GET /custom_fields.xml should return custom fields" do
get '/custom_fields.xml', :headers => credentials('admin')
assert_response :success
assert_equal 'application/xml', response.content_type
assert_select 'custom_fields' do
assert_select 'custom_field' do
assert_select 'name', :text => 'Database'
assert_select 'id', :text => '2'
assert_select 'customized_type', :text => 'issue'
assert_select 'possible_values[type=array]' do
assert_select 'possible_value>value', :text => 'PostgreSQL'
assert_select 'possible_value>label', :text => 'PostgreSQL'
end
assert_select 'trackers[type=array]'
assert_select 'roles[type=array]'
end
end
end
test "GET /custom_fields.xml should include value and label for enumeration custom fields" do
field = IssueCustomField.generate!(:field_format => 'enumeration')
foo = field.enumerations.create!(:name => 'Foo')
bar = field.enumerations.create!(:name => 'Bar')
get '/custom_fields.xml', :headers => credentials('admin')
assert_response :success
assert_select 'possible_value' do
assert_select "value:contains(?) + label:contains(?)", foo.id.to_s, 'Foo'
assert_select "value:contains(?) + label:contains(?)", bar.id.to_s, 'Bar'
end
end
end

View file

@ -0,0 +1,78 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class 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", :headers => credentials(@user.login, 'my_password')
assert_response :unauthorized
assert_equal User.anonymous, User.current
get "/news.json", :headers => 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", :headers => credentials(@token.value, 'X')
assert_response :unauthorized
assert_equal User.anonymous, User.current
get "/news.json", :headers => credentials(@token.value, 'X')
assert_response :unauthorized
assert_equal User.anonymous, User.current
end
end

View file

@ -0,0 +1,40 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::EnumerationsTest < Redmine::ApiTest::Base
fixtures :enumerations
test "GET /enumerations/issue_priorities.xml 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
test "GET /enumerations/invalid_subclass.xml should return 404" do
get '/enumerations/invalid_subclass.xml'
assert_response 404
assert_equal 'application/xml', response.content_type
end
end

View file

@ -0,0 +1,133 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::FilesTest < Redmine::ApiTest::Base
fixtures :projects,
:users,
:members,
:roles,
:member_roles,
:enabled_modules,
:attachments,
:versions
test "GET /projects/:project_id/files.xml should return the list of uploaded files" do
get '/projects/1/files.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'files>file>id', :text => '8'
end
test "POST /projects/:project_id/files.json should create a file" do
set_tmp_attachments_directory
post '/uploads.xml',
:params => 'File content',
:headers => {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
token = Attachment.last.token
payload = <<-JSON
{ "file": {
"token": "#{token}"
}
}
JSON
post '/projects/1/files.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
assert_response :success
assert_equal 1, Attachment.last.container_id
assert_equal "Project", Attachment.last.container_type
end
test "POST /projects/:project_id/files.xml should create a file" do
set_tmp_attachments_directory
post '/uploads.xml',
:params => 'File content',
:headers => {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
token = Attachment.last.token
payload = <<-XML
<file>
<token>#{token}</token>
</file>
XML
post '/projects/1/files.xml',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
assert_response :success
assert_equal 1, Attachment.last.container_id
assert_equal "Project", Attachment.last.container_type
end
test "POST /projects/:project_id/files.json should refuse requests without the :token parameter" do
payload = <<-JSON
{ "file": {
"filename": "project_file.zip",
}
}
JSON
post '/projects/1/files.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
assert_response :bad_request
end
test "POST /projects/:project_id/files.json should accept :filename, :description, :content_type as optional parameters" do
set_tmp_attachments_directory
post '/uploads.xml',
:params => 'File content',
:headers => {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
token = Attachment.last.token
payload = <<-JSON
{ "file": {
"filename": "New filename",
"description": "New description",
"content_type": "application/txt",
"token": "#{token}"
}
}
JSON
post '/projects/1/files.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
assert_response :success
assert_equal "New filename", Attachment.last.filename
assert_equal "New description", Attachment.last.description
assert_equal "application/txt", Attachment.last.content_type
end
test "POST /projects/:project_id/files.json should accept :version_id to attach the files to a version" do
set_tmp_attachments_directory
post '/uploads.xml',
:params => 'File content',
:headers => {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
token = Attachment.last.token
payload = <<-JSON
{ "file": {
"version_id": 3,
"filename": "New filename",
"description": "New description",
"token": "#{token}"
}
}
JSON
post '/projects/1/files.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
assert_equal 3, Attachment.last.container_id
assert_equal "Version", Attachment.last.container_type
end
end

View file

@ -0,0 +1,228 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::GroupsTest < Redmine::ApiTest::Base
fixtures :users, :groups_users, :email_addresses
test "GET /groups.xml should require authentication" do
get '/groups.xml'
assert_response 401
end
test "GET /groups.xml should return givable groups" do
get '/groups.xml', :headers => credentials('admin')
assert_response :success
assert_equal 'application/xml', response.content_type
assert_select 'groups' do
assert_select 'group', Group.givable.count
assert_select 'group' do
assert_select 'name', :text => 'A Team'
assert_select 'id', :text => '10'
end
end
end
test "GET /groups.xml?builtin=1 should return all groups" do
get '/groups.xml?builtin=1', :headers => credentials('admin')
assert_response :success
assert_equal 'application/xml', response.content_type
assert_select 'groups' do
assert_select 'group', Group.givable.count + 2
assert_select 'group' do
assert_select 'builtin', :text => 'non_member'
assert_select 'id', :text => '12'
end
assert_select 'group' do
assert_select 'builtin', :text => 'anonymous'
assert_select 'id', :text => '13'
end
end
end
test "GET /groups.json should require authentication" do
get '/groups.json'
assert_response 401
end
test "GET /groups.json should return groups" do
get '/groups.json', :headers => credentials('admin')
assert_response :success
assert_equal 'application/json', response.content_type
json = ActiveSupport::JSON.decode(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
test "GET /groups/:id.xml should return the group" do
get '/groups/10.xml', :headers => 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
test "GET /groups/:id.xml should return the builtin group" do
get '/groups/12.xml', :headers => credentials('admin')
assert_response :success
assert_equal 'application/xml', response.content_type
assert_select 'group' do
assert_select 'builtin', :text => 'non_member'
assert_select 'id', :text => '12'
end
end
test "GET /groups/:id.xml should include users if requested" do
get '/groups/10.xml?include=users', :headers => 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
test "GET /groups/:id.xml include memberships if requested" do
get '/groups/10.xml?include=memberships', :headers => credentials('admin')
assert_response :success
assert_equal 'application/xml', response.content_type
assert_select 'group' do
assert_select 'memberships'
end
end
test "POST /groups.xml with valid parameters should create the group" do
assert_difference('Group.count') do
post '/groups.xml',
:params => {:group => {:name => 'Test', :user_ids => [2, 3]}},
:headers => 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
test "POST /groups.xml with invalid parameters should return errors" do
assert_no_difference('Group.count') do
post '/groups.xml',
:params => {:group => {:name => ''}},
:headers => credentials('admin')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', response.content_type
assert_select 'errors' do
assert_select 'error', :text => /Name cannot be blank/
end
end
test "PUT /groups/:id.xml with valid parameters should update the group" do
group = Group.generate!
put "/groups/#{group.id}.xml",
:params => {:group => {:name => 'New name', :user_ids => [2, 3]}},
:headers => credentials('admin')
assert_response :ok
assert_equal '', @response.body
assert_equal 'New name', group.reload.name
assert_equal [2, 3], group.users.map(&:id).sort
end
test "PUT /groups/:id.xml with invalid parameters should return errors" do
group = Group.generate!
put "/groups/#{group.id}.xml",
:params => {:group => {:name => ''}},
:headers => credentials('admin')
assert_response :unprocessable_entity
assert_equal 'application/xml', response.content_type
assert_select 'errors' do
assert_select 'error', :text => /Name cannot be blank/
end
end
test "DELETE /groups/:id.xml should delete the group" do
group = Group.generate!
assert_difference 'Group.count', -1 do
delete "/groups/#{group.id}.xml", :headers => credentials('admin')
assert_response :ok
assert_equal '', @response.body
end
end
test "POST /groups/:id/users.xml should add user to the group" do
group = Group.generate!
assert_difference 'group.reload.users.count' do
post "/groups/#{group.id}/users.xml",
:params => {:user_id => 5},
:headers => credentials('admin')
assert_response :ok
assert_equal '', @response.body
end
assert_include User.find(5), group.reload.users
end
test "POST /groups/:id/users.xml should not add the user if already added" do
group = Group.generate!
group.users << User.find(5)
assert_no_difference 'group.reload.users.count' do
post "/groups/#{group.id}/users.xml",
:params => {:user_id => 5},
:headers => credentials('admin')
assert_response :unprocessable_entity
end
assert_select 'errors' do
assert_select 'error', :text => /User is invalid/
end
end
test "DELETE /groups/:id/users/:user_id.xml should remove user from the group" do
group = Group.generate!
group.users << User.find(8)
assert_difference 'group.reload.users.count', -1 do
delete "/groups/#{group.id}/users/8.xml", :headers => credentials('admin')
assert_response :ok
assert_equal '', @response.body
end
assert_not_include User.find(8), group.reload.users
end
end

View file

@ -0,0 +1,114 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::IssueCategoriesTest < Redmine::ApiTest::Base
fixtures :projects, :users, :issue_categories, :issues,
:roles,
:member_roles,
:members,
:enabled_modules
test "GET /projects/:project_id/issue_categories.xml should return the issue categories" do
get '/projects/1/issue_categories.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue_categories issue_category id', :text => '2'
end
test "GET /issue_categories/:id.xml should return the issue category" do
get '/issue_categories/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue_category id', :text => '2'
end
test "POST /projects/:project_id/issue_categories.xml should return create issue category" do
assert_difference 'IssueCategory.count' do
post '/projects/1/issue_categories.xml',
:params => {:issue_category => {:name => 'API'}},
:headers => credentials('jsmith')
end
assert_response :created
assert_equal 'application/xml', @response.content_type
category = IssueCategory.order('id DESC').first
assert_equal 'API', category.name
assert_equal 1, category.project_id
end
test "POST /projects/:project_id/issue_categories.xml with invalid parameters should return errors" do
assert_no_difference 'IssueCategory.count' do
post '/projects/1/issue_categories.xml',
:params => {:issue_category => {:name => ''}},
:headers => credentials('jsmith')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Name cannot be blank"
end
test "PUT /issue_categories/:id.xml with valid parameters should update the issue category" do
assert_no_difference 'IssueCategory.count' do
put '/issue_categories/2.xml',
:params => {:issue_category => {:name => 'API Update'}},
:headers => credentials('jsmith')
end
assert_response :ok
assert_equal '', @response.body
assert_equal 'API Update', IssueCategory.find(2).name
end
test "PUT /issue_categories/:id.xml with invalid parameters should return errors" do
assert_no_difference 'IssueCategory.count' do
put '/issue_categories/2.xml',
:params => {:issue_category => {:name => ''}},
:headers => credentials('jsmith')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Name cannot be blank"
end
test "DELETE /issue_categories/:id.xml should destroy the issue category" do
assert_difference 'IssueCategory.count', -1 do
delete '/issue_categories/1.xml', :headers => credentials('jsmith')
end
assert_response :ok
assert_equal '', @response.body
assert_nil IssueCategory.find_by_id(1)
end
test "DELETE /issue_categories/:id.xml should reassign issues with :reassign_to_id param" do
issue_count = Issue.where(:category_id => 1).count
assert issue_count > 0
assert_difference 'IssueCategory.count', -1 do
assert_difference 'Issue.where(:category_id => 2).count', 3 do
delete '/issue_categories/1.xml',
:params => {:reassign_to_id => 2},
:headers => credentials('jsmith')
end
end
assert_response :ok
assert_equal '', @response.body
assert_nil IssueCategory.find_by_id(1)
end
end

View file

@ -0,0 +1,84 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::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
test "GET /issues/:issue_id/relations.xml should return issue relations" do
get '/issues/9/relations.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'relations[type=array] relation id', :text => '1'
end
test "POST /issues/:issue_id/relations.xml should create the relation" do
assert_difference('IssueRelation.count') do
post '/issues/2/relations.xml',
:params => {:relation => {:issue_to_id => 7, :relation_type => 'relates'}},
:headers => credentials('jsmith')
end
relation = IssueRelation.order('id DESC').first
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_select 'relation id', :text => relation.id.to_s
end
test "POST /issues/:issue_id/relations.xml with failure should return errors" do
assert_no_difference('IssueRelation.count') do
post '/issues/2/relations.xml',
:params => {:relation => {:issue_to_id => 7, :relation_type => 'foo'}},
:headers => credentials('jsmith')
end
assert_response :unprocessable_entity
assert_select 'errors error', :text => /Relation type is not included in the list/
end
test "GET /relations/:id.xml should return the relation" do
get '/relations/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'relation id', :text => '2'
end
test "DELETE /relations/:id.xml should delete the relation" do
assert_difference('IssueRelation.count', -1) do
delete '/relations/2.xml', :headers => credentials('jsmith')
end
assert_response :ok
assert_equal '', @response.body
assert_nil IssueRelation.find_by_id(2)
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::IssueStatusesTest < Redmine::ApiTest::Base
fixtures :issue_statuses
test "GET /issue_statuses.xml should return issue statuses" do
get '/issue_statuses.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue_statuses[type=array] issue_status id', :text => '2' do
assert_select '~ name', :text => 'Assigned'
end
end
end

View file

@ -0,0 +1,978 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::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
test "GET /issues.xml should contain metadata" do
get '/issues.xml'
assert_select 'issues[type=array][total_count][limit="25"][offset="0"]'
end
test "GET /issues.xml with nometa param should not contain metadata" do
get '/issues.xml?nometa=1'
assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
end
test "GET /issues.xml with nometa header should not contain metadata" do
get '/issues.xml', :headers => {'X-Redmine-Nometa' => '1'}
assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
end
test "GET /issues.xml with offset and limit" do
get '/issues.xml?offset=2&limit=3'
assert_select 'issues[type=array][total_count][limit="3"][offset="2"]'
assert_select 'issues issue', 3
end
test "GET /issues.xml with relations" do
get '/issues.xml?include=relations'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue id', :text => '3' do
assert_select '~ relations relation', 1
assert_select '~ relations relation[id="2"][issue_id="2"][issue_to_id="3"][relation_type=relates]'
end
assert_select 'issue id', :text => '1' do
assert_select '~ relations'
assert_select '~ relations relation', 0
end
end
test "GET /issues.xml with attachments" do
get '/issues.xml?include=attachments'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue id', :text => '3' do
assert_select '~ attachments attachment', 4
end
assert_select 'issue id', :text => '1' do
assert_select '~ attachments'
assert_select '~ attachments attachment', 0
end
end
test "GET /issues.xml with invalid query params" do
get '/issues.xml', :params => {:f => ['start_date'], :op => {:start_date => '='}}
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Start date cannot be blank"
end
test "GET /issues.xml with custom field filter" do
get '/issues.xml',
:params => {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='}, :v => {:cf_1 => ['MySQL']}}
expected_ids = Issue.visible.
joins(:custom_values).
where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
assert expected_ids.any?
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
test "GET /issues.xml with custom field filter (shorthand method)" do
get '/issues.xml', :params => {:cf_1 => 'MySQL'}
expected_ids = Issue.visible.
joins(:custom_values).
where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
assert expected_ids.any?
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
def test_index_should_include_issue_attributes
get '/issues.xml'
assert_select 'issues>issue>is_private', :text => 'false'
end
def test_index_should_allow_timestamp_filtering
Issue.delete_all
Issue.generate!(:subject => '1').update_column(:updated_on, Time.parse("2014-01-02T10:25:00Z"))
Issue.generate!(:subject => '2').update_column(:updated_on, Time.parse("2014-01-02T12:13:00Z"))
get '/issues.xml', :params => {
:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '<='},
:v => {:updated_on => ['2014-01-02T12:00:00Z']}
}
assert_select 'issues>issue', :count => 1
assert_select 'issues>issue>subject', :text => '1'
get '/issues.xml', :params => {
:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
:v => {:updated_on => ['2014-01-02T12:00:00Z']}
}
assert_select 'issues>issue', :count => 1
assert_select 'issues>issue>subject', :text => '2'
get '/issues.xml', :params => {
:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
:v => {:updated_on => ['2014-01-02T08:00:00Z']}
}
assert_select 'issues>issue', :count => 2
end
test "GET /issues.xml with filter" do
get '/issues.xml?status_id=5'
expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
assert expected_ids.any?
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
test "GET /issues.json with filter" 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
test "GET /issues/:id.xml with journals" do
Journal.find(2).update_attribute(:private_notes, true)
get '/issues/1.xml?include=journals', :headers => credentials('jsmith')
assert_select 'issue journals[type=array]' do
assert_select 'journal[id="1"]' do
assert_select 'private_notes', :text => 'false'
assert_select 'details[type=array]' do
assert_select 'detail[name=status_id]' do
assert_select 'old_value', :text => '1'
assert_select 'new_value', :text => '2'
end
end
end
assert_select 'journal[id="2"]' do
assert_select 'private_notes', :text => 'true'
assert_select 'details[type=array]'
end
end
end
test "GET /issues/:id.xml with journals should format timestamps in ISO 8601" do
get '/issues/1.xml?include=journals'
iso_date = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/
assert_select 'issue>created_on', :text => iso_date
assert_select 'issue>updated_on', :text => iso_date
assert_select 'issue journal>created_on', :text => iso_date
end
test "GET /issues/:id.xml with custom fields" do
get '/issues/3.xml'
assert_select 'issue custom_fields[type=array]' do
assert_select 'custom_field[id="1"]' do
assert_select 'value', :text => 'MySQL'
end
end
assert_nothing_raised do
Hash.from_xml(response.body).to_xml
end
end
test "GET /issues/:id.xml with multi custom fields" do
field = CustomField.find(1)
field.update_attribute :multiple, true
issue = Issue.find(3)
issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
issue.save!
get '/issues/3.xml'
assert_response :success
assert_select 'issue custom_fields[type=array]' do
assert_select 'custom_field[id="1"]' do
assert_select 'value[type=array] value', 2
end
end
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
test "GET /issues/:id.json with multi custom fields" do
field = CustomField.find(1)
field.update_attribute :multiple, true
issue = Issue.find(3)
issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
issue.save!
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
test "GET /issues/:id.xml with empty value for multi custom field" do
field = CustomField.find(1)
field.update_attribute :multiple, true
issue = Issue.find(3)
issue.custom_field_values = {1 => ['']}
issue.save!
get '/issues/3.xml'
assert_select 'issue custom_fields[type=array]' do
assert_select 'custom_field[id="1"]' do
assert_select 'value[type=array]:empty'
end
end
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
test "GET /issues/:id.json with empty value for multi custom field" do
field = CustomField.find(1)
field.update_attribute :multiple, true
issue = Issue.find(3)
issue.custom_field_values = {1 => ['']}
issue.save!
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
test "GET /issues/:id.xml with attachments" do
get '/issues/3.xml?include=attachments'
assert_select 'issue attachments[type=array]' do
assert_select 'attachment', 4
assert_select 'attachment id', :text => '1' do
assert_select '~ filename', :text => 'error281.txt'
assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/1/error281.txt'
end
end
end
test "GET /issues/:id.xml with subtasks" do
issue = Issue.generate_with_descendants!(:project_id => 1)
get "/issues/#{issue.id}.xml?include=children"
assert_select 'issue id', :text => issue.id.to_s do
assert_select '~ children[type=array] > issue', 2
assert_select '~ children[type=array] > issue > children', 1
end
end
test "GET /issues/:id.json with subtasks" do
issue = Issue.generate_with_descendants!(:project_id => 1)
get "/issues/#{issue.id}.json?include=children"
json = ActiveSupport::JSON.decode(response.body)
assert_equal 2, json['issue']['children'].size
assert_equal 1, json['issue']['children'].select {|child| child.key?('children')}.size
end
test "GET /issues/:id.json with no spent time should return floats" do
issue = Issue.generate!
get "/issues/#{issue.id}.json"
json = ActiveSupport::JSON.decode(response.body)
assert_kind_of Float, json['issue']['spent_hours']
assert_kind_of Float, json['issue']['total_spent_hours']
end
def test_show_should_include_issue_attributes
get '/issues/1.xml'
assert_select 'issue>is_private', :text => 'false'
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', :headers => 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
test "GET /issues/:id.xml should not disclose associated changesets from projects the user has no access to" do
project = Project.generate!(:is_public => false)
repository = Repository::Subversion.create!(:project => project, :url => "svn://localhost")
Issue.find(1).changesets << Changeset.generate!(:repository => repository)
assert Issue.find(1).changesets.any?
get '/issues/1.xml?include=changesets', :headers => credentials('jsmith')
# the user jsmith has no permission to view the associated changeset
assert_select 'issue changesets[type=array]' do
assert_select 'changeset', 0
end
end
test "GET /issues/:id.xml should contains total_estimated_hours and total_spent_hours" do
parent = Issue.find(3)
parent.update_columns :estimated_hours => 2.0
child = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 3.0)
TimeEntry.create!(:project => child.project, :issue => child, :user => child.author, :spent_on => child.author.today,
:hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first.id)
get '/issues/3.xml'
assert_equal 'application/xml', response.content_type
assert_select 'issue' do
assert_select 'estimated_hours', parent.estimated_hours.to_s
assert_select 'total_estimated_hours', (parent.estimated_hours.to_f + 3.0).to_s
assert_select 'spent_hours', parent.spent_hours.to_s
assert_select 'total_spent_hours', (parent.spent_hours.to_f + 2.5).to_s
end
end
test "GET /issues/:id.xml should contains total_estimated_hours, and should not contains spent_hours and total_spent_hours when permission does not exists" do
parent = Issue.find(3)
parent.update_columns :estimated_hours => 2.0
child = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 3.0)
# remove permission!
Role.anonymous.remove_permission! :view_time_entries
#Role.all.each { |role| role.remove_permission! :view_time_entries }
get '/issues/3.xml'
assert_equal 'application/xml', response.content_type
assert_select 'issue' do
assert_select 'estimated_hours', parent.estimated_hours.to_s
assert_select 'total_estimated_hours', (parent.estimated_hours.to_f + 3.0).to_s
assert_select 'spent_hours', false
assert_select 'total_spent_hours', false
end
end
test "GET /issues/:id.xml should contains visible spent_hours only" do
user = User.find_by_login('jsmith')
Role.find(1).update(:time_entries_visibility => 'own')
parent = Issue.find(3)
child = Issue.generate!(:parent_issue_id => parent.id)
TimeEntry.generate!(:user => user, :hours => 5.5, :issue_id => parent.id)
TimeEntry.generate!(:user => user, :hours => 2, :issue_id => child.id)
TimeEntry.generate!(:user => User.find(1), :hours => 100, :issue_id => child.id)
get '/issues/3.xml', :headers => credentials(user.login)
assert_equal 'application/xml', response.content_type
assert_select 'issue' do
assert_select 'spent_hours', '5.5'
assert_select 'total_spent_hours', '7.5'
end
end
test "GET /issues/:id.json should contains total_estimated_hours and total_spent_hours" do
parent = Issue.find(3)
parent.update_columns :estimated_hours => 2.0
child = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 3.0)
TimeEntry.create!(:project => child.project, :issue => child, :user => child.author, :spent_on => child.author.today,
:hours => '2.5', :comments => '', :activity_id => TimeEntryActivity.first.id)
get '/issues/3.json'
assert_equal 'application/json', response.content_type
json = ActiveSupport::JSON.decode(response.body)
assert_equal parent.estimated_hours, json['issue']['estimated_hours']
assert_equal (parent.estimated_hours.to_f + 3.0), json['issue']['total_estimated_hours']
assert_equal parent.spent_hours, json['issue']['spent_hours']
assert_equal (parent.spent_hours.to_f + 2.5), json['issue']['total_spent_hours']
end
test "GET /issues/:id.json should contains total_estimated_hours, and should not contains spent_hours and total_spent_hours when permission does not exists" do
parent = Issue.find(3)
parent.update_columns :estimated_hours => 2.0
child = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 3.0)
# remove permission!
Role.anonymous.remove_permission! :view_time_entries
#Role.all.each { |role| role.remove_permission! :view_time_entries }
get '/issues/3.json'
assert_equal 'application/json', response.content_type
json = ActiveSupport::JSON.decode(response.body)
assert_equal parent.estimated_hours, json['issue']['estimated_hours']
assert_equal (parent.estimated_hours.to_f + 3.0), json['issue']['total_estimated_hours']
assert_nil json['issue']['spent_hours']
assert_nil json['issue']['total_spent_hours']
end
test "GET /issues/:id.json should contains visible spent_hours only" do
user = User.find_by_login('jsmith')
Role.find(1).update(:time_entries_visibility => 'own')
parent = Issue.find(3)
child = Issue.generate!(:parent_issue_id => parent.id)
TimeEntry.generate!(:user => user, :hours => 5.5, :issue_id => parent.id)
TimeEntry.generate!(:user => user, :hours => 2, :issue_id => child.id)
TimeEntry.generate!(:user => User.find(1), :hours => 100, :issue_id => child.id)
get '/issues/3.json', :headers => credentials(user.login)
assert_equal 'application/json', response.content_type
json = ActiveSupport::JSON.decode(response.body)
assert_equal 5.5, json['issue']['spent_hours']
assert_equal 7.5, json['issue']['total_spent_hours']
end
test "POST /issues.xml should create an issue with the attributes" do
payload = <<-XML
<?xml version="1.0" encoding="UTF-8" ?>
<issue>
<project_id>1</project_id>
<tracker_id>2</tracker_id>
<status_id>3</status_id>
<subject>API test</subject>
</issue>
XML
assert_difference('Issue.count') do
post '/issues.xml',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
end
issue = Issue.order('id DESC').first
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_select 'issue > id', :text => issue.id.to_s
end
test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
assert_difference('Issue.count') do
post '/issues.xml',
:params => {
:issue => {
:project_id => 1, :subject => 'Watchers',
:tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]
}
},
:headers => 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
test "POST /issues.xml with failure should return errors" do
assert_no_difference('Issue.count') do
post '/issues.xml',
:params => {:issue => {:project_id => 1}},
:headers => credentials('jsmith')
end
assert_select 'errors error', :text => "Subject cannot be blank"
end
test "POST /issues.json should create an issue with the attributes" do
payload = <<-JSON
{
"issue": {
"project_id": "1",
"tracker_id": "2",
"status_id": "3",
"subject": "API test"
}
}
JSON
assert_difference('Issue.count') do
post '/issues.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
end
issue = Issue.order('id DESC').first
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
test "POST /issues.json should accept project identifier as project_id" do
assert_difference('Issue.count') do
post '/issues.json',
:params => {:issue => {:project_id => 'subproject1', :tracker_id => 2, :subject => 'Foo'}},
:headers => credentials('jsmith')
assert_response :created
end
end
test "POST /issues.json without tracker_id should accept custom fields" do
field = IssueCustomField.generate!(
:field_format => 'list',
:multiple => true,
:possible_values => ["V1", "V2", "V3"],
:default_value => "V2",
:is_for_all => true,
:trackers => Tracker.all.to_a
)
payload = <<-JSON
{
"issue": {
"project_id": "1",
"subject": "Multivalued custom field",
"custom_field_values":{"#{field.id}":["V1","V3"]}
}
}
JSON
assert_difference('Issue.count') do
post '/issues.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
end
assert_response :created
issue = Issue.order('id DESC').first
assert_equal ["V1", "V3"], issue.custom_field_value(field).sort
end
test "POST /issues.json with omitted custom field should set default value" do
field = IssueCustomField.generate!(:default_value => "Default")
issue = new_record(Issue) do
post '/issues.json',
:params => {:issue => {:project_id => 1, :subject => 'API', :custom_field_values => {}}},
:headers => credentials('jsmith')
end
assert_equal "Default", issue.custom_field_value(field)
end
test "POST /issues.json with custom field set to blank should not set default value" do
field = IssueCustomField.generate!(:default_value => "Default")
issue = new_record(Issue) do
post '/issues.json',
:params => {:issue => {:project_id => 1, :subject => 'API', :custom_field_values => {field.id.to_s => ""}}},
:headers => credentials('jsmith')
end
assert_equal "", issue.custom_field_value(field)
end
test "POST /issues.json with failure should return errors" do
assert_no_difference('Issue.count') do
post '/issues.json',
:params => {:issue => {:project_id => 1}},
:headers => credentials('jsmith')
end
json = ActiveSupport::JSON.decode(response.body)
assert json['errors'].include?("Subject cannot be blank")
end
test "POST /issues.json with invalid project_id should respond with 422" do
post '/issues.json',
:params => {:issue => {:project_id => 999, :subject => "API"}},
:headers => credentials('jsmith')
assert_response 422
end
test "PUT /issues/:id.xml" do
assert_difference('Journal.count') do
put '/issues/6.xml',
:params => {:issue => {:subject => 'API update', :notes => 'A new note'}},
:headers => credentials('jsmith')
end
issue = Issue.find(6)
assert_equal "API update", issue.subject
journal = Journal.last
assert_equal "A new note", journal.notes
end
test "PUT /issues/:id.xml with custom fields" do
put '/issues/3.xml',
:params => {:issue => {:custom_fields => [
{'id' => '1', 'value' => 'PostgreSQL' },
{'id' => '2', 'value' => '150'}
]}
},
:headers => credentials('jsmith')
issue = Issue.find(3)
assert_equal '150', issue.custom_value_for(2).value
assert_equal 'PostgreSQL', issue.custom_value_for(1).value
end
test "PUT /issues/:id.xml with multi custom fields" do
field = CustomField.find(1)
field.update_attribute :multiple, true
put '/issues/3.xml',
:params => {:issue => {:custom_fields => [
{'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
{'id' => '2', 'value' => '150'}
]}
},
:headers => credentials('jsmith')
issue = Issue.find(3)
assert_equal '150', issue.custom_value_for(2).value
assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
end
test "PUT /issues/:id.xml with project change" do
put '/issues/3.xml',
:params => {:issue => {:project_id => 2, :subject => 'Project changed'}},
:headers => credentials('jsmith')
issue = Issue.find(3)
assert_equal 2, issue.project_id
assert_equal 'Project changed', issue.subject
end
test "PUT /issues/:id.xml with notes only" do
assert_difference('Journal.count') do
put '/issues/6.xml',
:params => {:issue => {:notes => 'Notes only'}},
:headers => credentials('jsmith')
end
journal = Journal.last
assert_equal "Notes only", journal.notes
end
test "PUT /issues/:id.json with omitted custom field should not change blank value to default value" do
field = IssueCustomField.generate!(:default_value => "Default")
issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id.to_s => ""})
assert_equal "", issue.reload.custom_field_value(field)
assert_difference('Journal.count') do
put "/issues/#{issue.id}.json",
:params => {:issue => {:custom_field_values => {}, :notes => 'API'}},
:headers => credentials('jsmith')
end
assert_equal "", issue.reload.custom_field_value(field)
end
test "PUT /issues/:id.json with custom field set to blank should not change blank value to default value" do
field = IssueCustomField.generate!(:default_value => "Default")
issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id.to_s => ""})
assert_equal "", issue.reload.custom_field_value(field)
assert_difference('Journal.count') do
put "/issues/#{issue.id}.json",
:params => {:issue => {:custom_field_values => {field.id.to_s => ""}, :notes => 'API'}},
:headers => credentials('jsmith')
end
assert_equal "", issue.reload.custom_field_value(field)
end
test "PUT /issues/:id.json with tracker change and omitted custom field specific to that tracker should set default value" do
field = IssueCustomField.generate!(:default_value => "Default", :tracker_ids => [2])
issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
assert_difference('Journal.count') do
put "/issues/#{issue.id}.json",
:params => {:issue => {:tracker_id => 2, :custom_field_values => {}, :notes => 'API'}},
:headers => credentials('jsmith')
end
assert_equal 2, issue.reload.tracker_id
assert_equal "Default", issue.reload.custom_field_value(field)
end
test "PUT /issues/:id.json with tracker change and custom field specific to that tracker set to blank should not set default value" do
field = IssueCustomField.generate!(:default_value => "Default", :tracker_ids => [2])
issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
assert_difference('Journal.count') do
put "/issues/#{issue.id}.json",
:params => {:issue => {:tracker_id => 2, :custom_field_values => {field.id.to_s => ""}, :notes => 'API'}},
:headers => credentials('jsmith')
end
assert_equal 2, issue.reload.tracker_id
assert_equal "", issue.reload.custom_field_value(field)
end
test "PUT /issues/:id.xml with failed update" do
put '/issues/6.xml',
:params => {:issue => {:subject => ''}},
:headers => credentials('jsmith')
assert_response :unprocessable_entity
assert_select 'errors error', :text => "Subject cannot be blank"
end
test "PUT /issues/:id.xml with invalid assignee should return error" do
user = User.generate!
put '/issues/6.xml',
:params => {:issue => {:assigned_to_id => user.id}},
:headers => credentials('jsmith')
assert_response :unprocessable_entity
assert_select 'errors error', :text => "Assignee is invalid"
end
test "PUT /issues/:id.json" do
assert_difference('Journal.count') do
put '/issues/6.json',
:params => {:issue => {:subject => 'API update', :notes => 'A new note'}},
:headers => credentials('jsmith')
assert_response :ok
assert_equal '', response.body
end
issue = Issue.find(6)
assert_equal "API update", issue.subject
journal = Journal.last
assert_equal "A new note", journal.notes
end
test "PUT /issues/:id.json with failed update" do
put '/issues/6.json',
:params => {:issue => {:subject => ''}},
:headers => credentials('jsmith')
assert_response :unprocessable_entity
json = ActiveSupport::JSON.decode(response.body)
assert json['errors'].include?("Subject cannot be blank")
end
test "DELETE /issues/:id.xml" do
assert_difference('Issue.count', -1) do
delete '/issues/6.xml', :headers => credentials('jsmith')
assert_response :ok
assert_equal '', response.body
end
assert_nil Issue.find_by_id(6)
end
test "DELETE /issues/:id.json" do
assert_difference('Issue.count', -1) do
delete '/issues/6.json', :headers => credentials('jsmith')
assert_response :ok
assert_equal '', response.body
end
assert_nil Issue.find_by_id(6)
end
test "POST /issues/:id/watchers.xml should add watcher" do
assert_difference 'Watcher.count' do
post '/issues/1/watchers.xml',
:params => {:user_id => 3},
:headers => 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', :headers => 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
token = xml_upload('test_create_with_upload', credentials('jsmith'))
attachment = Attachment.find_by_token(token)
# create the issue with the upload's token
assert_difference 'Issue.count' do
post '/issues.xml',
:params => {:issue => {:project_id => 1, :subject => 'Uploaded file',
:uploads => [{:token => token, :filename => 'test.txt',
:content_type => 'text/plain'}]}},
:headers => credentials('jsmith')
assert_response :created
end
issue = Issue.order('id DESC').first
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
assert_equal 'test_create_with_upload', response.body
end
def test_create_issue_with_multiple_uploaded_files_as_xml
token1 = xml_upload('File content 1', credentials('jsmith'))
token2 = xml_upload('File content 2', credentials('jsmith'))
payload = <<-XML
<?xml version="1.0" encoding="UTF-8" ?>
<issue>
<project_id>1</project_id>
<tracker_id>1</tracker_id>
<subject>Issue with multiple attachments</subject>
<uploads type="array">
<upload>
<token>#{token1}</token>
<filename>test1.txt</filename>
</upload>
<upload>
<token>#{token2}</token>
<filename>test1.txt</filename>
</upload>
</uploads>
</issue>
XML
assert_difference 'Issue.count' do
post '/issues.xml',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
assert_response :created
end
issue = Issue.order('id DESC').first
assert_equal 2, issue.attachments.count
end
def test_create_issue_with_multiple_uploaded_files_as_json
token1 = json_upload('File content 1', credentials('jsmith'))
token2 = json_upload('File content 2', credentials('jsmith'))
payload = <<-JSON
{
"issue": {
"project_id": "1",
"tracker_id": "1",
"subject": "Issue with multiple attachments",
"uploads": [
{"token": "#{token1}", "filename": "test1.txt"},
{"token": "#{token2}", "filename": "test2.txt"}
]
}
}
JSON
assert_difference 'Issue.count' do
post '/issues.json',
:params => payload,
:headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
assert_response :created
end
issue = Issue.order('id DESC').first
assert_equal 2, issue.attachments.count
end
def test_update_issue_with_uploaded_file
token = xml_upload('test_upload_with_upload', credentials('jsmith'))
attachment = Attachment.find_by_token(token)
# update the issue with the upload's token
assert_difference 'Journal.count' do
put '/issues/1.xml',
:params => {:issue => {:notes => 'Attachment added',
:uploads => [{:token => token, :filename => 'test.txt',
:content_type => 'text/plain'}]}},
:headers => 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-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::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,174 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base
fixtures :projects, :users, :roles, :members, :member_roles
test "GET /projects/:project_id/memberships.xml should return memberships" do
get '/projects/1/memberships.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'memberships[type=array] membership id', :text => '2' do
assert_select '~ user[id="3"][name="Dave Lopper"]'
assert_select '~ roles role[id="2"][name=Developer]'
end
end
test "GET /projects/:project_id/memberships.json should return memberships" do
get '/projects/1/memberships.json', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/json', @response.content_type
json = ActiveSupport::JSON.decode(response.body)
assert_equal 3, json["total_count"]
assert_equal 25, json["limit"]
assert_equal 0, json["offset"]
assert_include({
"id"=>1,
"project" => {"name"=>"eCookbook", "id"=>1},
"roles" => [{"name"=>"Manager", "id"=>1}],
"user" => {"name"=>"John Smith", "id"=>2}
},
json["memberships"]
)
end
test "GET /projects/:project_id/memberships.xml should succeed for closed project" do
project = Project.find(1)
project.close
assert !project.reload.active?
get '/projects/1/memberships.json', :headers => credentials('jsmith')
assert_response :success
end
test "GET /projects/:project_id/memberships.xml should include locked users" do
assert User.find(3).lock!
get '/projects/ecookbook/memberships.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'memberships[type=array] membership id', :text => '2' do
assert_select '~ user[id="3"][name="Dave Lopper"]'
end
end
test "POST /projects/:project_id/memberships.xml should create the membership" do
assert_difference 'Member.count' do
post '/projects/1/memberships.xml',
:params => {:membership => {:user_id => 7, :role_ids => [2,3]}},
:headers => credentials('jsmith')
assert_response :created
end
end
test "POST /projects/:project_id/memberships.xml should create the group membership" do
group = Group.find(11)
assert_difference 'Member.count', 1 + group.users.count do
post '/projects/1/memberships.xml',
:params => {:membership => {:user_id => 11, :role_ids => [2,3]}},
:headers => credentials('jsmith')
assert_response :created
end
end
test "POST /projects/:project_id/memberships.xml with invalid parameters should return errors" do
assert_no_difference 'Member.count' do
post '/projects/1/memberships.xml',
:params => {:membership => {:role_ids => [2,3]}},
:headers => credentials('jsmith')
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Principal cannot be blank"
end
end
test "GET /memberships/:id.xml should return the membership" do
get '/memberships/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'membership id', :text => '2' do
assert_select '~ user[id="3"][name="Dave Lopper"]'
assert_select '~ roles role[id="2"][name=Developer]'
end
end
test "GET /memberships/:id.json should return the membership" do
get '/memberships/2.json', :headers => 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
test "PUT /memberships/:id.xml should update the membership" do
assert_not_equal [1,2], Member.find(2).role_ids.sort
assert_no_difference 'Member.count' do
put '/memberships/2.xml',
:params => {:membership => {:user_id => 3, :role_ids => [1,2]}},
:headers => credentials('jsmith')
assert_response :ok
assert_equal '', @response.body
end
member = Member.find(2)
assert_equal [1,2], member.role_ids.sort
end
test "PUT /memberships/:id.xml with invalid parameters should return errors" do
put '/memberships/2.xml',
:params => {:membership => {:user_id => 3, :role_ids => [99]}},
:headers => credentials('jsmith')
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Role cannot be empty"
end
test "DELETE /memberships/:id.xml should destroy the membership" do
assert_difference 'Member.count', -1 do
delete '/memberships/2.xml', :headers => credentials('jsmith')
assert_response :ok
assert_equal '', @response.body
end
assert_nil Member.find_by_id(2)
end
test "DELETE /memberships/:id.xml should respond with 422 on failure" do
assert_no_difference 'Member.count' do
# A membership with an inherited role cannot be deleted
Member.find(2).member_roles.first.update_attribute :inherited_from, 99
delete '/memberships/2.xml', :headers => credentials('jsmith')
assert_response :unprocessable_entity
end
end
end

View file

@ -0,0 +1,61 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base
fixtures :projects, :trackers, :issue_statuses, :issues,
:enumerations, :users, :issue_categories,
:projects_trackers,
:roles,
:member_roles,
:members,
:enabled_modules,
:news
test "GET /news.xml should return news" do
get '/news.xml'
assert_select 'news[type=array] news id', :text => '2'
end
test "GET /news.json 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
test "GET /projects/:project_id/news.xml should return news" do
get '/projects/ecookbook/news.xml'
assert_select 'news[type=array] news id', :text => '2'
end
test "GET /projects/:project_id/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

View file

@ -0,0 +1,252 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::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
super
set_tmp_attachments_directory
end
test "GET /projects.xml should return projects" do
get '/projects.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'projects>project>id', :text => '1'
assert_select 'projects>project>status', :text => '1'
assert_select 'projects>project>is_public', :text => 'true'
end
test "GET /projects.json 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
test "GET /projects.xml with include=issue_categories should return categories" do
get '/projects.xml?include=issue_categories'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue_categories[type=array] issue_category[id="2"][name=Recipes]'
end
test "GET /projects.xml with include=trackers should return trackers" do
get '/projects.xml?include=trackers'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'trackers[type=array] tracker[id="2"][name="Feature request"]'
end
test "GET /projects.xml with include=enabled_modules should return enabled modules" do
get '/projects.xml?include=enabled_modules'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'enabled_modules[type=array] enabled_module[name=issue_tracking]'
end
test "GET /projects/:id.xml should return the project" do
get '/projects/1.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'project>id', :text => '1'
assert_select 'project>status', :text => '1'
assert_select 'project>is_public', :text => 'true'
assert_select 'custom_field[name="Development status"]', :text => 'Stable'
assert_select 'trackers', 0
assert_select 'issue_categories', 0
end
test "GET /projects/:id.json should return the 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
test "GET /projects/:id.xml with hidden custom fields should not display hidden custom fields" do
ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
get '/projects/1.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'custom_field[name=?]', 'Development status', 0
end
test "GET /projects/:id.xml with include=issue_categories should return categories" do
get '/projects/1.xml?include=issue_categories'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'issue_categories[type=array] issue_category[id="2"][name=Recipes]'
end
test "GET /projects/:id.xml with include=time_entry_activities should return activities" do
get '/projects/1.xml?include=time_entry_activities'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'time_entry_activities[type=array] time_entry_activity[id="10"][name=Development]'
end
test "GET /projects/:id.xml with include=trackers should return trackers" do
get '/projects/1.xml?include=trackers'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'trackers[type=array] tracker[id="2"][name="Feature request"]'
end
test "GET /projects/:id.xml with include=enabled_modules should return enabled modules" do
get '/projects/1.xml?include=enabled_modules'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'enabled_modules[type=array] enabled_module[name=issue_tracking]'
end
test "POST /projects.xml with valid parameters should create the project" do
with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
assert_difference('Project.count') do
post '/projects.xml',
:params => {:project => {:name => 'API test', :identifier => 'api-test'}},
:headers => credentials('admin')
end
end
project = Project.order('id DESC').first
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_select 'project id', :text => project.id.to_s
end
test "POST /projects.xml should accept enabled_module_names attribute" do
assert_difference('Project.count') do
post '/projects.xml',
:params => {:project => {:name => 'API test', :identifier => 'api-test', :enabled_module_names => ['issue_tracking', 'news', 'time_tracking']}},
:headers => credentials('admin')
end
project = Project.order('id DESC').first
assert_equal ['issue_tracking', 'news', 'time_tracking'], project.enabled_module_names.sort
end
test "POST /projects.xml should accept tracker_ids attribute" do
assert_difference('Project.count') do
post '/projects.xml',
:params => {:project => {:name => 'API test', :identifier => 'api-test', :tracker_ids => [1, 3]}},
:headers => credentials('admin')
end
project = Project.order('id DESC').first
assert_equal [1, 3], project.trackers.map(&:id).sort
end
test "POST /projects.xml with invalid parameters should return errors" do
assert_no_difference('Project.count') do
post '/projects.xml',
:params => {:project => {:name => 'API test'}},
:headers => credentials('admin')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Identifier cannot be blank"
end
test "PUT /projects/:id.xml with valid parameters should update the project" do
assert_no_difference 'Project.count' do
put '/projects/2.xml',
:params => {:project => {:name => 'API update'}},
:headers => 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
test "PUT /projects/:id.xml should accept enabled_module_names attribute" do
assert_no_difference 'Project.count' do
put '/projects/2.xml',
:params => {:project => {:name => 'API update', :enabled_module_names => ['issue_tracking', 'news', 'time_tracking']}},
:headers => 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
test "PUT /projects/:id.xml should accept tracker_ids attribute" do
assert_no_difference 'Project.count' do
put '/projects/2.xml',
:params => {:project => {:name => 'API update', :tracker_ids => [1, 3]}},
:headers => credentials('admin')
end
assert_response :ok
assert_equal '', @response.body
project = Project.find(2)
assert_equal [1, 3], project.trackers.map(&:id).sort
end
test "PUT /projects/:id.xml with invalid parameters should return errors" do
assert_no_difference('Project.count') do
put '/projects/2.xml',
:params => {:project => {:name => ''}},
:headers => credentials('admin')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Name cannot be blank"
end
test "DELETE /projects/:id.xml should delete the project" do
assert_difference('Project.count',-1) do
delete '/projects/2.xml', :headers => credentials('admin')
end
assert_response :ok
assert_equal '', @response.body
assert_nil Project.find_by_id(2)
end
end

View file

@ -0,0 +1,39 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::QueriesTest < Redmine::ApiTest::Base
fixtures :projects, :trackers, :issue_statuses, :issues,
:enumerations, :users, :issue_categories,
:projects_trackers,
:roles,
:member_roles,
:members,
:enabled_modules,
:queries
test "GET /queries.xml should return queries" do
get '/queries.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'queries[type=array] query id', :text => '4' do
assert_select '~ name', :text => 'Public query for all projects'
end
end
end

View file

@ -0,0 +1,62 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::RolesTest < Redmine::ApiTest::Base
fixtures :roles
test "GET /roles.xml should return the roles" do
get '/roles.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'roles role', 3
assert_select 'roles[type=array] role id', :text => '2' do
assert_select '~ name', :text => 'Developer'
end
end
test "GET /roles.json should return the roles" do
get '/roles.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['roles']
assert_equal 3, json['roles'].size
assert_include({'id' => 2, 'name' => 'Developer'}, json['roles'])
end
test "GET /roles/:id.xml 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

View file

@ -0,0 +1,92 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::SearchTest < Redmine::ApiTest::Base
fixtures :projects, :projects_trackers,
:enabled_modules, :roles, :users, :members, :member_roles,
:issues, :trackers, :issue_statuses, :enumerations,
:workflows,
:custom_fields, :custom_values,
:custom_fields_projects, :custom_fields_trackers,
:repositories, :changesets
test "GET /search.xml should return xml content" do
get '/search.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
end
test "GET /search.json should return json content" do
get '/search.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['results']
end
test "GET /search.xml without query strings should return empty results" do
get '/search.xml', :params => {:q => '', :all_words => ''}
assert_response :success
assert_select 'result', 0
end
test "GET /search.xml with query strings should return results" do
issue = Issue.generate!(:subject => 'searchapi')
get '/search.xml', :params => {:q => 'searchapi', :all_words => ''}
assert_response :success
assert_select 'results[type=array]' do
assert_select 'result', 1
assert_select 'result' do
assert_select 'id', :text => issue.id.to_s
assert_select 'title', :text => "Bug ##{issue.id} (New): searchapi"
assert_select 'type', :text => 'issue'
assert_select 'url', :text => "http://www.example.com/issues/#{issue.id}"
assert_select 'description', :text => ''
assert_select 'datetime'
end
end
end
test "GET /search.xml should paginate" do
issue = (0..10).map {Issue.generate! :subject => 'search_with_limited_results'}.reverse.map(&:id)
get '/search.json', :params => {:q => 'search_with_limited_results', :limit => 4}
json = ActiveSupport::JSON.decode(response.body)
assert_equal 11, json['total_count']
assert_equal 0, json['offset']
assert_equal 4, json['limit']
assert_equal issue[0..3], json['results'].map {|r| r['id']}
get '/search.json', :params => {:q => 'search_with_limited_results', :offset => 8, :limit => 4}
json = ActiveSupport::JSON.decode(response.body)
assert_equal 11, json['total_count']
assert_equal 8, json['offset']
assert_equal 4, json['limit']
assert_equal issue[8..10], json['results'].map {|r| r['id']}
end
end

View file

@ -0,0 +1,158 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::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
test "GET /time_entries.xml should return time entries" do
get '/time_entries.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'time_entries[type=array] time_entry id', :text => '2'
end
test "GET /time_entries.xml with limit should return limited results" do
get '/time_entries.xml?limit=2', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'time_entries[type=array] time_entry', 2
end
test "GET /time_entries/:id.xml should return the time entry" do
get '/time_entries/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'time_entry id', :text => '2'
end
test "GET /time_entries/:id.xml on closed project should return the time entry" do
project = TimeEntry.find(2).project
project.close
project.save!
get '/time_entries/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'time_entry id', :text => '2'
end
test "POST /time_entries.xml with issue_id should create time entry" do
assert_difference 'TimeEntry.count' do
post '/time_entries.xml',
:params => {:time_entry => {:issue_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11'}},
:headers => credentials('jsmith')
end
assert_response :created
assert_equal 'application/xml', @response.content_type
entry = TimeEntry.order('id DESC').first
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
test "POST /time_entries.xml with issue_id should accept custom fields" do
field = TimeEntryCustomField.create!(:name => 'Test', :field_format => 'string')
assert_difference 'TimeEntry.count' do
post '/time_entries.xml',
:params => {: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'}]
}},
:headers => credentials('jsmith')
end
assert_response :created
assert_equal 'application/xml', @response.content_type
entry = TimeEntry.order('id DESC').first
assert_equal 'accepted', entry.custom_field_value(field)
end
test "POST /time_entries.xml with project_id should create time entry" do
assert_difference 'TimeEntry.count' do
post '/time_entries.xml',
:params => {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :hours => '3.5', :activity_id => '11'}},
:headers => credentials('jsmith')
end
assert_response :created
assert_equal 'application/xml', @response.content_type
entry = TimeEntry.order('id DESC').first
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
test "POST /time_entries.xml with invalid parameters should return errors" do
assert_no_difference 'TimeEntry.count' do
post '/time_entries.xml',
:params => {:time_entry => {:project_id => '1', :spent_on => '2010-12-02', :activity_id => '11'}},
:headers => credentials('jsmith')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Hours cannot be blank"
end
test "PUT /time_entries/:id.xml with valid parameters should update time entry" do
assert_no_difference 'TimeEntry.count' do
put '/time_entries/2.xml',
:params => {:time_entry => {:comments => 'API Update'}},
:headers => credentials('jsmith')
end
assert_response :ok
assert_equal '', @response.body
assert_equal 'API Update', TimeEntry.find(2).comments
end
test "PUT /time_entries/:id.xml with invalid parameters should return errors" do
assert_no_difference 'TimeEntry.count' do
put '/time_entries/2.xml',
:params => {:time_entry => {:hours => '', :comments => 'API Update'}},
:headers => credentials('jsmith')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "Hours cannot be blank"
end
test "DELETE /time_entries/:id.xml should destroy time entry" do
assert_difference 'TimeEntry.count', -1 do
delete '/time_entries/2.xml', :headers => credentials('jsmith')
end
assert_response :ok
assert_equal '', @response.body
assert_nil TimeEntry.find_by_id(2)
end
end

View file

@ -0,0 +1,33 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::TrackersTest < Redmine::ApiTest::Base
fixtures :trackers
test "GET /trackers.xml should return trackers" do
get '/trackers.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'trackers[type=array] tracker id', :text => '2' do
assert_select '~ name', :text => 'Feature request'
end
end
end

View file

@ -0,0 +1,318 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base
fixtures :users, :email_addresses, :members, :member_roles, :roles, :projects
test "GET /users.xml should return users" do
get '/users.xml', :headers => credentials('admin')
assert_response :success
assert_equal 'application/xml', response.content_type
assert_select 'users' do
assert_select 'user', User.active.count
end
end
test "GET /users.json should return users" do
get '/users.json', :headers => credentials('admin')
assert_response :success
assert_equal 'application/json', response.content_type
json = ActiveSupport::JSON.decode(response.body)
assert json.key?('users')
assert_equal User.active.count, json['users'].size
end
test "GET /users/:id.xml should return the user" do
get '/users/2.xml'
assert_response :success
assert_select 'user id', :text => '2'
end
test "GET /users/:id.json should return the 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
test "GET /users/:id.xml with include=memberships should include memberships" do
get '/users/2.xml?include=memberships'
assert_response :success
assert_select 'user memberships', 1
end
test "GET /users/:id.json with include=memberships 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
test "GET /users/current.xml should require authentication" do
get '/users/current.xml'
assert_response 401
end
test "GET /users/current.xml should return current user" do
get '/users/current.xml', :headers => credentials('jsmith')
assert_select 'user id', :text => '2'
end
test "GET /users/:id should not return login for other user" do
get '/users/3.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'user login', 0
end
test "GET /users/:id should return login for current user" do
get '/users/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'user login', :text => 'jsmith'
end
test "GET /users/:id should not return api_key for other user" do
get '/users/3.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'user api_key', 0
end
test "GET /users/:id should return api_key for current user" do
get '/users/2.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'user api_key', :text => User.find(2).api_key
end
test "GET /users/:id should not return status for standard user" do
get '/users/3.xml', :headers => credentials('jsmith')
assert_response :success
assert_select 'user status', 0
end
test "GET /users/:id should return status for administrators" do
get '/users/2.xml', :headers => credentials('admin')
assert_response :success
assert_select 'user status', :text => User.find(1).status.to_s
end
test "POST /users.xml with valid parameters should create the user" do
assert_difference('User.count') do
post '/users.xml',
:params => {
:user => {
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
:mail => 'foo@example.net', :password => 'secret123',
:mail_notification => 'only_assigned'
}
},
:headers => credentials('admin')
end
user = User.order('id DESC').first
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_select 'user id', :text => user.id.to_s
end
test "POST /users.json with valid parameters should create the user" do
assert_difference('User.count') do
post '/users.json',
:params => {
:user => {
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
:mail => 'foo@example.net', :password => 'secret123',
:mail_notification => 'only_assigned'
}
},
:headers => credentials('admin')
end
user = User.order('id DESC').first
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
test "POST /users.xml with with invalid parameters should return errors" do
assert_no_difference('User.count') do
post '/users.xml',
:params => {
:user =>{
:login => 'foo', :lastname => 'Lastname', :mail => 'foo'
}
},
:headers => credentials('admin')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "First name cannot be blank"
end
test "POST /users.json with with invalid parameters should return errors" do
assert_no_difference('User.count') do
post '/users.json',
:params => {
:user => {
:login => 'foo', :lastname => 'Lastname', :mail => 'foo'
}
},
:headers => 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
test "PUT /users/:id.xml with valid parameters should update the user" do
assert_no_difference('User.count') do
put '/users/2.xml',
:params => {
:user => {
:login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
:mail => 'jsmith@somenet.foo'
}
},
:headers => 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
test "PUT /users/:id.json with valid parameters should update the user" do
assert_no_difference('User.count') do
put '/users/2.json',
:params => {
:user => {
:login => 'jsmith', :firstname => 'John', :lastname => 'Renamed',
:mail => 'jsmith@somenet.foo'
}
},
:headers => 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
test "PUT /users/:id.xml with invalid parameters" do
assert_no_difference('User.count') do
put '/users/2.xml',
:params => {
:user => {
:login => 'jsmith', :firstname => '', :lastname => 'Lastname',
:mail => 'foo'
}
},
:headers => credentials('admin')
end
assert_response :unprocessable_entity
assert_equal 'application/xml', @response.content_type
assert_select 'errors error', :text => "First name cannot be blank"
end
test "PUT /users/:id.json with invalid parameters" do
assert_no_difference('User.count') do
put '/users/2.json',
:params => {
:user => {
:login => 'jsmith', :firstname => '', :lastname => 'Lastname',
:mail => 'foo'
}
},
:headers => 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
test "DELETE /users/:id.xml should delete the user" do
assert_difference('User.count', -1) do
delete '/users/2.xml', :headers => credentials('admin')
end
assert_response :ok
assert_equal '', @response.body
end
test "DELETE /users/:id.json should delete the user" do
assert_difference('User.count', -1) do
delete '/users/2.json', :headers => credentials('admin')
end
assert_response :ok
assert_equal '', @response.body
end
end

View file

@ -0,0 +1,139 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::VersionsTest < Redmine::ApiTest::Base
fixtures :projects, :trackers, :issue_statuses, :issues,
:enumerations, :users, :issue_categories,
:projects_trackers,
:roles,
:member_roles,
:members,
:enabled_modules,
:versions
test "GET /projects/:project_id/versions.xml should return project versions" do
get '/projects/1/versions.xml'
assert_response :success
assert_equal 'application/xml', @response.content_type
assert_select 'versions[type=array] version id', :text => '2' do
assert_select '~ name', :text => '1.0'
end
end
test "POST /projects/:project_id/versions.xml should create the version" do
assert_difference 'Version.count' do
post '/projects/1/versions.xml',
:params => {:version => {:name => 'API test'}},
:headers => credentials('jsmith')
end
version = Version.order('id DESC').first
assert_equal 'API test', version.name
assert_response :created
assert_equal 'application/xml', @response.content_type
assert_select 'version id', :text => version.id.to_s
end
test "POST /projects/:project_id/versions.xml should create the version with due date" do
assert_difference 'Version.count' do
post '/projects/1/versions.xml',
:params => {:version => {:name => 'API test', :due_date => '2012-01-24'}},
:headers => credentials('jsmith')
end
version = Version.order('id DESC').first
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_select 'version id', :text => version.id.to_s
end
test "POST /projects/:project_id/versions.xml should create the version with custom fields" do
field = VersionCustomField.generate!
assert_difference 'Version.count' do
post '/projects/1/versions.xml',
:params => {
:version => {
:name => 'API test',
:custom_fields => [
{'id' => field.id.to_s, 'value' => 'Some value'}
]
}
},
:headers => credentials('jsmith')
end
version = Version.order('id DESC').first
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
test "POST /projects/:project_id/versions.xml with failure should return the errors" do
assert_no_difference('Version.count') do
post '/projects/1/versions.xml',
:params => {:version => {:name => ''}},
:headers => credentials('jsmith')
end
assert_response :unprocessable_entity
assert_select 'errors error', :text => "Name cannot be blank"
end
test "GET /versions/:id.xml 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
test "PUT /versions/:id.xml should update the version" do
put '/versions/2.xml',
:params => {:version => {:name => 'API update'}},
:headers => credentials('jsmith')
assert_response :ok
assert_equal '', @response.body
assert_equal 'API update', Version.find(2).name
end
test "DELETE /versions/:id.xml should destroy the version" do
assert_difference 'Version.count', -1 do
delete '/versions/3.xml', :headers => credentials('jsmith')
end
assert_response :ok
assert_equal '', @response.body
assert_nil Version.find_by_id(3)
end
end

View file

@ -0,0 +1,209 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class Redmine::ApiTest::WikiPagesTest < Redmine::ApiTest::Base
fixtures :projects, :users, :roles, :members, :member_roles,
:enabled_modules, :wikis, :wiki_pages, :wiki_contents,
:wiki_content_versions, :attachments
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', :headers => 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 'comments', :text => 'Small update'
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',
:params => {:wiki_page => {:text => 'New content from API', :comments => 'API update'}},
:headers => 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',
:params => {:wiki_page => {:text => 'New content from API', :comments => 'API update', :version => '3'}},
:headers => 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',
:params => {:wiki_page => {:text => 'New content from API', :comments => 'API update', :version => '2'}},
:headers => 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',
:params => {:wiki_page => {:text => 'New content from API', :comments => 'API create'}},
:headers => 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 attachment" do
set_tmp_attachments_directory
attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
assert_difference 'WikiPage.count' do
assert_difference 'WikiContent::Version.count' do
put '/projects/ecookbook/wiki/New_page_from_API.xml',
:params => {:wiki_page => {:text => 'New content from API with Attachments', :comments => 'API create with Attachments',
:uploads => [:token => attachment.token, :filename => 'testfile.txt', :content_type => "text/plain"]}},
:headers => credentials('jsmith')
assert_response 201
end
end
page = WikiPage.order('id DESC').first
assert_equal 'New_page_from_API', page.title
assert_include attachment, page.attachments
assert_equal attachment.filename, page.attachments.first.filename
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',
:params => {:wiki_page => {:parent_title => 'CookBook_documentation', :text => 'New content from API', :comments => 'API create'}},
:headers => 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', :headers => credentials('jsmith')
assert_response 200
end
assert_nil WikiPage.find_by_id(1)
end
end

View file

@ -0,0 +1,97 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class ApplicationTest < Redmine::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', :headers => {'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'}
assert_response :success
assert_select 'h2', :text => 'Projets'
assert_equal :fr, current_language
assert_select "html[lang=?]", "fr"
# then an italien user
get '/projects', :headers => {'HTTP_ACCEPT_LANGUAGE' => 'it;q=0.8,en-us;q=0.5,en;q=0.3'}
assert_response :success
assert_select 'h2', :text => 'Progetti'
assert_equal :it, current_language
assert_select "html[lang=?]", "it"
# not a supported language: default language should be used
get '/projects', :headers => {'HTTP_ACCEPT_LANGUAGE' => 'zz'}
assert_response :success
assert_select 'h2', :text => 'Projects'
assert_select "html[lang=?]", "en"
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
def test_invalid_token_should_call_custom_handler
ActionController::Base.allow_forgery_protection = true
post '/issues'
assert_response 422
assert_include "Invalid form authenticity token.", response.body
ensure
ActionController::Base.allow_forgery_protection = false
end
def test_localization_should_be_set_correctly_on_invalid_token
ActionController::Base.allow_forgery_protection = true
Setting.default_language = 'en'
post '/issues', :headers => {'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'}
assert_response 422
assert_equal :fr, current_language
assert_select "html[lang=?]", "fr"
ensure
ActionController::Base.allow_forgery_protection = false
end
def test_require_login_with_pdf_format_should_not_error
with_settings :login_required => '1' do
get '/issues/1.pdf'
assert_response 302
end
end
end

View file

@ -0,0 +1,172 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class AttachmentsTest < Redmine::IntegrationTest
fixtures :projects, :enabled_modules,
:users, :email_addresses,
:roles, :members, :member_roles,
:trackers, :projects_trackers,
:issues, :issue_statuses, :enumerations,
:attachments
def test_upload_should_set_default_content_type
log_user('jsmith', 'jsmith')
assert_difference 'Attachment.count' do
post "/uploads.js?attachment_id=1&filename=foo.txt",
:params => "File content",
:headers => {"CONTENT_TYPE" => 'application/octet-stream'}
assert_response :success
end
attachment = Attachment.order(:id => :desc).first
assert_equal 'text/plain', attachment.content_type
end
def test_upload_should_accept_content_type_param
log_user('jsmith', 'jsmith')
assert_difference 'Attachment.count' do
post "/uploads.js?attachment_id=1&filename=foo&content_type=image/jpeg",
:params => "File content",
:headers => {"CONTENT_TYPE" => 'application/octet-stream'}
assert_response :success
end
attachment = Attachment.order(:id => :desc).first
assert_equal 'image/jpeg', attachment.content_type
end
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', :params => {
: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', :params => {
: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', :params => {
: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', :params => {
: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
def test_download_should_set_sendfile_header
set_fixtures_attachments_directory
Rack::Sendfile.any_instance.stubs(:variation).returns("X-Sendfile")
get "/attachments/download/4"
assert_response :success
assert_not_nil response.headers["X-Sendfile"]
ensure
set_tmp_attachments_directory
end
private
def ajax_upload(filename, content, attachment_id=1)
assert_difference 'Attachment.count' do
post "/uploads.js?attachment_id=#{attachment_id}&filename=#{filename}",
:params => content,
:headers => {"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,31 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class FeedsTest < Redmine::IntegrationTest
fixtures :projects, :trackers, :issue_statuses, :issues,
:enumerations, :users, :issue_categories,
:projects_trackers, :enabled_modules,
:roles, :member_roles, :members
def test_feeds_should_include_icon_tag
get '/projects.atom'
assert_response :success
assert_select 'feed>icon', :text => %r{^http://www.example.com/favicon.ico}
end
end

View file

@ -0,0 +1,305 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class IssuesTest < Redmine::IntegrationTest
fixtures :projects,
:users, :email_addresses,
:roles,
:members,
:member_roles,
:trackers,
:projects_trackers,
:enabled_modules,
:issue_statuses,
:issues,
:enumerations,
:custom_fields,
:custom_values,
:custom_fields_trackers,
:attachments
# create an issue
def test_add_issue
log_user('jsmith', 'jsmith')
get '/projects/ecookbook/issues/new'
assert_response :success
issue = new_record(Issue) do
post '/projects/ecookbook/issues', :params => {
:issue => {
:tracker_id => "1",
: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_field_values => {'2' => 'Value for field 2'}
}
}
end
# check redirection
assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
follow_redirect!
# check issue attributes
assert_equal 'jsmith', issue.author.login
assert_equal 1, issue.project.id
assert_equal 1, issue.status.id
end
def test_create_issue_by_anonymous_without_permission_should_fail
Role.anonymous.remove_permission! :add_issues
assert_no_difference 'Issue.count' do
post '/projects/1/issues', :params => {
:issue => {
:tracker_id => "1",
:subject => "new test issue"
}
}
end
assert_response 302
end
def test_create_issue_by_anonymous_with_custom_permission_should_succeed
Role.anonymous.remove_permission! :add_issues
Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [3])
issue = new_record(Issue) do
post '/projects/1/issues', :params => {
:issue => {
:tracker_id => "1",
:subject => "new test issue"
}
}
assert_response 302
end
assert_equal User.anonymous, issue.author
end
# add then remove 2 attachments to an issue
def test_issue_attachments
log_user('jsmith', 'jsmith')
set_tmp_attachments_directory
attachment = new_record(Attachment) do
put '/issues/1', :params => {
:issue => {:notes => 'Some notes'},
:attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'This is an attachment'}}
}
assert_redirected_to "/issues/1"
end
assert_equal Issue.find(1), attachment.container
assert_equal 'testfile.txt', attachment.filename
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_next_and_previous_links_should_be_displayed_after_query_grouped_and_sorted_by_version
with_settings :default_language => 'en' do
get '/projects/ecookbook/issues?set_filter=1&group_by=fixed_version&sort=priority:desc,fixed_version,id'
assert_response :success
assert_select 'td.id', :text => '5'
get '/issues/5'
assert_response :success
assert_select '.next-prev-links .position', :text => '5 of 6'
end
end
def test_next_and_previous_links_should_be_displayed_after_filter
with_settings :default_language => 'en' do
get '/projects/ecookbook/issues?set_filter=1&tracker_id=1'
assert_response :success
assert_select 'td.id', :text => '5'
get '/issues/5'
assert_response :success
assert_select '.next-prev-links .position', :text => '3 of 5'
assert_select '.next-prev-links .position a[href^=?]', '/projects/ecookbook/issues?'
end
end
def test_next_and_previous_links_should_be_displayed_after_saved_query
query = IssueQuery.create!(:name => 'Calendar Query',
:visibility => IssueQuery::VISIBILITY_PUBLIC,
:filters => {'tracker_id' => {:operator => '=', :values => ['1']}}
)
with_settings :default_language => 'en' do
get "/projects/ecookbook/issues?set_filter=1&query_id=#{query.id}"
assert_response :success
assert_select 'td.id', :text => '5'
get '/issues/5'
assert_response :success
assert_select '.next-prev-links .position', :text => '6 of 8'
end
end
def test_other_formats_links_on_index
get '/projects/ecookbook/issues'
%w(Atom PDF CSV).each do |format|
assert_select 'a[rel=nofollow][href=?]', "/projects/ecookbook/issues.#{format.downcase}", :text => format
end
end
def test_other_formats_links_on_index_without_project_id_in_url
get '/issues', :params => {
:project_id => 'ecookbook'
}
%w(Atom PDF CSV).each do |format|
assert_select 'a[rel=nofollow][href=?]', "/issues.#{format.downcase}?project_id=ecookbook", :text => format
end
end
def test_pagination_links_on_index
with_settings :per_page_options => '2' do
get '/projects/ecookbook/issues'
assert_select 'a[href=?]', '/projects/ecookbook/issues?page=2', :text => '2'
end
end
def test_pagination_links_should_preserve_query_parameters
with_settings :per_page_options => '2' do
get '/projects/ecookbook/issues?foo=bar'
assert_select 'a[href=?]', '/projects/ecookbook/issues?foo=bar&page=2', :text => '2'
end
end
def test_pagination_links_should_not_use_params_as_url_options
with_settings :per_page_options => '2' do
get '/projects/ecookbook/issues?host=foo'
assert_select 'a[href=?]', '/projects/ecookbook/issues?host=foo&page=2', :text => '2'
end
end
def test_sort_links_on_index
get '/projects/ecookbook/issues'
assert_select 'a[href=?]', '/projects/ecookbook/issues?sort=subject%2Cid%3Adesc', :text => 'Subject'
end
def test_sort_links_should_preserve_query_parameters
get '/projects/ecookbook/issues?foo=bar'
assert_select 'a[href=?]', '/projects/ecookbook/issues?foo=bar&sort=subject%2Cid%3Adesc', :text => 'Subject'
end
def test_sort_links_should_not_use_params_as_url_options
get '/projects/ecookbook/issues?host=foo'
assert_select 'a[href=?]', '/projects/ecookbook/issues?host=foo&sort=subject%2Cid%3Adesc', :text => 'Subject'
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.sort
tester = users.first
# Issue form
get '/projects/ecookbook/issues/new'
assert_response :success
assert_select 'select[name=?]', "issue[custom_field_values][#{@field.id}]" do
assert_select 'option', users.size + 1 # +1 for blank value
assert_select 'option[value=?]', tester.id.to_s, :text => tester.name
end
# Create issue
issue = new_record(Issue) do
post '/projects/ecookbook/issues', :params => {
: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}
}
}
assert_response 302
end
# Issue view
follow_redirect!
assert_select ".cf_#{@field.id}" do
assert_select '.label', :text => 'Tester:'
assert_select '.value', :text => tester.name
end
assert_select 'select[name=?]', "issue[custom_field_values][#{@field.id}]" do
assert_select 'option', users.size + 1 # +1 for blank value
assert_select 'option[value=?][selected=selected]', tester.id.to_s, :text => tester.name
end
new_tester = users[1]
with_settings :default_language => 'en' do
# Update issue
assert_difference 'Journal.count' do
put "/issues/#{issue.id}", :params => {
:issue => {
:notes => 'Updating custom field',
:custom_field_values => {@field.id.to_s => new_tester.id.to_s}
}
}
assert_redirected_to "/issues/#{issue.id}"
end
# Issue view
follow_redirect!
assert_select 'ul.details li', :text => "Tester changed from #{tester} to #{new_tester}"
end
end
def test_update_using_invalid_http_verbs
log_user('jsmith', 'jsmith')
subject = 'Updated by an invalid http verb'
get '/issues/update/1', :params => {:issue => {:subject => subject}}
assert_response 404
assert_not_equal subject, Issue.find(1).subject
post '/issues/1', :params => {:issue => {:subject => subject}}
assert_response 404
assert_not_equal subject, Issue.find(1).subject
end
def test_get_watch_should_be_invalid
log_user('jsmith', 'jsmith')
assert_no_difference 'Watcher.count' do
get '/watchers/watch?object_type=issue&object_id=1'
assert_response 404
end
end
end

View file

@ -0,0 +1,127 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class LayoutTest < Redmine::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
log_user('jsmith','jsmith')
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_select 'head script[src^=?]', '/javascripts/jstoolbar/jstoolbar-textile.min.js?'
end
def test_calendar_header_tags
with_settings :default_language => 'fr' do
get '/issues'
assert_include "/javascripts/i18n/datepicker-fr.js", response.body
end
with_settings :default_language => 'en-GB' do
get '/issues'
assert_include "/javascripts/i18n/datepicker-en-GB.js", response.body
end
with_settings :default_language => 'en' do
get '/issues'
assert_not_include "/javascripts/i18n/datepicker", response.body
end
with_settings :default_language => 'es' do
get '/issues'
assert_include "/javascripts/i18n/datepicker-es.js", response.body
end
with_settings :default_language => 'es-PA' do
get '/issues'
# There is not datepicker-es-PA.js
# https://github.com/jquery/jquery-ui/tree/1.11.4/ui/i18n
assert_not_include "/javascripts/i18n/datepicker-es.js", response.body
end
with_settings :default_language => 'zh' do
get '/issues'
assert_include "/javascripts/i18n/datepicker-zh-CN.js", response.body
end
with_settings :default_language => 'zh-TW' do
get '/issues'
assert_include "/javascripts/i18n/datepicker-zh-TW.js", response.body
end
with_settings :default_language => 'pt' do
get '/issues'
assert_include "/javascripts/i18n/datepicker-pt.js", response.body
end
with_settings :default_language => 'pt-BR' do
get '/issues'
assert_include "/javascripts/i18n/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,194 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../../../test_helper', __FILE__)
class AttachmentFieldFormatTest < Redmine::IntegrationTest
fixtures :projects,
:users, :email_addresses,
:roles,
:members,
:member_roles,
:trackers,
:projects_trackers,
:enabled_modules,
:issue_statuses,
:issues,
:enumerations,
:custom_fields,
:custom_values,
:custom_fields_trackers,
:attachments
def setup
set_tmp_attachments_directory
@field = IssueCustomField.generate!(:name => "File", :field_format => "attachment")
log_user "jsmith", "jsmith"
end
def test_new_should_include_inputs
get '/projects/ecookbook/issues/new'
assert_response :success
assert_select '[name^=?]', "issue[custom_field_values][#{@field.id}]", 2
assert_select 'input[name=?][type=hidden][value=""]', "issue[custom_field_values][#{@field.id}][blank]"
end
def test_create_with_attachment
issue = new_record(Issue) do
assert_difference 'Attachment.count' do
post '/projects/ecookbook/issues', :params => {
:issue => {
:subject => "Subject",
:custom_field_values => {
@field.id => {
'blank' => '',
'1' => {:file => uploaded_test_file("testfile.txt", "text/plain")}
}
}
}
}
assert_response 302
end
end
custom_value = issue.custom_value_for(@field)
assert custom_value
assert custom_value.value.present?
attachment = Attachment.find_by_id(custom_value.value)
assert attachment
assert_equal custom_value, attachment.container
follow_redirect!
assert_response :success
# link to the attachment
link = css_select(".cf_#{@field.id} .value a")
assert_equal 1, link.size
assert_equal "testfile.txt", link.text
# preview the attachment
get link.attr('href')
assert_response :success
assert_template :file
end
def test_create_without_attachment
issue = new_record(Issue) do
assert_no_difference 'Attachment.count' do
post '/projects/ecookbook/issues', :params => {
:issue => {
:subject => "Subject",
:custom_field_values => {
@field.id => {:blank => ''}
}
}
}
assert_response 302
end
end
custom_value = issue.custom_value_for(@field)
assert custom_value
assert custom_value.value.blank?
follow_redirect!
assert_response :success
# no links to the attachment
assert_select ".cf_#{@field.id} .value a", 0
end
def test_failure_on_create_should_preserve_attachment
attachment = new_record(Attachment) do
assert_no_difference 'Issue.count' do
post '/projects/ecookbook/issues', :params => {
:issue => {
:subject => "",
:custom_field_values => {
@field.id => {:file => uploaded_test_file("testfile.txt", "text/plain")}
}
}
}
assert_response :success
assert_select_error /Subject cannot be blank/
end
end
assert_nil attachment.container_id
assert_select 'input[name=?][value=?][type=hidden]', "issue[custom_field_values][#{@field.id}][p0][token]", attachment.token
assert_select 'input[name=?][value=?]', "issue[custom_field_values][#{@field.id}][p0][filename]", 'testfile.txt'
issue = new_record(Issue) do
assert_no_difference 'Attachment.count' do
post '/projects/ecookbook/issues', :params => {
:issue => {
:subject => "Subject",
:custom_field_values => {
@field.id => {:token => attachment.token}
}
}
}
assert_response 302
end
end
custom_value = issue.custom_value_for(@field)
assert custom_value
assert_equal attachment.id.to_s, custom_value.value
assert_equal custom_value, attachment.reload.container
end
def test_create_with_valid_extension
@field.extensions_allowed = "txt, log"
@field.save!
attachment = new_record(Attachment) do
assert_difference 'Issue.count' do
post '/projects/ecookbook/issues', :params => {
:issue => {
:subject => "Blank",
:custom_field_values => {
@field.id => {:file => uploaded_test_file("testfile.txt", "text/plain")}
}
}
}
assert_response 302
end
end
end
def test_create_with_invalid_extension_should_fail
@field.extensions_allowed = "png, jpeg"
@field.save!
attachment = new_record(Attachment) do
assert_no_difference 'Issue.count' do
post '/projects/ecookbook/issues', :params => {
:issue => {
:subject => "Blank",
:custom_field_values => {
@field.id => {:file => uploaded_test_file("testfile.txt", "text/plain")}
}
}
}
assert_response :success
end
end
end
end

View file

@ -0,0 +1,124 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../../test_helper', __FILE__)
class HookTest < Redmine::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
Redmine::Hook.clear_listeners
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
class SingleRenderOn < Redmine::Hook::ViewListener
render_on :view_welcome_index_left, :inline => 'SingleRenderOn 1'
end
class MultipleRenderOn < Redmine::Hook::ViewListener
render_on :view_welcome_index_left, {:inline => 'MultipleRenderOn 1'}, {:inline => 'MultipleRenderOn 2'}
end
# Hooks that stores the call context
class ContextTestHook < Redmine::Hook::ViewListener
cattr_accessor :context
def controller_account_success_authentication_after(context)
self.class.context = context
end
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_select 'head link[href=?]', '/stylesheets/ecookbook.css'
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
def test_controller_hook_context_should_include_request
Redmine::Hook.add_listener(ContextTestHook)
post '/login', :params => {:username => 'admin', :password => 'admin'}
assert_not_nil ContextTestHook.context
context = ContextTestHook.context
assert_kind_of ActionDispatch::Request, context[:request]
assert_kind_of Hash, context[:request].params
assert_kind_of AccountController, context[:hook_caller]
end
def test_multiple_hooks
Redmine::Hook.add_listener(SingleRenderOn)
Redmine::Hook.add_listener(MultipleRenderOn)
get '/'
assert_equal 1, response.body.scan("SingleRenderOn 1 MultipleRenderOn 1 MultipleRenderOn 2").size
end
end

View file

@ -0,0 +1,80 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../../test_helper', __FILE__)
class MenuManagerTest < Redmine::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',
:headers => {'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'}
assert_select 'div#main-menu' do
assert_select 'li a.activity[href=?]', '/projects/ecookbook/activity', :text => ll('fr', :label_activity)
assert_select 'li a.issues.selected[href=?]', '/projects/ecookbook/issues', :text => ll('fr', :label_issue_plural)
end
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_select 'div#main-menu ul' do
assert_select 'li:last-child a.foo[href=?]', '/projects/ecookbook', :text => 'Foo'
assert_select 'li:nth-child(2) a.bar[href=?]', '/projects/ecookbook', :text => 'Bar'
assert_select 'li:nth-child(3) a.hello[href=?]', '/projects/ecookbook', :text => 'ECOOKBOOK'
assert_select 'li:nth-child(4) a', :text => 'Activity'
end
# Remove the menu items
Redmine::MenuManager.map :project_menu do |menu|
menu.delete :foo
menu.delete :bar
menu.delete :hello
end
end
end
def test_main_menu_should_select_projects_tab_on_project_list
get '/projects'
assert_select '#main-menu' do
assert_select 'a.projects'
assert_select 'a.projects.selected'
end
end
def test_main_menu_should_not_show_up_on_account
get '/login'
assert_select '#main-menu', 0
end
end

View file

@ -0,0 +1,102 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../../test_helper', __FILE__)
class ThemesTest < Redmine::IntegrationTest
def setup
Redmine::Themes.rescan
@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_select "link[rel=stylesheet][href^=?]", "/themes/#{@theme.dir}/stylesheets/application.css"
end
def test_without_theme_js
# simulate a state theme.js does not exists
@theme.javascripts.clear
get '/'
assert_response :success
assert_select "script[src^=?]", "/themes/#{@theme.dir}/javascripts/theme.js", 0
end
def test_with_theme_js
# Simulates a theme.js
@theme.javascripts << 'theme'
get '/'
assert_response :success
assert_select "script[src^=?]", "/themes/#{@theme.dir}/javascripts/theme.js", 1
ensure
@theme.javascripts.delete 'theme'
end
def test_use_default_favicon_if_theme_provides_none
get '/'
assert_response :success
assert_select 'link[rel="shortcut icon"][href^="/favicon.ico"]'
end
def test_use_theme_favicon_if_theme_provides_one
# Simulate a theme favicon
@theme.favicons << 'a.ico'
get '/'
assert_response :success
assert_select 'link[rel="shortcut icon"][href^=?]', "/themes/#{@theme.dir}/favicon/a.ico"
ensure
@theme.favicons.delete 'a.ico'
end
def test_use_only_one_theme_favicon_if_theme_provides_many
@theme.favicons.concat %w{b.ico a.png}
get '/'
assert_response :success
assert_select 'link[rel="shortcut icon"]', 1
assert_select 'link[rel="shortcut icon"][href^=?]', "/themes/#{@theme.dir}/favicon/b.ico"
ensure
@theme.favicons.delete("b.ico")
@theme.favicons.delete("a.png")
end
def test_with_sub_uri
Redmine::Utils.relative_url_root = '/foo'
@theme.javascripts << 'theme'
@theme.favicons << 'a.ico'
get '/'
assert_response :success
assert_select "link[rel=stylesheet][href^=?]", "/foo/themes/#{@theme.dir}/stylesheets/application.css"
assert_select "script[src^=?]", "/foo/themes/#{@theme.dir}/javascripts/theme.js"
assert_select 'link[rel="shortcut icon"][href^=?]', "/foo/themes/#{@theme.dir}/favicon/a.ico"
ensure
Redmine::Utils.relative_url_root = ''
end
end

View file

@ -0,0 +1,53 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class ProjectsTest < Redmine::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
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
log_user("admin", "admin")
assert_no_difference 'EnabledModule.count' do
get '/projects/1/modules', :params => {:enabled_module_names => ['']}
assert_response 404
end
end
end

View file

@ -0,0 +1,50 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class RepositoriesGitTest < Redmine::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,36 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingAccountTest < Redmine::RoutingTest
def test_account
should_route 'GET /login' => 'account#login'
should_route 'POST /login' => 'account#login'
should_route 'GET /logout' => 'account#logout'
should_route 'POST /logout' => 'account#logout'
should_route 'GET /account/register' => 'account#register'
should_route 'POST /account/register' => 'account#register'
should_route 'GET /account/lost_password' => 'account#lost_password'
should_route 'POST /account/lost_password' => 'account#lost_password'
should_route 'GET /account/activate' => 'account#activate'
end
end

View file

@ -0,0 +1,31 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingActivitiesTest < Redmine::RoutingTest
def test_activity
should_route 'GET /activity' => 'activities#index'
should_route 'GET /activity.atom' => 'activities#index', :format => 'atom'
end
def test_project_activity
should_route 'GET /projects/33/activity' => 'activities#index', :id => '33'
should_route 'GET /projects/33/activity.atom' => 'activities#index', :id => '33', :format => 'atom'
end
end

View file

@ -0,0 +1,29 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingAdminTest < Redmine::RoutingTest
def test_administration_panel
should_route 'GET /admin' => 'admin#index'
should_route 'GET /admin/projects' => 'admin#projects'
should_route 'GET /admin/plugins' => 'admin#plugins'
should_route 'GET /admin/info' => 'admin#info'
should_route 'POST /admin/test_email' => 'admin#test_email'
should_route 'POST /admin/default_configuration' => 'admin#default_configuration'
end
end

View file

@ -0,0 +1,36 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingAttachmentsTest < Redmine::RoutingTest
def test_attachments
should_route 'GET /attachments/1' => 'attachments#show', :id => '1'
should_route 'GET /attachments/1/filename.ext' => 'attachments#show', :id => '1', :filename => 'filename.ext'
should_route 'GET /attachments/download/1' => 'attachments#download', :id => '1'
should_route 'GET /attachments/download/1/filename.ext' => 'attachments#download', :id => '1', :filename => 'filename.ext'
should_route 'GET /attachments/thumbnail/1' => 'attachments#thumbnail', :id => '1'
should_route 'GET /attachments/thumbnail/1/200' => 'attachments#thumbnail', :id => '1', :size => '200'
should_route 'DELETE /attachments/1' => 'attachments#destroy', :id => '1'
should_route 'GET /attachments/issues/1/edit' => 'attachments#edit_all', :object_type => 'issues', :object_id => '1'
should_route 'PATCH /attachments/issues/1' => 'attachments#update_all', :object_type => 'issues', :object_id => '1'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingAuthSourcesTest < Redmine::RoutingTest
def test_auth_sources
should_route 'GET /auth_sources' => 'auth_sources#index'
should_route 'GET /auth_sources/new' => 'auth_sources#new'
should_route 'POST /auth_sources' => 'auth_sources#create'
should_route 'GET /auth_sources/autocomplete_for_new_user' => 'auth_sources#autocomplete_for_new_user'
should_route 'GET /auth_sources/1234/edit' => 'auth_sources#edit', :id => '1234'
should_route 'PUT /auth_sources/1234' => 'auth_sources#update', :id => '1234'
should_route 'DELETE /auth_sources/1234' => 'auth_sources#destroy', :id => '1234'
should_route 'GET /auth_sources/1234/test_connection' => 'auth_sources#test_connection', :id => '1234'
end
end

View file

@ -0,0 +1,24 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingAutoCompletesTest < Redmine::RoutingTest
def test_auto_completes
should_route 'GET /issues/auto_complete' => 'auto_completes#issues'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingBoardsTest < Redmine::RoutingTest
def test_boards
should_route 'GET /projects/foo/boards' => 'boards#index', :project_id => 'foo'
should_route 'GET /projects/foo/boards/new' => 'boards#new', :project_id => 'foo'
should_route 'POST /projects/foo/boards' => 'boards#create', :project_id => 'foo'
should_route 'GET /projects/foo/boards/44' => 'boards#show', :project_id => 'foo', :id => '44'
should_route 'GET /projects/foo/boards/44.atom' => 'boards#show', :project_id => 'foo', :id => '44', :format => 'atom'
should_route 'GET /projects/foo/boards/44/edit' => 'boards#edit', :project_id => 'foo', :id => '44'
should_route 'PUT /projects/foo/boards/44' => 'boards#update', :project_id => 'foo', :id => '44'
should_route 'DELETE /projects/foo/boards/44' => 'boards#destroy', :project_id => 'foo', :id => '44'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingCalendarsTest < Redmine::RoutingTest
def test_calendars
should_route 'GET /issues/calendar' => 'calendars#show'
should_route 'GET /projects/foo/issues/calendar' => 'calendars#show', :project_id => 'foo'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingCommentsTest < Redmine::RoutingTest
def test_comments
should_route 'POST /news/567/comments' => 'comments#create', :id => '567'
should_route 'DELETE /news/567/comments/15' => 'comments#destroy', :id => '567', :comment_id => '15'
end
end

View file

@ -0,0 +1,30 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingContextMenusTest < Redmine::RoutingTest
def test_context_menus_time_entries
should_route 'GET /time_entries/context_menu' => 'context_menus#time_entries'
should_route 'POST /time_entries/context_menu' => 'context_menus#time_entries'
end
def test_context_menus_issues
should_route 'GET /issues/context_menu' => 'context_menus#issues'
should_route 'POST /issues/context_menu' => 'context_menus#issues'
end
end

View file

@ -0,0 +1,37 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingCustomFieldsTest < Redmine::RoutingTest
def test_custom_fields
should_route 'GET /custom_fields' => 'custom_fields#index'
should_route 'GET /custom_fields/new' => 'custom_fields#new'
should_route 'POST /custom_fields' => 'custom_fields#create'
should_route 'GET /custom_fields/2/edit' => 'custom_fields#edit', :id => '2'
should_route 'PUT /custom_fields/2' => 'custom_fields#update', :id => '2'
should_route 'DELETE /custom_fields/2' => 'custom_fields#destroy', :id => '2'
end
def test_custom_field_enumerations
should_route 'GET /custom_fields/3/enumerations' => 'custom_field_enumerations#index', :custom_field_id => '3'
should_route 'POST /custom_fields/3/enumerations' => 'custom_field_enumerations#create', :custom_field_id => '3'
should_route 'PUT /custom_fields/3/enumerations' => 'custom_field_enumerations#update_each', :custom_field_id => '3'
should_route 'DELETE /custom_fields/3/enumerations/6' => 'custom_field_enumerations#destroy', :custom_field_id => '3', :id => '6'
end
end

View file

@ -0,0 +1,37 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingDocumentsTest < Redmine::RoutingTest
def test_documents_scoped_under_project
should_route 'GET /projects/567/documents' => 'documents#index', :project_id => '567'
should_route 'GET /projects/567/documents/new' => 'documents#new', :project_id => '567'
should_route 'POST /projects/567/documents' => 'documents#create', :project_id => '567'
end
def test_documents
should_route 'GET /documents/22' => 'documents#show', :id => '22'
should_route 'GET /documents/22/edit' => 'documents#edit', :id => '22'
should_route 'PUT /documents/22' => 'documents#update', :id => '22'
should_route 'DELETE /documents/22' => 'documents#destroy', :id => '22'
end
def test_document_attachments
should_route 'POST /documents/22/add_attachment' => 'documents#add_attachment', :id => '22'
end
end

View file

@ -0,0 +1,30 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingEnumerationsTest < Redmine::RoutingTest
def test_enumerations
should_route 'GET /enumerations' => 'enumerations#index'
should_route 'GET /enumerations/new' => 'enumerations#new'
should_route 'POST /enumerations' => 'enumerations#create'
should_route 'GET /enumerations/2/edit' => 'enumerations#edit', :id => '2'
should_route 'PUT /enumerations/2' => 'enumerations#update', :id => '2'
should_route 'DELETE /enumerations/2' => 'enumerations#destroy', :id => '2'
end
end

View file

@ -0,0 +1,26 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingFilesTest < Redmine::RoutingTest
def test_files
should_route 'GET /projects/foo/files' => 'files#index', :project_id => 'foo'
should_route 'GET /projects/foo/files/new' => 'files#new', :project_id => 'foo'
should_route 'POST /projects/foo/files' => 'files#create', :project_id => 'foo'
end
end

View file

@ -0,0 +1,28 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingGanttsTest < Redmine::RoutingTest
def test_gantts
should_route 'GET /issues/gantt' => 'gantts#show'
should_route 'GET /issues/gantt.pdf' => 'gantts#show', :format => 'pdf'
should_route 'GET /projects/foo/issues/gantt' => 'gantts#show', :project_id => 'foo'
should_route 'GET /projects/foo/issues/gantt.pdf' => 'gantts#show', :project_id => 'foo', :format => 'pdf'
end
end

View file

@ -0,0 +1,40 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingGroupsTest < Redmine::RoutingTest
def test_groups
should_route 'GET /groups' => 'groups#index'
should_route 'GET /groups/new' => 'groups#new'
should_route 'POST /groups' => 'groups#create'
should_route 'GET /groups/1' => 'groups#show', :id => '1'
should_route 'GET /groups/1/edit' => 'groups#edit', :id => '1'
should_route 'PUT /groups/1' => 'groups#update', :id => '1'
should_route 'DELETE /groups/1' => 'groups#destroy', :id => '1'
should_route 'GET /groups/1/autocomplete_for_user' => 'groups#autocomplete_for_user', :id => '1'
should_route 'GET /groups/1/autocomplete_for_user.js' => 'groups#autocomplete_for_user', :id => '1', :format => 'js'
end
def test_group_users
should_route 'GET /groups/567/users/new' => 'groups#new_users', :id => '567'
should_route 'POST /groups/567/users' => 'groups#add_users', :id => '567'
should_route 'DELETE /groups/567/users/12' => 'groups#remove_user', :id => '567', :user_id => '12'
end
end

View file

@ -0,0 +1,36 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingImportsTest < Redmine::RoutingTest
def test_imports
should_route 'GET /issues/imports/new' => 'imports#new'
should_route 'POST /imports' => 'imports#create'
should_route 'GET /imports/4ae6bc' => 'imports#show', :id => '4ae6bc'
should_route 'GET /imports/4ae6bc/settings' => 'imports#settings', :id => '4ae6bc'
should_route 'POST /imports/4ae6bc/settings' => 'imports#settings', :id => '4ae6bc'
should_route 'GET /imports/4ae6bc/mapping' => 'imports#mapping', :id => '4ae6bc'
should_route 'POST /imports/4ae6bc/mapping' => 'imports#mapping', :id => '4ae6bc'
should_route 'GET /imports/4ae6bc/run' => 'imports#run', :id => '4ae6bc'
should_route 'POST /imports/4ae6bc/run' => 'imports#run', :id => '4ae6bc'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingIssueCategoriesTest < Redmine::RoutingTest
def test_issue_categories_scoped_under_project
should_route 'GET /projects/foo/issue_categories' => 'issue_categories#index', :project_id => 'foo'
should_route 'GET /projects/foo/issue_categories/new' => 'issue_categories#new', :project_id => 'foo'
should_route 'POST /projects/foo/issue_categories' => 'issue_categories#create', :project_id => 'foo'
end
def test_issue_categories
should_route 'GET /issue_categories/1/edit' => 'issue_categories#edit', :id => '1'
should_route 'PUT /issue_categories/1' => 'issue_categories#update', :id => '1'
should_route 'DELETE /issue_categories/1' => 'issue_categories#destroy', :id => '1'
end
end

View file

@ -0,0 +1,27 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingIssueRelationsTest < Redmine::RoutingTest
def test_issue_relations
should_route 'GET /issues/1/relations' => 'issue_relations#index', :issue_id => '1'
should_route 'POST /issues/1/relations' => 'issue_relations#create', :issue_id => '1'
should_route 'DELETE /relations/23' => 'issue_relations#destroy', :id => '23'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingIssueStatusesTest < Redmine::RoutingTest
def test_issue_statuses
should_route 'GET /issue_statuses' => 'issue_statuses#index'
should_route 'POST /issue_statuses' => 'issue_statuses#create'
should_route 'GET /issue_statuses/new' => 'issue_statuses#new'
should_route 'GET /issue_statuses/1/edit' => 'issue_statuses#edit', :id => '1'
should_route 'PUT /issue_statuses/1' => 'issue_statuses#update', :id => '1'
should_route 'DELETE /issue_statuses/1' => 'issue_statuses#destroy', :id => '1'
should_route 'POST /issue_statuses/update_issue_done_ratio' => 'issue_statuses#update_issue_done_ratio'
end
end

View file

@ -0,0 +1,60 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingIssuesTest < Redmine::RoutingTest
def test_issues
should_route 'GET /issues' => 'issues#index'
should_route 'GET /issues.pdf' => 'issues#index', :format => 'pdf'
should_route 'GET /issues.atom' => 'issues#index', :format => 'atom'
should_route 'GET /issues/64' => 'issues#show', :id => '64'
should_route 'GET /issues/64.pdf' => 'issues#show', :id => '64', :format => 'pdf'
should_route 'GET /issues/64.atom' => 'issues#show', :id => '64', :format => 'atom'
should_route 'GET /issues/new' => 'issues#new'
should_route 'POST /issues' => 'issues#create'
should_route 'GET /issues/64/edit' => 'issues#edit', :id => '64'
should_route 'PUT /issues/64' => 'issues#update', :id => '64'
should_route 'DELETE /issues/64' => 'issues#destroy', :id => '64'
end
def test_issues_bulk_edit
should_route 'GET /issues/bulk_edit' => 'issues#bulk_edit'
should_route 'POST /issues/bulk_edit' => 'issues#bulk_edit' # For updating the bulk edit form
should_route 'POST /issues/bulk_update' => 'issues#bulk_update'
end
def test_issues_scoped_under_project
should_route 'GET /projects/23/issues' => 'issues#index', :project_id => '23'
should_route 'GET /projects/23/issues.pdf' => 'issues#index', :project_id => '23', :format => 'pdf'
should_route 'GET /projects/23/issues.atom' => 'issues#index', :project_id => '23', :format => 'atom'
should_route 'GET /projects/23/issues/new' => 'issues#new', :project_id => '23'
should_route 'POST /projects/23/issues' => 'issues#create', :project_id => '23'
should_route 'GET /projects/23/issues/64/copy' => 'issues#new', :project_id => '23', :copy_from => '64'
end
def test_issues_form_update
should_route 'POST /issues/new' => 'issues#new'
should_route 'POST /projects/23/issues/new' => 'issues#new', :project_id => '23'
should_route 'PATCH /issues/23/edit' => 'issues#edit', :id => '23'
end
end

View file

@ -0,0 +1,29 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingJournalsTest < Redmine::RoutingTest
def test_journals
should_route 'POST /issues/1/quoted' => 'journals#new', :id => '1'
should_route 'GET /issues/changes' => 'journals#index'
should_route 'GET /journals/1/diff' => 'journals#diff', :id => '1'
should_route 'GET /journals/1/edit' => 'journals#edit', :id => '1'
should_route 'PUT /journals/1' => 'journals#update', :id => '1'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingMailHandlerTest < Redmine::RoutingTest
def test_mail_handler
should_route 'GET /mail_handler' => 'mail_handler#new'
should_route 'POST /mail_handler' => 'mail_handler#index'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingMembersTest < Redmine::RoutingTest
def test_members
should_route 'GET /projects/foo/memberships/new' => 'members#new', :project_id => 'foo'
should_route 'POST /projects/foo/memberships' => 'members#create', :project_id => 'foo'
should_route 'GET /memberships/5234/edit' => 'members#edit', :id => '5234'
should_route 'PUT /memberships/5234' => 'members#update', :id => '5234'
should_route 'DELETE /memberships/5234' => 'members#destroy', :id => '5234'
should_route 'GET /projects/foo/memberships/autocomplete' => 'members#autocomplete', :project_id => 'foo'
should_route 'GET /projects/foo/memberships/autocomplete.js' => 'members#autocomplete', :project_id => 'foo', :format => 'js'
end
end

View file

@ -0,0 +1,33 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingMessagesTest < Redmine::RoutingTest
def test_messages
# TODO: refactor routes
should_route 'GET /boards/22/topics/new' => 'messages#new', :board_id => '22'
should_route 'POST /boards/22/topics/new' => 'messages#new', :board_id => '22'
should_route 'POST /boards/22/topics/preview' => 'messages#preview', :board_id => '22'
should_route 'GET /boards/22/topics/2' => 'messages#show', :id => '2', :board_id => '22'
should_route 'GET /boards/22/topics/2/edit' => 'messages#edit', :id => '2', :board_id => '22'
should_route 'POST /boards/22/topics/quote/2' => 'messages#quote', :id => '2', :board_id => '22'
should_route 'POST /boards/22/topics/2/replies' => 'messages#reply', :id => '2', :board_id => '22'
should_route 'POST /boards/22/topics/2/destroy' => 'messages#destroy', :id => '2', :board_id => '22'
end
end

View file

@ -0,0 +1,43 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingMyTest < Redmine::RoutingTest
def test_my
should_route 'GET /my/account' => 'my#account'
should_route 'POST /my/account' => 'my#account'
should_route 'GET /my/account/destroy' => 'my#destroy'
should_route 'POST /my/account/destroy' => 'my#destroy'
should_route 'GET /my/page' => 'my#page'
should_route 'POST /my/page' => 'my#update_page'
should_route 'GET /my' => 'my#index'
should_route 'GET /my/api_key' => 'my#show_api_key'
should_route 'POST /my/api_key' => 'my#reset_api_key'
should_route 'POST /my/rss_key' => 'my#reset_rss_key'
should_route 'GET /my/password' => 'my#password'
should_route 'POST /my/password' => 'my#password'
should_route 'POST /my/add_block' => 'my#add_block'
should_route 'POST /my/remove_block' => 'my#remove_block'
should_route 'POST /my/order_blocks' => 'my#order_blocks'
end
end

View file

@ -0,0 +1,36 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingNewsTest < Redmine::RoutingTest
def test_news_scoped_under_project
should_route 'GET /projects/foo/news' => 'news#index', :project_id => 'foo'
should_route 'GET /projects/foo/news.atom' => 'news#index', :project_id => 'foo', :format => 'atom'
should_route 'GET /projects/foo/news/new' => 'news#new', :project_id => 'foo'
should_route 'POST /projects/foo/news' => 'news#create', :project_id => 'foo'
end
def test_news
should_route 'GET /news' => 'news#index'
should_route 'GET /news.atom' => 'news#index', :format => 'atom'
should_route 'GET /news/2' => 'news#show', :id => '2'
should_route 'GET /news/2/edit' => 'news#edit', :id => '2'
should_route 'PUT /news/2' => 'news#update', :id => '2'
should_route 'DELETE /news/2' => 'news#destroy', :id => '2'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingPreviewsTest < Redmine::RoutingTest
def test_previews
should_route 'GET /issues/preview/new/foo' => 'previews#issue', :project_id => 'foo'
should_route 'PUT /issues/preview/new/foo' => 'previews#issue', :project_id => 'foo'
should_route 'POST /issues/preview/new/foo' => 'previews#issue', :project_id => 'foo'
should_route 'GET /issues/preview/edit/321' => 'previews#issue', :id => '321'
should_route 'PUT /issues/preview/edit/321' => 'previews#issue', :id => '321'
should_route 'POST /issues/preview/edit/321' => 'previews#issue', :id => '321'
should_route 'GET /news/preview' => 'previews#news'
end
end

View file

@ -0,0 +1,36 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingPrincipalMembershipsTest < Redmine::RoutingTest
def test_user_memberships
should_route 'GET /users/123/memberships/new' => 'principal_memberships#new', :user_id => '123'
should_route 'POST /users/123/memberships' => 'principal_memberships#create', :user_id => '123'
should_route 'GET /users/123/memberships/55/edit' => 'principal_memberships#edit', :user_id => '123', :id => '55'
should_route 'PUT /users/123/memberships/55' => 'principal_memberships#update', :user_id => '123', :id => '55'
should_route 'DELETE /users/123/memberships/55' => 'principal_memberships#destroy', :user_id => '123', :id => '55'
end
def test_group_memberships
should_route 'GET /groups/123/memberships/new' => 'principal_memberships#new', :group_id => '123'
should_route 'POST /groups/123/memberships' => 'principal_memberships#create', :group_id => '123'
should_route 'GET /groups/123/memberships/55/edit' => 'principal_memberships#edit', :group_id => '123', :id => '55'
should_route 'PUT /groups/123/memberships/55' => 'principal_memberships#update', :group_id => '123', :id => '55'
should_route 'DELETE /groups/123/memberships/55' => 'principal_memberships#destroy', :group_id => '123', :id => '55'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingProjectEnumerationsTest < Redmine::RoutingTest
def test_project_enumerations
should_route 'PUT /projects/foo/enumerations' => 'project_enumerations#update', :project_id => 'foo'
should_route 'DELETE /projects/foo/enumerations' => 'project_enumerations#destroy', :project_id => 'foo'
end
end

View file

@ -0,0 +1,41 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingProjectsTest < Redmine::RoutingTest
def test_projects
should_route 'GET /projects' => 'projects#index'
should_route 'GET /projects.atom' => 'projects#index', :format => 'atom'
should_route 'GET /projects/new' => 'projects#new'
should_route 'POST /projects' => 'projects#create'
should_route 'GET /projects/autocomplete.js' => 'projects#autocomplete', :format => 'js'
should_route 'GET /projects/foo' => 'projects#show', :id => 'foo'
should_route 'PUT /projects/foo' => 'projects#update', :id => 'foo'
should_route 'DELETE /projects/foo' => 'projects#destroy', :id => 'foo'
should_route 'GET /projects/foo/settings' => 'projects#settings', :id => 'foo'
should_route 'GET /projects/foo/settings/members' => 'projects#settings', :id => 'foo', :tab => 'members'
should_route 'POST /projects/foo/archive' => 'projects#archive', :id => 'foo'
should_route 'POST /projects/foo/unarchive' => 'projects#unarchive', :id => 'foo'
should_route 'POST /projects/foo/close' => 'projects#close', :id => 'foo'
should_route 'POST /projects/foo/reopen' => 'projects#reopen', :id => 'foo'
end
end

View file

@ -0,0 +1,35 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingQueriesTest < Redmine::RoutingTest
def test_queries
should_route 'GET /queries/new' => 'queries#new'
should_route 'POST /queries' => 'queries#create'
should_route 'GET /queries/filter' => 'queries#filter'
should_route 'GET /queries/1/edit' => 'queries#edit', :id => '1'
should_route 'PUT /queries/1' => 'queries#update', :id => '1'
should_route 'DELETE /queries/1' => 'queries#destroy', :id => '1'
end
def test_queries_scoped_under_project
should_route 'GET /projects/foo/queries/new' => 'queries#new', :project_id => 'foo'
should_route 'POST /projects/foo/queries' => 'queries#create', :project_id => 'foo'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingReportsTest < Redmine::RoutingTest
def test_reports
should_route 'GET /projects/foo/issues/report' => 'reports#issue_report', :id => 'foo'
should_route 'GET /projects/foo/issues/report/assigned_to' => 'reports#issue_report_details', :id => 'foo', :detail => 'assigned_to'
end
end

View file

@ -0,0 +1,139 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingRepositoriesTest < Redmine::RoutingTest
def setup
@path_hash = repository_path_hash(%w[path to file.c])
assert_equal "path/to/file.c", @path_hash[:path]
assert_equal "path/to/file.c", @path_hash[:param]
end
def test_repositories_resources
should_route 'GET /projects/foo/repositories/new' => 'repositories#new', :project_id => 'foo'
should_route 'POST /projects/foo/repositories' => 'repositories#create', :project_id => 'foo'
should_route 'GET /repositories/1/edit' => 'repositories#edit', :id => '1'
should_route 'PUT /repositories/1' => 'repositories#update', :id => '1'
should_route 'DELETE /repositories/1' => 'repositories#destroy', :id => '1'
should_route 'GET /repositories/1/committers' => 'repositories#committers', :id => '1'
should_route 'POST /repositories/1/committers' => 'repositories#committers', :id => '1'
end
def test_repositories
should_route 'GET /projects/foo/repository' => 'repositories#show', :id => 'foo'
should_route 'GET /projects/foo/repository/statistics' => 'repositories#stats', :id => 'foo'
should_route 'GET /projects/foo/repository/graph' => 'repositories#graph', :id => 'foo'
end
def test_repositories_with_repository_id
should_route 'GET /projects/foo/repository/svn' => 'repositories#show', :id => 'foo', :repository_id => 'svn'
should_route 'GET /projects/foo/repository/svn/statistics' => 'repositories#stats', :id => 'foo', :repository_id => 'svn'
should_route 'GET /projects/foo/repository/svn/graph' => 'repositories#graph', :id => 'foo', :repository_id => 'svn'
end
def test_repositories_revisions
should_route 'GET /projects/foo/repository/revision' => 'repositories#revision', :id => 'foo'
should_route 'GET /projects/foo/repository/revisions' => 'repositories#revisions', :id => 'foo'
should_route 'GET /projects/foo/repository/revisions.atom' => 'repositories#revisions', :id => 'foo', :format => 'atom'
should_route 'GET /projects/foo/repository/revisions/2457' => 'repositories#revision', :id => 'foo', :rev => '2457'
should_route 'GET /projects/foo/repository/revisions/2457/show' => 'repositories#show', :id => 'foo', :rev => '2457'
should_route 'GET /projects/foo/repository/revisions/2457/diff' => 'repositories#diff', :id => 'foo', :rev => '2457'
should_route "GET /projects/foo/repository/revisions/2457/show/#{@path_hash[:path]}" => 'repositories#show',
:id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/revisions/2457/diff/#{@path_hash[:path]}" => 'repositories#diff',
:id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/revisions/2457/entry/#{@path_hash[:path]}" => 'repositories#entry',
:id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/revisions/2457/raw/#{@path_hash[:path]}" => 'repositories#raw',
:id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/revisions/2457/annotate/#{@path_hash[:path]}" => 'repositories#annotate',
:id => 'foo', :rev => '2457', :path => @path_hash[:param]
end
def test_repositories_revisions_with_repository_id
should_route 'GET /projects/foo/repository/foo/revision' => 'repositories#revision', :id => 'foo', :repository_id => 'foo'
should_route 'GET /projects/foo/repository/foo/revisions' => 'repositories#revisions', :id => 'foo', :repository_id => 'foo'
should_route 'GET /projects/foo/repository/foo/revisions.atom' => 'repositories#revisions', :id => 'foo', :repository_id => 'foo', :format => 'atom'
should_route 'GET /projects/foo/repository/foo/revisions/2457' => 'repositories#revision', :id => 'foo', :repository_id => 'foo', :rev => '2457'
should_route 'GET /projects/foo/repository/foo/revisions/2457/show' => 'repositories#show', :id => 'foo', :repository_id => 'foo', :rev => '2457'
should_route 'GET /projects/foo/repository/foo/revisions/2457/diff' => 'repositories#diff', :id => 'foo', :repository_id => 'foo', :rev => '2457'
should_route "GET /projects/foo/repository/foo/revisions/2457/show/#{@path_hash[:path]}" => 'repositories#show',
:id => 'foo', :repository_id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/foo/revisions/2457/diff/#{@path_hash[:path]}" => 'repositories#diff',
:id => 'foo', :repository_id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/foo/revisions/2457/entry/#{@path_hash[:path]}" => 'repositories#entry',
:id => 'foo', :repository_id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/foo/revisions/2457/raw/#{@path_hash[:path]}" => 'repositories#raw',
:id => 'foo', :repository_id => 'foo', :rev => '2457', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/foo/revisions/2457/annotate/#{@path_hash[:path]}" => 'repositories#annotate',
:id => 'foo', :repository_id => 'foo', :rev => '2457', :path => @path_hash[:param]
end
def test_repositories_non_revisions_path
should_route 'GET /projects/foo/repository/changes' => 'repositories#changes', :id => 'foo'
should_route "GET /projects/foo/repository/changes/#{@path_hash[:path]}" => 'repositories#changes',
:id => 'foo', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/diff/#{@path_hash[:path]}" => 'repositories#diff',
:id => 'foo', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/browse/#{@path_hash[:path]}" => 'repositories#browse',
:id => 'foo', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/entry/#{@path_hash[:path]}" => 'repositories#entry',
:id => 'foo', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/raw/#{@path_hash[:path]}" => 'repositories#raw',
:id => 'foo', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/annotate/#{@path_hash[:path]}" => 'repositories#annotate',
:id => 'foo', :path => @path_hash[:param]
end
def test_repositories_non_revisions_path_with_repository_id
should_route 'GET /projects/foo/repository/svn/changes' => 'repositories#changes', :id => 'foo', :repository_id => 'svn'
should_route "GET /projects/foo/repository/svn/changes/#{@path_hash[:path]}" => 'repositories#changes',
:id => 'foo', :repository_id => 'svn', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/svn/diff/#{@path_hash[:path]}" => 'repositories#diff',
:id => 'foo', :repository_id => 'svn', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/svn/browse/#{@path_hash[:path]}" => 'repositories#browse',
:id => 'foo', :repository_id => 'svn', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/svn/entry/#{@path_hash[:path]}" => 'repositories#entry',
:id => 'foo', :repository_id => 'svn', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/svn/raw/#{@path_hash[:path]}" => 'repositories#raw',
:id => 'foo', :repository_id => 'svn', :path => @path_hash[:param]
should_route "GET /projects/foo/repository/svn/annotate/#{@path_hash[:path]}" => 'repositories#annotate',
:id => 'foo', :repository_id => 'svn', :path => @path_hash[:param]
end
def test_repositories_related_issues
should_route 'POST /projects/foo/repository/revisions/123/issues' => 'repositories#add_related_issue',
:id => 'foo', :rev => '123'
should_route 'DELETE /projects/foo/repository/revisions/123/issues/25' => 'repositories#remove_related_issue',
:id => 'foo', :rev => '123', :issue_id => '25'
end
def test_repositories_related_issues_with_repository_id
should_route 'POST /projects/foo/repository/svn/revisions/123/issues' => 'repositories#add_related_issue',
:id => 'foo', :repository_id => 'svn', :rev => '123'
should_route 'DELETE /projects/foo/repository/svn/revisions/123/issues/25' => 'repositories#remove_related_issue',
:id => 'foo', :repository_id => 'svn', :rev => '123', :issue_id => '25'
end
end

View file

@ -0,0 +1,33 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingRolesTest < Redmine::RoutingTest
def test_roles
should_route 'GET /roles' => 'roles#index'
should_route 'GET /roles/new' => 'roles#new'
should_route 'POST /roles' => 'roles#create'
should_route 'GET /roles/2/edit' => 'roles#edit', :id => '2'
should_route 'PUT /roles/2' => 'roles#update', :id => '2'
should_route 'DELETE /roles/2' => 'roles#destroy', :id => '2'
should_route 'GET /roles/permissions' => 'roles#permissions'
should_route 'POST /roles/permissions' => 'roles#permissions'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingSearchTest < Redmine::RoutingTest
def test_search
should_route 'GET /search' => 'search#index'
should_route 'GET /projects/foo/search' => 'search#index', :id => 'foo'
end
end

View file

@ -0,0 +1,29 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingSettingsTest < Redmine::RoutingTest
def test_settings
should_route 'GET /settings' => 'settings#index'
should_route 'GET /settings/edit' => 'settings#edit'
should_route 'POST /settings/edit' => 'settings#edit'
should_route 'GET /settings/plugin/testid' => 'settings#plugin', :id => 'testid'
should_route 'POST /settings/plugin/testid' => 'settings#plugin', :id => 'testid'
end
end

View file

@ -0,0 +1,27 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingSysTest < Redmine::RoutingTest
def test_sys
should_route 'GET /sys/projects' => 'sys#projects'
should_route 'POST /sys/projects/foo/repository' => 'sys#create_project_repository', :id => 'foo'
should_route 'GET /sys/fetch_changesets' => 'sys#fetch_changesets'
should_route 'POST /sys/fetch_changesets' => 'sys#fetch_changesets'
end
end

View file

@ -0,0 +1,61 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingTimelogsTest < Redmine::RoutingTest
def test_timelogs_global
should_route 'GET /time_entries' => 'timelog#index'
should_route 'GET /time_entries.csv' => 'timelog#index', :format => 'csv'
should_route 'GET /time_entries.atom' => 'timelog#index', :format => 'atom'
should_route 'GET /time_entries/new' => 'timelog#new'
should_route 'POST /time_entries/new' => 'timelog#new'
should_route 'POST /time_entries' => 'timelog#create'
should_route 'GET /time_entries/22/edit' => 'timelog#edit', :id => '22'
should_route 'PATCH /time_entries/22/edit' => 'timelog#edit', :id => '22'
should_route 'PATCH /time_entries/22' => 'timelog#update', :id => '22'
should_route 'DELETE /time_entries/22' => 'timelog#destroy', :id => '22'
end
def test_timelogs_scoped_under_project
should_route 'GET /projects/foo/time_entries' => 'timelog#index', :project_id => 'foo'
should_route 'GET /projects/foo/time_entries.csv' => 'timelog#index', :project_id => 'foo', :format => 'csv'
should_route 'GET /projects/foo/time_entries.atom' => 'timelog#index', :project_id => 'foo', :format => 'atom'
should_route 'GET /projects/foo/time_entries/new' => 'timelog#new', :project_id => 'foo'
should_route 'POST /projects/foo/time_entries' => 'timelog#create', :project_id => 'foo'
end
def test_timelogs_scoped_under_issues
should_route 'GET /issues/234/time_entries/new' => 'timelog#new', :issue_id => '234'
should_route 'POST /issues/234/time_entries' => 'timelog#create', :issue_id => '234'
end
def test_timelogs_report
should_route 'GET /time_entries/report' => 'timelog#report'
should_route 'GET /time_entries/report.csv' => 'timelog#report', :format => 'csv'
should_route 'GET /projects/foo/time_entries/report' => 'timelog#report', :project_id => 'foo'
should_route 'GET /projects/foo/time_entries/report.csv' => 'timelog#report', :project_id => 'foo', :format => 'csv'
end
def test_timelogs_bulk_edit
should_route 'GET /time_entries/bulk_edit' => 'timelog#bulk_edit'
should_route 'POST /time_entries/bulk_update' => 'timelog#bulk_update'
should_route 'DELETE /time_entries/destroy' => 'timelog#destroy'
end
end

View file

@ -0,0 +1,33 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingTrackersTest < Redmine::RoutingTest
def test_trackers
should_route 'GET /trackers' => 'trackers#index'
should_route 'GET /trackers/new' => 'trackers#new'
should_route 'POST /trackers' => 'trackers#create'
should_route 'GET /trackers/1/edit' => 'trackers#edit', :id => '1'
should_route 'PUT /trackers/1' => 'trackers#update', :id => '1'
should_route 'DELETE /trackers/1' => 'trackers#destroy', :id => '1'
should_route 'GET /trackers/fields' => 'trackers#fields'
should_route 'POST /trackers/fields' => 'trackers#fields'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingUsersTest < Redmine::RoutingTest
def test_users
should_route 'GET /users' => 'users#index'
should_route 'GET /users/new' => 'users#new'
should_route 'POST /users' => 'users#create'
should_route 'GET /users/44' => 'users#show', :id => '44'
should_route 'GET /users/current' => 'users#show', :id => 'current'
should_route 'GET /users/44/edit' => 'users#edit', :id => '44'
should_route 'PUT /users/44' => 'users#update', :id => '44'
should_route 'DELETE /users/44' => 'users#destroy', :id => '44'
end
end

View file

@ -0,0 +1,36 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingVersionsTest < Redmine::RoutingTest
def test_project_versions
should_route 'GET /projects/foo/roadmap' => 'versions#index', :project_id => 'foo'
should_route 'GET /projects/foo/versions/new' => 'versions#new', :project_id => 'foo'
should_route 'POST /projects/foo/versions' => 'versions#create', :project_id => 'foo'
should_route 'PUT /projects/foo/versions/close_completed' => 'versions#close_completed', :project_id => 'foo'
end
def test_versions
should_route 'GET /versions/1' => 'versions#show', :id => '1'
should_route 'GET /versions/1/edit' => 'versions#edit', :id => '1'
should_route 'PUT /versions/1' => 'versions#update', :id => '1'
should_route 'DELETE /versions/1' => 'versions#destroy', :id => '1'
should_route 'POST /versions/1/status_by' => 'versions#status_by', :id => '1'
end
end

View file

@ -0,0 +1,31 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingWatchersTest < Redmine::RoutingTest
def test_watchers
should_route 'GET /watchers/new' => 'watchers#new'
should_route 'POST /watchers/append' => 'watchers#append'
should_route 'POST /watchers' => 'watchers#create'
should_route 'DELETE /watchers' => 'watchers#destroy'
should_route 'GET /watchers/autocomplete_for_user' => 'watchers#autocomplete_for_user'
should_route 'POST /watchers/watch' => 'watchers#watch'
should_route 'DELETE /watchers/watch' => 'watchers#unwatch'
end
end

View file

@ -0,0 +1,25 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingWelcomeTest < Redmine::RoutingTest
def test_welcome
should_route 'GET /' => 'welcome#index'
should_route 'GET /robots.txt' => 'welcome#robots'
end
end

View file

@ -0,0 +1,62 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingWikiTest < Redmine::RoutingTest
def test_wiki
should_route 'GET /projects/foo/wiki' => 'wiki#show', :project_id => 'foo'
should_route 'GET /projects/foo/wiki/index' => 'wiki#index', :project_id => 'foo'
should_route 'GET /projects/foo/wiki/date_index' => 'wiki#date_index', :project_id => 'foo'
should_route 'GET /projects/foo/wiki/export' => 'wiki#export', :project_id => 'foo'
should_route 'GET /projects/foo/wiki/export.pdf' => 'wiki#export', :project_id => 'foo', :format => 'pdf'
end
def test_wiki_pages
should_route 'GET /projects/foo/wiki/page' => 'wiki#show', :project_id => 'foo', :id => 'page'
should_route 'GET /projects/foo/wiki/page.pdf' => 'wiki#show', :project_id => 'foo', :id => 'page', :format => 'pdf'
should_route 'GET /projects/foo/wiki/new' => 'wiki#new', :project_id => 'foo'
should_route 'POST /projects/foo/wiki/new' => 'wiki#new', :project_id => 'foo'
should_route 'GET /projects/foo/wiki/page/edit' => 'wiki#edit', :project_id => 'foo', :id => 'page'
should_route 'PUT /projects/foo/wiki/page' => 'wiki#update', :project_id => 'foo', :id => 'page'
should_route 'DELETE /projects/foo/wiki/page' => 'wiki#destroy', :project_id => 'foo', :id => 'page'
should_route 'GET /projects/foo/wiki/page/history' => 'wiki#history', :project_id => 'foo', :id => 'page'
should_route 'GET /projects/foo/wiki/page/diff' => 'wiki#diff', :project_id => 'foo', :id => 'page'
should_route 'GET /projects/foo/wiki/page/rename' => 'wiki#rename', :project_id => 'foo', :id => 'page'
should_route 'POST /projects/foo/wiki/page/rename' => 'wiki#rename', :project_id => 'foo', :id => 'page'
should_route 'POST /projects/foo/wiki/page/protect' => 'wiki#protect', :project_id => 'foo', :id => 'page'
should_route 'POST /projects/foo/wiki/page/add_attachment' => 'wiki#add_attachment', :project_id => 'foo', :id => 'page'
should_route 'POST /projects/foo/wiki/page/preview' => 'wiki#preview', :project_id => 'foo', :id => 'page'
should_route 'PUT /projects/foo/wiki/page/preview' => 'wiki#preview', :project_id => 'foo', :id => 'page'
# Make sure we don't route wiki page sub-uris to let plugins handle them
assert_raise(Minitest::Assertion) do
assert_recognizes({}, {:method => 'get', :path => "/projects/foo/wiki/page/whatever"})
end
end
def test_wiki_page_versions
should_route 'GET /projects/foo/wiki/page/2' => 'wiki#show', :project_id => 'foo', :id => 'page', :version => '2'
should_route 'GET /projects/foo/wiki/page/2/diff' => 'wiki#diff', :project_id => 'foo', :id => 'page', :version => '2'
should_route 'GET /projects/foo/wiki/page/2/annotate' => 'wiki#annotate', :project_id => 'foo', :id => 'page', :version => '2'
should_route 'DELETE /projects/foo/wiki/page/2' => 'wiki#destroy_version', :project_id => 'foo', :id => 'page', :version => '2'
end
end

View file

@ -0,0 +1,27 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingWikisTest < Redmine::RoutingTest
def test_wikis
should_route 'POST /projects/foo/wiki' => 'wikis#edit', :id => 'foo'
should_route 'GET /projects/foo/wiki/destroy' => 'wikis#destroy', :id => 'foo'
should_route 'POST /projects/foo/wiki/destroy' => 'wikis#destroy', :id => 'foo'
end
end

View file

@ -0,0 +1,32 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../test_helper', __FILE__)
class RoutingWorkflowsTest < Redmine::RoutingTest
def test_workflows
should_route 'GET /workflows' => 'workflows#index'
should_route 'GET /workflows/edit' => 'workflows#edit'
should_route 'POST /workflows/edit' => 'workflows#edit'
should_route 'GET /workflows/permissions' => 'workflows#permissions'
should_route 'POST /workflows/permissions' => 'workflows#permissions'
should_route 'GET /workflows/copy' => 'workflows#copy'
should_route 'POST /workflows/copy' => 'workflows#copy'
end
end

View file

@ -0,0 +1,99 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class SessionsTest < Redmine::IntegrationTest
fixtures :users, :email_addresses, :roles
def setup
Rails.application.config.redmine_verify_sessions = true
end
def teardown
Rails.application.config.redmine_verify_sessions = false
end
def test_change_password_kills_sessions
log_user('jsmith', 'jsmith')
jsmith = User.find(2)
jsmith.password = "somenewpassword"
jsmith.save!
get '/my/account'
assert_response 302
assert flash[:error].match(/Your session has expired/)
end
def test_lock_user_kills_sessions
log_user('jsmith', 'jsmith')
jsmith = User.find(2)
assert jsmith.lock!
assert jsmith.activate!
get '/my/account'
assert_response 302
assert flash[:error].match(/Your session has expired/)
end
def test_update_user_does_not_kill_sessions
log_user('jsmith', 'jsmith')
jsmith = User.find(2)
jsmith.firstname = 'Robert'
jsmith.save!
get '/my/account'
assert_response 200
end
def test_change_password_generates_a_new_token_for_current_session
log_user('jsmith', 'jsmith')
assert_not_nil token = session[:tk]
get '/my/password'
assert_response 200
post '/my/password', :params => {
:password => 'jsmith',
:new_password => 'secret123',
:new_password_confirmation => 'secret123'
}
assert_response 302
assert_not_equal token, session[:tk]
get '/my/account'
assert_response 200
end
def test_simultaneous_sessions_should_be_valid
first = open_session do |session|
session.post "/login", :params => {:username => 'jsmith', :password => 'jsmith'}
end
other = open_session do |session|
session.post "/login", :params => {:username => 'jsmith', :password => 'jsmith'}
end
first.get '/my/account'
assert_equal 200, first.response.response_code
first.post '/logout'
other.get '/my/account'
assert_equal 200, other.response.response_code
end
end

View file

@ -0,0 +1,199 @@
require File.expand_path('../../test_helper', __FILE__)
class SudoModeTest < Redmine::IntegrationTest
fixtures :projects, :members, :member_roles, :roles, :users, :email_addresses
def setup
Redmine::SudoMode.stubs(:enabled?).returns(true)
end
def teardown
travel_back
end
def test_sudo_mode_should_be_active_after_login
log_user("admin", "admin")
get "/users/new"
assert_response :success
post "/users", :params => {
:user => { :login => "psmith", :firstname => "Paul",
:lastname => "Smith", :mail => "psmith@somenet.foo",
:language => "en", :password => "psmith09",
:password_confirmation => "psmith09" }
}
assert_response 302
user = User.find_by_login("psmith")
assert_kind_of User, user
end
def test_add_user
log_user("admin", "admin")
expire_sudo_mode!
get "/users/new"
assert_response :success
post "/users", :params => {
:user => { :login => "psmith", :firstname => "Paul",
:lastname => "Smith", :mail => "psmith@somenet.foo",
:language => "en", :password => "psmith09",
:password_confirmation => "psmith09" }
}
assert_response :success
assert_nil User.find_by_login("psmith")
assert_select 'input[name=?][value=?]', 'user[login]', 'psmith'
assert_select 'input[name=?][value=?]', 'user[firstname]', 'Paul'
post "/users", :params => {
:user => { :login => "psmith", :firstname => "Paul",
:lastname => "Smith", :mail => "psmith@somenet.foo",
:language => "en", :password => "psmith09",
:password_confirmation => "psmith09" },
:sudo_password => 'admin'
}
assert_response 302
user = User.find_by_login("psmith")
assert_kind_of User, user
end
def test_create_member_xhr
log_user 'admin', 'admin'
expire_sudo_mode!
get '/projects/ecookbook/settings/members'
assert_response :success
assert_no_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}}, :xhr => true
end
assert_no_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}, sudo_password: ''}, :xhr => true
end
assert_no_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}, sudo_password: 'wrong'}, :xhr => true
end
assert_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}, sudo_password: 'admin'}, :xhr => true
end
assert User.find(7).member_of?(Project.find(1))
end
def test_create_member
log_user 'admin', 'admin'
expire_sudo_mode!
get '/projects/ecookbook/settings/members'
assert_response :success
assert_no_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}}
end
assert_no_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}, sudo_password: ''}
end
assert_no_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}, sudo_password: 'wrong'}
end
assert_difference 'Member.count' do
post '/projects/ecookbook/memberships', :params => {membership: {role_ids: [1], user_id: 7}, sudo_password: 'admin'}
end
assert_redirected_to '/projects/ecookbook/settings/members'
assert User.find(7).member_of?(Project.find(1))
end
def test_create_role
log_user 'admin', 'admin'
expire_sudo_mode!
get '/roles'
assert_response :success
get '/roles/new'
assert_response :success
post '/roles', :params => {role: { }}
assert_response :success
assert_select 'h2', 'Confirm your password to continue'
assert_select 'form[action="/roles"]'
assert_select '#flash_error', 0
post '/roles', :params => {role: { name: 'new role', issues_visibility: 'all' }}
assert_response :success
assert_select 'h2', 'Confirm your password to continue'
assert_select 'form[action="/roles"]'
assert_select 'input[type=hidden][name=?][value=?]', 'role[name]', 'new role'
assert_select '#flash_error', 0
post '/roles', :params => {role: { name: 'new role', issues_visibility: 'all' }, sudo_password: 'wrong'}
assert_response :success
assert_select 'h2', 'Confirm your password to continue'
assert_select 'form[action="/roles"]'
assert_select 'input[type=hidden][name=?][value=?]', 'role[name]', 'new role'
assert_select '#flash_error'
assert_difference 'Role.count' do
post '/roles', :params => {role: { name: 'new role', issues_visibility: 'all', assignable: '1', permissions: %w(view_calendar) }, sudo_password: 'admin'}
end
assert_redirected_to '/roles'
end
def test_update_email_address
log_user 'jsmith', 'jsmith'
expire_sudo_mode!
get '/my/account'
assert_response :success
post '/my/account', :params => {user: { mail: 'newmail@test.com' }}
assert_response :success
assert_select 'h2', 'Confirm your password to continue'
assert_select 'form[action="/my/account"]'
assert_select 'input[type=hidden][name=?][value=?]', 'user[mail]', 'newmail@test.com'
assert_select '#flash_error', 0
# wrong password
post '/my/account', :params => {user: { mail: 'newmail@test.com' }, sudo_password: 'wrong'}
assert_response :success
assert_select 'h2', 'Confirm your password to continue'
assert_select 'form[action="/my/account"]'
assert_select 'input[type=hidden][name=?][value=?]', 'user[mail]', 'newmail@test.com'
assert_select '#flash_error'
# correct password
post '/my/account', :params => {user: { mail: 'newmail@test.com' }, sudo_password: 'jsmith'}
assert_redirected_to '/my/account'
assert_equal 'newmail@test.com', User.find_by_login('jsmith').mail
# sudo mode should now be active and not require password again
post '/my/account', :params => {user: { mail: 'even.newer.mail@test.com' }}
assert_redirected_to '/my/account'
assert_equal 'even.newer.mail@test.com', User.find_by_login('jsmith').mail
end
def test_sudo_mode_should_skip_api_requests
with_settings :rest_api_enabled => '1' do
assert_difference('User.count') do
post '/users.json', :params => {
:user => {
:login => 'foo', :firstname => 'Firstname', :lastname => 'Lastname',
:mail => 'foo@example.net', :password => 'secret123',
:mail_notification => 'only_assigned'
}
},
:headers => credentials('admin')
assert_response :created
end
end
end
private
# sudo mode is active after sign, let it expire by advancing the time
def expire_sudo_mode!
travel_to 20.minutes.from_now
end
end

View file

@ -0,0 +1,31 @@
# Redmine - project management software
# Copyright (C) 2006-2017 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../test_helper', __FILE__)
class UsersTest < Redmine::IntegrationTest
fixtures :users, :email_addresses
def test_destroy_should_not_accept_get_requests
log_user('admin', 'admin')
assert_no_difference 'User.count' do
get '/users/destroy/2'
assert_response 404
end
end
end