##// END OF EJS Templates
Removes RJS from UsersController....
Jean-Philippe Lang -
r9876:47e496f049d7
parent child
Show More
@@ -0,0 +1,1
1 Element.update('tab-content-memberships', '<%= escape_javascript(render :partial => 'users/memberships') %>');
@@ -0,0 +1,6
1 <% if @membership.valid? %>
2 Element.update("tab-content-memberships", '<%= escape_javascript(render :partial => 'users/memberships') %>');
3 new Effect.Highlight("member-<%= @membership.id %>")
4 <% else %>
5 alert('<%= escape_javascript l(:notice_failed_to_save_members, :errors => @membership.errors.full_messages.join(', ')) %>');
6 <% end %>
@@ -1,227 +1,214
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class UsersController < ApplicationController
18 class UsersController < ApplicationController
19 layout 'admin'
19 layout 'admin'
20
20
21 before_filter :require_admin, :except => :show
21 before_filter :require_admin, :except => :show
22 before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
22 before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership]
23 accept_api_auth :index, :show, :create, :update, :destroy
23 accept_api_auth :index, :show, :create, :update, :destroy
24
24
25 helper :sort
25 helper :sort
26 include SortHelper
26 include SortHelper
27 helper :custom_fields
27 helper :custom_fields
28 include CustomFieldsHelper
28 include CustomFieldsHelper
29
29
30 def index
30 def index
31 sort_init 'login', 'asc'
31 sort_init 'login', 'asc'
32 sort_update %w(login firstname lastname mail admin created_on last_login_on)
32 sort_update %w(login firstname lastname mail admin created_on last_login_on)
33
33
34 case params[:format]
34 case params[:format]
35 when 'xml', 'json'
35 when 'xml', 'json'
36 @offset, @limit = api_offset_and_limit
36 @offset, @limit = api_offset_and_limit
37 else
37 else
38 @limit = per_page_option
38 @limit = per_page_option
39 end
39 end
40
40
41 @status = params[:status] || 1
41 @status = params[:status] || 1
42
42
43 scope = User.logged.status(@status)
43 scope = User.logged.status(@status)
44 scope = scope.like(params[:name]) if params[:name].present?
44 scope = scope.like(params[:name]) if params[:name].present?
45 scope = scope.in_group(params[:group_id]) if params[:group_id].present?
45 scope = scope.in_group(params[:group_id]) if params[:group_id].present?
46
46
47 @user_count = scope.count
47 @user_count = scope.count
48 @user_pages = Paginator.new self, @user_count, @limit, params['page']
48 @user_pages = Paginator.new self, @user_count, @limit, params['page']
49 @offset ||= @user_pages.current.offset
49 @offset ||= @user_pages.current.offset
50 @users = scope.find :all,
50 @users = scope.find :all,
51 :order => sort_clause,
51 :order => sort_clause,
52 :limit => @limit,
52 :limit => @limit,
53 :offset => @offset
53 :offset => @offset
54
54
55 respond_to do |format|
55 respond_to do |format|
56 format.html {
56 format.html {
57 @groups = Group.all.sort
57 @groups = Group.all.sort
58 render :layout => !request.xhr?
58 render :layout => !request.xhr?
59 }
59 }
60 format.api
60 format.api
61 end
61 end
62 end
62 end
63
63
64 def show
64 def show
65 # show projects based on current user visibility
65 # show projects based on current user visibility
66 @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current))
66 @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current))
67
67
68 events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
68 events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
69 @events_by_day = events.group_by(&:event_date)
69 @events_by_day = events.group_by(&:event_date)
70
70
71 unless User.current.admin?
71 unless User.current.admin?
72 if !@user.active? || (@user != User.current && @memberships.empty? && events.empty?)
72 if !@user.active? || (@user != User.current && @memberships.empty? && events.empty?)
73 render_404
73 render_404
74 return
74 return
75 end
75 end
76 end
76 end
77
77
78 respond_to do |format|
78 respond_to do |format|
79 format.html { render :layout => 'base' }
79 format.html { render :layout => 'base' }
80 format.api
80 format.api
81 end
81 end
82 end
82 end
83
83
84 def new
84 def new
85 @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
85 @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
86 @auth_sources = AuthSource.find(:all)
86 @auth_sources = AuthSource.find(:all)
87 end
87 end
88
88
89 def create
89 def create
90 @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
90 @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option)
91 @user.safe_attributes = params[:user]
91 @user.safe_attributes = params[:user]
92 @user.admin = params[:user][:admin] || false
92 @user.admin = params[:user][:admin] || false
93 @user.login = params[:user][:login]
93 @user.login = params[:user][:login]
94 @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
94 @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id
95
95
96 if @user.save
96 if @user.save
97 @user.pref.attributes = params[:pref]
97 @user.pref.attributes = params[:pref]
98 @user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
98 @user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
99 @user.pref.save
99 @user.pref.save
100 @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
100 @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
101
101
102 Mailer.account_information(@user, params[:user][:password]).deliver if params[:send_information]
102 Mailer.account_information(@user, params[:user][:password]).deliver if params[:send_information]
103
103
104 respond_to do |format|
104 respond_to do |format|
105 format.html {
105 format.html {
106 flash[:notice] = l(:notice_user_successful_create, :id => view_context.link_to(@user.login, user_path(@user)))
106 flash[:notice] = l(:notice_user_successful_create, :id => view_context.link_to(@user.login, user_path(@user)))
107 redirect_to(params[:continue] ?
107 redirect_to(params[:continue] ?
108 {:controller => 'users', :action => 'new'} :
108 {:controller => 'users', :action => 'new'} :
109 {:controller => 'users', :action => 'edit', :id => @user}
109 {:controller => 'users', :action => 'edit', :id => @user}
110 )
110 )
111 }
111 }
112 format.api { render :action => 'show', :status => :created, :location => user_url(@user) }
112 format.api { render :action => 'show', :status => :created, :location => user_url(@user) }
113 end
113 end
114 else
114 else
115 @auth_sources = AuthSource.find(:all)
115 @auth_sources = AuthSource.find(:all)
116 # Clear password input
116 # Clear password input
117 @user.password = @user.password_confirmation = nil
117 @user.password = @user.password_confirmation = nil
118
118
119 respond_to do |format|
119 respond_to do |format|
120 format.html { render :action => 'new' }
120 format.html { render :action => 'new' }
121 format.api { render_validation_errors(@user) }
121 format.api { render_validation_errors(@user) }
122 end
122 end
123 end
123 end
124 end
124 end
125
125
126 def edit
126 def edit
127 @auth_sources = AuthSource.find(:all)
127 @auth_sources = AuthSource.find(:all)
128 @membership ||= Member.new
128 @membership ||= Member.new
129 end
129 end
130
130
131 def update
131 def update
132 @user.admin = params[:user][:admin] if params[:user][:admin]
132 @user.admin = params[:user][:admin] if params[:user][:admin]
133 @user.login = params[:user][:login] if params[:user][:login]
133 @user.login = params[:user][:login] if params[:user][:login]
134 if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
134 if params[:user][:password].present? && (@user.auth_source_id.nil? || params[:user][:auth_source_id].blank?)
135 @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation]
135 @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation]
136 end
136 end
137 @user.safe_attributes = params[:user]
137 @user.safe_attributes = params[:user]
138 # Was the account actived ? (do it before User#save clears the change)
138 # Was the account actived ? (do it before User#save clears the change)
139 was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
139 was_activated = (@user.status_change == [User::STATUS_REGISTERED, User::STATUS_ACTIVE])
140 # TODO: Similar to My#account
140 # TODO: Similar to My#account
141 @user.pref.attributes = params[:pref]
141 @user.pref.attributes = params[:pref]
142 @user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
142 @user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
143
143
144 if @user.save
144 if @user.save
145 @user.pref.save
145 @user.pref.save
146 @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
146 @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
147
147
148 if was_activated
148 if was_activated
149 Mailer.account_activated(@user).deliver
149 Mailer.account_activated(@user).deliver
150 elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
150 elsif @user.active? && params[:send_information] && !params[:user][:password].blank? && @user.auth_source_id.nil?
151 Mailer.account_information(@user, params[:user][:password]).deliver
151 Mailer.account_information(@user, params[:user][:password]).deliver
152 end
152 end
153
153
154 respond_to do |format|
154 respond_to do |format|
155 format.html {
155 format.html {
156 flash[:notice] = l(:notice_successful_update)
156 flash[:notice] = l(:notice_successful_update)
157 redirect_to_referer_or edit_user_path(@user)
157 redirect_to_referer_or edit_user_path(@user)
158 }
158 }
159 format.api { render_api_ok }
159 format.api { render_api_ok }
160 end
160 end
161 else
161 else
162 @auth_sources = AuthSource.find(:all)
162 @auth_sources = AuthSource.find(:all)
163 @membership ||= Member.new
163 @membership ||= Member.new
164 # Clear password input
164 # Clear password input
165 @user.password = @user.password_confirmation = nil
165 @user.password = @user.password_confirmation = nil
166
166
167 respond_to do |format|
167 respond_to do |format|
168 format.html { render :action => :edit }
168 format.html { render :action => :edit }
169 format.api { render_validation_errors(@user) }
169 format.api { render_validation_errors(@user) }
170 end
170 end
171 end
171 end
172 end
172 end
173
173
174 def destroy
174 def destroy
175 @user.destroy
175 @user.destroy
176 respond_to do |format|
176 respond_to do |format|
177 format.html { redirect_to_referer_or(users_url) }
177 format.html { redirect_to_referer_or(users_url) }
178 format.api { render_api_ok }
178 format.api { render_api_ok }
179 end
179 end
180 end
180 end
181
181
182 def edit_membership
182 def edit_membership
183 @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
183 @membership = Member.edit_membership(params[:membership_id], params[:membership], @user)
184 @membership.save
184 @membership.save
185 respond_to do |format|
185 respond_to do |format|
186 if @membership.valid?
186 format.html { redirect_to :controller => 'users', :action => 'edit', :id => @user, :tab => 'memberships' }
187 format.html { redirect_to :controller => 'users', :action => 'edit', :id => @user, :tab => 'memberships' }
187 format.js
188 format.js {
189 render(:update) {|page|
190 page.replace_html "tab-content-memberships", :partial => 'users/memberships'
191 page.visual_effect(:highlight, "member-#{@membership.id}")
192 }
193 }
194 else
195 format.js {
196 render(:update) {|page|
197 page.alert(l(:notice_failed_to_save_members, :errors => @membership.errors.full_messages.join(', ')))
198 }
199 }
200 end
201 end
188 end
202 end
189 end
203
190
204 def destroy_membership
191 def destroy_membership
205 @membership = Member.find(params[:membership_id])
192 @membership = Member.find(params[:membership_id])
206 if @membership.deletable?
193 if @membership.deletable?
207 @membership.destroy
194 @membership.destroy
208 end
195 end
209 respond_to do |format|
196 respond_to do |format|
210 format.html { redirect_to :controller => 'users', :action => 'edit', :id => @user, :tab => 'memberships' }
197 format.html { redirect_to :controller => 'users', :action => 'edit', :id => @user, :tab => 'memberships' }
211 format.js { render(:update) {|page| page.replace_html "tab-content-memberships", :partial => 'users/memberships'} }
198 format.js
212 end
199 end
213 end
200 end
214
201
215 private
202 private
216
203
217 def find_user
204 def find_user
218 if params[:id] == 'current'
205 if params[:id] == 'current'
219 require_login || return
206 require_login || return
220 @user = User.current
207 @user = User.current
221 else
208 else
222 @user = User.find(params[:id])
209 @user = User.find(params[:id])
223 end
210 end
224 rescue ActiveRecord::RecordNotFound
211 rescue ActiveRecord::RecordNotFound
225 render_404
212 render_404
226 end
213 end
227 end
214 end
@@ -1,415 +1,425
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19 require 'users_controller'
19 require 'users_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class UsersController; def rescue_action(e) raise e end; end
22 class UsersController; def rescue_action(e) raise e end; end
23
23
24 class UsersControllerTest < ActionController::TestCase
24 class UsersControllerTest < ActionController::TestCase
25 include Redmine::I18n
25 include Redmine::I18n
26
26
27 fixtures :users, :projects, :members, :member_roles, :roles,
27 fixtures :users, :projects, :members, :member_roles, :roles,
28 :custom_fields, :custom_values, :groups_users,
28 :custom_fields, :custom_values, :groups_users,
29 :auth_sources
29 :auth_sources
30
30
31 def setup
31 def setup
32 @controller = UsersController.new
32 @controller = UsersController.new
33 @request = ActionController::TestRequest.new
33 @request = ActionController::TestRequest.new
34 @response = ActionController::TestResponse.new
34 @response = ActionController::TestResponse.new
35 User.current = nil
35 User.current = nil
36 @request.session[:user_id] = 1 # admin
36 @request.session[:user_id] = 1 # admin
37 end
37 end
38
38
39 def test_index
39 def test_index
40 get :index
40 get :index
41 assert_response :success
41 assert_response :success
42 assert_template 'index'
42 assert_template 'index'
43 end
43 end
44
44
45 def test_index
45 def test_index
46 get :index
46 get :index
47 assert_response :success
47 assert_response :success
48 assert_template 'index'
48 assert_template 'index'
49 assert_not_nil assigns(:users)
49 assert_not_nil assigns(:users)
50 # active users only
50 # active users only
51 assert_nil assigns(:users).detect {|u| !u.active?}
51 assert_nil assigns(:users).detect {|u| !u.active?}
52 end
52 end
53
53
54 def test_index_with_status_filter
54 def test_index_with_status_filter
55 get :index, :status => 3
55 get :index, :status => 3
56 assert_response :success
56 assert_response :success
57 assert_template 'index'
57 assert_template 'index'
58 assert_not_nil assigns(:users)
58 assert_not_nil assigns(:users)
59 assert_equal [3], assigns(:users).map(&:status).uniq
59 assert_equal [3], assigns(:users).map(&:status).uniq
60 end
60 end
61
61
62 def test_index_with_name_filter
62 def test_index_with_name_filter
63 get :index, :name => 'john'
63 get :index, :name => 'john'
64 assert_response :success
64 assert_response :success
65 assert_template 'index'
65 assert_template 'index'
66 users = assigns(:users)
66 users = assigns(:users)
67 assert_not_nil users
67 assert_not_nil users
68 assert_equal 1, users.size
68 assert_equal 1, users.size
69 assert_equal 'John', users.first.firstname
69 assert_equal 'John', users.first.firstname
70 end
70 end
71
71
72 def test_index_with_group_filter
72 def test_index_with_group_filter
73 get :index, :group_id => '10'
73 get :index, :group_id => '10'
74 assert_response :success
74 assert_response :success
75 assert_template 'index'
75 assert_template 'index'
76 users = assigns(:users)
76 users = assigns(:users)
77 assert users.any?
77 assert users.any?
78 assert_equal([], (users - Group.find(10).users))
78 assert_equal([], (users - Group.find(10).users))
79 assert_select 'select[name=group_id]' do
79 assert_select 'select[name=group_id]' do
80 assert_select 'option[value=10][selected=selected]'
80 assert_select 'option[value=10][selected=selected]'
81 end
81 end
82 end
82 end
83
83
84 def test_show
84 def test_show
85 @request.session[:user_id] = nil
85 @request.session[:user_id] = nil
86 get :show, :id => 2
86 get :show, :id => 2
87 assert_response :success
87 assert_response :success
88 assert_template 'show'
88 assert_template 'show'
89 assert_not_nil assigns(:user)
89 assert_not_nil assigns(:user)
90
90
91 assert_tag 'li', :content => /Phone number/
91 assert_tag 'li', :content => /Phone number/
92 end
92 end
93
93
94 def test_show_should_not_display_hidden_custom_fields
94 def test_show_should_not_display_hidden_custom_fields
95 @request.session[:user_id] = nil
95 @request.session[:user_id] = nil
96 UserCustomField.find_by_name('Phone number').update_attribute :visible, false
96 UserCustomField.find_by_name('Phone number').update_attribute :visible, false
97 get :show, :id => 2
97 get :show, :id => 2
98 assert_response :success
98 assert_response :success
99 assert_template 'show'
99 assert_template 'show'
100 assert_not_nil assigns(:user)
100 assert_not_nil assigns(:user)
101
101
102 assert_no_tag 'li', :content => /Phone number/
102 assert_no_tag 'li', :content => /Phone number/
103 end
103 end
104
104
105 def test_show_should_not_fail_when_custom_values_are_nil
105 def test_show_should_not_fail_when_custom_values_are_nil
106 user = User.find(2)
106 user = User.find(2)
107
107
108 # Create a custom field to illustrate the issue
108 # Create a custom field to illustrate the issue
109 custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
109 custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
110 custom_value = user.custom_values.build(:custom_field => custom_field).save!
110 custom_value = user.custom_values.build(:custom_field => custom_field).save!
111
111
112 get :show, :id => 2
112 get :show, :id => 2
113 assert_response :success
113 assert_response :success
114 end
114 end
115
115
116 def test_show_inactive
116 def test_show_inactive
117 @request.session[:user_id] = nil
117 @request.session[:user_id] = nil
118 get :show, :id => 5
118 get :show, :id => 5
119 assert_response 404
119 assert_response 404
120 end
120 end
121
121
122 def test_show_should_not_reveal_users_with_no_visible_activity_or_project
122 def test_show_should_not_reveal_users_with_no_visible_activity_or_project
123 @request.session[:user_id] = nil
123 @request.session[:user_id] = nil
124 get :show, :id => 9
124 get :show, :id => 9
125 assert_response 404
125 assert_response 404
126 end
126 end
127
127
128 def test_show_inactive_by_admin
128 def test_show_inactive_by_admin
129 @request.session[:user_id] = 1
129 @request.session[:user_id] = 1
130 get :show, :id => 5
130 get :show, :id => 5
131 assert_response 200
131 assert_response 200
132 assert_not_nil assigns(:user)
132 assert_not_nil assigns(:user)
133 end
133 end
134
134
135 def test_show_displays_memberships_based_on_project_visibility
135 def test_show_displays_memberships_based_on_project_visibility
136 @request.session[:user_id] = 1
136 @request.session[:user_id] = 1
137 get :show, :id => 2
137 get :show, :id => 2
138 assert_response :success
138 assert_response :success
139 memberships = assigns(:memberships)
139 memberships = assigns(:memberships)
140 assert_not_nil memberships
140 assert_not_nil memberships
141 project_ids = memberships.map(&:project_id)
141 project_ids = memberships.map(&:project_id)
142 assert project_ids.include?(2) #private project admin can see
142 assert project_ids.include?(2) #private project admin can see
143 end
143 end
144
144
145 def test_show_current_should_require_authentication
145 def test_show_current_should_require_authentication
146 @request.session[:user_id] = nil
146 @request.session[:user_id] = nil
147 get :show, :id => 'current'
147 get :show, :id => 'current'
148 assert_response 302
148 assert_response 302
149 end
149 end
150
150
151 def test_show_current
151 def test_show_current
152 @request.session[:user_id] = 2
152 @request.session[:user_id] = 2
153 get :show, :id => 'current'
153 get :show, :id => 'current'
154 assert_response :success
154 assert_response :success
155 assert_template 'show'
155 assert_template 'show'
156 assert_equal User.find(2), assigns(:user)
156 assert_equal User.find(2), assigns(:user)
157 end
157 end
158
158
159 def test_new
159 def test_new
160 get :new
160 get :new
161 assert_response :success
161 assert_response :success
162 assert_template :new
162 assert_template :new
163 assert assigns(:user)
163 assert assigns(:user)
164 end
164 end
165
165
166 def test_create
166 def test_create
167 Setting.bcc_recipients = '1'
167 Setting.bcc_recipients = '1'
168
168
169 assert_difference 'User.count' do
169 assert_difference 'User.count' do
170 assert_difference 'ActionMailer::Base.deliveries.size' do
170 assert_difference 'ActionMailer::Base.deliveries.size' do
171 post :create,
171 post :create,
172 :user => {
172 :user => {
173 :firstname => 'John',
173 :firstname => 'John',
174 :lastname => 'Doe',
174 :lastname => 'Doe',
175 :login => 'jdoe',
175 :login => 'jdoe',
176 :password => 'secret',
176 :password => 'secret',
177 :password_confirmation => 'secret',
177 :password_confirmation => 'secret',
178 :mail => 'jdoe@gmail.com',
178 :mail => 'jdoe@gmail.com',
179 :mail_notification => 'none'
179 :mail_notification => 'none'
180 },
180 },
181 :send_information => '1'
181 :send_information => '1'
182 end
182 end
183 end
183 end
184
184
185 user = User.first(:order => 'id DESC')
185 user = User.first(:order => 'id DESC')
186 assert_redirected_to :controller => 'users', :action => 'edit', :id => user.id
186 assert_redirected_to :controller => 'users', :action => 'edit', :id => user.id
187
187
188 assert_equal 'John', user.firstname
188 assert_equal 'John', user.firstname
189 assert_equal 'Doe', user.lastname
189 assert_equal 'Doe', user.lastname
190 assert_equal 'jdoe', user.login
190 assert_equal 'jdoe', user.login
191 assert_equal 'jdoe@gmail.com', user.mail
191 assert_equal 'jdoe@gmail.com', user.mail
192 assert_equal 'none', user.mail_notification
192 assert_equal 'none', user.mail_notification
193 assert user.check_password?('secret')
193 assert user.check_password?('secret')
194
194
195 mail = ActionMailer::Base.deliveries.last
195 mail = ActionMailer::Base.deliveries.last
196 assert_not_nil mail
196 assert_not_nil mail
197 assert_equal [user.mail], mail.bcc
197 assert_equal [user.mail], mail.bcc
198 assert_mail_body_match 'secret', mail
198 assert_mail_body_match 'secret', mail
199 end
199 end
200
200
201 def test_create_with_preferences
201 def test_create_with_preferences
202 assert_difference 'User.count' do
202 assert_difference 'User.count' do
203 post :create,
203 post :create,
204 :user => {
204 :user => {
205 :firstname => 'John',
205 :firstname => 'John',
206 :lastname => 'Doe',
206 :lastname => 'Doe',
207 :login => 'jdoe',
207 :login => 'jdoe',
208 :password => 'secret',
208 :password => 'secret',
209 :password_confirmation => 'secret',
209 :password_confirmation => 'secret',
210 :mail => 'jdoe@gmail.com',
210 :mail => 'jdoe@gmail.com',
211 :mail_notification => 'none'
211 :mail_notification => 'none'
212 },
212 },
213 :pref => {
213 :pref => {
214 'hide_mail' => '1',
214 'hide_mail' => '1',
215 'time_zone' => 'Paris',
215 'time_zone' => 'Paris',
216 'comments_sorting' => 'desc',
216 'comments_sorting' => 'desc',
217 'warn_on_leaving_unsaved' => '0'
217 'warn_on_leaving_unsaved' => '0'
218 }
218 }
219 end
219 end
220 user = User.first(:order => 'id DESC')
220 user = User.first(:order => 'id DESC')
221 assert_equal 'jdoe', user.login
221 assert_equal 'jdoe', user.login
222 assert_equal true, user.pref.hide_mail
222 assert_equal true, user.pref.hide_mail
223 assert_equal 'Paris', user.pref.time_zone
223 assert_equal 'Paris', user.pref.time_zone
224 assert_equal 'desc', user.pref[:comments_sorting]
224 assert_equal 'desc', user.pref[:comments_sorting]
225 assert_equal '0', user.pref[:warn_on_leaving_unsaved]
225 assert_equal '0', user.pref[:warn_on_leaving_unsaved]
226 end
226 end
227
227
228 def test_create_with_failure
228 def test_create_with_failure
229 assert_no_difference 'User.count' do
229 assert_no_difference 'User.count' do
230 post :create, :user => {}
230 post :create, :user => {}
231 end
231 end
232 assert_response :success
232 assert_response :success
233 assert_template 'new'
233 assert_template 'new'
234 end
234 end
235
235
236 def test_edit
236 def test_edit
237 get :edit, :id => 2
237 get :edit, :id => 2
238 assert_response :success
238 assert_response :success
239 assert_template 'edit'
239 assert_template 'edit'
240 assert_equal User.find(2), assigns(:user)
240 assert_equal User.find(2), assigns(:user)
241 end
241 end
242
242
243 def test_update
243 def test_update
244 ActionMailer::Base.deliveries.clear
244 ActionMailer::Base.deliveries.clear
245 put :update, :id => 2,
245 put :update, :id => 2,
246 :user => {:firstname => 'Changed', :mail_notification => 'only_assigned'},
246 :user => {:firstname => 'Changed', :mail_notification => 'only_assigned'},
247 :pref => {:hide_mail => '1', :comments_sorting => 'desc'}
247 :pref => {:hide_mail => '1', :comments_sorting => 'desc'}
248 user = User.find(2)
248 user = User.find(2)
249 assert_equal 'Changed', user.firstname
249 assert_equal 'Changed', user.firstname
250 assert_equal 'only_assigned', user.mail_notification
250 assert_equal 'only_assigned', user.mail_notification
251 assert_equal true, user.pref[:hide_mail]
251 assert_equal true, user.pref[:hide_mail]
252 assert_equal 'desc', user.pref[:comments_sorting]
252 assert_equal 'desc', user.pref[:comments_sorting]
253 assert ActionMailer::Base.deliveries.empty?
253 assert ActionMailer::Base.deliveries.empty?
254 end
254 end
255
255
256 def test_update_with_failure
256 def test_update_with_failure
257 assert_no_difference 'User.count' do
257 assert_no_difference 'User.count' do
258 put :update, :id => 2, :user => {:firstname => ''}
258 put :update, :id => 2, :user => {:firstname => ''}
259 end
259 end
260 assert_response :success
260 assert_response :success
261 assert_template 'edit'
261 assert_template 'edit'
262 end
262 end
263
263
264 def test_update_with_group_ids_should_assign_groups
264 def test_update_with_group_ids_should_assign_groups
265 put :update, :id => 2, :user => {:group_ids => ['10']}
265 put :update, :id => 2, :user => {:group_ids => ['10']}
266 user = User.find(2)
266 user = User.find(2)
267 assert_equal [10], user.group_ids
267 assert_equal [10], user.group_ids
268 end
268 end
269
269
270 def test_update_with_activation_should_send_a_notification
270 def test_update_with_activation_should_send_a_notification
271 u = User.new(:firstname => 'Foo', :lastname => 'Bar', :mail => 'foo.bar@somenet.foo', :language => 'fr')
271 u = User.new(:firstname => 'Foo', :lastname => 'Bar', :mail => 'foo.bar@somenet.foo', :language => 'fr')
272 u.login = 'foo'
272 u.login = 'foo'
273 u.status = User::STATUS_REGISTERED
273 u.status = User::STATUS_REGISTERED
274 u.save!
274 u.save!
275 ActionMailer::Base.deliveries.clear
275 ActionMailer::Base.deliveries.clear
276 Setting.bcc_recipients = '1'
276 Setting.bcc_recipients = '1'
277
277
278 put :update, :id => u.id, :user => {:status => User::STATUS_ACTIVE}
278 put :update, :id => u.id, :user => {:status => User::STATUS_ACTIVE}
279 assert u.reload.active?
279 assert u.reload.active?
280 mail = ActionMailer::Base.deliveries.last
280 mail = ActionMailer::Base.deliveries.last
281 assert_not_nil mail
281 assert_not_nil mail
282 assert_equal ['foo.bar@somenet.foo'], mail.bcc
282 assert_equal ['foo.bar@somenet.foo'], mail.bcc
283 assert_mail_body_match ll('fr', :notice_account_activated), mail
283 assert_mail_body_match ll('fr', :notice_account_activated), mail
284 end
284 end
285
285
286 def test_update_with_password_change_should_send_a_notification
286 def test_update_with_password_change_should_send_a_notification
287 ActionMailer::Base.deliveries.clear
287 ActionMailer::Base.deliveries.clear
288 Setting.bcc_recipients = '1'
288 Setting.bcc_recipients = '1'
289
289
290 put :update, :id => 2, :user => {:password => 'newpass', :password_confirmation => 'newpass'}, :send_information => '1'
290 put :update, :id => 2, :user => {:password => 'newpass', :password_confirmation => 'newpass'}, :send_information => '1'
291 u = User.find(2)
291 u = User.find(2)
292 assert u.check_password?('newpass')
292 assert u.check_password?('newpass')
293
293
294 mail = ActionMailer::Base.deliveries.last
294 mail = ActionMailer::Base.deliveries.last
295 assert_not_nil mail
295 assert_not_nil mail
296 assert_equal [u.mail], mail.bcc
296 assert_equal [u.mail], mail.bcc
297 assert_mail_body_match 'newpass', mail
297 assert_mail_body_match 'newpass', mail
298 end
298 end
299
299
300 def test_update_user_switchin_from_auth_source_to_password_authentication
300 def test_update_user_switchin_from_auth_source_to_password_authentication
301 # Configure as auth source
301 # Configure as auth source
302 u = User.find(2)
302 u = User.find(2)
303 u.auth_source = AuthSource.find(1)
303 u.auth_source = AuthSource.find(1)
304 u.save!
304 u.save!
305
305
306 put :update, :id => u.id, :user => {:auth_source_id => '', :password => 'newpass', :password_confirmation => 'newpass'}
306 put :update, :id => u.id, :user => {:auth_source_id => '', :password => 'newpass', :password_confirmation => 'newpass'}
307
307
308 assert_equal nil, u.reload.auth_source
308 assert_equal nil, u.reload.auth_source
309 assert u.check_password?('newpass')
309 assert u.check_password?('newpass')
310 end
310 end
311
311
312 def test_update_notified_project
312 def test_update_notified_project
313 get :edit, :id => 2
313 get :edit, :id => 2
314 assert_response :success
314 assert_response :success
315 assert_template 'edit'
315 assert_template 'edit'
316 u = User.find(2)
316 u = User.find(2)
317 assert_equal [1, 2, 5], u.projects.collect{|p| p.id}.sort
317 assert_equal [1, 2, 5], u.projects.collect{|p| p.id}.sort
318 assert_equal [1, 2, 5], u.notified_projects_ids.sort
318 assert_equal [1, 2, 5], u.notified_projects_ids.sort
319 assert_tag :tag => 'input',
319 assert_tag :tag => 'input',
320 :attributes => {
320 :attributes => {
321 :id => 'notified_project_ids_',
321 :id => 'notified_project_ids_',
322 :value => 1,
322 :value => 1,
323 }
323 }
324 assert_equal 'all', u.mail_notification
324 assert_equal 'all', u.mail_notification
325 put :update, :id => 2,
325 put :update, :id => 2,
326 :user => {
326 :user => {
327 :mail_notification => 'selected',
327 :mail_notification => 'selected',
328 },
328 },
329 :notified_project_ids => [1, 2]
329 :notified_project_ids => [1, 2]
330 u = User.find(2)
330 u = User.find(2)
331 assert_equal 'selected', u.mail_notification
331 assert_equal 'selected', u.mail_notification
332 assert_equal [1, 2], u.notified_projects_ids.sort
332 assert_equal [1, 2], u.notified_projects_ids.sort
333 end
333 end
334
334
335 def test_destroy
335 def test_destroy
336 assert_difference 'User.count', -1 do
336 assert_difference 'User.count', -1 do
337 delete :destroy, :id => 2
337 delete :destroy, :id => 2
338 end
338 end
339 assert_redirected_to '/users'
339 assert_redirected_to '/users'
340 assert_nil User.find_by_id(2)
340 assert_nil User.find_by_id(2)
341 end
341 end
342
342
343 def test_destroy_should_be_denied_for_non_admin_users
343 def test_destroy_should_be_denied_for_non_admin_users
344 @request.session[:user_id] = 3
344 @request.session[:user_id] = 3
345
345
346 assert_no_difference 'User.count' do
346 assert_no_difference 'User.count' do
347 get :destroy, :id => 2
347 get :destroy, :id => 2
348 end
348 end
349 assert_response 403
349 assert_response 403
350 end
350 end
351
351
352 def test_create_membership
352 def test_create_membership
353 assert_difference 'Member.count' do
353 assert_difference 'Member.count' do
354 post :edit_membership, :id => 7, :membership => { :project_id => 3, :role_ids => [2]}
354 post :edit_membership, :id => 7, :membership => { :project_id => 3, :role_ids => [2]}
355 end
355 end
356 assert_redirected_to :action => 'edit', :id => '7', :tab => 'memberships'
356 assert_redirected_to :action => 'edit', :id => '7', :tab => 'memberships'
357 member = Member.first(:order => 'id DESC')
357 member = Member.first(:order => 'id DESC')
358 assert_equal User.find(7), member.principal
358 assert_equal User.find(7), member.principal
359 assert_equal [2], member.role_ids
359 assert_equal [2], member.role_ids
360 assert_equal 3, member.project_id
360 assert_equal 3, member.project_id
361 end
361 end
362
362
363 def test_create_membership_js_format
363 def test_create_membership_js_format
364 assert_difference 'Member.count' do
364 assert_difference 'Member.count' do
365 post :edit_membership, :id => 7, :membership => {:project_id => 3, :role_ids => [2]}, :format => 'js'
365 post :edit_membership, :id => 7, :membership => {:project_id => 3, :role_ids => [2]}, :format => 'js'
366 assert_response :success
367 assert_template 'edit_membership'
368 assert_equal 'text/javascript', response.content_type
366 end
369 end
367 assert_response :success
368 assert_select_rjs :replace_html, 'tab-content-memberships'
369 member = Member.first(:order => 'id DESC')
370 member = Member.first(:order => 'id DESC')
370 assert_equal User.find(7), member.principal
371 assert_equal User.find(7), member.principal
371 assert_equal [2], member.role_ids
372 assert_equal [2], member.role_ids
372 assert_equal 3, member.project_id
373 assert_equal 3, member.project_id
374 assert_include 'tab-content-memberships', response.body
373 end
375 end
374
376
375 def test_create_membership_js_format_with_failure
377 def test_create_membership_js_format_with_failure
376 assert_no_difference 'Member.count' do
378 assert_no_difference 'Member.count' do
377 post :edit_membership, :id => 7, :membership => {:project_id => 3}, :format => 'js'
379 post :edit_membership, :id => 7, :membership => {:project_id => 3}, :format => 'js'
380 assert_response :success
381 assert_template 'edit_membership'
382 assert_equal 'text/javascript', response.content_type
378 end
383 end
379 assert_response :success
384 assert_include 'alert', response.body, "Alert message not sent"
380 assert @response.body.match(/alert/i), "Alert message not sent"
385 assert_include 'Role can\\\'t be empty', response.body, "Error message not sent"
381 assert @response.body.match(/role can't be empty/i), "Error message not sent"
382 end
386 end
383
387
384 def test_update_membership
388 def test_update_membership
385 assert_no_difference 'Member.count' do
389 assert_no_difference 'Member.count' do
386 put :edit_membership, :id => 2, :membership_id => 1, :membership => { :role_ids => [2]}
390 put :edit_membership, :id => 2, :membership_id => 1, :membership => { :role_ids => [2]}
391 assert_redirected_to :action => 'edit', :id => '2', :tab => 'memberships'
387 end
392 end
388 assert_redirected_to :action => 'edit', :id => '2', :tab => 'memberships'
389 assert_equal [2], Member.find(1).role_ids
393 assert_equal [2], Member.find(1).role_ids
390 end
394 end
391
395
392 def test_update_membership_js_format
396 def test_update_membership_js_format
393 assert_no_difference 'Member.count' do
397 assert_no_difference 'Member.count' do
394 put :edit_membership, :id => 2, :membership_id => 1, :membership => {:role_ids => [2]}, :format => 'js'
398 put :edit_membership, :id => 2, :membership_id => 1, :membership => {:role_ids => [2]}, :format => 'js'
399 assert_response :success
400 assert_template 'edit_membership'
401 assert_equal 'text/javascript', response.content_type
395 end
402 end
396 assert_response :success
403 assert_equal [2], Member.find(1).role_ids
397 assert_select_rjs :replace_html, 'tab-content-memberships'
404 assert_include 'tab-content-memberships', response.body
398 end
405 end
399
406
400 def test_destroy_membership
407 def test_destroy_membership
401 assert_difference 'Member.count', -1 do
408 assert_difference 'Member.count', -1 do
402 delete :destroy_membership, :id => 2, :membership_id => 1
409 delete :destroy_membership, :id => 2, :membership_id => 1
403 end
410 end
404 assert_redirected_to :action => 'edit', :id => '2', :tab => 'memberships'
411 assert_redirected_to :action => 'edit', :id => '2', :tab => 'memberships'
405 assert_nil Member.find_by_id(1)
412 assert_nil Member.find_by_id(1)
406 end
413 end
407
414
408 def test_destroy_membership_js_format
415 def test_destroy_membership_js_format
409 assert_difference 'Member.count', -1 do
416 assert_difference 'Member.count', -1 do
410 delete :destroy_membership, :id => 2, :membership_id => 1, :format => 'js'
417 delete :destroy_membership, :id => 2, :membership_id => 1, :format => 'js'
418 assert_response :success
419 assert_template 'destroy_membership'
420 assert_equal 'text/javascript', response.content_type
411 end
421 end
412 assert_response :success
422 assert_nil Member.find_by_id(1)
413 assert_select_rjs :replace_html, 'tab-content-memberships'
423 assert_include 'tab-content-memberships', response.body
414 end
424 end
415 end
425 end
@@ -1,480 +1,480
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 #require 'shoulda'
18 #require 'shoulda'
19 ENV["RAILS_ENV"] = "test"
19 ENV["RAILS_ENV"] = "test"
20 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
20 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
21 require 'rails/test_help'
21 require 'rails/test_help'
22 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
22 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
23
23
24 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
24 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
25 include ObjectHelpers
25 include ObjectHelpers
26
26
27 class ActiveSupport::TestCase
27 class ActiveSupport::TestCase
28 include ActionDispatch::TestProcess
28 include ActionDispatch::TestProcess
29
29
30 # Transactional fixtures accelerate your tests by wrapping each test method
30 # Transactional fixtures accelerate your tests by wrapping each test method
31 # in a transaction that's rolled back on completion. This ensures that the
31 # in a transaction that's rolled back on completion. This ensures that the
32 # test database remains unchanged so your fixtures don't have to be reloaded
32 # test database remains unchanged so your fixtures don't have to be reloaded
33 # between every test method. Fewer database queries means faster tests.
33 # between every test method. Fewer database queries means faster tests.
34 #
34 #
35 # Read Mike Clark's excellent walkthrough at
35 # Read Mike Clark's excellent walkthrough at
36 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
36 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
37 #
37 #
38 # Every Active Record database supports transactions except MyISAM tables
38 # Every Active Record database supports transactions except MyISAM tables
39 # in MySQL. Turn off transactional fixtures in this case; however, if you
39 # in MySQL. Turn off transactional fixtures in this case; however, if you
40 # don't care one way or the other, switching from MyISAM to InnoDB tables
40 # don't care one way or the other, switching from MyISAM to InnoDB tables
41 # is recommended.
41 # is recommended.
42 self.use_transactional_fixtures = true
42 self.use_transactional_fixtures = true
43
43
44 # Instantiated fixtures are slow, but give you @david where otherwise you
44 # Instantiated fixtures are slow, but give you @david where otherwise you
45 # would need people(:david). If you don't want to migrate your existing
45 # would need people(:david). If you don't want to migrate your existing
46 # test cases which use the @david style and don't mind the speed hit (each
46 # test cases which use the @david style and don't mind the speed hit (each
47 # instantiated fixtures translates to a database query per test method),
47 # instantiated fixtures translates to a database query per test method),
48 # then set this back to true.
48 # then set this back to true.
49 self.use_instantiated_fixtures = false
49 self.use_instantiated_fixtures = false
50
50
51 # Add more helper methods to be used by all tests here...
51 # Add more helper methods to be used by all tests here...
52
52
53 def log_user(login, password)
53 def log_user(login, password)
54 User.anonymous
54 User.anonymous
55 get "/login"
55 get "/login"
56 assert_equal nil, session[:user_id]
56 assert_equal nil, session[:user_id]
57 assert_response :success
57 assert_response :success
58 assert_template "account/login"
58 assert_template "account/login"
59 post "/login", :username => login, :password => password
59 post "/login", :username => login, :password => password
60 assert_equal login, User.find(session[:user_id]).login
60 assert_equal login, User.find(session[:user_id]).login
61 end
61 end
62
62
63 def uploaded_test_file(name, mime)
63 def uploaded_test_file(name, mime)
64 fixture_file_upload("files/#{name}", mime, true)
64 fixture_file_upload("files/#{name}", mime, true)
65 end
65 end
66
66
67 def credentials(user, password=nil)
67 def credentials(user, password=nil)
68 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
68 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
69 end
69 end
70
70
71 # Mock out a file
71 # Mock out a file
72 def self.mock_file
72 def self.mock_file
73 file = 'a_file.png'
73 file = 'a_file.png'
74 file.stubs(:size).returns(32)
74 file.stubs(:size).returns(32)
75 file.stubs(:original_filename).returns('a_file.png')
75 file.stubs(:original_filename).returns('a_file.png')
76 file.stubs(:content_type).returns('image/png')
76 file.stubs(:content_type).returns('image/png')
77 file.stubs(:read).returns(false)
77 file.stubs(:read).returns(false)
78 file
78 file
79 end
79 end
80
80
81 def mock_file
81 def mock_file
82 self.class.mock_file
82 self.class.mock_file
83 end
83 end
84
84
85 def mock_file_with_options(options={})
85 def mock_file_with_options(options={})
86 file = ''
86 file = ''
87 file.stubs(:size).returns(32)
87 file.stubs(:size).returns(32)
88 original_filename = options[:original_filename] || nil
88 original_filename = options[:original_filename] || nil
89 file.stubs(:original_filename).returns(original_filename)
89 file.stubs(:original_filename).returns(original_filename)
90 content_type = options[:content_type] || nil
90 content_type = options[:content_type] || nil
91 file.stubs(:content_type).returns(content_type)
91 file.stubs(:content_type).returns(content_type)
92 file.stubs(:read).returns(false)
92 file.stubs(:read).returns(false)
93 file
93 file
94 end
94 end
95
95
96 # Use a temporary directory for attachment related tests
96 # Use a temporary directory for attachment related tests
97 def set_tmp_attachments_directory
97 def set_tmp_attachments_directory
98 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
98 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
99 unless File.directory?("#{Rails.root}/tmp/test/attachments")
99 unless File.directory?("#{Rails.root}/tmp/test/attachments")
100 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
100 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
101 end
101 end
102 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
102 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
103 end
103 end
104
104
105 def set_fixtures_attachments_directory
105 def set_fixtures_attachments_directory
106 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
106 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
107 end
107 end
108
108
109 def with_settings(options, &block)
109 def with_settings(options, &block)
110 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].is_a?(Symbol) ? Setting[k] : Setting[k].dup; h}
110 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].is_a?(Symbol) ? Setting[k] : Setting[k].dup; h}
111 options.each {|k, v| Setting[k] = v}
111 options.each {|k, v| Setting[k] = v}
112 yield
112 yield
113 ensure
113 ensure
114 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
114 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
115 end
115 end
116
116
117 def change_user_password(login, new_password)
117 def change_user_password(login, new_password)
118 user = User.first(:conditions => {:login => login})
118 user = User.first(:conditions => {:login => login})
119 user.password, user.password_confirmation = new_password, new_password
119 user.password, user.password_confirmation = new_password, new_password
120 user.save!
120 user.save!
121 end
121 end
122
122
123 def self.ldap_configured?
123 def self.ldap_configured?
124 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
124 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
125 return @test_ldap.bind
125 return @test_ldap.bind
126 rescue Exception => e
126 rescue Exception => e
127 # LDAP is not listening
127 # LDAP is not listening
128 return nil
128 return nil
129 end
129 end
130
130
131 def self.convert_installed?
131 def self.convert_installed?
132 Redmine::Thumbnail.convert_available?
132 Redmine::Thumbnail.convert_available?
133 end
133 end
134
134
135 # Returns the path to the test +vendor+ repository
135 # Returns the path to the test +vendor+ repository
136 def self.repository_path(vendor)
136 def self.repository_path(vendor)
137 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
137 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
138 end
138 end
139
139
140 # Returns the url of the subversion test repository
140 # Returns the url of the subversion test repository
141 def self.subversion_repository_url
141 def self.subversion_repository_url
142 path = repository_path('subversion')
142 path = repository_path('subversion')
143 path = '/' + path unless path.starts_with?('/')
143 path = '/' + path unless path.starts_with?('/')
144 "file://#{path}"
144 "file://#{path}"
145 end
145 end
146
146
147 # Returns true if the +vendor+ test repository is configured
147 # Returns true if the +vendor+ test repository is configured
148 def self.repository_configured?(vendor)
148 def self.repository_configured?(vendor)
149 File.directory?(repository_path(vendor))
149 File.directory?(repository_path(vendor))
150 end
150 end
151
151
152 def repository_path_hash(arr)
152 def repository_path_hash(arr)
153 hs = {}
153 hs = {}
154 hs[:path] = arr.join("/")
154 hs[:path] = arr.join("/")
155 hs[:param] = arr.join("/")
155 hs[:param] = arr.join("/")
156 hs
156 hs
157 end
157 end
158
158
159 def assert_error_tag(options={})
159 def assert_error_tag(options={})
160 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
160 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
161 end
161 end
162
162
163 def assert_include(expected, s)
163 def assert_include(expected, s, message=nil)
164 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
164 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
165 end
165 end
166
166
167 def assert_not_include(expected, s)
167 def assert_not_include(expected, s)
168 assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\""
168 assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\""
169 end
169 end
170
170
171 def assert_mail_body_match(expected, mail)
171 def assert_mail_body_match(expected, mail)
172 if expected.is_a?(String)
172 if expected.is_a?(String)
173 assert_include expected, mail_body(mail)
173 assert_include expected, mail_body(mail)
174 else
174 else
175 assert_match expected, mail_body(mail)
175 assert_match expected, mail_body(mail)
176 end
176 end
177 end
177 end
178
178
179 def assert_mail_body_no_match(expected, mail)
179 def assert_mail_body_no_match(expected, mail)
180 if expected.is_a?(String)
180 if expected.is_a?(String)
181 assert_not_include expected, mail_body(mail)
181 assert_not_include expected, mail_body(mail)
182 else
182 else
183 assert_no_match expected, mail_body(mail)
183 assert_no_match expected, mail_body(mail)
184 end
184 end
185 end
185 end
186
186
187 def mail_body(mail)
187 def mail_body(mail)
188 mail.parts.first.body.encoded
188 mail.parts.first.body.encoded
189 end
189 end
190
190
191 # Shoulda macros
191 # Shoulda macros
192 def self.should_render_404
192 def self.should_render_404
193 should_respond_with :not_found
193 should_respond_with :not_found
194 should_render_template 'common/error'
194 should_render_template 'common/error'
195 end
195 end
196
196
197 def self.should_have_before_filter(expected_method, options = {})
197 def self.should_have_before_filter(expected_method, options = {})
198 should_have_filter('before', expected_method, options)
198 should_have_filter('before', expected_method, options)
199 end
199 end
200
200
201 def self.should_have_after_filter(expected_method, options = {})
201 def self.should_have_after_filter(expected_method, options = {})
202 should_have_filter('after', expected_method, options)
202 should_have_filter('after', expected_method, options)
203 end
203 end
204
204
205 def self.should_have_filter(filter_type, expected_method, options)
205 def self.should_have_filter(filter_type, expected_method, options)
206 description = "have #{filter_type}_filter :#{expected_method}"
206 description = "have #{filter_type}_filter :#{expected_method}"
207 description << " with #{options.inspect}" unless options.empty?
207 description << " with #{options.inspect}" unless options.empty?
208
208
209 should description do
209 should description do
210 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
210 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
211 expected = klass.new(:filter, expected_method.to_sym, options)
211 expected = klass.new(:filter, expected_method.to_sym, options)
212 assert_equal 1, @controller.class.filter_chain.select { |filter|
212 assert_equal 1, @controller.class.filter_chain.select { |filter|
213 filter.method == expected.method && filter.kind == expected.kind &&
213 filter.method == expected.method && filter.kind == expected.kind &&
214 filter.options == expected.options && filter.class == expected.class
214 filter.options == expected.options && filter.class == expected.class
215 }.size
215 }.size
216 end
216 end
217 end
217 end
218
218
219 # Test that a request allows the three types of API authentication
219 # Test that a request allows the three types of API authentication
220 #
220 #
221 # * HTTP Basic with username and password
221 # * HTTP Basic with username and password
222 # * HTTP Basic with an api key for the username
222 # * HTTP Basic with an api key for the username
223 # * Key based with the key=X parameter
223 # * Key based with the key=X parameter
224 #
224 #
225 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
225 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
226 # @param [String] url the request url
226 # @param [String] url the request url
227 # @param [optional, Hash] parameters additional request parameters
227 # @param [optional, Hash] parameters additional request parameters
228 # @param [optional, Hash] options additional options
228 # @param [optional, Hash] options additional options
229 # @option options [Symbol] :success_code Successful response code (:success)
229 # @option options [Symbol] :success_code Successful response code (:success)
230 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
230 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
231 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
231 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
232 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
232 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
233 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
233 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
234 should_allow_key_based_auth(http_method, url, parameters, options)
234 should_allow_key_based_auth(http_method, url, parameters, options)
235 end
235 end
236
236
237 # Test that a request allows the username and password for HTTP BASIC
237 # Test that a request allows the username and password for HTTP BASIC
238 #
238 #
239 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
239 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
240 # @param [String] url the request url
240 # @param [String] url the request url
241 # @param [optional, Hash] parameters additional request parameters
241 # @param [optional, Hash] parameters additional request parameters
242 # @param [optional, Hash] options additional options
242 # @param [optional, Hash] options additional options
243 # @option options [Symbol] :success_code Successful response code (:success)
243 # @option options [Symbol] :success_code Successful response code (:success)
244 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
244 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
245 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
245 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
246 success_code = options[:success_code] || :success
246 success_code = options[:success_code] || :success
247 failure_code = options[:failure_code] || :unauthorized
247 failure_code = options[:failure_code] || :unauthorized
248
248
249 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
249 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
250 context "with a valid HTTP authentication" do
250 context "with a valid HTTP authentication" do
251 setup do
251 setup do
252 @user = User.generate! do |user|
252 @user = User.generate! do |user|
253 user.admin = true
253 user.admin = true
254 user.password = 'my_password'
254 user.password = 'my_password'
255 end
255 end
256 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
256 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
257 end
257 end
258
258
259 should_respond_with success_code
259 should_respond_with success_code
260 should_respond_with_content_type_based_on_url(url)
260 should_respond_with_content_type_based_on_url(url)
261 should "login as the user" do
261 should "login as the user" do
262 assert_equal @user, User.current
262 assert_equal @user, User.current
263 end
263 end
264 end
264 end
265
265
266 context "with an invalid HTTP authentication" do
266 context "with an invalid HTTP authentication" do
267 setup do
267 setup do
268 @user = User.generate!
268 @user = User.generate!
269 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
269 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
270 end
270 end
271
271
272 should_respond_with failure_code
272 should_respond_with failure_code
273 should_respond_with_content_type_based_on_url(url)
273 should_respond_with_content_type_based_on_url(url)
274 should "not login as the user" do
274 should "not login as the user" do
275 assert_equal User.anonymous, User.current
275 assert_equal User.anonymous, User.current
276 end
276 end
277 end
277 end
278
278
279 context "without credentials" do
279 context "without credentials" do
280 setup do
280 setup do
281 send(http_method, url, parameters)
281 send(http_method, url, parameters)
282 end
282 end
283
283
284 should_respond_with failure_code
284 should_respond_with failure_code
285 should_respond_with_content_type_based_on_url(url)
285 should_respond_with_content_type_based_on_url(url)
286 should "include_www_authenticate_header" do
286 should "include_www_authenticate_header" do
287 assert @controller.response.headers.has_key?('WWW-Authenticate')
287 assert @controller.response.headers.has_key?('WWW-Authenticate')
288 end
288 end
289 end
289 end
290 end
290 end
291
291
292 end
292 end
293
293
294 # Test that a request allows the API key with HTTP BASIC
294 # Test that a request allows the API key with HTTP BASIC
295 #
295 #
296 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
296 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
297 # @param [String] url the request url
297 # @param [String] url the request url
298 # @param [optional, Hash] parameters additional request parameters
298 # @param [optional, Hash] parameters additional request parameters
299 # @param [optional, Hash] options additional options
299 # @param [optional, Hash] options additional options
300 # @option options [Symbol] :success_code Successful response code (:success)
300 # @option options [Symbol] :success_code Successful response code (:success)
301 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
301 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
302 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
302 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
303 success_code = options[:success_code] || :success
303 success_code = options[:success_code] || :success
304 failure_code = options[:failure_code] || :unauthorized
304 failure_code = options[:failure_code] || :unauthorized
305
305
306 context "should allow http basic auth with a key for #{http_method} #{url}" do
306 context "should allow http basic auth with a key for #{http_method} #{url}" do
307 context "with a valid HTTP authentication using the API token" do
307 context "with a valid HTTP authentication using the API token" do
308 setup do
308 setup do
309 @user = User.generate! do |user|
309 @user = User.generate! do |user|
310 user.admin = true
310 user.admin = true
311 end
311 end
312 @token = Token.create!(:user => @user, :action => 'api')
312 @token = Token.create!(:user => @user, :action => 'api')
313 send(http_method, url, parameters, credentials(@token.value, 'X'))
313 send(http_method, url, parameters, credentials(@token.value, 'X'))
314 end
314 end
315
315
316 should_respond_with success_code
316 should_respond_with success_code
317 should_respond_with_content_type_based_on_url(url)
317 should_respond_with_content_type_based_on_url(url)
318 should_be_a_valid_response_string_based_on_url(url)
318 should_be_a_valid_response_string_based_on_url(url)
319 should "login as the user" do
319 should "login as the user" do
320 assert_equal @user, User.current
320 assert_equal @user, User.current
321 end
321 end
322 end
322 end
323
323
324 context "with an invalid HTTP authentication" do
324 context "with an invalid HTTP authentication" do
325 setup do
325 setup do
326 @user = User.generate!
326 @user = User.generate!
327 @token = Token.create!(:user => @user, :action => 'feeds')
327 @token = Token.create!(:user => @user, :action => 'feeds')
328 send(http_method, url, parameters, credentials(@token.value, 'X'))
328 send(http_method, url, parameters, credentials(@token.value, 'X'))
329 end
329 end
330
330
331 should_respond_with failure_code
331 should_respond_with failure_code
332 should_respond_with_content_type_based_on_url(url)
332 should_respond_with_content_type_based_on_url(url)
333 should "not login as the user" do
333 should "not login as the user" do
334 assert_equal User.anonymous, User.current
334 assert_equal User.anonymous, User.current
335 end
335 end
336 end
336 end
337 end
337 end
338 end
338 end
339
339
340 # Test that a request allows full key authentication
340 # Test that a request allows full key authentication
341 #
341 #
342 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
342 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
343 # @param [String] url the request url, without the key=ZXY parameter
343 # @param [String] url the request url, without the key=ZXY parameter
344 # @param [optional, Hash] parameters additional request parameters
344 # @param [optional, Hash] parameters additional request parameters
345 # @param [optional, Hash] options additional options
345 # @param [optional, Hash] options additional options
346 # @option options [Symbol] :success_code Successful response code (:success)
346 # @option options [Symbol] :success_code Successful response code (:success)
347 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
347 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
348 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
348 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
349 success_code = options[:success_code] || :success
349 success_code = options[:success_code] || :success
350 failure_code = options[:failure_code] || :unauthorized
350 failure_code = options[:failure_code] || :unauthorized
351
351
352 context "should allow key based auth using key=X for #{http_method} #{url}" do
352 context "should allow key based auth using key=X for #{http_method} #{url}" do
353 context "with a valid api token" do
353 context "with a valid api token" do
354 setup do
354 setup do
355 @user = User.generate! do |user|
355 @user = User.generate! do |user|
356 user.admin = true
356 user.admin = true
357 end
357 end
358 @token = Token.create!(:user => @user, :action => 'api')
358 @token = Token.create!(:user => @user, :action => 'api')
359 # Simple url parse to add on ?key= or &key=
359 # Simple url parse to add on ?key= or &key=
360 request_url = if url.match(/\?/)
360 request_url = if url.match(/\?/)
361 url + "&key=#{@token.value}"
361 url + "&key=#{@token.value}"
362 else
362 else
363 url + "?key=#{@token.value}"
363 url + "?key=#{@token.value}"
364 end
364 end
365 send(http_method, request_url, parameters)
365 send(http_method, request_url, parameters)
366 end
366 end
367
367
368 should_respond_with success_code
368 should_respond_with success_code
369 should_respond_with_content_type_based_on_url(url)
369 should_respond_with_content_type_based_on_url(url)
370 should_be_a_valid_response_string_based_on_url(url)
370 should_be_a_valid_response_string_based_on_url(url)
371 should "login as the user" do
371 should "login as the user" do
372 assert_equal @user, User.current
372 assert_equal @user, User.current
373 end
373 end
374 end
374 end
375
375
376 context "with an invalid api token" do
376 context "with an invalid api token" do
377 setup do
377 setup do
378 @user = User.generate! do |user|
378 @user = User.generate! do |user|
379 user.admin = true
379 user.admin = true
380 end
380 end
381 @token = Token.create!(:user => @user, :action => 'feeds')
381 @token = Token.create!(:user => @user, :action => 'feeds')
382 # Simple url parse to add on ?key= or &key=
382 # Simple url parse to add on ?key= or &key=
383 request_url = if url.match(/\?/)
383 request_url = if url.match(/\?/)
384 url + "&key=#{@token.value}"
384 url + "&key=#{@token.value}"
385 else
385 else
386 url + "?key=#{@token.value}"
386 url + "?key=#{@token.value}"
387 end
387 end
388 send(http_method, request_url, parameters)
388 send(http_method, request_url, parameters)
389 end
389 end
390
390
391 should_respond_with failure_code
391 should_respond_with failure_code
392 should_respond_with_content_type_based_on_url(url)
392 should_respond_with_content_type_based_on_url(url)
393 should "not login as the user" do
393 should "not login as the user" do
394 assert_equal User.anonymous, User.current
394 assert_equal User.anonymous, User.current
395 end
395 end
396 end
396 end
397 end
397 end
398
398
399 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
399 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
400 setup do
400 setup do
401 @user = User.generate! do |user|
401 @user = User.generate! do |user|
402 user.admin = true
402 user.admin = true
403 end
403 end
404 @token = Token.create!(:user => @user, :action => 'api')
404 @token = Token.create!(:user => @user, :action => 'api')
405 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
405 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
406 end
406 end
407
407
408 should_respond_with success_code
408 should_respond_with success_code
409 should_respond_with_content_type_based_on_url(url)
409 should_respond_with_content_type_based_on_url(url)
410 should_be_a_valid_response_string_based_on_url(url)
410 should_be_a_valid_response_string_based_on_url(url)
411 should "login as the user" do
411 should "login as the user" do
412 assert_equal @user, User.current
412 assert_equal @user, User.current
413 end
413 end
414 end
414 end
415 end
415 end
416
416
417 # Uses should_respond_with_content_type based on what's in the url:
417 # Uses should_respond_with_content_type based on what's in the url:
418 #
418 #
419 # '/project/issues.xml' => should_respond_with_content_type :xml
419 # '/project/issues.xml' => should_respond_with_content_type :xml
420 # '/project/issues.json' => should_respond_with_content_type :json
420 # '/project/issues.json' => should_respond_with_content_type :json
421 #
421 #
422 # @param [String] url Request
422 # @param [String] url Request
423 def self.should_respond_with_content_type_based_on_url(url)
423 def self.should_respond_with_content_type_based_on_url(url)
424 case
424 case
425 when url.match(/xml/i)
425 when url.match(/xml/i)
426 should "respond with XML" do
426 should "respond with XML" do
427 assert_equal 'application/xml', @response.content_type
427 assert_equal 'application/xml', @response.content_type
428 end
428 end
429 when url.match(/json/i)
429 when url.match(/json/i)
430 should "respond with JSON" do
430 should "respond with JSON" do
431 assert_equal 'application/json', @response.content_type
431 assert_equal 'application/json', @response.content_type
432 end
432 end
433 else
433 else
434 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
434 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
435 end
435 end
436
436
437 end
437 end
438
438
439 # Uses the url to assert which format the response should be in
439 # Uses the url to assert which format the response should be in
440 #
440 #
441 # '/project/issues.xml' => should_be_a_valid_xml_string
441 # '/project/issues.xml' => should_be_a_valid_xml_string
442 # '/project/issues.json' => should_be_a_valid_json_string
442 # '/project/issues.json' => should_be_a_valid_json_string
443 #
443 #
444 # @param [String] url Request
444 # @param [String] url Request
445 def self.should_be_a_valid_response_string_based_on_url(url)
445 def self.should_be_a_valid_response_string_based_on_url(url)
446 case
446 case
447 when url.match(/xml/i)
447 when url.match(/xml/i)
448 should_be_a_valid_xml_string
448 should_be_a_valid_xml_string
449 when url.match(/json/i)
449 when url.match(/json/i)
450 should_be_a_valid_json_string
450 should_be_a_valid_json_string
451 else
451 else
452 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
452 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
453 end
453 end
454
454
455 end
455 end
456
456
457 # Checks that the response is a valid JSON string
457 # Checks that the response is a valid JSON string
458 def self.should_be_a_valid_json_string
458 def self.should_be_a_valid_json_string
459 should "be a valid JSON string (or empty)" do
459 should "be a valid JSON string (or empty)" do
460 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
460 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
461 end
461 end
462 end
462 end
463
463
464 # Checks that the response is a valid XML string
464 # Checks that the response is a valid XML string
465 def self.should_be_a_valid_xml_string
465 def self.should_be_a_valid_xml_string
466 should "be a valid XML string" do
466 should "be a valid XML string" do
467 assert REXML::Document.new(response.body)
467 assert REXML::Document.new(response.body)
468 end
468 end
469 end
469 end
470
470
471 def self.should_respond_with(status)
471 def self.should_respond_with(status)
472 should "respond with #{status}" do
472 should "respond with #{status}" do
473 assert_response status
473 assert_response status
474 end
474 end
475 end
475 end
476 end
476 end
477
477
478 # Simple module to "namespace" all of the API tests
478 # Simple module to "namespace" all of the API tests
479 module ApiTest
479 module ApiTest
480 end
480 end
General Comments 0
You need to be logged in to leave comments. Login now