You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

issues_custom_fields_visibility_test.rb 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. # Redmine - project management software
  2. # Copyright (C) 2006-2017 Jean-Philippe Lang
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; either version 2
  7. # of the License, or (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  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
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. require File.expand_path('../../test_helper', __FILE__)
  18. class IssuesCustomFieldsVisibilityTest < Redmine::ControllerTest
  19. tests IssuesController
  20. fixtures :projects,
  21. :users, :email_addresses, :user_preferences,
  22. :roles,
  23. :members,
  24. :member_roles,
  25. :issue_statuses,
  26. :trackers,
  27. :projects_trackers,
  28. :enabled_modules,
  29. :enumerations,
  30. :workflows,
  31. :custom_fields, :custom_fields_trackers
  32. def setup
  33. CustomField.destroy_all
  34. Issue.delete_all
  35. Watcher.delete_all
  36. field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all}
  37. @fields = []
  38. @fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true)))
  39. @fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2])))
  40. @fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3])))
  41. @issue = Issue.generate!(
  42. :author_id => 1,
  43. :project_id => 1,
  44. :tracker_id => 1,
  45. :custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'}
  46. )
  47. @user_with_role_on_other_project = User.generate!
  48. User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3))
  49. @users_to_test = {
  50. User.find(1) => [@field1, @field2, @field3],
  51. User.find(3) => [@field1, @field2],
  52. @user_with_role_on_other_project => [@field1], # should see field1 only on Project 1
  53. User.generate! => [@field1],
  54. User.anonymous => [@field1]
  55. }
  56. Member.where(:project_id => 1).each do |member|
  57. member.destroy unless @users_to_test.keys.include?(member.principal)
  58. end
  59. end
  60. def test_show_should_show_visible_custom_fields_only
  61. @users_to_test.each do |user, fields|
  62. @request.session[:user_id] = user.id
  63. get :show, :params => {
  64. :id => @issue.id
  65. }
  66. @fields.each_with_index do |field, i|
  67. if fields.include?(field)
  68. assert_select '.value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
  69. else
  70. assert_select '.value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
  71. end
  72. end
  73. end
  74. end
  75. def test_show_should_show_visible_custom_fields_only_in_api
  76. @users_to_test.each do |user, fields|
  77. with_settings :rest_api_enabled => '1' do
  78. get :show, :params => {
  79. :id => @issue.id,
  80. :format => 'xml',
  81. :include => 'custom_fields',
  82. :key => user.api_key
  83. }
  84. end
  85. @fields.each_with_index do |field, i|
  86. if fields.include?(field)
  87. assert_select "custom_field[id=?] value", field.id.to_s, {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} in API"
  88. else
  89. assert_select "custom_field[id=?] value", field.id.to_s, {:text => "Value#{i}", :count => 0}, "User #{user.id} was not able to view #{field.name} in API"
  90. end
  91. end
  92. end
  93. end
  94. def test_show_should_show_visible_custom_fields_only_in_history
  95. @issue.init_journal(User.find(1))
  96. @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
  97. @issue.save!
  98. @users_to_test.each do |user, fields|
  99. @request.session[:user_id] = user.id
  100. get :show, :params => {
  101. :id => @issue.id
  102. }
  103. @fields.each_with_index do |field, i|
  104. if fields.include?(field)
  105. assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change"
  106. else
  107. assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change"
  108. end
  109. end
  110. end
  111. end
  112. def test_show_should_show_visible_custom_fields_only_in_history_api
  113. @issue.init_journal(User.find(1))
  114. @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'}
  115. @issue.save!
  116. @users_to_test.each do |user, fields|
  117. with_settings :rest_api_enabled => '1' do
  118. get :show, :params => {
  119. :id => @issue.id,
  120. :format => 'xml',
  121. :include => 'journals',
  122. :key => user.api_key
  123. }
  124. end
  125. @fields.each_with_index do |field, i|
  126. if fields.include?(field)
  127. assert_select 'details old_value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change in API"
  128. else
  129. assert_select 'details old_value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change in API"
  130. end
  131. end
  132. end
  133. end
  134. def test_edit_should_show_visible_custom_fields_only
  135. Role.anonymous.add_permission! :edit_issues
  136. @users_to_test.each do |user, fields|
  137. @request.session[:user_id] = user.id
  138. get :edit, :params => {
  139. :id => @issue.id
  140. }
  141. @fields.each_with_index do |field, i|
  142. if fields.include?(field)
  143. assert_select 'input[value=?]', "Value#{i}", 1, "User #{user.id} was not able to edit #{field.name}"
  144. else
  145. assert_select 'input[value=?]', "Value#{i}", 0, "User #{user.id} was able to edit #{field.name}"
  146. end
  147. end
  148. end
  149. end
  150. def test_update_should_update_visible_custom_fields_only
  151. Role.anonymous.add_permission! :edit_issues
  152. @users_to_test.each do |user, fields|
  153. @request.session[:user_id] = user.id
  154. put :update, :params => {
  155. :id => @issue.id,
  156. :issue => {
  157. :custom_field_values => {
  158. @field1.id.to_s => "User#{user.id}Value0",
  159. @field2.id.to_s => "User#{user.id}Value1",
  160. @field3.id.to_s => "User#{user.id}Value2",
  161. }
  162. }
  163. }
  164. @issue.reload
  165. @fields.each_with_index do |field, i|
  166. if fields.include?(field)
  167. assert_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was not able to update #{field.name}"
  168. else
  169. assert_not_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was able to update #{field.name}"
  170. end
  171. end
  172. end
  173. end
  174. def test_index_should_show_visible_custom_fields_only
  175. @users_to_test.each do |user, fields|
  176. @request.session[:user_id] = user.id
  177. get :index, :params => {
  178. :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"})
  179. }
  180. @fields.each_with_index do |field, i|
  181. if fields.include?(field)
  182. assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}"
  183. else
  184. assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}"
  185. end
  186. end
  187. end
  188. end
  189. def test_index_as_csv_should_show_visible_custom_fields_only
  190. @users_to_test.each do |user, fields|
  191. @request.session[:user_id] = user.id
  192. get :index, :params => {
  193. :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}),
  194. :format => 'csv'
  195. }
  196. @fields.each_with_index do |field, i|
  197. if fields.include?(field)
  198. assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV"
  199. else
  200. assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV"
  201. end
  202. end
  203. end
  204. end
  205. def test_index_with_partial_custom_field_visibility
  206. CustomValue.delete_all
  207. Issue.delete_all
  208. p1 = Project.generate!
  209. p2 = Project.generate!
  210. user = User.generate!
  211. User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a)
  212. User.add_to_project(user, p2, Role.where(:id => 3).to_a)
  213. Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'})
  214. Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'})
  215. Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'})
  216. @request.session[:user_id] = user.id
  217. get :index, :params => {
  218. :c => ["subject", "cf_#{@field2.id}"]
  219. }
  220. assert_select 'td', :text => 'ValueA'
  221. assert_select 'td', :text => 'ValueB', :count => 0
  222. assert_select 'td', :text => 'ValueC'
  223. get :index, :params => {
  224. :sort => "cf_#{@field2.id}"
  225. }
  226. # ValueB is not visible to user and ignored while sorting
  227. assert_equal %w(ValueB ValueA ValueC), issues_in_list.map{|i| i.custom_field_value(@field2)}
  228. get :index, :params => {
  229. :set_filter => '1', "cf_#{@field2.id}" => '*',
  230. :sort => "cf_#{@field2.id}"
  231. }
  232. assert_equal %w(ValueA ValueC), issues_in_list.map{|i| i.custom_field_value(@field2)}
  233. CustomField.update_all(:field_format => 'list')
  234. get :index, :params => {
  235. :group => "cf_#{@field2.id}"
  236. }
  237. assert_equal %w(ValueA ValueC), issues_in_list.map{|i| i.custom_field_value(@field2)}
  238. end
  239. def test_create_should_send_notifications_according_custom_fields_visibility
  240. # anonymous user is never notified
  241. users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
  242. ActionMailer::Base.deliveries.clear
  243. @request.session[:user_id] = 1
  244. with_settings :bcc_recipients => '1' do
  245. assert_difference 'Issue.count' do
  246. post :create, :params => {
  247. :project_id => 1,
  248. :issue => {
  249. :tracker_id => 1,
  250. :status_id => 1,
  251. :subject => 'New issue',
  252. :priority_id => 5,
  253. :custom_field_values => {
  254. @field1.id.to_s => 'Value0', @field2.id.to_s => 'Value1', @field3.id.to_s => 'Value2'
  255. },
  256. :watcher_user_ids => users_to_test.keys.map(&:id)
  257. }
  258. }
  259. assert_response 302
  260. end
  261. end
  262. assert_equal users_to_test.keys.size, ActionMailer::Base.deliveries.size
  263. # tests that each user receives 1 email with the custom fields he is allowed to see only
  264. users_to_test.each do |user, fields|
  265. mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
  266. assert_equal 1, mails.size
  267. mail = mails.first
  268. @fields.each_with_index do |field, i|
  269. if fields.include?(field)
  270. assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification"
  271. else
  272. assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification"
  273. end
  274. end
  275. end
  276. end
  277. def test_update_should_send_notifications_according_custom_fields_visibility
  278. # anonymous user is never notified
  279. users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
  280. users_to_test.keys.each do |user|
  281. Watcher.create!(:user => user, :watchable => @issue)
  282. end
  283. ActionMailer::Base.deliveries.clear
  284. @request.session[:user_id] = 1
  285. with_settings :bcc_recipients => '1' do
  286. put :update, :params => {
  287. :id => @issue.id,
  288. :issue => {
  289. :custom_field_values => {
  290. @field1.id.to_s => 'NewValue0', @field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'
  291. }
  292. }
  293. }
  294. assert_response 302
  295. end
  296. assert_equal users_to_test.keys.size, ActionMailer::Base.deliveries.size
  297. # tests that each user receives 1 email with the custom fields he is allowed to see only
  298. users_to_test.each do |user, fields|
  299. mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
  300. assert_equal 1, mails.size
  301. mail = mails.first
  302. @fields.each_with_index do |field, i|
  303. if fields.include?(field)
  304. assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification"
  305. else
  306. assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification"
  307. end
  308. end
  309. end
  310. end
  311. def test_updating_hidden_custom_fields_only_should_not_notifiy_user
  312. # anonymous user is never notified
  313. users_to_test = @users_to_test.reject {|k,v| k.anonymous?}
  314. users_to_test.keys.each do |user|
  315. Watcher.create!(:user => user, :watchable => @issue)
  316. end
  317. ActionMailer::Base.deliveries.clear
  318. @request.session[:user_id] = 1
  319. with_settings :bcc_recipients => '1' do
  320. put :update, :params => {
  321. :id => @issue.id,
  322. :issue => {
  323. :custom_field_values => {
  324. @field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'
  325. }
  326. }
  327. }
  328. assert_response 302
  329. end
  330. users_to_test.each do |user, fields|
  331. mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail}
  332. if (fields & [@field2, @field3]).any?
  333. assert_equal 1, mails.size, "User #{user.id} was not notified"
  334. else
  335. assert_equal 0, mails.size, "User #{user.id} was notified"
  336. end
  337. end
  338. end
  339. end