##// END OF EJS Templates
Removed some test contexts....
Jean-Philippe Lang -
r13264:4989c9f6a845
parent child
Show More
@@ -1,54 +1,43
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 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
19
20 class Redmine::ApiTest::HttpBasicLoginTest < Redmine::ApiTest::Base
20 class Redmine::ApiTest::HttpBasicLoginTest < Redmine::ApiTest::Base
21 fixtures :projects, :trackers, :issue_statuses, :issues,
21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 :enumerations, :users, :issue_categories,
22 :enumerations, :users, :issue_categories,
23 :projects_trackers,
23 :projects_trackers,
24 :roles,
24 :roles,
25 :member_roles,
25 :member_roles,
26 :members,
26 :members,
27 :enabled_modules
27 :enabled_modules
28
28
29 def setup
29 def setup
30 Setting.rest_api_enabled = '1'
30 Setting.rest_api_enabled = '1'
31 Setting.login_required = '1'
31 Setting.login_required = '1'
32 project = Project.find('onlinestore')
33 EnabledModule.create(:project => project, :name => 'news')
32 end
34 end
33
35
34 def teardown
36 def teardown
35 Setting.rest_api_enabled = '0'
37 Setting.rest_api_enabled = '0'
36 Setting.login_required = '0'
38 Setting.login_required = '0'
37 end
39 end
38
40
39 # Using the NewsController because it's a simple API.
41 should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.xml")
40 context "get /news" do
42 should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.json")
41 setup do
42 project = Project.find('onlinestore')
43 EnabledModule.create(:project => project, :name => 'news')
44 end
45
46 context "in :xml format" do
47 should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.xml")
48 end
49
50 context "in :json format" do
51 should_allow_http_basic_auth_with_username_and_password(:get, "/projects/onlinestore/news.json")
52 end
53 end
54 end
43 end
@@ -1,50 +1,41
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 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
19
20 class Redmine::ApiTest::HttpBasicLoginWithApiTokenTest < Redmine::ApiTest::Base
20 class Redmine::ApiTest::HttpBasicLoginWithApiTokenTest < Redmine::ApiTest::Base
21 fixtures :projects, :trackers, :issue_statuses, :issues,
21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 :enumerations, :users, :issue_categories,
22 :enumerations, :users, :issue_categories,
23 :projects_trackers,
23 :projects_trackers,
24 :roles,
24 :roles,
25 :member_roles,
25 :member_roles,
26 :members,
26 :members,
27 :enabled_modules
27 :enabled_modules
28
28
29 def setup
29 def setup
30 Setting.rest_api_enabled = '1'
30 Setting.rest_api_enabled = '1'
31 Setting.login_required = '1'
31 Setting.login_required = '1'
32 end
32 end
33
33
34 def teardown
34 def teardown
35 Setting.rest_api_enabled = '0'
35 Setting.rest_api_enabled = '0'
36 Setting.login_required = '0'
36 Setting.login_required = '0'
37 end
37 end
38
38
39 # Using the NewsController because it's a simple API.
39 should_allow_http_basic_auth_with_key(:get, "/news.xml")
40 context "get /news" do
40 should_allow_http_basic_auth_with_key(:get, "/news.json")
41
42 context "in :xml format" do
43 should_allow_http_basic_auth_with_key(:get, "/news.xml")
44 end
45
46 context "in :json format" do
47 should_allow_http_basic_auth_with_key(:get, "/news.json")
48 end
49 end
50 end
41 end
This diff has been collapsed as it changes many lines, (811 lines changed) Show them Hide them
@@ -1,799 +1,632
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 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
19
20 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
20 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
21 fixtures :projects,
21 fixtures :projects,
22 :users,
22 :users,
23 :roles,
23 :roles,
24 :members,
24 :members,
25 :member_roles,
25 :member_roles,
26 :issues,
26 :issues,
27 :issue_statuses,
27 :issue_statuses,
28 :issue_relations,
28 :issue_relations,
29 :versions,
29 :versions,
30 :trackers,
30 :trackers,
31 :projects_trackers,
31 :projects_trackers,
32 :issue_categories,
32 :issue_categories,
33 :enabled_modules,
33 :enabled_modules,
34 :enumerations,
34 :enumerations,
35 :attachments,
35 :attachments,
36 :workflows,
36 :workflows,
37 :custom_fields,
37 :custom_fields,
38 :custom_values,
38 :custom_values,
39 :custom_fields_projects,
39 :custom_fields_projects,
40 :custom_fields_trackers,
40 :custom_fields_trackers,
41 :time_entries,
41 :time_entries,
42 :journals,
42 :journals,
43 :journal_details,
43 :journal_details,
44 :queries,
44 :queries,
45 :attachments
45 :attachments
46
46
47 def setup
47 def setup
48 Setting.rest_api_enabled = '1'
48 Setting.rest_api_enabled = '1'
49 end
49 end
50
50
51 context "/issues" do
51 # Use a private project to make sure auth is really working and not just
52 # Use a private project to make sure auth is really working and not just
52 # only showing public issues.
53 # only showing public issues.
53 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
54 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
54 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
55
55
56 should "contain metadata" do
56 should_allow_api_authentication(:get, "/issues/6.xml")
57 get '/issues.xml'
57 should_allow_api_authentication(:get, "/issues/6.json")
58
59 should_allow_api_authentication(
60 :post,
61 '/issues.xml',
62 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
63 {:success_code => :created}
64 )
65 should_allow_api_authentication(:post,
66 '/issues.json',
67 {:issue => {:project_id => 1, :subject => 'API test',
68 :tracker_id => 2, :status_id => 3}},
69 {:success_code => :created})
70
71 should_allow_api_authentication(:put,
72 '/issues/6.xml',
73 {:issue => {:subject => 'API update', :notes => 'A new note'}},
74 {:success_code => :ok})
75 should_allow_api_authentication(:put,
76 '/issues/6.json',
77 {:issue => {:subject => 'API update', :notes => 'A new note'}},
78 {:success_code => :ok})
79
80 should_allow_api_authentication(:delete,
81 '/issues/6.xml',
82 {},
83 {:success_code => :ok})
84 should_allow_api_authentication(:delete,
85 '/issues/6.json',
86 {},
87 {:success_code => :ok})
88
89 test "GET /issues.xml should contain metadata" do
90 get '/issues.xml'
91 assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]',
92 assigns(:issue_count).to_s
93 end
58
94
59 assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]', assigns(:issue_count).to_s
95 test "GET /issues.xml with nometa param should not contain metadata" do
60 end
96 get '/issues.xml?nometa=1'
97 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
98 end
61
99
62 context "with offset and limit" do
100 test "GET /issues.xml with nometa header should not contain metadata" do
63 should "use the params" do
101 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
64 get '/issues.xml?offset=2&limit=3'
102 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
103 end
65
104
66 assert_equal 3, assigns(:limit)
105 test "GET /issues.xml with offset and limit" do
67 assert_equal 2, assigns(:offset)
106 get '/issues.xml?offset=2&limit=3'
68 assert_select 'issues issue', 3
69 end
70 end
71
107
72 context "with nometa param" do
108 assert_equal 3, assigns(:limit)
73 should "not contain metadata" do
109 assert_equal 2, assigns(:offset)
74 get '/issues.xml?nometa=1'
110 assert_select 'issues issue', 3
111 end
75
112
76 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
113 test "GET /issues.xml with relations" do
77 end
114 get '/issues.xml?include=relations'
78 end
79
115
80 context "with nometa header" do
116 assert_response :success
81 should "not contain metadata" do
117 assert_equal 'application/xml', @response.content_type
82 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
83
118
84 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
119 assert_select 'issue id:content(3)' do
85 end
120 assert_select '~ relations relation', 1
121 assert_select '~ relations relation[id="2"][issue_id="2"][issue_to_id="3"][relation_type=relates]'
86 end
122 end
87
123
88 context "with relations" do
124 assert_select 'issue id:content(1)' do
89 should "display relations" do
125 assert_select '~ relations'
90 get '/issues.xml?include=relations'
126 assert_select '~ relations relation', 0
91
127 end
92 assert_response :success
128 end
93 assert_equal 'application/xml', @response.content_type
94
129
95 assert_select 'issue id:content(3)' do
130 test "GET /issues.xml with invalid query params" do
96 assert_select '~ relations relation', 1
131 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
97 assert_select '~ relations relation[id="2"][issue_id="2"][issue_to_id="3"][relation_type=relates]'
98 end
99
132
100 assert_select 'issue id:content(1)' do
133 assert_response :unprocessable_entity
101 assert_select '~ relations'
134 assert_equal 'application/xml', @response.content_type
102 assert_select '~ relations relation', 0
135 assert_select 'errors error', :text => "Start date can't be blank"
103 end
136 end
104 end
105 end
106
137
107 context "with invalid query params" do
138 test "GET /issues.xml with custom field filter" do
108 should "return errors" do
139 get '/issues.xml',
109 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
140 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='}, :v => {:cf_1 => ['MySQL']}}
110
141
111 assert_response :unprocessable_entity
142 expected_ids = Issue.visible.
112 assert_equal 'application/xml', @response.content_type
143 joins(:custom_values).
113 assert_select 'errors error', :text => "Start date can't be blank"
144 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
114 end
145 assert expected_ids.any?
115 end
116
146
117 context "with custom field filter" do
147 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
118 should "show only issues with the custom field value" do
148 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
119 get '/issues.xml',
120 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='},
121 :v => {:cf_1 => ['MySQL']}}
122 expected_ids = Issue.visible.
123 joins(:custom_values).
124 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
125 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
126 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
127 end
128 end
129 end
149 end
150 end
130
151
131 context "with custom field filter (shorthand method)" do
152 test "GET /issues.xml with custom field filter (shorthand method)" do
132 should "show only issues with the custom field value" do
153 get '/issues.xml', {:cf_1 => 'MySQL'}
133 get '/issues.xml', { :cf_1 => 'MySQL' }
134
154
135 expected_ids = Issue.visible.
155 expected_ids = Issue.visible.
136 joins(:custom_values).
156 joins(:custom_values).
137 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
157 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
158 assert expected_ids.any?
138
159
139 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
160 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
140 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
161 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
141 end
142 end
143 end
162 end
144 end
163 end
145
164
146 def test_index_should_include_issue_attributes
165 def test_index_should_include_issue_attributes
147 get '/issues.xml'
166 get '/issues.xml'
148 assert_select 'issues>issue>is_private', :text => 'false'
167 assert_select 'issues>issue>is_private', :text => 'false'
149 end
168 end
150
169
151 def test_index_should_allow_timestamp_filtering
170 def test_index_should_allow_timestamp_filtering
152 Issue.delete_all
171 Issue.delete_all
153 Issue.generate!(:subject => '1').update_column(:updated_on, Time.parse("2014-01-02T10:25:00Z"))
172 Issue.generate!(:subject => '1').update_column(:updated_on, Time.parse("2014-01-02T10:25:00Z"))
154 Issue.generate!(:subject => '2').update_column(:updated_on, Time.parse("2014-01-02T12:13:00Z"))
173 Issue.generate!(:subject => '2').update_column(:updated_on, Time.parse("2014-01-02T12:13:00Z"))
155
174
156 get '/issues.xml',
175 get '/issues.xml',
157 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '<='},
176 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '<='},
158 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
177 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
159 assert_select 'issues>issue', :count => 1
178 assert_select 'issues>issue', :count => 1
160 assert_select 'issues>issue>subject', :text => '1'
179 assert_select 'issues>issue>subject', :text => '1'
161
180
162 get '/issues.xml',
181 get '/issues.xml',
163 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
182 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
164 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
183 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
165 assert_select 'issues>issue', :count => 1
184 assert_select 'issues>issue', :count => 1
166 assert_select 'issues>issue>subject', :text => '2'
185 assert_select 'issues>issue>subject', :text => '2'
167
186
168 get '/issues.xml',
187 get '/issues.xml',
169 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
188 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
170 :v => {:updated_on => ['2014-01-02T08:00:00Z']}}
189 :v => {:updated_on => ['2014-01-02T08:00:00Z']}}
171 assert_select 'issues>issue', :count => 2
190 assert_select 'issues>issue', :count => 2
172 end
191 end
173
192
174 context "/index.json" do
193 test "GET /issues.xml with filter" do
175 should_allow_api_authentication(:get, "/projects/private-child/issues.json")
194 get '/issues.xml?status_id=5'
176 end
177
195
178 context "/index.xml with filter" do
196 expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
179 should "show only issues with the status_id" do
197 assert expected_ids.any?
180 get '/issues.xml?status_id=5'
181
198
182 expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
199 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
183
200 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
184 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
185 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
186 end
187 end
201 end
188 end
202 end
189
203
190 context "/index.json with filter" do
204 test "GET /issues.json with filter" do
191 should "show only issues with the status_id" do
205 get '/issues.json?status_id=5'
192 get '/issues.json?status_id=5'
193
194 json = ActiveSupport::JSON.decode(response.body)
195 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
196 assert_equal 3, status_ids_used.length
197 assert status_ids_used.all? {|id| id == 5 }
198 end
199
206
207 json = ActiveSupport::JSON.decode(response.body)
208 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
209 assert_equal 3, status_ids_used.length
210 assert status_ids_used.all? {|id| id == 5 }
200 end
211 end
201
212
202 # Issue 6 is on a private project
213 test "GET /issues/:id.xml with journals" do
203 context "/issues/6.xml" do
214 get '/issues/1.xml?include=journals'
204 should_allow_api_authentication(:get, "/issues/6.xml")
205 end
206
215
207 context "/issues/6.json" do
216 assert_select 'issue journals[type=array]' do
208 should_allow_api_authentication(:get, "/issues/6.json")
217 assert_select 'journal[id="1"]' do
218 assert_select 'details[type=array]' do
219 assert_select 'detail[name=status_id]' do
220 assert_select 'old_value', :text => '1'
221 assert_select 'new_value', :text => '2'
222 end
223 end
224 end
225 end
209 end
226 end
210
227
211 context "GET /issues/:id" do
228 test "GET /issues/:id.xml with custom fields" do
212 context "with journals" do
229 get '/issues/3.xml'
213 context ".xml" do
214 should "display journals" do
215 get '/issues/1.xml?include=journals'
216
230
217 assert_select 'issue journals[type=array]' do
231 assert_select 'issue custom_fields[type=array]' do
218 assert_select 'journal[id="1"]' do
232 assert_select 'custom_field[id="1"]' do
219 assert_select 'details[type=array]' do
233 assert_select 'value', :text => 'MySQL'
220 assert_select 'detail[name=status_id]' do
221 assert_select 'old_value', :text => '1'
222 assert_select 'new_value', :text => '2'
223 end
224 end
225 end
226 end
227 end
228 end
234 end
229 end
235 end
236 assert_nothing_raised do
237 Hash.from_xml(response.body).to_xml
238 end
239 end
230
240
231 context "with custom fields" do
241 test "GET /issues/:id.xml with multi custom fields" do
232 context ".xml" do
242 field = CustomField.find(1)
233 should "display custom fields" do
243 field.update_attribute :multiple, true
234 get '/issues/3.xml'
244 issue = Issue.find(3)
245 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
246 issue.save!
235
247
236 assert_select 'issue custom_fields[type=array]' do
248 get '/issues/3.xml'
237 assert_select 'custom_field[id="1"]' do
249 assert_response :success
238 assert_select 'value', :text => 'MySQL'
239 end
240 end
241
250
242 assert_nothing_raised do
251 assert_select 'issue custom_fields[type=array]' do
243 Hash.from_xml(response.body).to_xml
252 assert_select 'custom_field[id="1"]' do
244 end
253 assert_select 'value[type=array] value', 2
245 end
246 end
254 end
247 end
255 end
256 xml = Hash.from_xml(response.body)
257 custom_fields = xml['issue']['custom_fields']
258 assert_kind_of Array, custom_fields
259 field = custom_fields.detect {|f| f['id'] == '1'}
260 assert_kind_of Hash, field
261 assert_equal ['MySQL', 'Oracle'], field['value'].sort
262 end
248
263
249 context "with multi custom fields" do
264 test "GET /issues/:id.json with multi custom fields" do
250 setup do
265 field = CustomField.find(1)
251 field = CustomField.find(1)
266 field.update_attribute :multiple, true
252 field.update_attribute :multiple, true
267 issue = Issue.find(3)
253 issue = Issue.find(3)
268 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
254 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
269 issue.save!
255 issue.save!
256 end
257
270
258 context ".xml" do
271 get '/issues/3.json'
259 should "display custom fields" do
272 assert_response :success
260 get '/issues/3.xml'
261 assert_response :success
262
273
263 assert_select 'issue custom_fields[type=array]' do
274 json = ActiveSupport::JSON.decode(response.body)
264 assert_select 'custom_field[id="1"]' do
275 custom_fields = json['issue']['custom_fields']
265 assert_select 'value[type=array] value', 2
276 assert_kind_of Array, custom_fields
266 end
277 field = custom_fields.detect {|f| f['id'] == 1}
267 end
278 assert_kind_of Hash, field
279 assert_equal ['MySQL', 'Oracle'], field['value'].sort
280 end
268
281
269 xml = Hash.from_xml(response.body)
282 test "GET /issues/:id.xml with empty value for multi custom field" do
270 custom_fields = xml['issue']['custom_fields']
283 field = CustomField.find(1)
271 assert_kind_of Array, custom_fields
284 field.update_attribute :multiple, true
272 field = custom_fields.detect {|f| f['id'] == '1'}
285 issue = Issue.find(3)
273 assert_kind_of Hash, field
286 issue.custom_field_values = {1 => ['']}
274 assert_equal ['MySQL', 'Oracle'], field['value'].sort
287 issue.save!
275 end
276 end
277
288
278 context ".json" do
289 get '/issues/3.xml'
279 should "display custom fields" do
280 get '/issues/3.json'
281 assert_response :success
282 json = ActiveSupport::JSON.decode(response.body)
283 custom_fields = json['issue']['custom_fields']
284 assert_kind_of Array, custom_fields
285 field = custom_fields.detect {|f| f['id'] == 1}
286 assert_kind_of Hash, field
287 assert_equal ['MySQL', 'Oracle'], field['value'].sort
288 end
289 end
290 end
291
290
292 context "with empty value for multi custom field" do
291 assert_select 'issue custom_fields[type=array]' do
293 setup do
292 assert_select 'custom_field[id="1"]' do
294 field = CustomField.find(1)
293 assert_select 'value[type=array]:empty'
295 field.update_attribute :multiple, true
296 issue = Issue.find(3)
297 issue.custom_field_values = {1 => ['']}
298 issue.save!
299 end
294 end
295 end
296 xml = Hash.from_xml(response.body)
297 custom_fields = xml['issue']['custom_fields']
298 assert_kind_of Array, custom_fields
299 field = custom_fields.detect {|f| f['id'] == '1'}
300 assert_kind_of Hash, field
301 assert_equal [], field['value']
302 end
300
303
301 context ".xml" do
304 test "GET /issues/:id.json with empty value for multi custom field" do
302 should "display custom fields" do
305 field = CustomField.find(1)
303 get '/issues/3.xml'
306 field.update_attribute :multiple, true
307 issue = Issue.find(3)
308 issue.custom_field_values = {1 => ['']}
309 issue.save!
304
310
305 assert_select 'issue custom_fields[type=array]' do
311 get '/issues/3.json'
306 assert_select 'custom_field[id="1"]' do
312 assert_response :success
307 assert_select 'value[type=array]:empty'
313 json = ActiveSupport::JSON.decode(response.body)
308 end
314 custom_fields = json['issue']['custom_fields']
309 end
315 assert_kind_of Array, custom_fields
316 field = custom_fields.detect {|f| f['id'] == 1}
317 assert_kind_of Hash, field
318 assert_equal [], field['value'].sort
319 end
310
320
311 xml = Hash.from_xml(response.body)
321 test "GET /issues/:id.xml with attachments" do
312 custom_fields = xml['issue']['custom_fields']
322 get '/issues/3.xml?include=attachments'
313 assert_kind_of Array, custom_fields
314 field = custom_fields.detect {|f| f['id'] == '1'}
315 assert_kind_of Hash, field
316 assert_equal [], field['value']
317 end
318 end
319
323
320 context ".json" do
324 assert_select 'issue attachments[type=array]' do
321 should "display custom fields" do
325 assert_select 'attachment', 5
322 get '/issues/3.json'
326 assert_select 'attachment id:content(4)' do
323 assert_response :success
327 assert_select '~ filename', :text => 'source.rb'
324 json = ActiveSupport::JSON.decode(response.body)
328 assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/4/source.rb'
325 custom_fields = json['issue']['custom_fields']
326 assert_kind_of Array, custom_fields
327 field = custom_fields.detect {|f| f['id'] == 1}
328 assert_kind_of Hash, field
329 assert_equal [], field['value'].sort
330 end
331 end
329 end
332 end
330 end
331 end
333
332
334 context "with attachments" do
333 test "GET /issues/:id.xml with subtasks" do
335 context ".xml" do
334 issue = Issue.generate_with_descendants!(:project_id => 1)
336 should "display attachments" do
335 get "/issues/#{issue.id}.xml?include=children"
337 get '/issues/3.xml?include=attachments'
338
339 assert_select 'issue attachments[type=array]' do
340 assert_select 'attachment', 5
341 assert_select 'attachment id:content(4)' do
342 assert_select '~ filename', :text => 'source.rb'
343 assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/4/source.rb'
344 end
345 end
346 end
347 end
348 end
349
336
350 context "with subtasks" do
337 assert_select 'issue children[type=array]' do
351 setup do
338 assert_select 'issue', 2
352 @c1 = Issue.create!(
339 assert_select 'issue children', 1
353 :status_id => 1, :subject => "child c1",
340 end
354 :tracker_id => 1, :project_id => 1, :author_id => 1,
341 end
355 :parent_issue_id => 1
356 )
357 @c2 = Issue.create!(
358 :status_id => 1, :subject => "child c2",
359 :tracker_id => 1, :project_id => 1, :author_id => 1,
360 :parent_issue_id => 1
361 )
362 @c3 = Issue.create!(
363 :status_id => 1, :subject => "child c3",
364 :tracker_id => 1, :project_id => 1, :author_id => 1,
365 :parent_issue_id => @c1.id
366 )
367 end
368
342
369 context ".xml" do
343 test "GET /issues/:id.json with subtasks" do
370 should "display children" do
344 issue = Issue.generate_with_descendants!(:project_id => 1)
371 get '/issues/1.xml?include=children'
345 get "/issues/#{issue.id}.json?include=children"
372
373 assert_select 'issue children[type=array]' do
374 assert_select 'issue', 2
375 assert_select 'issue[id=?]', @c1.id.to_s do
376 assert_select 'subject', :text => 'child c1'
377 assert_select 'children' do
378 assert_select 'issue[id=?]', @c3.id.to_s
379 end
380 end
381 end
382 end
383
346
384 context ".json" do
347 json = ActiveSupport::JSON.decode(response.body)
385 should "display children" do
348 assert_equal 2, json['issue']['children'].size
386 get '/issues/1.json?include=children'
349 assert_equal 1, json['issue']['children'].select {|child| child.key?('children')}.size
387
388 json = ActiveSupport::JSON.decode(response.body)
389 assert_equal([
390 {
391 'id' => @c1.id, 'subject' => 'child c1', 'tracker' => {'id' => 1, 'name' => 'Bug'},
392 'children' => [{'id' => @c3.id, 'subject' => 'child c3',
393 'tracker' => {'id' => 1, 'name' => 'Bug'} }]
394 },
395 { 'id' => @c2.id, 'subject' => 'child c2', 'tracker' => {'id' => 1, 'name' => 'Bug'} }
396 ],
397 json['issue']['children'])
398 end
399 end
400 end
401 end
402 end
350 end
403
351
404 def test_show_should_include_issue_attributes
352 def test_show_should_include_issue_attributes
405 get '/issues/1.xml'
353 get '/issues/1.xml'
406 assert_select 'issue>is_private', :text => 'false'
354 assert_select 'issue>is_private', :text => 'false'
407 end
355 end
408
356
409 test "GET /issues/:id.xml?include=watchers should include watchers" do
357 test "GET /issues/:id.xml?include=watchers should include watchers" do
410 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
358 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
411
359
412 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
360 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
413
361
414 assert_response :ok
362 assert_response :ok
415 assert_equal 'application/xml', response.content_type
363 assert_equal 'application/xml', response.content_type
416 assert_select 'issue' do
364 assert_select 'issue' do
417 assert_select 'watchers', Issue.find(1).watchers.count
365 assert_select 'watchers', Issue.find(1).watchers.count
418 assert_select 'watchers' do
366 assert_select 'watchers' do
419 assert_select 'user[id=3]'
367 assert_select 'user[id=3]'
420 end
368 end
421 end
369 end
422 end
370 end
423
371
424 context "POST /issues.xml" do
372 test "POST /issues.xml should create an issue with the attributes" do
425 should_allow_api_authentication(
373 assert_difference('Issue.count') do
426 :post,
374 post '/issues.xml',
427 '/issues.xml',
375 {:issue => {:project_id => 1, :subject => 'API test',
428 {:issue => {:project_id => 1, :subject => 'API test', :tracker_id => 2, :status_id => 3}},
376 :tracker_id => 2, :status_id => 3}}, credentials('jsmith')
429 {:success_code => :created}
430 )
431 should "create an issue with the attributes" do
432 assert_difference('Issue.count') do
433 post '/issues.xml',
434 {:issue => {:project_id => 1, :subject => 'API test',
435 :tracker_id => 2, :status_id => 3}}, credentials('jsmith')
436 end
437 issue = Issue.order('id DESC').first
438 assert_equal 1, issue.project_id
439 assert_equal 2, issue.tracker_id
440 assert_equal 3, issue.status_id
441 assert_equal 'API test', issue.subject
442
443 assert_response :created
444 assert_equal 'application/xml', @response.content_type
445 assert_select 'issue > id', :text => issue.id.to_s
446 end
377 end
378 issue = Issue.order('id DESC').first
379 assert_equal 1, issue.project_id
380 assert_equal 2, issue.tracker_id
381 assert_equal 3, issue.status_id
382 assert_equal 'API test', issue.subject
383
384 assert_response :created
385 assert_equal 'application/xml', @response.content_type
386 assert_select 'issue > id', :text => issue.id.to_s
447 end
387 end
448
388
449 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
389 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
450 assert_difference('Issue.count') do
390 assert_difference('Issue.count') do
451 post '/issues.xml',
391 post '/issues.xml',
452 {:issue => {:project_id => 1, :subject => 'Watchers',
392 {:issue => {:project_id => 1, :subject => 'Watchers',
453 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
393 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
454 assert_response :created
394 assert_response :created
455 end
395 end
456 issue = Issue.order('id desc').first
396 issue = Issue.order('id desc').first
457 assert_equal 2, issue.watchers.size
397 assert_equal 2, issue.watchers.size
458 assert_equal [1, 3], issue.watcher_user_ids.sort
398 assert_equal [1, 3], issue.watcher_user_ids.sort
459 end
399 end
460
400
461 context "POST /issues.xml with failure" do
401 test "POST /issues.xml with failure should return errors" do
462 should "have an errors tag" do
402 assert_no_difference('Issue.count') do
463 assert_no_difference('Issue.count') do
403 post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
464 post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
465 end
466
467 assert_select 'errors error', :text => "Subject can't be blank"
468 end
469 end
470
471 context "POST /issues.json" do
472 should_allow_api_authentication(:post,
473 '/issues.json',
474 {:issue => {:project_id => 1, :subject => 'API test',
475 :tracker_id => 2, :status_id => 3}},
476 {:success_code => :created})
477
478 should "create an issue with the attributes" do
479 assert_difference('Issue.count') do
480 post '/issues.json',
481 {:issue => {:project_id => 1, :subject => 'API test',
482 :tracker_id => 2, :status_id => 3}},
483 credentials('jsmith')
484 end
485
486 issue = Issue.order('id DESC').first
487 assert_equal 1, issue.project_id
488 assert_equal 2, issue.tracker_id
489 assert_equal 3, issue.status_id
490 assert_equal 'API test', issue.subject
491 end
404 end
492
405
406 assert_select 'errors error', :text => "Subject can't be blank"
493 end
407 end
494
408
495 context "POST /issues.json with failure" do
409 test "POST /issues.json should create an issue with the attributes" do
496 should "have an errors element" do
410 assert_difference('Issue.count') do
497 assert_no_difference('Issue.count') do
411 post '/issues.json',
498 post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
412 {:issue => {:project_id => 1, :subject => 'API test',
499 end
413 :tracker_id => 2, :status_id => 3}},
500
414 credentials('jsmith')
501 json = ActiveSupport::JSON.decode(response.body)
502 assert json['errors'].include?("Subject can't be blank")
503 end
504 end
505
506 # Issue 6 is on a private project
507 context "PUT /issues/6.xml" do
508 setup do
509 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
510 end
511
512 should_allow_api_authentication(:put,
513 '/issues/6.xml',
514 {:issue => {:subject => 'API update', :notes => 'A new note'}},
515 {:success_code => :ok})
516
517 should "not create a new issue" do
518 assert_no_difference('Issue.count') do
519 put '/issues/6.xml', @parameters, credentials('jsmith')
520 end
521 end
522
523 should "create a new journal" do
524 assert_difference('Journal.count') do
525 put '/issues/6.xml', @parameters, credentials('jsmith')
526 end
527 end
528
529 should "add the note to the journal" do
530 put '/issues/6.xml', @parameters, credentials('jsmith')
531
532 journal = Journal.last
533 assert_equal "A new note", journal.notes
534 end
535
536 should "update the issue" do
537 put '/issues/6.xml', @parameters, credentials('jsmith')
538
539 issue = Issue.find(6)
540 assert_equal "API update", issue.subject
541 end
415 end
542
416
417 issue = Issue.order('id DESC').first
418 assert_equal 1, issue.project_id
419 assert_equal 2, issue.tracker_id
420 assert_equal 3, issue.status_id
421 assert_equal 'API test', issue.subject
543 end
422 end
544
423
545 context "PUT /issues/3.xml with custom fields" do
424 test "POST /issues.json with failure should return errors" do
546 setup do
425 assert_no_difference('Issue.count') do
547 @parameters = {
426 post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
548 :issue => {:custom_fields => [{'id' => '1', 'value' => 'PostgreSQL' },
549 {'id' => '2', 'value' => '150'}]}
550 }
551 end
427 end
552
428
553 should "update custom fields" do
429 json = ActiveSupport::JSON.decode(response.body)
554 assert_no_difference('Issue.count') do
430 assert json['errors'].include?("Subject can't be blank")
555 put '/issues/3.xml', @parameters, credentials('jsmith')
556 end
557
558 issue = Issue.find(3)
559 assert_equal '150', issue.custom_value_for(2).value
560 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
561 end
562 end
431 end
563
432
564 context "PUT /issues/3.xml with multi custom fields" do
433 test "PUT /issues/:id.xml" do
565 setup do
434 assert_difference('Journal.count') do
566 field = CustomField.find(1)
435 put '/issues/6.xml',
567 field.update_attribute :multiple, true
436 {:issue => {:subject => 'API update', :notes => 'A new note'}},
568 @parameters = {
437 credentials('jsmith')
569 :issue => {:custom_fields => [{'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
570 {'id' => '2', 'value' => '150'}]}
571 }
572 end
438 end
573
439
574 should "update custom fields" do
440 issue = Issue.find(6)
575 assert_no_difference('Issue.count') do
441 assert_equal "API update", issue.subject
576 put '/issues/3.xml', @parameters, credentials('jsmith')
442 journal = Journal.last
577 end
443 assert_equal "A new note", journal.notes
578
579 issue = Issue.find(3)
580 assert_equal '150', issue.custom_value_for(2).value
581 assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
582 end
583 end
444 end
584
445
585 context "PUT /issues/3.xml with project change" do
446 test "PUT /issues/:id.xml with custom fields" do
586 setup do
447 put '/issues/3.xml',
587 @parameters = {:issue => {:project_id => 2, :subject => 'Project changed'}}
448 {:issue => {:custom_fields => [
588 end
449 {'id' => '1', 'value' => 'PostgreSQL' },
589
450 {'id' => '2', 'value' => '150'}
590 should "update project" do
451 ]}},
591 assert_no_difference('Issue.count') do
452 credentials('jsmith')
592 put '/issues/3.xml', @parameters, credentials('jsmith')
453
593 end
454 issue = Issue.find(3)
594
455 assert_equal '150', issue.custom_value_for(2).value
595 issue = Issue.find(3)
456 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
596 assert_equal 2, issue.project_id
597 assert_equal 'Project changed', issue.subject
598 end
599 end
457 end
600
458
601 context "PUT /issues/6.xml with failed update" do
459 test "PUT /issues/:id.xml with multi custom fields" do
602 setup do
460 field = CustomField.find(1)
603 @parameters = {:issue => {:subject => ''}}
461 field.update_attribute :multiple, true
604 end
605
606 should "not create a new issue" do
607 assert_no_difference('Issue.count') do
608 put '/issues/6.xml', @parameters, credentials('jsmith')
609 end
610 end
611
612 should "not create a new journal" do
613 assert_no_difference('Journal.count') do
614 put '/issues/6.xml', @parameters, credentials('jsmith')
615 end
616 end
617
462
618 should "have an errors tag" do
463 put '/issues/3.xml',
619 put '/issues/6.xml', @parameters, credentials('jsmith')
464 {:issue => {:custom_fields => [
465 {'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
466 {'id' => '2', 'value' => '150'}
467 ]}},
468 credentials('jsmith')
620
469
621 assert_select 'errors error', :text => "Subject can't be blank"
470 issue = Issue.find(3)
622 end
471 assert_equal '150', issue.custom_value_for(2).value
472 assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
623 end
473 end
624
474
625 context "PUT /issues/6.json" do
475 test "PUT /issues/:id.xml with project change" do
626 setup do
476 put '/issues/3.xml',
627 @parameters = {:issue => {:subject => 'API update', :notes => 'A new note'}}
477 {:issue => {:project_id => 2, :subject => 'Project changed'}},
628 end
478 credentials('jsmith')
629
630 should_allow_api_authentication(:put,
631 '/issues/6.json',
632 {:issue => {:subject => 'API update', :notes => 'A new note'}},
633 {:success_code => :ok})
634
479
635 should "update the issue" do
480 issue = Issue.find(3)
636 assert_no_difference('Issue.count') do
481 assert_equal 2, issue.project_id
637 assert_difference('Journal.count') do
482 assert_equal 'Project changed', issue.subject
638 put '/issues/6.json', @parameters, credentials('jsmith')
483 end
639
484
640 assert_response :ok
485 test "PUT /issues/:id.xml with failed update" do
641 assert_equal '', response.body
486 put '/issues/6.xml', {:issue => {:subject => ''}}, credentials('jsmith')
642 end
643 end
644
487
645 issue = Issue.find(6)
488 assert_response :unprocessable_entity
646 assert_equal "API update", issue.subject
489 assert_select 'errors error', :text => "Subject can't be blank"
647 journal = Journal.last
648 assert_equal "A new note", journal.notes
649 end
650 end
490 end
651
491
652 context "PUT /issues/6.json with failed update" do
492 test "PUT /issues/:id.json" do
653 should "return errors" do
493 assert_difference('Journal.count') do
654 assert_no_difference('Issue.count') do
494 put '/issues/6.json',
655 assert_no_difference('Journal.count') do
495 {:issue => {:subject => 'API update', :notes => 'A new note'}},
656 put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
496 credentials('jsmith')
657
658 assert_response :unprocessable_entity
659 end
660 end
661
497
662 json = ActiveSupport::JSON.decode(response.body)
498 assert_response :ok
663 assert json['errors'].include?("Subject can't be blank")
499 assert_equal '', response.body
664 end
500 end
501
502 issue = Issue.find(6)
503 assert_equal "API update", issue.subject
504 journal = Journal.last
505 assert_equal "A new note", journal.notes
665 end
506 end
666
507
667 context "DELETE /issues/1.xml" do
508 test "PUT /issues/:id.json with failed update" do
668 should_allow_api_authentication(:delete,
509 put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
669 '/issues/6.xml',
670 {},
671 {:success_code => :ok})
672
510
673 should "delete the issue" do
511 assert_response :unprocessable_entity
674 assert_difference('Issue.count', -1) do
512 json = ActiveSupport::JSON.decode(response.body)
675 delete '/issues/6.xml', {}, credentials('jsmith')
513 assert json['errors'].include?("Subject can't be blank")
514 end
676
515
677 assert_response :ok
516 test "DELETE /issues/:id.xml" do
678 assert_equal '', response.body
517 assert_difference('Issue.count', -1) do
679 end
518 delete '/issues/6.xml', {}, credentials('jsmith')
680
519
681 assert_nil Issue.find_by_id(6)
520 assert_response :ok
521 assert_equal '', response.body
682 end
522 end
523 assert_nil Issue.find_by_id(6)
683 end
524 end
684
525
685 context "DELETE /issues/1.json" do
526 test "DELETE /issues/:id.json" do
686 should_allow_api_authentication(:delete,
527 assert_difference('Issue.count', -1) do
687 '/issues/6.json',
528 delete '/issues/6.json', {}, credentials('jsmith')
688 {},
689 {:success_code => :ok})
690
691 should "delete the issue" do
692 assert_difference('Issue.count', -1) do
693 delete '/issues/6.json', {}, credentials('jsmith')
694
529
695 assert_response :ok
530 assert_response :ok
696 assert_equal '', response.body
531 assert_equal '', response.body
697 end
698
699 assert_nil Issue.find_by_id(6)
700 end
532 end
533 assert_nil Issue.find_by_id(6)
701 end
534 end
702
535
703 test "POST /issues/:id/watchers.xml should add watcher" do
536 test "POST /issues/:id/watchers.xml should add watcher" do
704 assert_difference 'Watcher.count' do
537 assert_difference 'Watcher.count' do
705 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
538 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
706
539
707 assert_response :ok
540 assert_response :ok
708 assert_equal '', response.body
541 assert_equal '', response.body
709 end
542 end
710 watcher = Watcher.order('id desc').first
543 watcher = Watcher.order('id desc').first
711 assert_equal Issue.find(1), watcher.watchable
544 assert_equal Issue.find(1), watcher.watchable
712 assert_equal User.find(3), watcher.user
545 assert_equal User.find(3), watcher.user
713 end
546 end
714
547
715 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
548 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
716 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
549 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
717
550
718 assert_difference 'Watcher.count', -1 do
551 assert_difference 'Watcher.count', -1 do
719 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
552 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
720
553
721 assert_response :ok
554 assert_response :ok
722 assert_equal '', response.body
555 assert_equal '', response.body
723 end
556 end
724 assert_equal false, Issue.find(1).watched_by?(User.find(3))
557 assert_equal false, Issue.find(1).watched_by?(User.find(3))
725 end
558 end
726
559
727 def test_create_issue_with_uploaded_file
560 def test_create_issue_with_uploaded_file
728 set_tmp_attachments_directory
561 set_tmp_attachments_directory
729 # upload the file
562 # upload the file
730 assert_difference 'Attachment.count' do
563 assert_difference 'Attachment.count' do
731 post '/uploads.xml', 'test_create_with_upload',
564 post '/uploads.xml', 'test_create_with_upload',
732 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
565 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
733 assert_response :created
566 assert_response :created
734 end
567 end
735 xml = Hash.from_xml(response.body)
568 xml = Hash.from_xml(response.body)
736 token = xml['upload']['token']
569 token = xml['upload']['token']
737 attachment = Attachment.order('id DESC').first
570 attachment = Attachment.order('id DESC').first
738
571
739 # create the issue with the upload's token
572 # create the issue with the upload's token
740 assert_difference 'Issue.count' do
573 assert_difference 'Issue.count' do
741 post '/issues.xml',
574 post '/issues.xml',
742 {:issue => {:project_id => 1, :subject => 'Uploaded file',
575 {:issue => {:project_id => 1, :subject => 'Uploaded file',
743 :uploads => [{:token => token, :filename => 'test.txt',
576 :uploads => [{:token => token, :filename => 'test.txt',
744 :content_type => 'text/plain'}]}},
577 :content_type => 'text/plain'}]}},
745 credentials('jsmith')
578 credentials('jsmith')
746 assert_response :created
579 assert_response :created
747 end
580 end
748 issue = Issue.order('id DESC').first
581 issue = Issue.order('id DESC').first
749 assert_equal 1, issue.attachments.count
582 assert_equal 1, issue.attachments.count
750 assert_equal attachment, issue.attachments.first
583 assert_equal attachment, issue.attachments.first
751
584
752 attachment.reload
585 attachment.reload
753 assert_equal 'test.txt', attachment.filename
586 assert_equal 'test.txt', attachment.filename
754 assert_equal 'text/plain', attachment.content_type
587 assert_equal 'text/plain', attachment.content_type
755 assert_equal 'test_create_with_upload'.size, attachment.filesize
588 assert_equal 'test_create_with_upload'.size, attachment.filesize
756 assert_equal 2, attachment.author_id
589 assert_equal 2, attachment.author_id
757
590
758 # get the issue with its attachments
591 # get the issue with its attachments
759 get "/issues/#{issue.id}.xml", :include => 'attachments'
592 get "/issues/#{issue.id}.xml", :include => 'attachments'
760 assert_response :success
593 assert_response :success
761 xml = Hash.from_xml(response.body)
594 xml = Hash.from_xml(response.body)
762 attachments = xml['issue']['attachments']
595 attachments = xml['issue']['attachments']
763 assert_kind_of Array, attachments
596 assert_kind_of Array, attachments
764 assert_equal 1, attachments.size
597 assert_equal 1, attachments.size
765 url = attachments.first['content_url']
598 url = attachments.first['content_url']
766 assert_not_nil url
599 assert_not_nil url
767
600
768 # download the attachment
601 # download the attachment
769 get url
602 get url
770 assert_response :success
603 assert_response :success
771 end
604 end
772
605
773 def test_update_issue_with_uploaded_file
606 def test_update_issue_with_uploaded_file
774 set_tmp_attachments_directory
607 set_tmp_attachments_directory
775 # upload the file
608 # upload the file
776 assert_difference 'Attachment.count' do
609 assert_difference 'Attachment.count' do
777 post '/uploads.xml', 'test_upload_with_upload',
610 post '/uploads.xml', 'test_upload_with_upload',
778 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
611 {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
779 assert_response :created
612 assert_response :created
780 end
613 end
781 xml = Hash.from_xml(response.body)
614 xml = Hash.from_xml(response.body)
782 token = xml['upload']['token']
615 token = xml['upload']['token']
783 attachment = Attachment.order('id DESC').first
616 attachment = Attachment.order('id DESC').first
784
617
785 # update the issue with the upload's token
618 # update the issue with the upload's token
786 assert_difference 'Journal.count' do
619 assert_difference 'Journal.count' do
787 put '/issues/1.xml',
620 put '/issues/1.xml',
788 {:issue => {:notes => 'Attachment added',
621 {:issue => {:notes => 'Attachment added',
789 :uploads => [{:token => token, :filename => 'test.txt',
622 :uploads => [{:token => token, :filename => 'test.txt',
790 :content_type => 'text/plain'}]}},
623 :content_type => 'text/plain'}]}},
791 credentials('jsmith')
624 credentials('jsmith')
792 assert_response :ok
625 assert_response :ok
793 assert_equal '', @response.body
626 assert_equal '', @response.body
794 end
627 end
795
628
796 issue = Issue.find(1)
629 issue = Issue.find(1)
797 assert_include attachment, issue.attachments
630 assert_include attachment, issue.attachments
798 end
631 end
799 end
632 end
@@ -1,1271 +1,1236
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 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
19
20 class UserTest < ActiveSupport::TestCase
20 class UserTest < ActiveSupport::TestCase
21 fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources,
21 fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources,
22 :trackers, :issue_statuses,
22 :trackers, :issue_statuses,
23 :projects_trackers,
23 :projects_trackers,
24 :watchers,
24 :watchers,
25 :issue_categories, :enumerations, :issues,
25 :issue_categories, :enumerations, :issues,
26 :journals, :journal_details,
26 :journals, :journal_details,
27 :groups_users,
27 :groups_users,
28 :enabled_modules
28 :enabled_modules
29
29
30 include Redmine::I18n
30 include Redmine::I18n
31
31
32 def setup
32 def setup
33 @admin = User.find(1)
33 @admin = User.find(1)
34 @jsmith = User.find(2)
34 @jsmith = User.find(2)
35 @dlopper = User.find(3)
35 @dlopper = User.find(3)
36 end
36 end
37
37
38 def test_sorted_scope_should_sort_user_by_display_name
38 def test_sorted_scope_should_sort_user_by_display_name
39 # Use .active to ignore anonymous with localized display name
39 # Use .active to ignore anonymous with localized display name
40 assert_equal User.active.map(&:name).map(&:downcase).sort,
40 assert_equal User.active.map(&:name).map(&:downcase).sort,
41 User.active.sorted.map(&:name).map(&:downcase)
41 User.active.sorted.map(&:name).map(&:downcase)
42 end
42 end
43
43
44 def test_generate
44 def test_generate
45 User.generate!(:firstname => 'Testing connection')
45 User.generate!(:firstname => 'Testing connection')
46 User.generate!(:firstname => 'Testing connection')
46 User.generate!(:firstname => 'Testing connection')
47 assert_equal 2, User.where(:firstname => 'Testing connection').count
47 assert_equal 2, User.where(:firstname => 'Testing connection').count
48 end
48 end
49
49
50 def test_truth
50 def test_truth
51 assert_kind_of User, @jsmith
51 assert_kind_of User, @jsmith
52 end
52 end
53
53
54 def test_mail_should_be_stripped
54 def test_mail_should_be_stripped
55 u = User.new
55 u = User.new
56 u.mail = " foo@bar.com "
56 u.mail = " foo@bar.com "
57 assert_equal "foo@bar.com", u.mail
57 assert_equal "foo@bar.com", u.mail
58 end
58 end
59
59
60 def test_mail_validation
60 def test_mail_validation
61 u = User.new
61 u = User.new
62 u.mail = ''
62 u.mail = ''
63 assert !u.valid?
63 assert !u.valid?
64 assert_include I18n.translate('activerecord.errors.messages.blank'), u.errors[:mail]
64 assert_include I18n.translate('activerecord.errors.messages.blank'), u.errors[:mail]
65 end
65 end
66
66
67 def test_login_length_validation
67 def test_login_length_validation
68 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
68 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
69 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
69 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
70 assert !user.valid?
70 assert !user.valid?
71
71
72 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
72 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
73 assert user.valid?
73 assert user.valid?
74 assert user.save
74 assert user.save
75 end
75 end
76
76
77 def test_generate_password_should_respect_minimum_password_length
77 def test_generate_password_should_respect_minimum_password_length
78 with_settings :password_min_length => 15 do
78 with_settings :password_min_length => 15 do
79 user = User.generate!(:generate_password => true)
79 user = User.generate!(:generate_password => true)
80 assert user.password.length >= 15
80 assert user.password.length >= 15
81 end
81 end
82 end
82 end
83
83
84 def test_generate_password_should_not_generate_password_with_less_than_10_characters
84 def test_generate_password_should_not_generate_password_with_less_than_10_characters
85 with_settings :password_min_length => 4 do
85 with_settings :password_min_length => 4 do
86 user = User.generate!(:generate_password => true)
86 user = User.generate!(:generate_password => true)
87 assert user.password.length >= 10
87 assert user.password.length >= 10
88 end
88 end
89 end
89 end
90
90
91 def test_generate_password_on_create_should_set_password
91 def test_generate_password_on_create_should_set_password
92 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
92 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
93 user.login = "newuser"
93 user.login = "newuser"
94 user.generate_password = true
94 user.generate_password = true
95 assert user.save
95 assert user.save
96
96
97 password = user.password
97 password = user.password
98 assert user.check_password?(password)
98 assert user.check_password?(password)
99 end
99 end
100
100
101 def test_generate_password_on_update_should_update_password
101 def test_generate_password_on_update_should_update_password
102 user = User.find(2)
102 user = User.find(2)
103 hash = user.hashed_password
103 hash = user.hashed_password
104 user.generate_password = true
104 user.generate_password = true
105 assert user.save
105 assert user.save
106
106
107 password = user.password
107 password = user.password
108 assert user.check_password?(password)
108 assert user.check_password?(password)
109 assert_not_equal hash, user.reload.hashed_password
109 assert_not_equal hash, user.reload.hashed_password
110 end
110 end
111
111
112 def test_create
112 def test_create
113 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
113 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
114
114
115 user.login = "jsmith"
115 user.login = "jsmith"
116 user.password, user.password_confirmation = "password", "password"
116 user.password, user.password_confirmation = "password", "password"
117 # login uniqueness
117 # login uniqueness
118 assert !user.save
118 assert !user.save
119 assert_equal 1, user.errors.count
119 assert_equal 1, user.errors.count
120
120
121 user.login = "newuser"
121 user.login = "newuser"
122 user.password, user.password_confirmation = "password", "pass"
122 user.password, user.password_confirmation = "password", "pass"
123 # password confirmation
123 # password confirmation
124 assert !user.save
124 assert !user.save
125 assert_equal 1, user.errors.count
125 assert_equal 1, user.errors.count
126
126
127 user.password, user.password_confirmation = "password", "password"
127 user.password, user.password_confirmation = "password", "password"
128 assert user.save
128 assert user.save
129 end
129 end
130
130
131 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
131 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
132 @user1 = User.generate!
132 @user1 = User.generate!
133 assert_equal 'only_my_events', @user1.mail_notification
133 assert_equal 'only_my_events', @user1.mail_notification
134 with_settings :default_notification_option => 'all' do
134 with_settings :default_notification_option => 'all' do
135 @user2 = User.generate!
135 @user2 = User.generate!
136 assert_equal 'all', @user2.mail_notification
136 assert_equal 'all', @user2.mail_notification
137 end
137 end
138 end
138 end
139
139
140 def test_user_login_should_be_case_insensitive
140 def test_user_login_should_be_case_insensitive
141 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
141 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
142 u.login = 'newuser'
142 u.login = 'newuser'
143 u.password, u.password_confirmation = "password", "password"
143 u.password, u.password_confirmation = "password", "password"
144 assert u.save
144 assert u.save
145 u = User.new(:firstname => "Similar", :lastname => "User",
145 u = User.new(:firstname => "Similar", :lastname => "User",
146 :mail => "similaruser@somenet.foo")
146 :mail => "similaruser@somenet.foo")
147 u.login = 'NewUser'
147 u.login = 'NewUser'
148 u.password, u.password_confirmation = "password", "password"
148 u.password, u.password_confirmation = "password", "password"
149 assert !u.save
149 assert !u.save
150 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
150 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
151 end
151 end
152
152
153 def test_mail_uniqueness_should_not_be_case_sensitive
153 def test_mail_uniqueness_should_not_be_case_sensitive
154 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
154 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
155 u.login = 'newuser1'
155 u.login = 'newuser1'
156 u.password, u.password_confirmation = "password", "password"
156 u.password, u.password_confirmation = "password", "password"
157 assert u.save
157 assert u.save
158
158
159 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
159 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
160 u.login = 'newuser2'
160 u.login = 'newuser2'
161 u.password, u.password_confirmation = "password", "password"
161 u.password, u.password_confirmation = "password", "password"
162 assert !u.save
162 assert !u.save
163 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:mail]
163 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:mail]
164 end
164 end
165
165
166 def test_update
166 def test_update
167 assert_equal "admin", @admin.login
167 assert_equal "admin", @admin.login
168 @admin.login = "john"
168 @admin.login = "john"
169 assert @admin.save, @admin.errors.full_messages.join("; ")
169 assert @admin.save, @admin.errors.full_messages.join("; ")
170 @admin.reload
170 @admin.reload
171 assert_equal "john", @admin.login
171 assert_equal "john", @admin.login
172 end
172 end
173
173
174 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
174 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
175 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
175 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
176 u1.login = 'newuser1'
176 u1.login = 'newuser1'
177 assert u1.save
177 assert u1.save
178
178
179 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
179 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
180 u2.login = 'newuser1'
180 u2.login = 'newuser1'
181 assert u2.save(:validate => false)
181 assert u2.save(:validate => false)
182
182
183 user = User.find(u2.id)
183 user = User.find(u2.id)
184 user.firstname = "firstname"
184 user.firstname = "firstname"
185 assert user.save, "Save failed"
185 assert user.save, "Save failed"
186 end
186 end
187
187
188 def test_destroy_should_delete_members_and_roles
188 def test_destroy_should_delete_members_and_roles
189 members = Member.where(:user_id => 2)
189 members = Member.where(:user_id => 2)
190 ms = members.count
190 ms = members.count
191 rs = members.collect(&:roles).flatten.size
191 rs = members.collect(&:roles).flatten.size
192 assert ms > 0
192 assert ms > 0
193 assert rs > 0
193 assert rs > 0
194 assert_difference 'Member.count', - ms do
194 assert_difference 'Member.count', - ms do
195 assert_difference 'MemberRole.count', - rs do
195 assert_difference 'MemberRole.count', - rs do
196 User.find(2).destroy
196 User.find(2).destroy
197 end
197 end
198 end
198 end
199 assert_nil User.find_by_id(2)
199 assert_nil User.find_by_id(2)
200 assert_equal 0, Member.where(:user_id => 2).count
200 assert_equal 0, Member.where(:user_id => 2).count
201 end
201 end
202
202
203 def test_destroy_should_update_attachments
203 def test_destroy_should_update_attachments
204 attachment = Attachment.create!(:container => Project.find(1),
204 attachment = Attachment.create!(:container => Project.find(1),
205 :file => uploaded_test_file("testfile.txt", "text/plain"),
205 :file => uploaded_test_file("testfile.txt", "text/plain"),
206 :author_id => 2)
206 :author_id => 2)
207
207
208 User.find(2).destroy
208 User.find(2).destroy
209 assert_nil User.find_by_id(2)
209 assert_nil User.find_by_id(2)
210 assert_equal User.anonymous, attachment.reload.author
210 assert_equal User.anonymous, attachment.reload.author
211 end
211 end
212
212
213 def test_destroy_should_update_comments
213 def test_destroy_should_update_comments
214 comment = Comment.create!(
214 comment = Comment.create!(
215 :commented => News.create!(:project_id => 1,
215 :commented => News.create!(:project_id => 1,
216 :author_id => 1, :title => 'foo', :description => 'foo'),
216 :author_id => 1, :title => 'foo', :description => 'foo'),
217 :author => User.find(2),
217 :author => User.find(2),
218 :comments => 'foo'
218 :comments => 'foo'
219 )
219 )
220
220
221 User.find(2).destroy
221 User.find(2).destroy
222 assert_nil User.find_by_id(2)
222 assert_nil User.find_by_id(2)
223 assert_equal User.anonymous, comment.reload.author
223 assert_equal User.anonymous, comment.reload.author
224 end
224 end
225
225
226 def test_destroy_should_update_issues
226 def test_destroy_should_update_issues
227 issue = Issue.create!(:project_id => 1, :author_id => 2,
227 issue = Issue.create!(:project_id => 1, :author_id => 2,
228 :tracker_id => 1, :subject => 'foo')
228 :tracker_id => 1, :subject => 'foo')
229
229
230 User.find(2).destroy
230 User.find(2).destroy
231 assert_nil User.find_by_id(2)
231 assert_nil User.find_by_id(2)
232 assert_equal User.anonymous, issue.reload.author
232 assert_equal User.anonymous, issue.reload.author
233 end
233 end
234
234
235 def test_destroy_should_unassign_issues
235 def test_destroy_should_unassign_issues
236 issue = Issue.create!(:project_id => 1, :author_id => 1,
236 issue = Issue.create!(:project_id => 1, :author_id => 1,
237 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
237 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
238
238
239 User.find(2).destroy
239 User.find(2).destroy
240 assert_nil User.find_by_id(2)
240 assert_nil User.find_by_id(2)
241 assert_nil issue.reload.assigned_to
241 assert_nil issue.reload.assigned_to
242 end
242 end
243
243
244 def test_destroy_should_update_journals
244 def test_destroy_should_update_journals
245 issue = Issue.create!(:project_id => 1, :author_id => 2,
245 issue = Issue.create!(:project_id => 1, :author_id => 2,
246 :tracker_id => 1, :subject => 'foo')
246 :tracker_id => 1, :subject => 'foo')
247 issue.init_journal(User.find(2), "update")
247 issue.init_journal(User.find(2), "update")
248 issue.save!
248 issue.save!
249
249
250 User.find(2).destroy
250 User.find(2).destroy
251 assert_nil User.find_by_id(2)
251 assert_nil User.find_by_id(2)
252 assert_equal User.anonymous, issue.journals.first.reload.user
252 assert_equal User.anonymous, issue.journals.first.reload.user
253 end
253 end
254
254
255 def test_destroy_should_update_journal_details_old_value
255 def test_destroy_should_update_journal_details_old_value
256 issue = Issue.create!(:project_id => 1, :author_id => 1,
256 issue = Issue.create!(:project_id => 1, :author_id => 1,
257 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
257 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
258 issue.init_journal(User.find(1), "update")
258 issue.init_journal(User.find(1), "update")
259 issue.assigned_to_id = nil
259 issue.assigned_to_id = nil
260 assert_difference 'JournalDetail.count' do
260 assert_difference 'JournalDetail.count' do
261 issue.save!
261 issue.save!
262 end
262 end
263 journal_detail = JournalDetail.order('id DESC').first
263 journal_detail = JournalDetail.order('id DESC').first
264 assert_equal '2', journal_detail.old_value
264 assert_equal '2', journal_detail.old_value
265
265
266 User.find(2).destroy
266 User.find(2).destroy
267 assert_nil User.find_by_id(2)
267 assert_nil User.find_by_id(2)
268 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
268 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
269 end
269 end
270
270
271 def test_destroy_should_update_journal_details_value
271 def test_destroy_should_update_journal_details_value
272 issue = Issue.create!(:project_id => 1, :author_id => 1,
272 issue = Issue.create!(:project_id => 1, :author_id => 1,
273 :tracker_id => 1, :subject => 'foo')
273 :tracker_id => 1, :subject => 'foo')
274 issue.init_journal(User.find(1), "update")
274 issue.init_journal(User.find(1), "update")
275 issue.assigned_to_id = 2
275 issue.assigned_to_id = 2
276 assert_difference 'JournalDetail.count' do
276 assert_difference 'JournalDetail.count' do
277 issue.save!
277 issue.save!
278 end
278 end
279 journal_detail = JournalDetail.order('id DESC').first
279 journal_detail = JournalDetail.order('id DESC').first
280 assert_equal '2', journal_detail.value
280 assert_equal '2', journal_detail.value
281
281
282 User.find(2).destroy
282 User.find(2).destroy
283 assert_nil User.find_by_id(2)
283 assert_nil User.find_by_id(2)
284 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
284 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
285 end
285 end
286
286
287 def test_destroy_should_update_messages
287 def test_destroy_should_update_messages
288 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
288 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
289 message = Message.create!(:board_id => board.id, :author_id => 2,
289 message = Message.create!(:board_id => board.id, :author_id => 2,
290 :subject => 'foo', :content => 'foo')
290 :subject => 'foo', :content => 'foo')
291 User.find(2).destroy
291 User.find(2).destroy
292 assert_nil User.find_by_id(2)
292 assert_nil User.find_by_id(2)
293 assert_equal User.anonymous, message.reload.author
293 assert_equal User.anonymous, message.reload.author
294 end
294 end
295
295
296 def test_destroy_should_update_news
296 def test_destroy_should_update_news
297 news = News.create!(:project_id => 1, :author_id => 2,
297 news = News.create!(:project_id => 1, :author_id => 2,
298 :title => 'foo', :description => 'foo')
298 :title => 'foo', :description => 'foo')
299 User.find(2).destroy
299 User.find(2).destroy
300 assert_nil User.find_by_id(2)
300 assert_nil User.find_by_id(2)
301 assert_equal User.anonymous, news.reload.author
301 assert_equal User.anonymous, news.reload.author
302 end
302 end
303
303
304 def test_destroy_should_delete_private_queries
304 def test_destroy_should_delete_private_queries
305 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
305 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
306 query.project_id = 1
306 query.project_id = 1
307 query.user_id = 2
307 query.user_id = 2
308 query.save!
308 query.save!
309
309
310 User.find(2).destroy
310 User.find(2).destroy
311 assert_nil User.find_by_id(2)
311 assert_nil User.find_by_id(2)
312 assert_nil Query.find_by_id(query.id)
312 assert_nil Query.find_by_id(query.id)
313 end
313 end
314
314
315 def test_destroy_should_update_public_queries
315 def test_destroy_should_update_public_queries
316 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
316 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
317 query.project_id = 1
317 query.project_id = 1
318 query.user_id = 2
318 query.user_id = 2
319 query.save!
319 query.save!
320
320
321 User.find(2).destroy
321 User.find(2).destroy
322 assert_nil User.find_by_id(2)
322 assert_nil User.find_by_id(2)
323 assert_equal User.anonymous, query.reload.user
323 assert_equal User.anonymous, query.reload.user
324 end
324 end
325
325
326 def test_destroy_should_update_time_entries
326 def test_destroy_should_update_time_entries
327 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
327 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
328 :activity => TimeEntryActivity.create!(:name => 'foo'))
328 :activity => TimeEntryActivity.create!(:name => 'foo'))
329 entry.project_id = 1
329 entry.project_id = 1
330 entry.user_id = 2
330 entry.user_id = 2
331 entry.save!
331 entry.save!
332
332
333 User.find(2).destroy
333 User.find(2).destroy
334 assert_nil User.find_by_id(2)
334 assert_nil User.find_by_id(2)
335 assert_equal User.anonymous, entry.reload.user
335 assert_equal User.anonymous, entry.reload.user
336 end
336 end
337
337
338 def test_destroy_should_delete_tokens
338 def test_destroy_should_delete_tokens
339 token = Token.create!(:user_id => 2, :value => 'foo')
339 token = Token.create!(:user_id => 2, :value => 'foo')
340
340
341 User.find(2).destroy
341 User.find(2).destroy
342 assert_nil User.find_by_id(2)
342 assert_nil User.find_by_id(2)
343 assert_nil Token.find_by_id(token.id)
343 assert_nil Token.find_by_id(token.id)
344 end
344 end
345
345
346 def test_destroy_should_delete_watchers
346 def test_destroy_should_delete_watchers
347 issue = Issue.create!(:project_id => 1, :author_id => 1,
347 issue = Issue.create!(:project_id => 1, :author_id => 1,
348 :tracker_id => 1, :subject => 'foo')
348 :tracker_id => 1, :subject => 'foo')
349 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
349 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
350
350
351 User.find(2).destroy
351 User.find(2).destroy
352 assert_nil User.find_by_id(2)
352 assert_nil User.find_by_id(2)
353 assert_nil Watcher.find_by_id(watcher.id)
353 assert_nil Watcher.find_by_id(watcher.id)
354 end
354 end
355
355
356 def test_destroy_should_update_wiki_contents
356 def test_destroy_should_update_wiki_contents
357 wiki_content = WikiContent.create!(
357 wiki_content = WikiContent.create!(
358 :text => 'foo',
358 :text => 'foo',
359 :author_id => 2,
359 :author_id => 2,
360 :page => WikiPage.create!(:title => 'Foo',
360 :page => WikiPage.create!(:title => 'Foo',
361 :wiki => Wiki.create!(:project_id => 3,
361 :wiki => Wiki.create!(:project_id => 3,
362 :start_page => 'Start'))
362 :start_page => 'Start'))
363 )
363 )
364 wiki_content.text = 'bar'
364 wiki_content.text = 'bar'
365 assert_difference 'WikiContent::Version.count' do
365 assert_difference 'WikiContent::Version.count' do
366 wiki_content.save!
366 wiki_content.save!
367 end
367 end
368
368
369 User.find(2).destroy
369 User.find(2).destroy
370 assert_nil User.find_by_id(2)
370 assert_nil User.find_by_id(2)
371 assert_equal User.anonymous, wiki_content.reload.author
371 assert_equal User.anonymous, wiki_content.reload.author
372 wiki_content.versions.each do |version|
372 wiki_content.versions.each do |version|
373 assert_equal User.anonymous, version.reload.author
373 assert_equal User.anonymous, version.reload.author
374 end
374 end
375 end
375 end
376
376
377 def test_destroy_should_nullify_issue_categories
377 def test_destroy_should_nullify_issue_categories
378 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
378 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
379
379
380 User.find(2).destroy
380 User.find(2).destroy
381 assert_nil User.find_by_id(2)
381 assert_nil User.find_by_id(2)
382 assert_nil category.reload.assigned_to_id
382 assert_nil category.reload.assigned_to_id
383 end
383 end
384
384
385 def test_destroy_should_nullify_changesets
385 def test_destroy_should_nullify_changesets
386 changeset = Changeset.create!(
386 changeset = Changeset.create!(
387 :repository => Repository::Subversion.create!(
387 :repository => Repository::Subversion.create!(
388 :project_id => 1,
388 :project_id => 1,
389 :url => 'file:///tmp',
389 :url => 'file:///tmp',
390 :identifier => 'tmp'
390 :identifier => 'tmp'
391 ),
391 ),
392 :revision => '12',
392 :revision => '12',
393 :committed_on => Time.now,
393 :committed_on => Time.now,
394 :committer => 'jsmith'
394 :committer => 'jsmith'
395 )
395 )
396 assert_equal 2, changeset.user_id
396 assert_equal 2, changeset.user_id
397
397
398 User.find(2).destroy
398 User.find(2).destroy
399 assert_nil User.find_by_id(2)
399 assert_nil User.find_by_id(2)
400 assert_nil changeset.reload.user_id
400 assert_nil changeset.reload.user_id
401 end
401 end
402
402
403 def test_anonymous_user_should_not_be_destroyable
403 def test_anonymous_user_should_not_be_destroyable
404 assert_no_difference 'User.count' do
404 assert_no_difference 'User.count' do
405 assert_equal false, User.anonymous.destroy
405 assert_equal false, User.anonymous.destroy
406 end
406 end
407 end
407 end
408
408
409 def test_password_change_should_destroy_tokens
409 def test_password_change_should_destroy_tokens
410 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
410 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
411 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
411 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
412
412
413 user = User.find(2)
413 user = User.find(2)
414 user.password, user.password_confirmation = "a new password", "a new password"
414 user.password, user.password_confirmation = "a new password", "a new password"
415 assert user.save
415 assert user.save
416
416
417 assert_nil Token.find_by_id(recovery_token.id)
417 assert_nil Token.find_by_id(recovery_token.id)
418 assert_nil Token.find_by_id(autologin_token.id)
418 assert_nil Token.find_by_id(autologin_token.id)
419 end
419 end
420
420
421 def test_mail_change_should_destroy_tokens
421 def test_mail_change_should_destroy_tokens
422 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
422 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
423 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
423 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
424
424
425 user = User.find(2)
425 user = User.find(2)
426 user.mail = "user@somwehere.com"
426 user.mail = "user@somwehere.com"
427 assert user.save
427 assert user.save
428
428
429 assert_nil Token.find_by_id(recovery_token.id)
429 assert_nil Token.find_by_id(recovery_token.id)
430 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
430 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
431 end
431 end
432
432
433 def test_change_on_other_fields_should_not_destroy_tokens
433 def test_change_on_other_fields_should_not_destroy_tokens
434 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
434 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
435 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
435 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
436
436
437 user = User.find(2)
437 user = User.find(2)
438 user.firstname = "Bobby"
438 user.firstname = "Bobby"
439 assert user.save
439 assert user.save
440
440
441 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
441 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
442 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
442 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
443 end
443 end
444
444
445 def test_validate_login_presence
445 def test_validate_login_presence
446 @admin.login = ""
446 @admin.login = ""
447 assert !@admin.save
447 assert !@admin.save
448 assert_equal 1, @admin.errors.count
448 assert_equal 1, @admin.errors.count
449 end
449 end
450
450
451 def test_validate_mail_notification_inclusion
451 def test_validate_mail_notification_inclusion
452 u = User.new
452 u = User.new
453 u.mail_notification = 'foo'
453 u.mail_notification = 'foo'
454 u.save
454 u.save
455 assert_not_equal [], u.errors[:mail_notification]
455 assert_not_equal [], u.errors[:mail_notification]
456 end
456 end
457
457
458 def test_password
458 def test_password
459 user = User.try_to_login("admin", "admin")
459 user = User.try_to_login("admin", "admin")
460 assert_kind_of User, user
460 assert_kind_of User, user
461 assert_equal "admin", user.login
461 assert_equal "admin", user.login
462 user.password = "hello123"
462 user.password = "hello123"
463 assert user.save
463 assert user.save
464
464
465 user = User.try_to_login("admin", "hello123")
465 user = User.try_to_login("admin", "hello123")
466 assert_kind_of User, user
466 assert_kind_of User, user
467 assert_equal "admin", user.login
467 assert_equal "admin", user.login
468 end
468 end
469
469
470 def test_validate_password_length
470 def test_validate_password_length
471 with_settings :password_min_length => '100' do
471 with_settings :password_min_length => '100' do
472 user = User.new(:firstname => "new100",
472 user = User.new(:firstname => "new100",
473 :lastname => "user100", :mail => "newuser100@somenet.foo")
473 :lastname => "user100", :mail => "newuser100@somenet.foo")
474 user.login = "newuser100"
474 user.login = "newuser100"
475 user.password, user.password_confirmation = "password100", "password100"
475 user.password, user.password_confirmation = "password100", "password100"
476 assert !user.save
476 assert !user.save
477 assert_equal 1, user.errors.count
477 assert_equal 1, user.errors.count
478 end
478 end
479 end
479 end
480
480
481 def test_name_format
481 def test_name_format
482 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
482 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
483 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
483 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
484 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
484 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
485 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
485 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
486 end
486 end
487
487
488 def test_name_should_use_setting_as_default_format
488 def test_name_should_use_setting_as_default_format
489 with_settings :user_format => :firstname_lastname do
489 with_settings :user_format => :firstname_lastname do
490 assert_equal 'John Smith', @jsmith.reload.name
490 assert_equal 'John Smith', @jsmith.reload.name
491 end
491 end
492 with_settings :user_format => :username do
492 with_settings :user_format => :username do
493 assert_equal 'jsmith', @jsmith.reload.name
493 assert_equal 'jsmith', @jsmith.reload.name
494 end
494 end
495 with_settings :user_format => :lastname do
495 with_settings :user_format => :lastname do
496 assert_equal 'Smith', @jsmith.reload.name
496 assert_equal 'Smith', @jsmith.reload.name
497 end
497 end
498 end
498 end
499
499
500 def test_today_should_return_the_day_according_to_user_time_zone
500 def test_today_should_return_the_day_according_to_user_time_zone
501 preference = User.find(1).pref
501 preference = User.find(1).pref
502 date = Date.new(2012, 05, 15)
502 date = Date.new(2012, 05, 15)
503 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
503 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
504 Date.stubs(:today).returns(date)
504 Date.stubs(:today).returns(date)
505 Time.stubs(:now).returns(time)
505 Time.stubs(:now).returns(time)
506
506
507 preference.update_attribute :time_zone, 'Baku' # UTC+4
507 preference.update_attribute :time_zone, 'Baku' # UTC+4
508 assert_equal '2012-05-16', User.find(1).today.to_s
508 assert_equal '2012-05-16', User.find(1).today.to_s
509
509
510 preference.update_attribute :time_zone, 'La Paz' # UTC-4
510 preference.update_attribute :time_zone, 'La Paz' # UTC-4
511 assert_equal '2012-05-15', User.find(1).today.to_s
511 assert_equal '2012-05-15', User.find(1).today.to_s
512
512
513 preference.update_attribute :time_zone, ''
513 preference.update_attribute :time_zone, ''
514 assert_equal '2012-05-15', User.find(1).today.to_s
514 assert_equal '2012-05-15', User.find(1).today.to_s
515 end
515 end
516
516
517 def test_time_to_date_should_return_the_date_according_to_user_time_zone
517 def test_time_to_date_should_return_the_date_according_to_user_time_zone
518 preference = User.find(1).pref
518 preference = User.find(1).pref
519 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
519 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
520
520
521 preference.update_attribute :time_zone, 'Baku' # UTC+4
521 preference.update_attribute :time_zone, 'Baku' # UTC+4
522 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
522 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
523
523
524 preference.update_attribute :time_zone, 'La Paz' # UTC-4
524 preference.update_attribute :time_zone, 'La Paz' # UTC-4
525 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
525 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
526
526
527 preference.update_attribute :time_zone, ''
527 preference.update_attribute :time_zone, ''
528 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
528 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
529 end
529 end
530
530
531 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
531 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
532 with_settings :user_format => 'lastname_coma_firstname' do
532 with_settings :user_format => 'lastname_coma_firstname' do
533 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
533 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
534 User.fields_for_order_statement
534 User.fields_for_order_statement
535 end
535 end
536 end
536 end
537
537
538 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
538 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
539 with_settings :user_format => 'lastname_firstname' do
539 with_settings :user_format => 'lastname_firstname' do
540 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
540 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
541 User.fields_for_order_statement('authors')
541 User.fields_for_order_statement('authors')
542 end
542 end
543 end
543 end
544
544
545 def test_fields_for_order_statement_with_blank_format_should_return_default
545 def test_fields_for_order_statement_with_blank_format_should_return_default
546 with_settings :user_format => '' do
546 with_settings :user_format => '' do
547 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
547 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
548 User.fields_for_order_statement
548 User.fields_for_order_statement
549 end
549 end
550 end
550 end
551
551
552 def test_fields_for_order_statement_with_invalid_format_should_return_default
552 def test_fields_for_order_statement_with_invalid_format_should_return_default
553 with_settings :user_format => 'foo' do
553 with_settings :user_format => 'foo' do
554 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
554 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
555 User.fields_for_order_statement
555 User.fields_for_order_statement
556 end
556 end
557 end
557 end
558
558
559 test ".try_to_login with good credentials should return the user" do
559 test ".try_to_login with good credentials should return the user" do
560 user = User.try_to_login("admin", "admin")
560 user = User.try_to_login("admin", "admin")
561 assert_kind_of User, user
561 assert_kind_of User, user
562 assert_equal "admin", user.login
562 assert_equal "admin", user.login
563 end
563 end
564
564
565 test ".try_to_login with wrong credentials should return nil" do
565 test ".try_to_login with wrong credentials should return nil" do
566 assert_nil User.try_to_login("admin", "foo")
566 assert_nil User.try_to_login("admin", "foo")
567 end
567 end
568
568
569 def test_try_to_login_with_locked_user_should_return_nil
569 def test_try_to_login_with_locked_user_should_return_nil
570 @jsmith.status = User::STATUS_LOCKED
570 @jsmith.status = User::STATUS_LOCKED
571 @jsmith.save!
571 @jsmith.save!
572
572
573 user = User.try_to_login("jsmith", "jsmith")
573 user = User.try_to_login("jsmith", "jsmith")
574 assert_equal nil, user
574 assert_equal nil, user
575 end
575 end
576
576
577 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
577 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
578 @jsmith.status = User::STATUS_LOCKED
578 @jsmith.status = User::STATUS_LOCKED
579 @jsmith.save!
579 @jsmith.save!
580
580
581 user = User.try_to_login("jsmith", "jsmith", false)
581 user = User.try_to_login("jsmith", "jsmith", false)
582 assert_equal @jsmith, user
582 assert_equal @jsmith, user
583 end
583 end
584
584
585 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
585 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
586 user = User.try_to_login("AdMin", "admin")
586 user = User.try_to_login("AdMin", "admin")
587 assert_kind_of User, user
587 assert_kind_of User, user
588 assert_equal "admin", user.login
588 assert_equal "admin", user.login
589 end
589 end
590
590
591 test ".try_to_login should select the exact matching user first" do
591 test ".try_to_login should select the exact matching user first" do
592 case_sensitive_user = User.generate! do |user|
592 case_sensitive_user = User.generate! do |user|
593 user.password = "admin123"
593 user.password = "admin123"
594 end
594 end
595 # bypass validations to make it appear like existing data
595 # bypass validations to make it appear like existing data
596 case_sensitive_user.update_attribute(:login, 'ADMIN')
596 case_sensitive_user.update_attribute(:login, 'ADMIN')
597
597
598 user = User.try_to_login("ADMIN", "admin123")
598 user = User.try_to_login("ADMIN", "admin123")
599 assert_kind_of User, user
599 assert_kind_of User, user
600 assert_equal "ADMIN", user.login
600 assert_equal "ADMIN", user.login
601 end
601 end
602
602
603 if ldap_configured?
603 if ldap_configured?
604 context "#try_to_login using LDAP" do
604 test "#try_to_login using LDAP with failed connection to the LDAP server" do
605 context "with failed connection to the LDAP server" do
605 auth_source = AuthSourceLdap.find(1)
606 should "return nil" do
606 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
607 @auth_source = AuthSourceLdap.find(1)
608 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
609
607
610 assert_equal nil, User.try_to_login('edavis', 'wrong')
608 assert_equal nil, User.try_to_login('edavis', 'wrong')
611 end
609 end
612 end
613
610
614 context "with an unsuccessful authentication" do
611 test "#try_to_login using LDAP" do
615 should "return nil" do
612 assert_equal nil, User.try_to_login('edavis', 'wrong')
616 assert_equal nil, User.try_to_login('edavis', 'wrong')
613 end
617 end
618 end
619
614
620 context "binding with user's account" do
615 test "#try_to_login using LDAP binding with user's account" do
621 setup do
616 auth_source = AuthSourceLdap.find(1)
622 @auth_source = AuthSourceLdap.find(1)
617 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
623 @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
618 auth_source.account_password = ''
624 @auth_source.account_password = ''
619 auth_source.save!
625 @auth_source.save!
626
620
627 @ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
621 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
628 @ldap_user.login = 'example1'
622 ldap_user.login = 'example1'
629 @ldap_user.save!
623 ldap_user.save!
630 end
631
624
632 context "with a successful authentication" do
625 assert_equal @ldap_user, User.try_to_login('example1', '123456')
633 should "return the user" do
626 assert_nil User.try_to_login('example1', '11111')
634 assert_equal @ldap_user, User.try_to_login('example1', '123456')
627 end
635 end
636 end
637
628
638 context "with an unsuccessful authentication" do
629 test "#try_to_login using LDAP on the fly registration" do
639 should "return nil" do
630 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
640 assert_nil User.try_to_login('example1', '11111')
631
641 end
632 assert_difference('User.count') do
642 end
633 assert User.try_to_login('edavis', '123456')
643 end
634 end
644
635
645 context "on the fly registration" do
636 assert_no_difference('User.count') do
646 setup do
637 assert User.try_to_login('edavis', '123456')
647 @auth_source = AuthSourceLdap.find(1)
638 end
648 @auth_source.update_attribute :onthefly_register, true
649 end
650
639
651 context "with a successful authentication" do
640 assert_nil User.try_to_login('example1', '11111')
652 should "create a new user account if it doesn't exist" do
641 end
653 assert_difference('User.count') do
654 user = User.try_to_login('edavis', '123456')
655 assert !user.admin?
656 end
657 end
658
659 should "retrieve existing user" do
660 user = User.try_to_login('edavis', '123456')
661 user.admin = true
662 user.save!
663
664 assert_no_difference('User.count') do
665 user = User.try_to_login('edavis', '123456')
666 assert user.admin?
667 end
668 end
669 end
670
642
671 context "binding with user's account" do
643 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
672 setup do
644 auth_source = AuthSourceLdap.find(1)
673 @auth_source = AuthSourceLdap.find(1)
645 auth_source.update_attribute :onthefly_register, true
674 @auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
646 auth_source = AuthSourceLdap.find(1)
675 @auth_source.account_password = ''
647 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
676 @auth_source.save!
648 auth_source.account_password = ''
677 end
649 auth_source.save!
678
650
679 context "with a successful authentication" do
651 assert_difference('User.count') do
680 should "create a new user account if it doesn't exist" do
652 assert User.try_to_login('example1', '123456')
681 assert_difference('User.count') do
682 user = User.try_to_login('example1', '123456')
683 assert_kind_of User, user
684 end
685 end
686 end
687
688 context "with an unsuccessful authentication" do
689 should "return nil" do
690 assert_nil User.try_to_login('example1', '11111')
691 end
692 end
693 end
694 end
653 end
654
655 assert_no_difference('User.count') do
656 assert User.try_to_login('edavis', '123456')
657 end
658
659 assert_nil User.try_to_login('example1', '11111')
695 end
660 end
696
661
697 else
662 else
698 puts "Skipping LDAP tests."
663 puts "Skipping LDAP tests."
699 end
664 end
700
665
701 def test_create_anonymous
666 def test_create_anonymous
702 AnonymousUser.delete_all
667 AnonymousUser.delete_all
703 anon = User.anonymous
668 anon = User.anonymous
704 assert !anon.new_record?
669 assert !anon.new_record?
705 assert_kind_of AnonymousUser, anon
670 assert_kind_of AnonymousUser, anon
706 end
671 end
707
672
708 def test_ensure_single_anonymous_user
673 def test_ensure_single_anonymous_user
709 AnonymousUser.delete_all
674 AnonymousUser.delete_all
710 anon1 = User.anonymous
675 anon1 = User.anonymous
711 assert !anon1.new_record?
676 assert !anon1.new_record?
712 assert_kind_of AnonymousUser, anon1
677 assert_kind_of AnonymousUser, anon1
713 anon2 = AnonymousUser.create(
678 anon2 = AnonymousUser.create(
714 :lastname => 'Anonymous', :firstname => '',
679 :lastname => 'Anonymous', :firstname => '',
715 :mail => '', :login => '', :status => 0)
680 :mail => '', :login => '', :status => 0)
716 assert_equal 1, anon2.errors.count
681 assert_equal 1, anon2.errors.count
717 end
682 end
718
683
719 def test_rss_key
684 def test_rss_key
720 assert_nil @jsmith.rss_token
685 assert_nil @jsmith.rss_token
721 key = @jsmith.rss_key
686 key = @jsmith.rss_key
722 assert_equal 40, key.length
687 assert_equal 40, key.length
723
688
724 @jsmith.reload
689 @jsmith.reload
725 assert_equal key, @jsmith.rss_key
690 assert_equal key, @jsmith.rss_key
726 end
691 end
727
692
728 def test_rss_key_should_not_be_generated_twice
693 def test_rss_key_should_not_be_generated_twice
729 assert_difference 'Token.count', 1 do
694 assert_difference 'Token.count', 1 do
730 key1 = @jsmith.rss_key
695 key1 = @jsmith.rss_key
731 key2 = @jsmith.rss_key
696 key2 = @jsmith.rss_key
732 assert_equal key1, key2
697 assert_equal key1, key2
733 end
698 end
734 end
699 end
735
700
736 def test_api_key_should_not_be_generated_twice
701 def test_api_key_should_not_be_generated_twice
737 assert_difference 'Token.count', 1 do
702 assert_difference 'Token.count', 1 do
738 key1 = @jsmith.api_key
703 key1 = @jsmith.api_key
739 key2 = @jsmith.api_key
704 key2 = @jsmith.api_key
740 assert_equal key1, key2
705 assert_equal key1, key2
741 end
706 end
742 end
707 end
743
708
744 test "#api_key should generate a new one if the user doesn't have one" do
709 test "#api_key should generate a new one if the user doesn't have one" do
745 user = User.generate!(:api_token => nil)
710 user = User.generate!(:api_token => nil)
746 assert_nil user.api_token
711 assert_nil user.api_token
747
712
748 key = user.api_key
713 key = user.api_key
749 assert_equal 40, key.length
714 assert_equal 40, key.length
750 user.reload
715 user.reload
751 assert_equal key, user.api_key
716 assert_equal key, user.api_key
752 end
717 end
753
718
754 test "#api_key should return the existing api token value" do
719 test "#api_key should return the existing api token value" do
755 user = User.generate!
720 user = User.generate!
756 token = Token.create!(:action => 'api')
721 token = Token.create!(:action => 'api')
757 user.api_token = token
722 user.api_token = token
758 assert user.save
723 assert user.save
759
724
760 assert_equal token.value, user.api_key
725 assert_equal token.value, user.api_key
761 end
726 end
762
727
763 test "#find_by_api_key should return nil if no matching key is found" do
728 test "#find_by_api_key should return nil if no matching key is found" do
764 assert_nil User.find_by_api_key('zzzzzzzzz')
729 assert_nil User.find_by_api_key('zzzzzzzzz')
765 end
730 end
766
731
767 test "#find_by_api_key should return nil if the key is found for an inactive user" do
732 test "#find_by_api_key should return nil if the key is found for an inactive user" do
768 user = User.generate!
733 user = User.generate!
769 user.status = User::STATUS_LOCKED
734 user.status = User::STATUS_LOCKED
770 token = Token.create!(:action => 'api')
735 token = Token.create!(:action => 'api')
771 user.api_token = token
736 user.api_token = token
772 user.save
737 user.save
773
738
774 assert_nil User.find_by_api_key(token.value)
739 assert_nil User.find_by_api_key(token.value)
775 end
740 end
776
741
777 test "#find_by_api_key should return the user if the key is found for an active user" do
742 test "#find_by_api_key should return the user if the key is found for an active user" do
778 user = User.generate!
743 user = User.generate!
779 token = Token.create!(:action => 'api')
744 token = Token.create!(:action => 'api')
780 user.api_token = token
745 user.api_token = token
781 user.save
746 user.save
782
747
783 assert_equal user, User.find_by_api_key(token.value)
748 assert_equal user, User.find_by_api_key(token.value)
784 end
749 end
785
750
786 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
751 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
787 user = User.find_by_login("admin")
752 user = User.find_by_login("admin")
788 user.password = "admin"
753 user.password = "admin"
789 assert user.save(:validate => false)
754 assert user.save(:validate => false)
790
755
791 assert_equal false, User.default_admin_account_changed?
756 assert_equal false, User.default_admin_account_changed?
792 end
757 end
793
758
794 def test_default_admin_account_changed_should_return_true_if_password_was_changed
759 def test_default_admin_account_changed_should_return_true_if_password_was_changed
795 user = User.find_by_login("admin")
760 user = User.find_by_login("admin")
796 user.password = "newpassword"
761 user.password = "newpassword"
797 user.save!
762 user.save!
798
763
799 assert_equal true, User.default_admin_account_changed?
764 assert_equal true, User.default_admin_account_changed?
800 end
765 end
801
766
802 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
767 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
803 user = User.find_by_login("admin")
768 user = User.find_by_login("admin")
804 user.password = "admin"
769 user.password = "admin"
805 user.status = User::STATUS_LOCKED
770 user.status = User::STATUS_LOCKED
806 assert user.save(:validate => false)
771 assert user.save(:validate => false)
807
772
808 assert_equal true, User.default_admin_account_changed?
773 assert_equal true, User.default_admin_account_changed?
809 end
774 end
810
775
811 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
776 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
812 user = User.find_by_login("admin")
777 user = User.find_by_login("admin")
813 user.destroy
778 user.destroy
814
779
815 assert_equal true, User.default_admin_account_changed?
780 assert_equal true, User.default_admin_account_changed?
816 end
781 end
817
782
818 def test_membership_with_project_should_return_membership
783 def test_membership_with_project_should_return_membership
819 project = Project.find(1)
784 project = Project.find(1)
820
785
821 membership = @jsmith.membership(project)
786 membership = @jsmith.membership(project)
822 assert_kind_of Member, membership
787 assert_kind_of Member, membership
823 assert_equal @jsmith, membership.user
788 assert_equal @jsmith, membership.user
824 assert_equal project, membership.project
789 assert_equal project, membership.project
825 end
790 end
826
791
827 def test_membership_with_project_id_should_return_membership
792 def test_membership_with_project_id_should_return_membership
828 project = Project.find(1)
793 project = Project.find(1)
829
794
830 membership = @jsmith.membership(1)
795 membership = @jsmith.membership(1)
831 assert_kind_of Member, membership
796 assert_kind_of Member, membership
832 assert_equal @jsmith, membership.user
797 assert_equal @jsmith, membership.user
833 assert_equal project, membership.project
798 assert_equal project, membership.project
834 end
799 end
835
800
836 def test_membership_for_non_member_should_return_nil
801 def test_membership_for_non_member_should_return_nil
837 project = Project.find(1)
802 project = Project.find(1)
838
803
839 user = User.generate!
804 user = User.generate!
840 membership = user.membership(1)
805 membership = user.membership(1)
841 assert_nil membership
806 assert_nil membership
842 end
807 end
843
808
844 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
809 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
845 roles = @jsmith.roles_for_project(Project.find(1))
810 roles = @jsmith.roles_for_project(Project.find(1))
846 assert_kind_of Role, roles.first
811 assert_kind_of Role, roles.first
847 assert_equal ["Manager"], roles.map(&:name)
812 assert_equal ["Manager"], roles.map(&:name)
848 end
813 end
849
814
850 def test_roles_for_project_with_member_on_private_project_should_return_roles
815 def test_roles_for_project_with_member_on_private_project_should_return_roles
851 Project.find(1).update_attribute :is_public, false
816 Project.find(1).update_attribute :is_public, false
852
817
853 roles = @jsmith.roles_for_project(Project.find(1))
818 roles = @jsmith.roles_for_project(Project.find(1))
854 assert_kind_of Role, roles.first
819 assert_kind_of Role, roles.first
855 assert_equal ["Manager"], roles.map(&:name)
820 assert_equal ["Manager"], roles.map(&:name)
856 end
821 end
857
822
858 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
823 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
859 set_language_if_valid 'en'
824 set_language_if_valid 'en'
860 roles = User.find(8).roles_for_project(Project.find(1))
825 roles = User.find(8).roles_for_project(Project.find(1))
861 assert_equal ["Non member"], roles.map(&:name)
826 assert_equal ["Non member"], roles.map(&:name)
862 end
827 end
863
828
864 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
829 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
865 project = Project.find(1)
830 project = Project.find(1)
866 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
831 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
867 roles = User.find(8).roles_for_project(project)
832 roles = User.find(8).roles_for_project(project)
868 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
833 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
869 end
834 end
870
835
871 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
836 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
872 Project.find(1).update_attribute :is_public, false
837 Project.find(1).update_attribute :is_public, false
873
838
874 roles = User.find(8).roles_for_project(Project.find(1))
839 roles = User.find(8).roles_for_project(Project.find(1))
875 assert_equal [], roles.map(&:name)
840 assert_equal [], roles.map(&:name)
876 end
841 end
877
842
878 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
843 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
879 project = Project.find(1)
844 project = Project.find(1)
880 project.update_attribute :is_public, false
845 project.update_attribute :is_public, false
881 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
846 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
882 roles = User.find(8).roles_for_project(project)
847 roles = User.find(8).roles_for_project(project)
883 assert_equal [], roles.map(&:name).sort
848 assert_equal [], roles.map(&:name).sort
884 end
849 end
885
850
886 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
851 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
887 set_language_if_valid 'en'
852 set_language_if_valid 'en'
888 roles = User.anonymous.roles_for_project(Project.find(1))
853 roles = User.anonymous.roles_for_project(Project.find(1))
889 assert_equal ["Anonymous"], roles.map(&:name)
854 assert_equal ["Anonymous"], roles.map(&:name)
890 end
855 end
891
856
892 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
857 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
893 project = Project.find(1)
858 project = Project.find(1)
894 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
859 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
895 roles = User.anonymous.roles_for_project(project)
860 roles = User.anonymous.roles_for_project(project)
896 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
861 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
897 end
862 end
898
863
899 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
864 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
900 Project.find(1).update_attribute :is_public, false
865 Project.find(1).update_attribute :is_public, false
901
866
902 roles = User.anonymous.roles_for_project(Project.find(1))
867 roles = User.anonymous.roles_for_project(Project.find(1))
903 assert_equal [], roles.map(&:name)
868 assert_equal [], roles.map(&:name)
904 end
869 end
905
870
906 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
871 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
907 project = Project.find(1)
872 project = Project.find(1)
908 project.update_attribute :is_public, false
873 project.update_attribute :is_public, false
909 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
874 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
910 roles = User.anonymous.roles_for_project(project)
875 roles = User.anonymous.roles_for_project(project)
911 assert_equal [], roles.map(&:name).sort
876 assert_equal [], roles.map(&:name).sort
912 end
877 end
913
878
914 def test_projects_by_role_for_user_with_role
879 def test_projects_by_role_for_user_with_role
915 user = User.find(2)
880 user = User.find(2)
916 assert_kind_of Hash, user.projects_by_role
881 assert_kind_of Hash, user.projects_by_role
917 assert_equal 2, user.projects_by_role.size
882 assert_equal 2, user.projects_by_role.size
918 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
883 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
919 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
884 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
920 end
885 end
921
886
922 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
887 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
923 user = User.find(2)
888 user = User.find(2)
924 assert_equal [], user.projects_by_role[Role.find(3)]
889 assert_equal [], user.projects_by_role[Role.find(3)]
925 # should not update the hash
890 # should not update the hash
926 assert_nil user.projects_by_role.values.detect(&:blank?)
891 assert_nil user.projects_by_role.values.detect(&:blank?)
927 end
892 end
928
893
929 def test_projects_by_role_for_user_with_no_role
894 def test_projects_by_role_for_user_with_no_role
930 user = User.generate!
895 user = User.generate!
931 assert_equal({}, user.projects_by_role)
896 assert_equal({}, user.projects_by_role)
932 end
897 end
933
898
934 def test_projects_by_role_for_anonymous
899 def test_projects_by_role_for_anonymous
935 assert_equal({}, User.anonymous.projects_by_role)
900 assert_equal({}, User.anonymous.projects_by_role)
936 end
901 end
937
902
938 def test_valid_notification_options
903 def test_valid_notification_options
939 # without memberships
904 # without memberships
940 assert_equal 5, User.find(7).valid_notification_options.size
905 assert_equal 5, User.find(7).valid_notification_options.size
941 # with memberships
906 # with memberships
942 assert_equal 6, User.find(2).valid_notification_options.size
907 assert_equal 6, User.find(2).valid_notification_options.size
943 end
908 end
944
909
945 def test_valid_notification_options_class_method
910 def test_valid_notification_options_class_method
946 assert_equal 5, User.valid_notification_options.size
911 assert_equal 5, User.valid_notification_options.size
947 assert_equal 5, User.valid_notification_options(User.find(7)).size
912 assert_equal 5, User.valid_notification_options(User.find(7)).size
948 assert_equal 6, User.valid_notification_options(User.find(2)).size
913 assert_equal 6, User.valid_notification_options(User.find(2)).size
949 end
914 end
950
915
951 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
916 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
952 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
917 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
953 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
918 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
954 end
919 end
955
920
956 def test_mail_notification_all
921 def test_mail_notification_all
957 @jsmith.mail_notification = 'all'
922 @jsmith.mail_notification = 'all'
958 @jsmith.notified_project_ids = []
923 @jsmith.notified_project_ids = []
959 @jsmith.save
924 @jsmith.save
960 @jsmith.reload
925 @jsmith.reload
961 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
926 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
962 end
927 end
963
928
964 def test_mail_notification_selected
929 def test_mail_notification_selected
965 @jsmith.mail_notification = 'selected'
930 @jsmith.mail_notification = 'selected'
966 @jsmith.notified_project_ids = [1]
931 @jsmith.notified_project_ids = [1]
967 @jsmith.save
932 @jsmith.save
968 @jsmith.reload
933 @jsmith.reload
969 assert Project.find(1).recipients.include?(@jsmith.mail)
934 assert Project.find(1).recipients.include?(@jsmith.mail)
970 end
935 end
971
936
972 def test_mail_notification_only_my_events
937 def test_mail_notification_only_my_events
973 @jsmith.mail_notification = 'only_my_events'
938 @jsmith.mail_notification = 'only_my_events'
974 @jsmith.notified_project_ids = []
939 @jsmith.notified_project_ids = []
975 @jsmith.save
940 @jsmith.save
976 @jsmith.reload
941 @jsmith.reload
977 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
942 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
978 end
943 end
979
944
980 def test_comments_sorting_preference
945 def test_comments_sorting_preference
981 assert !@jsmith.wants_comments_in_reverse_order?
946 assert !@jsmith.wants_comments_in_reverse_order?
982 @jsmith.pref.comments_sorting = 'asc'
947 @jsmith.pref.comments_sorting = 'asc'
983 assert !@jsmith.wants_comments_in_reverse_order?
948 assert !@jsmith.wants_comments_in_reverse_order?
984 @jsmith.pref.comments_sorting = 'desc'
949 @jsmith.pref.comments_sorting = 'desc'
985 assert @jsmith.wants_comments_in_reverse_order?
950 assert @jsmith.wants_comments_in_reverse_order?
986 end
951 end
987
952
988 def test_find_by_mail_should_be_case_insensitive
953 def test_find_by_mail_should_be_case_insensitive
989 u = User.find_by_mail('JSmith@somenet.foo')
954 u = User.find_by_mail('JSmith@somenet.foo')
990 assert_not_nil u
955 assert_not_nil u
991 assert_equal 'jsmith@somenet.foo', u.mail
956 assert_equal 'jsmith@somenet.foo', u.mail
992 end
957 end
993
958
994 def test_random_password
959 def test_random_password
995 u = User.new
960 u = User.new
996 u.random_password
961 u.random_password
997 assert !u.password.blank?
962 assert !u.password.blank?
998 assert !u.password_confirmation.blank?
963 assert !u.password_confirmation.blank?
999 end
964 end
1000
965
1001 test "#change_password_allowed? should be allowed if no auth source is set" do
966 test "#change_password_allowed? should be allowed if no auth source is set" do
1002 user = User.generate!
967 user = User.generate!
1003 assert user.change_password_allowed?
968 assert user.change_password_allowed?
1004 end
969 end
1005
970
1006 test "#change_password_allowed? should delegate to the auth source" do
971 test "#change_password_allowed? should delegate to the auth source" do
1007 user = User.generate!
972 user = User.generate!
1008
973
1009 allowed_auth_source = AuthSource.generate!
974 allowed_auth_source = AuthSource.generate!
1010 def allowed_auth_source.allow_password_changes?; true; end
975 def allowed_auth_source.allow_password_changes?; true; end
1011
976
1012 denied_auth_source = AuthSource.generate!
977 denied_auth_source = AuthSource.generate!
1013 def denied_auth_source.allow_password_changes?; false; end
978 def denied_auth_source.allow_password_changes?; false; end
1014
979
1015 assert user.change_password_allowed?
980 assert user.change_password_allowed?
1016
981
1017 user.auth_source = allowed_auth_source
982 user.auth_source = allowed_auth_source
1018 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
983 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1019
984
1020 user.auth_source = denied_auth_source
985 user.auth_source = denied_auth_source
1021 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
986 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1022 end
987 end
1023
988
1024 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
989 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1025 with_settings :unsubscribe => '1' do
990 with_settings :unsubscribe => '1' do
1026 assert_equal true, User.find(2).own_account_deletable?
991 assert_equal true, User.find(2).own_account_deletable?
1027 end
992 end
1028 end
993 end
1029
994
1030 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
995 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1031 with_settings :unsubscribe => '0' do
996 with_settings :unsubscribe => '0' do
1032 assert_equal false, User.find(2).own_account_deletable?
997 assert_equal false, User.find(2).own_account_deletable?
1033 end
998 end
1034 end
999 end
1035
1000
1036 def test_own_account_deletable_should_be_false_for_a_single_admin
1001 def test_own_account_deletable_should_be_false_for_a_single_admin
1037 User.delete_all(["admin = ? AND id <> ?", true, 1])
1002 User.delete_all(["admin = ? AND id <> ?", true, 1])
1038
1003
1039 with_settings :unsubscribe => '1' do
1004 with_settings :unsubscribe => '1' do
1040 assert_equal false, User.find(1).own_account_deletable?
1005 assert_equal false, User.find(1).own_account_deletable?
1041 end
1006 end
1042 end
1007 end
1043
1008
1044 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1009 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1045 User.generate! do |user|
1010 User.generate! do |user|
1046 user.admin = true
1011 user.admin = true
1047 end
1012 end
1048
1013
1049 with_settings :unsubscribe => '1' do
1014 with_settings :unsubscribe => '1' do
1050 assert_equal true, User.find(1).own_account_deletable?
1015 assert_equal true, User.find(1).own_account_deletable?
1051 end
1016 end
1052 end
1017 end
1053
1018
1054 context "#allowed_to?" do
1019 context "#allowed_to?" do
1055 context "with a unique project" do
1020 context "with a unique project" do
1056 should "return false if project is archived" do
1021 should "return false if project is archived" do
1057 project = Project.find(1)
1022 project = Project.find(1)
1058 Project.any_instance.stubs(:status).returns(Project::STATUS_ARCHIVED)
1023 Project.any_instance.stubs(:status).returns(Project::STATUS_ARCHIVED)
1059 assert_equal false, @admin.allowed_to?(:view_issues, Project.find(1))
1024 assert_equal false, @admin.allowed_to?(:view_issues, Project.find(1))
1060 end
1025 end
1061
1026
1062 should "return false for write action if project is closed" do
1027 should "return false for write action if project is closed" do
1063 project = Project.find(1)
1028 project = Project.find(1)
1064 Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
1029 Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
1065 assert_equal false, @admin.allowed_to?(:edit_project, Project.find(1))
1030 assert_equal false, @admin.allowed_to?(:edit_project, Project.find(1))
1066 end
1031 end
1067
1032
1068 should "return true for read action if project is closed" do
1033 should "return true for read action if project is closed" do
1069 project = Project.find(1)
1034 project = Project.find(1)
1070 Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
1035 Project.any_instance.stubs(:status).returns(Project::STATUS_CLOSED)
1071 assert_equal true, @admin.allowed_to?(:view_project, Project.find(1))
1036 assert_equal true, @admin.allowed_to?(:view_project, Project.find(1))
1072 end
1037 end
1073
1038
1074 should "return false if related module is disabled" do
1039 should "return false if related module is disabled" do
1075 project = Project.find(1)
1040 project = Project.find(1)
1076 project.enabled_module_names = ["issue_tracking"]
1041 project.enabled_module_names = ["issue_tracking"]
1077 assert_equal true, @admin.allowed_to?(:add_issues, project)
1042 assert_equal true, @admin.allowed_to?(:add_issues, project)
1078 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1043 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1079 end
1044 end
1080
1045
1081 should "authorize nearly everything for admin users" do
1046 should "authorize nearly everything for admin users" do
1082 project = Project.find(1)
1047 project = Project.find(1)
1083 assert ! @admin.member_of?(project)
1048 assert ! @admin.member_of?(project)
1084 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1049 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1085 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1050 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1086 end
1051 end
1087 end
1052 end
1088
1053
1089 should "authorize normal users depending on their roles" do
1054 should "authorize normal users depending on their roles" do
1090 project = Project.find(1)
1055 project = Project.find(1)
1091 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1056 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1092 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1057 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1093 end
1058 end
1094 end
1059 end
1095
1060
1096 context "with multiple projects" do
1061 context "with multiple projects" do
1097 should "return false if array is empty" do
1062 should "return false if array is empty" do
1098 assert_equal false, @admin.allowed_to?(:view_project, [])
1063 assert_equal false, @admin.allowed_to?(:view_project, [])
1099 end
1064 end
1100
1065
1101 should "return true only if user has permission on all these projects" do
1066 should "return true only if user has permission on all these projects" do
1102 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1067 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1103 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1068 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1104 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1069 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1105 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1070 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1106 end
1071 end
1107
1072
1108 should "behave correctly with arrays of 1 project" do
1073 should "behave correctly with arrays of 1 project" do
1109 assert_equal false, User.anonymous.allowed_to?(:delete_issues, [Project.first])
1074 assert_equal false, User.anonymous.allowed_to?(:delete_issues, [Project.first])
1110 end
1075 end
1111 end
1076 end
1112
1077
1113 context "with options[:global]" do
1078 context "with options[:global]" do
1114 should "authorize if user has at least one role that has this permission" do
1079 should "authorize if user has at least one role that has this permission" do
1115 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1080 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1116 @anonymous = User.find(6)
1081 @anonymous = User.find(6)
1117 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1082 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1118 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1083 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1119 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1084 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1120 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1085 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1121 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1086 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1122 end
1087 end
1123 end
1088 end
1124 end
1089 end
1125
1090
1126 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1091 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1127 context "#allowed_to_globally?" do
1092 context "#allowed_to_globally?" do
1128 should "proxy to #allowed_to? and reflect global permissions" do
1093 should "proxy to #allowed_to? and reflect global permissions" do
1129 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1094 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1130 @anonymous = User.find(6)
1095 @anonymous = User.find(6)
1131 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1096 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1132 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1097 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1133 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1098 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1134 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1099 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1135 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1100 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1136 end
1101 end
1137 end
1102 end
1138
1103
1139 context "User#notify_about?" do
1104 context "User#notify_about?" do
1140 context "Issues" do
1105 context "Issues" do
1141 setup do
1106 setup do
1142 @project = Project.find(1)
1107 @project = Project.find(1)
1143 @author = User.generate!
1108 @author = User.generate!
1144 @assignee = User.generate!
1109 @assignee = User.generate!
1145 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1110 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1146 end
1111 end
1147
1112
1148 should "be true for a user with :all" do
1113 should "be true for a user with :all" do
1149 @author.update_attribute(:mail_notification, 'all')
1114 @author.update_attribute(:mail_notification, 'all')
1150 assert @author.notify_about?(@issue)
1115 assert @author.notify_about?(@issue)
1151 end
1116 end
1152
1117
1153 should "be false for a user with :none" do
1118 should "be false for a user with :none" do
1154 @author.update_attribute(:mail_notification, 'none')
1119 @author.update_attribute(:mail_notification, 'none')
1155 assert ! @author.notify_about?(@issue)
1120 assert ! @author.notify_about?(@issue)
1156 end
1121 end
1157
1122
1158 should "be false for a user with :only_my_events and isn't an author, creator, or assignee" do
1123 should "be false for a user with :only_my_events and isn't an author, creator, or assignee" do
1159 @user = User.generate!(:mail_notification => 'only_my_events')
1124 @user = User.generate!(:mail_notification => 'only_my_events')
1160 Member.create!(:user => @user, :project => @project, :role_ids => [1])
1125 Member.create!(:user => @user, :project => @project, :role_ids => [1])
1161 assert ! @user.notify_about?(@issue)
1126 assert ! @user.notify_about?(@issue)
1162 end
1127 end
1163
1128
1164 should "be true for a user with :only_my_events and is the author" do
1129 should "be true for a user with :only_my_events and is the author" do
1165 @author.update_attribute(:mail_notification, 'only_my_events')
1130 @author.update_attribute(:mail_notification, 'only_my_events')
1166 assert @author.notify_about?(@issue)
1131 assert @author.notify_about?(@issue)
1167 end
1132 end
1168
1133
1169 should "be true for a user with :only_my_events and is the assignee" do
1134 should "be true for a user with :only_my_events and is the assignee" do
1170 @assignee.update_attribute(:mail_notification, 'only_my_events')
1135 @assignee.update_attribute(:mail_notification, 'only_my_events')
1171 assert @assignee.notify_about?(@issue)
1136 assert @assignee.notify_about?(@issue)
1172 end
1137 end
1173
1138
1174 should "be true for a user with :only_assigned and is the assignee" do
1139 should "be true for a user with :only_assigned and is the assignee" do
1175 @assignee.update_attribute(:mail_notification, 'only_assigned')
1140 @assignee.update_attribute(:mail_notification, 'only_assigned')
1176 assert @assignee.notify_about?(@issue)
1141 assert @assignee.notify_about?(@issue)
1177 end
1142 end
1178
1143
1179 should "be false for a user with :only_assigned and is not the assignee" do
1144 should "be false for a user with :only_assigned and is not the assignee" do
1180 @author.update_attribute(:mail_notification, 'only_assigned')
1145 @author.update_attribute(:mail_notification, 'only_assigned')
1181 assert ! @author.notify_about?(@issue)
1146 assert ! @author.notify_about?(@issue)
1182 end
1147 end
1183
1148
1184 should "be true for a user with :only_owner and is the author" do
1149 should "be true for a user with :only_owner and is the author" do
1185 @author.update_attribute(:mail_notification, 'only_owner')
1150 @author.update_attribute(:mail_notification, 'only_owner')
1186 assert @author.notify_about?(@issue)
1151 assert @author.notify_about?(@issue)
1187 end
1152 end
1188
1153
1189 should "be false for a user with :only_owner and is not the author" do
1154 should "be false for a user with :only_owner and is not the author" do
1190 @assignee.update_attribute(:mail_notification, 'only_owner')
1155 @assignee.update_attribute(:mail_notification, 'only_owner')
1191 assert ! @assignee.notify_about?(@issue)
1156 assert ! @assignee.notify_about?(@issue)
1192 end
1157 end
1193
1158
1194 should "be true for a user with :selected and is the author" do
1159 should "be true for a user with :selected and is the author" do
1195 @author.update_attribute(:mail_notification, 'selected')
1160 @author.update_attribute(:mail_notification, 'selected')
1196 assert @author.notify_about?(@issue)
1161 assert @author.notify_about?(@issue)
1197 end
1162 end
1198
1163
1199 should "be true for a user with :selected and is the assignee" do
1164 should "be true for a user with :selected and is the assignee" do
1200 @assignee.update_attribute(:mail_notification, 'selected')
1165 @assignee.update_attribute(:mail_notification, 'selected')
1201 assert @assignee.notify_about?(@issue)
1166 assert @assignee.notify_about?(@issue)
1202 end
1167 end
1203
1168
1204 should "be false for a user with :selected and is not the author or assignee" do
1169 should "be false for a user with :selected and is not the author or assignee" do
1205 @user = User.generate!(:mail_notification => 'selected')
1170 @user = User.generate!(:mail_notification => 'selected')
1206 Member.create!(:user => @user, :project => @project, :role_ids => [1])
1171 Member.create!(:user => @user, :project => @project, :role_ids => [1])
1207 assert ! @user.notify_about?(@issue)
1172 assert ! @user.notify_about?(@issue)
1208 end
1173 end
1209 end
1174 end
1210 end
1175 end
1211
1176
1212 def test_notify_about_news
1177 def test_notify_about_news
1213 user = User.generate!
1178 user = User.generate!
1214 news = News.new
1179 news = News.new
1215
1180
1216 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1181 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1217 user.mail_notification = option
1182 user.mail_notification = option
1218 assert_equal (option != 'none'), user.notify_about?(news)
1183 assert_equal (option != 'none'), user.notify_about?(news)
1219 end
1184 end
1220 end
1185 end
1221
1186
1222 def test_salt_unsalted_passwords
1187 def test_salt_unsalted_passwords
1223 # Restore a user with an unsalted password
1188 # Restore a user with an unsalted password
1224 user = User.find(1)
1189 user = User.find(1)
1225 user.salt = nil
1190 user.salt = nil
1226 user.hashed_password = User.hash_password("unsalted")
1191 user.hashed_password = User.hash_password("unsalted")
1227 user.save!
1192 user.save!
1228
1193
1229 User.salt_unsalted_passwords!
1194 User.salt_unsalted_passwords!
1230
1195
1231 user.reload
1196 user.reload
1232 # Salt added
1197 # Salt added
1233 assert !user.salt.blank?
1198 assert !user.salt.blank?
1234 # Password still valid
1199 # Password still valid
1235 assert user.check_password?("unsalted")
1200 assert user.check_password?("unsalted")
1236 assert_equal user, User.try_to_login(user.login, "unsalted")
1201 assert_equal user, User.try_to_login(user.login, "unsalted")
1237 end
1202 end
1238
1203
1239 if Object.const_defined?(:OpenID)
1204 if Object.const_defined?(:OpenID)
1240 def test_setting_identity_url
1205 def test_setting_identity_url
1241 normalized_open_id_url = 'http://example.com/'
1206 normalized_open_id_url = 'http://example.com/'
1242 u = User.new( :identity_url => 'http://example.com/' )
1207 u = User.new( :identity_url => 'http://example.com/' )
1243 assert_equal normalized_open_id_url, u.identity_url
1208 assert_equal normalized_open_id_url, u.identity_url
1244 end
1209 end
1245
1210
1246 def test_setting_identity_url_without_trailing_slash
1211 def test_setting_identity_url_without_trailing_slash
1247 normalized_open_id_url = 'http://example.com/'
1212 normalized_open_id_url = 'http://example.com/'
1248 u = User.new( :identity_url => 'http://example.com' )
1213 u = User.new( :identity_url => 'http://example.com' )
1249 assert_equal normalized_open_id_url, u.identity_url
1214 assert_equal normalized_open_id_url, u.identity_url
1250 end
1215 end
1251
1216
1252 def test_setting_identity_url_without_protocol
1217 def test_setting_identity_url_without_protocol
1253 normalized_open_id_url = 'http://example.com/'
1218 normalized_open_id_url = 'http://example.com/'
1254 u = User.new( :identity_url => 'example.com' )
1219 u = User.new( :identity_url => 'example.com' )
1255 assert_equal normalized_open_id_url, u.identity_url
1220 assert_equal normalized_open_id_url, u.identity_url
1256 end
1221 end
1257
1222
1258 def test_setting_blank_identity_url
1223 def test_setting_blank_identity_url
1259 u = User.new( :identity_url => 'example.com' )
1224 u = User.new( :identity_url => 'example.com' )
1260 u.identity_url = ''
1225 u.identity_url = ''
1261 assert u.identity_url.blank?
1226 assert u.identity_url.blank?
1262 end
1227 end
1263
1228
1264 def test_setting_invalid_identity_url
1229 def test_setting_invalid_identity_url
1265 u = User.new( :identity_url => 'this is not an openid url' )
1230 u = User.new( :identity_url => 'this is not an openid url' )
1266 assert u.identity_url.blank?
1231 assert u.identity_url.blank?
1267 end
1232 end
1268 else
1233 else
1269 puts "Skipping openid tests."
1234 puts "Skipping openid tests."
1270 end
1235 end
1271 end
1236 end
General Comments 0
You need to be logged in to leave comments. Login now