The requested changes are too big and content was truncated. Show full diff
@@ -1,68 +1,71 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2016 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2016 Jean-Philippe Lang | |
3 | # |
|
3 | # | |
4 | # This program is free software; you can redistribute it and/or |
|
4 | # This program is free software; you can redistribute it and/or | |
5 | # modify it under the terms of the GNU General Public License |
|
5 | # modify it under the terms of the GNU General Public License | |
6 | # as published by the Free Software Foundation; either version 2 |
|
6 | # as published by the Free Software Foundation; either version 2 | |
7 | # of the License, or (at your option) any later version. |
|
7 | # of the License, or (at your option) any later version. | |
8 | # |
|
8 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
12 | # GNU General Public License for more details. | |
13 | # |
|
13 | # | |
14 | # You should have received a copy of the GNU General Public License |
|
14 | # You should have received a copy of the GNU General Public License | |
15 | # along with this program; if not, write to the Free Software |
|
15 | # along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
17 |
|
17 | |||
18 | class UserPreference < ActiveRecord::Base |
|
18 | class UserPreference < ActiveRecord::Base | |
19 | belongs_to :user |
|
19 | belongs_to :user | |
20 | serialize :others |
|
20 | serialize :others | |
21 |
|
21 | |||
22 | attr_protected :others, :user_id |
|
22 | attr_protected :others, :user_id | |
23 |
|
23 | |||
24 | before_save :set_others_hash |
|
24 | before_save :set_others_hash | |
25 |
|
25 | |||
26 | def initialize(attributes=nil, *args) |
|
26 | def initialize(attributes=nil, *args) | |
27 | super |
|
27 | super | |
28 | if new_record? && !(attributes && attributes.key?(:hide_mail)) |
|
28 | if new_record? && !(attributes && attributes.key?(:hide_mail)) | |
29 | self.hide_mail = Setting.default_users_hide_mail? |
|
29 | self.hide_mail = Setting.default_users_hide_mail? | |
30 | end |
|
30 | end | |
|
31 | if new_record? && !(attributes && attributes.key?(:no_self_notified)) | |||
|
32 | self.no_self_notified = true | |||
|
33 | end | |||
31 | self.others ||= {} |
|
34 | self.others ||= {} | |
32 | end |
|
35 | end | |
33 |
|
36 | |||
34 | def set_others_hash |
|
37 | def set_others_hash | |
35 | self.others ||= {} |
|
38 | self.others ||= {} | |
36 | end |
|
39 | end | |
37 |
|
40 | |||
38 | def [](attr_name) |
|
41 | def [](attr_name) | |
39 | if has_attribute? attr_name |
|
42 | if has_attribute? attr_name | |
40 | super |
|
43 | super | |
41 | else |
|
44 | else | |
42 | others ? others[attr_name] : nil |
|
45 | others ? others[attr_name] : nil | |
43 | end |
|
46 | end | |
44 | end |
|
47 | end | |
45 |
|
48 | |||
46 | def []=(attr_name, value) |
|
49 | def []=(attr_name, value) | |
47 | if has_attribute? attr_name |
|
50 | if has_attribute? attr_name | |
48 | super |
|
51 | super | |
49 | else |
|
52 | else | |
50 | h = (read_attribute(:others) || {}).dup |
|
53 | h = (read_attribute(:others) || {}).dup | |
51 | h.update(attr_name => value) |
|
54 | h.update(attr_name => value) | |
52 | write_attribute(:others, h) |
|
55 | write_attribute(:others, h) | |
53 | value |
|
56 | value | |
54 | end |
|
57 | end | |
55 | end |
|
58 | end | |
56 |
|
59 | |||
57 | def comments_sorting; self[:comments_sorting] end |
|
60 | def comments_sorting; self[:comments_sorting] end | |
58 | def comments_sorting=(order); self[:comments_sorting]=order end |
|
61 | def comments_sorting=(order); self[:comments_sorting]=order end | |
59 |
|
62 | |||
60 | def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end |
|
63 | def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end | |
61 | def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end |
|
64 | def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end | |
62 |
|
65 | |||
63 | def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end |
|
66 | def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end | |
64 | def no_self_notified=(value); self[:no_self_notified]=value; end |
|
67 | def no_self_notified=(value); self[:no_self_notified]=value; end | |
65 |
|
68 | |||
66 | def activity_scope; Array(self[:activity_scope]) ; end |
|
69 | def activity_scope; Array(self[:activity_scope]) ; end | |
67 | def activity_scope=(value); self[:activity_scope]=value ; end |
|
70 | def activity_scope=(value); self[:activity_scope]=value ; end | |
68 | end |
|
71 | end |
@@ -1,31 +1,41 | |||||
1 | --- |
|
1 | --- | |
2 | user_preferences_001: |
|
2 | user_preferences_001: | |
3 | others: | |
|
3 | others: | | |
4 | --- |
|
4 | --- | |
|
5 | :no_self_notified: false | |||
5 | :my_page_layout: |
|
6 | :my_page_layout: | |
6 | left: |
|
7 | left: | |
7 | - latestnews |
|
8 | - latestnews | |
8 | - documents |
|
9 | - documents | |
9 | right: |
|
10 | right: | |
10 | - issuesassignedtome |
|
11 | - issuesassignedtome | |
11 | top: |
|
12 | top: | |
12 | - calendar |
|
13 | - calendar | |
13 |
|
14 | |||
14 | id: 1 |
|
15 | id: 1 | |
15 | user_id: 1 |
|
16 | user_id: 1 | |
16 | hide_mail: true |
|
17 | hide_mail: true | |
17 | user_preferences_002: |
|
18 | user_preferences_002: | |
18 | others: | |
|
19 | others: | | |
19 | --- |
|
20 | --- | |
|
21 | :no_self_notified: false | |||
|
22 | ||||
|
23 | id: 2 | |||
|
24 | user_id: 2 | |||
|
25 | hide_mail: true | |||
|
26 | user_preferences_003: | |||
|
27 | others: | | |||
|
28 | --- | |||
|
29 | :no_self_notified: false | |||
20 | :my_page_layout: |
|
30 | :my_page_layout: | |
21 | left: |
|
31 | left: | |
22 | - latestnews |
|
32 | - latestnews | |
23 | - documents |
|
33 | - documents | |
24 | right: |
|
34 | right: | |
25 | - issuesassignedtome |
|
35 | - issuesassignedtome | |
26 | top: |
|
36 | top: | |
27 | - calendar |
|
37 | - calendar | |
28 |
|
38 | |||
29 |
id: |
|
39 | id: 3 | |
30 | user_id: 3 |
|
40 | user_id: 3 | |
31 | hide_mail: false |
|
41 | hide_mail: false |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
@@ -1,322 +1,322 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2016 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2016 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 IssuesCustomFieldsVisibilityTest < ActionController::TestCase |
|
20 | class IssuesCustomFieldsVisibilityTest < ActionController::TestCase | |
21 | tests IssuesController |
|
21 | tests IssuesController | |
22 | fixtures :projects, |
|
22 | fixtures :projects, | |
23 | :users, :email_addresses, |
|
23 | :users, :email_addresses, :user_preferences, | |
24 | :roles, |
|
24 | :roles, | |
25 | :members, |
|
25 | :members, | |
26 | :member_roles, |
|
26 | :member_roles, | |
27 | :issue_statuses, |
|
27 | :issue_statuses, | |
28 | :trackers, |
|
28 | :trackers, | |
29 | :projects_trackers, |
|
29 | :projects_trackers, | |
30 | :enabled_modules, |
|
30 | :enabled_modules, | |
31 | :enumerations, |
|
31 | :enumerations, | |
32 | :workflows |
|
32 | :workflows | |
33 |
|
33 | |||
34 | def setup |
|
34 | def setup | |
35 | CustomField.delete_all |
|
35 | CustomField.delete_all | |
36 | Issue.delete_all |
|
36 | Issue.delete_all | |
37 | field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all} |
|
37 | field_attributes = {:field_format => 'string', :is_for_all => true, :is_filter => true, :trackers => Tracker.all} | |
38 | @fields = [] |
|
38 | @fields = [] | |
39 | @fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true))) |
|
39 | @fields << (@field1 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 1', :visible => true))) | |
40 | @fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2]))) |
|
40 | @fields << (@field2 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 2', :visible => false, :role_ids => [1, 2]))) | |
41 | @fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3]))) |
|
41 | @fields << (@field3 = IssueCustomField.create!(field_attributes.merge(:name => 'Field 3', :visible => false, :role_ids => [1, 3]))) | |
42 | @issue = Issue.generate!( |
|
42 | @issue = Issue.generate!( | |
43 | :author_id => 1, |
|
43 | :author_id => 1, | |
44 | :project_id => 1, |
|
44 | :project_id => 1, | |
45 | :tracker_id => 1, |
|
45 | :tracker_id => 1, | |
46 | :custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'} |
|
46 | :custom_field_values => {@field1.id => 'Value0', @field2.id => 'Value1', @field3.id => 'Value2'} | |
47 | ) |
|
47 | ) | |
48 |
|
48 | |||
49 | @user_with_role_on_other_project = User.generate! |
|
49 | @user_with_role_on_other_project = User.generate! | |
50 | User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3)) |
|
50 | User.add_to_project(@user_with_role_on_other_project, Project.find(2), Role.find(3)) | |
51 |
|
51 | |||
52 | @users_to_test = { |
|
52 | @users_to_test = { | |
53 | User.find(1) => [@field1, @field2, @field3], |
|
53 | User.find(1) => [@field1, @field2, @field3], | |
54 | User.find(3) => [@field1, @field2], |
|
54 | User.find(3) => [@field1, @field2], | |
55 | @user_with_role_on_other_project => [@field1], # should see field1 only on Project 1 |
|
55 | @user_with_role_on_other_project => [@field1], # should see field1 only on Project 1 | |
56 | User.generate! => [@field1], |
|
56 | User.generate! => [@field1], | |
57 | User.anonymous => [@field1] |
|
57 | User.anonymous => [@field1] | |
58 | } |
|
58 | } | |
59 |
|
59 | |||
60 | Member.where(:project_id => 1).each do |member| |
|
60 | Member.where(:project_id => 1).each do |member| | |
61 | member.destroy unless @users_to_test.keys.include?(member.principal) |
|
61 | member.destroy unless @users_to_test.keys.include?(member.principal) | |
62 | end |
|
62 | end | |
63 | end |
|
63 | end | |
64 |
|
64 | |||
65 | def test_show_should_show_visible_custom_fields_only |
|
65 | def test_show_should_show_visible_custom_fields_only | |
66 | @users_to_test.each do |user, fields| |
|
66 | @users_to_test.each do |user, fields| | |
67 | @request.session[:user_id] = user.id |
|
67 | @request.session[:user_id] = user.id | |
68 | get :show, :id => @issue.id |
|
68 | get :show, :id => @issue.id | |
69 | @fields.each_with_index do |field, i| |
|
69 | @fields.each_with_index do |field, i| | |
70 | if fields.include?(field) |
|
70 | if fields.include?(field) | |
71 | assert_select '.value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}" |
|
71 | assert_select '.value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}" | |
72 | else |
|
72 | else | |
73 | assert_select '.value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}" |
|
73 | assert_select '.value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}" | |
74 | end |
|
74 | end | |
75 | end |
|
75 | end | |
76 | end |
|
76 | end | |
77 | end |
|
77 | end | |
78 |
|
78 | |||
79 | def test_show_should_show_visible_custom_fields_only_in_api |
|
79 | def test_show_should_show_visible_custom_fields_only_in_api | |
80 | @users_to_test.each do |user, fields| |
|
80 | @users_to_test.each do |user, fields| | |
81 | with_settings :rest_api_enabled => '1' do |
|
81 | with_settings :rest_api_enabled => '1' do | |
82 | get :show, :id => @issue.id, :format => 'xml', :include => 'custom_fields', :key => user.api_key |
|
82 | get :show, :id => @issue.id, :format => 'xml', :include => 'custom_fields', :key => user.api_key | |
83 | end |
|
83 | end | |
84 | @fields.each_with_index do |field, i| |
|
84 | @fields.each_with_index do |field, i| | |
85 | if fields.include?(field) |
|
85 | if fields.include?(field) | |
86 | 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" |
|
86 | 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" | |
87 | else |
|
87 | else | |
88 | 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" |
|
88 | 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" | |
89 | end |
|
89 | end | |
90 | end |
|
90 | end | |
91 | end |
|
91 | end | |
92 | end |
|
92 | end | |
93 |
|
93 | |||
94 | def test_show_should_show_visible_custom_fields_only_in_history |
|
94 | def test_show_should_show_visible_custom_fields_only_in_history | |
95 | @issue.init_journal(User.find(1)) |
|
95 | @issue.init_journal(User.find(1)) | |
96 | @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'} |
|
96 | @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'} | |
97 | @issue.save! |
|
97 | @issue.save! | |
98 |
|
98 | |||
99 | @users_to_test.each do |user, fields| |
|
99 | @users_to_test.each do |user, fields| | |
100 | @request.session[:user_id] = user.id |
|
100 | @request.session[:user_id] = user.id | |
101 | get :show, :id => @issue.id |
|
101 | get :show, :id => @issue.id | |
102 | @fields.each_with_index do |field, i| |
|
102 | @fields.each_with_index do |field, i| | |
103 | if fields.include?(field) |
|
103 | if fields.include?(field) | |
104 | assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change" |
|
104 | assert_select 'ul.details i', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change" | |
105 | else |
|
105 | else | |
106 | assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change" |
|
106 | assert_select 'ul.details i', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change" | |
107 | end |
|
107 | end | |
108 | end |
|
108 | end | |
109 | end |
|
109 | end | |
110 | end |
|
110 | end | |
111 |
|
111 | |||
112 | def test_show_should_show_visible_custom_fields_only_in_history_api |
|
112 | def test_show_should_show_visible_custom_fields_only_in_history_api | |
113 | @issue.init_journal(User.find(1)) |
|
113 | @issue.init_journal(User.find(1)) | |
114 | @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'} |
|
114 | @issue.custom_field_values = {@field1.id => 'NewValue0', @field2.id => 'NewValue1', @field3.id => 'NewValue2'} | |
115 | @issue.save! |
|
115 | @issue.save! | |
116 |
|
116 | |||
117 | @users_to_test.each do |user, fields| |
|
117 | @users_to_test.each do |user, fields| | |
118 | with_settings :rest_api_enabled => '1' do |
|
118 | with_settings :rest_api_enabled => '1' do | |
119 | get :show, :id => @issue.id, :format => 'xml', :include => 'journals', :key => user.api_key |
|
119 | get :show, :id => @issue.id, :format => 'xml', :include => 'journals', :key => user.api_key | |
120 | end |
|
120 | end | |
121 | @fields.each_with_index do |field, i| |
|
121 | @fields.each_with_index do |field, i| | |
122 | if fields.include?(field) |
|
122 | if fields.include?(field) | |
123 | assert_select 'details old_value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change in API" |
|
123 | assert_select 'details old_value', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name} change in API" | |
124 | else |
|
124 | else | |
125 | assert_select 'details old_value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change in API" |
|
125 | assert_select 'details old_value', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name} change in API" | |
126 | end |
|
126 | end | |
127 | end |
|
127 | end | |
128 | end |
|
128 | end | |
129 | end |
|
129 | end | |
130 |
|
130 | |||
131 | def test_edit_should_show_visible_custom_fields_only |
|
131 | def test_edit_should_show_visible_custom_fields_only | |
132 | Role.anonymous.add_permission! :edit_issues |
|
132 | Role.anonymous.add_permission! :edit_issues | |
133 |
|
133 | |||
134 | @users_to_test.each do |user, fields| |
|
134 | @users_to_test.each do |user, fields| | |
135 | @request.session[:user_id] = user.id |
|
135 | @request.session[:user_id] = user.id | |
136 | get :edit, :id => @issue.id |
|
136 | get :edit, :id => @issue.id | |
137 | @fields.each_with_index do |field, i| |
|
137 | @fields.each_with_index do |field, i| | |
138 | if fields.include?(field) |
|
138 | if fields.include?(field) | |
139 | assert_select 'input[value=?]', "Value#{i}", 1, "User #{user.id} was not able to edit #{field.name}" |
|
139 | assert_select 'input[value=?]', "Value#{i}", 1, "User #{user.id} was not able to edit #{field.name}" | |
140 | else |
|
140 | else | |
141 | assert_select 'input[value=?]', "Value#{i}", 0, "User #{user.id} was able to edit #{field.name}" |
|
141 | assert_select 'input[value=?]', "Value#{i}", 0, "User #{user.id} was able to edit #{field.name}" | |
142 | end |
|
142 | end | |
143 | end |
|
143 | end | |
144 | end |
|
144 | end | |
145 | end |
|
145 | end | |
146 |
|
146 | |||
147 | def test_update_should_update_visible_custom_fields_only |
|
147 | def test_update_should_update_visible_custom_fields_only | |
148 | Role.anonymous.add_permission! :edit_issues |
|
148 | Role.anonymous.add_permission! :edit_issues | |
149 |
|
149 | |||
150 | @users_to_test.each do |user, fields| |
|
150 | @users_to_test.each do |user, fields| | |
151 | @request.session[:user_id] = user.id |
|
151 | @request.session[:user_id] = user.id | |
152 | put :update, :id => @issue.id, |
|
152 | put :update, :id => @issue.id, | |
153 | :issue => {:custom_field_values => { |
|
153 | :issue => {:custom_field_values => { | |
154 | @field1.id.to_s => "User#{user.id}Value0", |
|
154 | @field1.id.to_s => "User#{user.id}Value0", | |
155 | @field2.id.to_s => "User#{user.id}Value1", |
|
155 | @field2.id.to_s => "User#{user.id}Value1", | |
156 | @field3.id.to_s => "User#{user.id}Value2", |
|
156 | @field3.id.to_s => "User#{user.id}Value2", | |
157 | }} |
|
157 | }} | |
158 | @issue.reload |
|
158 | @issue.reload | |
159 | @fields.each_with_index do |field, i| |
|
159 | @fields.each_with_index do |field, i| | |
160 | if fields.include?(field) |
|
160 | if fields.include?(field) | |
161 | assert_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was not able to update #{field.name}" |
|
161 | assert_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was not able to update #{field.name}" | |
162 | else |
|
162 | else | |
163 | assert_not_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was able to update #{field.name}" |
|
163 | assert_not_equal "User#{user.id}Value#{i}", @issue.custom_field_value(field), "User #{user.id} was able to update #{field.name}" | |
164 | end |
|
164 | end | |
165 | end |
|
165 | end | |
166 | end |
|
166 | end | |
167 | end |
|
167 | end | |
168 |
|
168 | |||
169 | def test_index_should_show_visible_custom_fields_only |
|
169 | def test_index_should_show_visible_custom_fields_only | |
170 | @users_to_test.each do |user, fields| |
|
170 | @users_to_test.each do |user, fields| | |
171 | @request.session[:user_id] = user.id |
|
171 | @request.session[:user_id] = user.id | |
172 | get :index, :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}) |
|
172 | get :index, :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}) | |
173 | @fields.each_with_index do |field, i| |
|
173 | @fields.each_with_index do |field, i| | |
174 | if fields.include?(field) |
|
174 | if fields.include?(field) | |
175 | assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}" |
|
175 | assert_select 'td', {:text => "Value#{i}", :count => 1}, "User #{user.id} was not able to view #{field.name}" | |
176 | else |
|
176 | else | |
177 | assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}" |
|
177 | assert_select 'td', {:text => "Value#{i}", :count => 0}, "User #{user.id} was able to view #{field.name}" | |
178 | end |
|
178 | end | |
179 | end |
|
179 | end | |
180 | end |
|
180 | end | |
181 | end |
|
181 | end | |
182 |
|
182 | |||
183 | def test_index_as_csv_should_show_visible_custom_fields_only |
|
183 | def test_index_as_csv_should_show_visible_custom_fields_only | |
184 | @users_to_test.each do |user, fields| |
|
184 | @users_to_test.each do |user, fields| | |
185 | @request.session[:user_id] = user.id |
|
185 | @request.session[:user_id] = user.id | |
186 | get :index, :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}), :format => 'csv' |
|
186 | get :index, :c => (["subject"] + @fields.map{|f| "cf_#{f.id}"}), :format => 'csv' | |
187 | @fields.each_with_index do |field, i| |
|
187 | @fields.each_with_index do |field, i| | |
188 | if fields.include?(field) |
|
188 | if fields.include?(field) | |
189 | assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV" |
|
189 | assert_include "Value#{i}", response.body, "User #{user.id} was not able to view #{field.name} in CSV" | |
190 | else |
|
190 | else | |
191 | assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV" |
|
191 | assert_not_include "Value#{i}", response.body, "User #{user.id} was able to view #{field.name} in CSV" | |
192 | end |
|
192 | end | |
193 | end |
|
193 | end | |
194 | end |
|
194 | end | |
195 | end |
|
195 | end | |
196 |
|
196 | |||
197 | def test_index_with_partial_custom_field_visibility |
|
197 | def test_index_with_partial_custom_field_visibility | |
198 | Issue.delete_all |
|
198 | Issue.delete_all | |
199 | p1 = Project.generate! |
|
199 | p1 = Project.generate! | |
200 | p2 = Project.generate! |
|
200 | p2 = Project.generate! | |
201 | user = User.generate! |
|
201 | user = User.generate! | |
202 | User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a) |
|
202 | User.add_to_project(user, p1, Role.where(:id => [1, 3]).to_a) | |
203 | User.add_to_project(user, p2, Role.where(:id => 3).to_a) |
|
203 | User.add_to_project(user, p2, Role.where(:id => 3).to_a) | |
204 | Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'}) |
|
204 | Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueA'}) | |
205 | Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'}) |
|
205 | Issue.generate!(:project => p2, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueB'}) | |
206 | Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'}) |
|
206 | Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'}) | |
207 |
|
207 | |||
208 | @request.session[:user_id] = user.id |
|
208 | @request.session[:user_id] = user.id | |
209 | get :index, :c => ["subject", "cf_#{@field2.id}"] |
|
209 | get :index, :c => ["subject", "cf_#{@field2.id}"] | |
210 | assert_select 'td', :text => 'ValueA' |
|
210 | assert_select 'td', :text => 'ValueA' | |
211 | assert_select 'td', :text => 'ValueB', :count => 0 |
|
211 | assert_select 'td', :text => 'ValueB', :count => 0 | |
212 | assert_select 'td', :text => 'ValueC' |
|
212 | assert_select 'td', :text => 'ValueC' | |
213 |
|
213 | |||
214 | get :index, :sort => "cf_#{@field2.id}" |
|
214 | get :index, :sort => "cf_#{@field2.id}" | |
215 | # ValueB is not visible to user and ignored while sorting |
|
215 | # ValueB is not visible to user and ignored while sorting | |
216 | assert_equal %w(ValueB ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)} |
|
216 | assert_equal %w(ValueB ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)} | |
217 |
|
217 | |||
218 | get :index, :set_filter => '1', "cf_#{@field2.id}" => '*' |
|
218 | get :index, :set_filter => '1', "cf_#{@field2.id}" => '*' | |
219 | assert_equal %w(ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)} |
|
219 | assert_equal %w(ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)} | |
220 |
|
220 | |||
221 | CustomField.update_all(:field_format => 'list') |
|
221 | CustomField.update_all(:field_format => 'list') | |
222 | get :index, :group => "cf_#{@field2.id}" |
|
222 | get :index, :group => "cf_#{@field2.id}" | |
223 | assert_equal %w(ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)} |
|
223 | assert_equal %w(ValueA ValueC), assigns(:issues).map{|i| i.custom_field_value(@field2)} | |
224 | end |
|
224 | end | |
225 |
|
225 | |||
226 | def test_create_should_send_notifications_according_custom_fields_visibility |
|
226 | def test_create_should_send_notifications_according_custom_fields_visibility | |
227 | # anonymous user is never notified |
|
227 | # anonymous user is never notified | |
228 | users_to_test = @users_to_test.reject {|k,v| k.anonymous?} |
|
228 | users_to_test = @users_to_test.reject {|k,v| k.anonymous?} | |
229 |
|
229 | |||
230 | ActionMailer::Base.deliveries.clear |
|
230 | ActionMailer::Base.deliveries.clear | |
231 | @request.session[:user_id] = 1 |
|
231 | @request.session[:user_id] = 1 | |
232 | with_settings :bcc_recipients => '1' do |
|
232 | with_settings :bcc_recipients => '1' do | |
233 | assert_difference 'Issue.count' do |
|
233 | assert_difference 'Issue.count' do | |
234 | post :create, |
|
234 | post :create, | |
235 | :project_id => 1, |
|
235 | :project_id => 1, | |
236 | :issue => { |
|
236 | :issue => { | |
237 | :tracker_id => 1, |
|
237 | :tracker_id => 1, | |
238 | :status_id => 1, |
|
238 | :status_id => 1, | |
239 | :subject => 'New issue', |
|
239 | :subject => 'New issue', | |
240 | :priority_id => 5, |
|
240 | :priority_id => 5, | |
241 | :custom_field_values => {@field1.id.to_s => 'Value0', @field2.id.to_s => 'Value1', @field3.id.to_s => 'Value2'}, |
|
241 | :custom_field_values => {@field1.id.to_s => 'Value0', @field2.id.to_s => 'Value1', @field3.id.to_s => 'Value2'}, | |
242 | :watcher_user_ids => users_to_test.keys.map(&:id) |
|
242 | :watcher_user_ids => users_to_test.keys.map(&:id) | |
243 | } |
|
243 | } | |
244 | assert_response 302 |
|
244 | assert_response 302 | |
245 | end |
|
245 | end | |
246 | end |
|
246 | end | |
247 | assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size |
|
247 | assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size | |
248 | # tests that each user receives 1 email with the custom fields he is allowed to see only |
|
248 | # tests that each user receives 1 email with the custom fields he is allowed to see only | |
249 | users_to_test.each do |user, fields| |
|
249 | users_to_test.each do |user, fields| | |
250 | mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail} |
|
250 | mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail} | |
251 | assert_equal 1, mails.size |
|
251 | assert_equal 1, mails.size | |
252 | mail = mails.first |
|
252 | mail = mails.first | |
253 | @fields.each_with_index do |field, i| |
|
253 | @fields.each_with_index do |field, i| | |
254 | if fields.include?(field) |
|
254 | if fields.include?(field) | |
255 | assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification" |
|
255 | assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification" | |
256 | else |
|
256 | else | |
257 | assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification" |
|
257 | assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification" | |
258 | end |
|
258 | end | |
259 | end |
|
259 | end | |
260 | end |
|
260 | end | |
261 | end |
|
261 | end | |
262 |
|
262 | |||
263 | def test_update_should_send_notifications_according_custom_fields_visibility |
|
263 | def test_update_should_send_notifications_according_custom_fields_visibility | |
264 | # anonymous user is never notified |
|
264 | # anonymous user is never notified | |
265 | users_to_test = @users_to_test.reject {|k,v| k.anonymous?} |
|
265 | users_to_test = @users_to_test.reject {|k,v| k.anonymous?} | |
266 |
|
266 | |||
267 | users_to_test.keys.each do |user| |
|
267 | users_to_test.keys.each do |user| | |
268 | Watcher.create!(:user => user, :watchable => @issue) |
|
268 | Watcher.create!(:user => user, :watchable => @issue) | |
269 | end |
|
269 | end | |
270 | ActionMailer::Base.deliveries.clear |
|
270 | ActionMailer::Base.deliveries.clear | |
271 | @request.session[:user_id] = 1 |
|
271 | @request.session[:user_id] = 1 | |
272 | with_settings :bcc_recipients => '1' do |
|
272 | with_settings :bcc_recipients => '1' do | |
273 | put :update, |
|
273 | put :update, | |
274 | :id => @issue.id, |
|
274 | :id => @issue.id, | |
275 | :issue => { |
|
275 | :issue => { | |
276 | :custom_field_values => {@field1.id.to_s => 'NewValue0', @field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'} |
|
276 | :custom_field_values => {@field1.id.to_s => 'NewValue0', @field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'} | |
277 | } |
|
277 | } | |
278 | assert_response 302 |
|
278 | assert_response 302 | |
279 | end |
|
279 | end | |
280 | assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size |
|
280 | assert_equal users_to_test.values.uniq.size, ActionMailer::Base.deliveries.size | |
281 | # tests that each user receives 1 email with the custom fields he is allowed to see only |
|
281 | # tests that each user receives 1 email with the custom fields he is allowed to see only | |
282 | users_to_test.each do |user, fields| |
|
282 | users_to_test.each do |user, fields| | |
283 | mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail} |
|
283 | mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail} | |
284 | assert_equal 1, mails.size |
|
284 | assert_equal 1, mails.size | |
285 | mail = mails.first |
|
285 | mail = mails.first | |
286 | @fields.each_with_index do |field, i| |
|
286 | @fields.each_with_index do |field, i| | |
287 | if fields.include?(field) |
|
287 | if fields.include?(field) | |
288 | assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification" |
|
288 | assert_mail_body_match "Value#{i}", mail, "User #{user.id} was not able to view #{field.name} in notification" | |
289 | else |
|
289 | else | |
290 | assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification" |
|
290 | assert_mail_body_no_match "Value#{i}", mail, "User #{user.id} was able to view #{field.name} in notification" | |
291 | end |
|
291 | end | |
292 | end |
|
292 | end | |
293 | end |
|
293 | end | |
294 | end |
|
294 | end | |
295 |
|
295 | |||
296 | def test_updating_hidden_custom_fields_only_should_not_notifiy_user |
|
296 | def test_updating_hidden_custom_fields_only_should_not_notifiy_user | |
297 | # anonymous user is never notified |
|
297 | # anonymous user is never notified | |
298 | users_to_test = @users_to_test.reject {|k,v| k.anonymous?} |
|
298 | users_to_test = @users_to_test.reject {|k,v| k.anonymous?} | |
299 |
|
299 | |||
300 | users_to_test.keys.each do |user| |
|
300 | users_to_test.keys.each do |user| | |
301 | Watcher.create!(:user => user, :watchable => @issue) |
|
301 | Watcher.create!(:user => user, :watchable => @issue) | |
302 | end |
|
302 | end | |
303 | ActionMailer::Base.deliveries.clear |
|
303 | ActionMailer::Base.deliveries.clear | |
304 | @request.session[:user_id] = 1 |
|
304 | @request.session[:user_id] = 1 | |
305 | with_settings :bcc_recipients => '1' do |
|
305 | with_settings :bcc_recipients => '1' do | |
306 | put :update, |
|
306 | put :update, | |
307 | :id => @issue.id, |
|
307 | :id => @issue.id, | |
308 | :issue => { |
|
308 | :issue => { | |
309 | :custom_field_values => {@field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'} |
|
309 | :custom_field_values => {@field2.id.to_s => 'NewValue1', @field3.id.to_s => 'NewValue2'} | |
310 | } |
|
310 | } | |
311 | assert_response 302 |
|
311 | assert_response 302 | |
312 | end |
|
312 | end | |
313 | users_to_test.each do |user, fields| |
|
313 | users_to_test.each do |user, fields| | |
314 | mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail} |
|
314 | mails = ActionMailer::Base.deliveries.select {|m| m.bcc.include? user.mail} | |
315 | if (fields & [@field2, @field3]).any? |
|
315 | if (fields & [@field2, @field3]).any? | |
316 | assert_equal 1, mails.size, "User #{user.id} was not notified" |
|
316 | assert_equal 1, mails.size, "User #{user.id} was not notified" | |
317 | else |
|
317 | else | |
318 | assert_equal 0, mails.size, "User #{user.id} was notified" |
|
318 | assert_equal 0, mails.size, "User #{user.id} was notified" | |
319 | end |
|
319 | end | |
320 | end |
|
320 | end | |
321 | end |
|
321 | end | |
322 | end |
|
322 | end |
@@ -1,219 +1,219 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2016 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2016 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 MessagesControllerTest < ActionController::TestCase |
|
20 | class MessagesControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :boards, :messages, :enabled_modules |
|
21 | fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, :boards, :messages, :enabled_modules | |
22 |
|
22 | |||
23 | def setup |
|
23 | def setup | |
24 | User.current = nil |
|
24 | User.current = nil | |
25 | end |
|
25 | end | |
26 |
|
26 | |||
27 | def test_show |
|
27 | def test_show | |
28 | get :show, :board_id => 1, :id => 1 |
|
28 | get :show, :board_id => 1, :id => 1 | |
29 | assert_response :success |
|
29 | assert_response :success | |
30 | assert_template 'show' |
|
30 | assert_template 'show' | |
31 | assert_not_nil assigns(:board) |
|
31 | assert_not_nil assigns(:board) | |
32 | assert_not_nil assigns(:project) |
|
32 | assert_not_nil assigns(:project) | |
33 | assert_not_nil assigns(:topic) |
|
33 | assert_not_nil assigns(:topic) | |
34 | end |
|
34 | end | |
35 |
|
35 | |||
36 | def test_show_should_contain_reply_field_tags_for_quoting |
|
36 | def test_show_should_contain_reply_field_tags_for_quoting | |
37 | @request.session[:user_id] = 2 |
|
37 | @request.session[:user_id] = 2 | |
38 | get :show, :board_id => 1, :id => 1 |
|
38 | get :show, :board_id => 1, :id => 1 | |
39 | assert_response :success |
|
39 | assert_response :success | |
40 |
|
40 | |||
41 | # tags required by MessagesController#quote |
|
41 | # tags required by MessagesController#quote | |
42 | assert_select 'input#message_subject' |
|
42 | assert_select 'input#message_subject' | |
43 | assert_select 'textarea#message_content' |
|
43 | assert_select 'textarea#message_content' | |
44 | assert_select 'div#reply' |
|
44 | assert_select 'div#reply' | |
45 | end |
|
45 | end | |
46 |
|
46 | |||
47 | def test_show_with_pagination |
|
47 | def test_show_with_pagination | |
48 | message = Message.find(1) |
|
48 | message = Message.find(1) | |
49 | assert_difference 'Message.count', 30 do |
|
49 | assert_difference 'Message.count', 30 do | |
50 | 30.times do |
|
50 | 30.times do | |
51 | message.children << Message.new(:subject => 'Reply', |
|
51 | message.children << Message.new(:subject => 'Reply', | |
52 | :content => 'Reply body', |
|
52 | :content => 'Reply body', | |
53 | :author_id => 2, |
|
53 | :author_id => 2, | |
54 | :board_id => 1) |
|
54 | :board_id => 1) | |
55 | end |
|
55 | end | |
56 | end |
|
56 | end | |
57 | get :show, :board_id => 1, :id => 1, :r => message.children.order('id').last.id |
|
57 | get :show, :board_id => 1, :id => 1, :r => message.children.order('id').last.id | |
58 | assert_response :success |
|
58 | assert_response :success | |
59 | assert_template 'show' |
|
59 | assert_template 'show' | |
60 | replies = assigns(:replies) |
|
60 | replies = assigns(:replies) | |
61 | assert_not_nil replies |
|
61 | assert_not_nil replies | |
62 | assert_not_include message.children.reorder('id').first, replies |
|
62 | assert_not_include message.children.reorder('id').first, replies | |
63 | assert_include message.children.reorder('id').last, replies |
|
63 | assert_include message.children.reorder('id').last, replies | |
64 | end |
|
64 | end | |
65 |
|
65 | |||
66 | def test_show_with_reply_permission |
|
66 | def test_show_with_reply_permission | |
67 | @request.session[:user_id] = 2 |
|
67 | @request.session[:user_id] = 2 | |
68 | get :show, :board_id => 1, :id => 1 |
|
68 | get :show, :board_id => 1, :id => 1 | |
69 | assert_response :success |
|
69 | assert_response :success | |
70 | assert_template 'show' |
|
70 | assert_template 'show' | |
71 | assert_select 'div#reply textarea#message_content' |
|
71 | assert_select 'div#reply textarea#message_content' | |
72 | end |
|
72 | end | |
73 |
|
73 | |||
74 | def test_show_message_not_found |
|
74 | def test_show_message_not_found | |
75 | get :show, :board_id => 1, :id => 99999 |
|
75 | get :show, :board_id => 1, :id => 99999 | |
76 | assert_response 404 |
|
76 | assert_response 404 | |
77 | end |
|
77 | end | |
78 |
|
78 | |||
79 | def test_show_message_from_invalid_board_should_respond_with_404 |
|
79 | def test_show_message_from_invalid_board_should_respond_with_404 | |
80 | get :show, :board_id => 999, :id => 1 |
|
80 | get :show, :board_id => 999, :id => 1 | |
81 | assert_response 404 |
|
81 | assert_response 404 | |
82 | end |
|
82 | end | |
83 |
|
83 | |||
84 | def test_get_new |
|
84 | def test_get_new | |
85 | @request.session[:user_id] = 2 |
|
85 | @request.session[:user_id] = 2 | |
86 | get :new, :board_id => 1 |
|
86 | get :new, :board_id => 1 | |
87 | assert_response :success |
|
87 | assert_response :success | |
88 | assert_template 'new' |
|
88 | assert_template 'new' | |
89 | end |
|
89 | end | |
90 |
|
90 | |||
91 | def test_get_new_with_invalid_board |
|
91 | def test_get_new_with_invalid_board | |
92 | @request.session[:user_id] = 2 |
|
92 | @request.session[:user_id] = 2 | |
93 | get :new, :board_id => 99 |
|
93 | get :new, :board_id => 99 | |
94 | assert_response 404 |
|
94 | assert_response 404 | |
95 | end |
|
95 | end | |
96 |
|
96 | |||
97 | def test_post_new |
|
97 | def test_post_new | |
98 | @request.session[:user_id] = 2 |
|
98 | @request.session[:user_id] = 2 | |
99 | ActionMailer::Base.deliveries.clear |
|
99 | ActionMailer::Base.deliveries.clear | |
100 |
|
100 | |||
101 | with_settings :notified_events => %w(message_posted) do |
|
101 | with_settings :notified_events => %w(message_posted) do | |
102 | post :new, :board_id => 1, |
|
102 | post :new, :board_id => 1, | |
103 | :message => { :subject => 'Test created message', |
|
103 | :message => { :subject => 'Test created message', | |
104 | :content => 'Message body'} |
|
104 | :content => 'Message body'} | |
105 | end |
|
105 | end | |
106 | message = Message.find_by_subject('Test created message') |
|
106 | message = Message.find_by_subject('Test created message') | |
107 | assert_not_nil message |
|
107 | assert_not_nil message | |
108 | assert_redirected_to "/boards/1/topics/#{message.to_param}" |
|
108 | assert_redirected_to "/boards/1/topics/#{message.to_param}" | |
109 | assert_equal 'Message body', message.content |
|
109 | assert_equal 'Message body', message.content | |
110 | assert_equal 2, message.author_id |
|
110 | assert_equal 2, message.author_id | |
111 | assert_equal 1, message.board_id |
|
111 | assert_equal 1, message.board_id | |
112 |
|
112 | |||
113 | mail = ActionMailer::Base.deliveries.last |
|
113 | mail = ActionMailer::Base.deliveries.last | |
114 | assert_not_nil mail |
|
114 | assert_not_nil mail | |
115 | assert_equal "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] Test created message", mail.subject |
|
115 | assert_equal "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] Test created message", mail.subject | |
116 | assert_mail_body_match 'Message body', mail |
|
116 | assert_mail_body_match 'Message body', mail | |
117 | # author |
|
117 | # author | |
118 | assert mail.bcc.include?('jsmith@somenet.foo') |
|
118 | assert mail.bcc.include?('jsmith@somenet.foo') | |
119 | # project member |
|
119 | # project member | |
120 | assert mail.bcc.include?('dlopper@somenet.foo') |
|
120 | assert mail.bcc.include?('dlopper@somenet.foo') | |
121 | end |
|
121 | end | |
122 |
|
122 | |||
123 | def test_get_edit |
|
123 | def test_get_edit | |
124 | @request.session[:user_id] = 2 |
|
124 | @request.session[:user_id] = 2 | |
125 | get :edit, :board_id => 1, :id => 1 |
|
125 | get :edit, :board_id => 1, :id => 1 | |
126 | assert_response :success |
|
126 | assert_response :success | |
127 | assert_template 'edit' |
|
127 | assert_template 'edit' | |
128 | end |
|
128 | end | |
129 |
|
129 | |||
130 | def test_post_edit |
|
130 | def test_post_edit | |
131 | @request.session[:user_id] = 2 |
|
131 | @request.session[:user_id] = 2 | |
132 | post :edit, :board_id => 1, :id => 1, |
|
132 | post :edit, :board_id => 1, :id => 1, | |
133 | :message => { :subject => 'New subject', |
|
133 | :message => { :subject => 'New subject', | |
134 | :content => 'New body'} |
|
134 | :content => 'New body'} | |
135 | assert_redirected_to '/boards/1/topics/1' |
|
135 | assert_redirected_to '/boards/1/topics/1' | |
136 | message = Message.find(1) |
|
136 | message = Message.find(1) | |
137 | assert_equal 'New subject', message.subject |
|
137 | assert_equal 'New subject', message.subject | |
138 | assert_equal 'New body', message.content |
|
138 | assert_equal 'New body', message.content | |
139 | end |
|
139 | end | |
140 |
|
140 | |||
141 | def test_post_edit_sticky_and_locked |
|
141 | def test_post_edit_sticky_and_locked | |
142 | @request.session[:user_id] = 2 |
|
142 | @request.session[:user_id] = 2 | |
143 | post :edit, :board_id => 1, :id => 1, |
|
143 | post :edit, :board_id => 1, :id => 1, | |
144 | :message => { :subject => 'New subject', |
|
144 | :message => { :subject => 'New subject', | |
145 | :content => 'New body', |
|
145 | :content => 'New body', | |
146 | :locked => '1', |
|
146 | :locked => '1', | |
147 | :sticky => '1'} |
|
147 | :sticky => '1'} | |
148 | assert_redirected_to '/boards/1/topics/1' |
|
148 | assert_redirected_to '/boards/1/topics/1' | |
149 | message = Message.find(1) |
|
149 | message = Message.find(1) | |
150 | assert_equal true, message.sticky? |
|
150 | assert_equal true, message.sticky? | |
151 | assert_equal true, message.locked? |
|
151 | assert_equal true, message.locked? | |
152 | end |
|
152 | end | |
153 |
|
153 | |||
154 | def test_post_edit_should_allow_to_change_board |
|
154 | def test_post_edit_should_allow_to_change_board | |
155 | @request.session[:user_id] = 2 |
|
155 | @request.session[:user_id] = 2 | |
156 | post :edit, :board_id => 1, :id => 1, |
|
156 | post :edit, :board_id => 1, :id => 1, | |
157 | :message => { :subject => 'New subject', |
|
157 | :message => { :subject => 'New subject', | |
158 | :content => 'New body', |
|
158 | :content => 'New body', | |
159 | :board_id => 2} |
|
159 | :board_id => 2} | |
160 | assert_redirected_to '/boards/2/topics/1' |
|
160 | assert_redirected_to '/boards/2/topics/1' | |
161 | message = Message.find(1) |
|
161 | message = Message.find(1) | |
162 | assert_equal Board.find(2), message.board |
|
162 | assert_equal Board.find(2), message.board | |
163 | end |
|
163 | end | |
164 |
|
164 | |||
165 | def test_reply |
|
165 | def test_reply | |
166 | @request.session[:user_id] = 2 |
|
166 | @request.session[:user_id] = 2 | |
167 | post :reply, :board_id => 1, :id => 1, :reply => { :content => 'This is a test reply', :subject => 'Test reply' } |
|
167 | post :reply, :board_id => 1, :id => 1, :reply => { :content => 'This is a test reply', :subject => 'Test reply' } | |
168 | reply = Message.order('id DESC').first |
|
168 | reply = Message.order('id DESC').first | |
169 | assert_redirected_to "/boards/1/topics/1?r=#{reply.id}" |
|
169 | assert_redirected_to "/boards/1/topics/1?r=#{reply.id}" | |
170 | assert Message.find_by_subject('Test reply') |
|
170 | assert Message.find_by_subject('Test reply') | |
171 | end |
|
171 | end | |
172 |
|
172 | |||
173 | def test_destroy_topic |
|
173 | def test_destroy_topic | |
174 | @request.session[:user_id] = 2 |
|
174 | @request.session[:user_id] = 2 | |
175 | assert_difference 'Message.count', -3 do |
|
175 | assert_difference 'Message.count', -3 do | |
176 | post :destroy, :board_id => 1, :id => 1 |
|
176 | post :destroy, :board_id => 1, :id => 1 | |
177 | end |
|
177 | end | |
178 | assert_redirected_to '/projects/ecookbook/boards/1' |
|
178 | assert_redirected_to '/projects/ecookbook/boards/1' | |
179 | assert_nil Message.find_by_id(1) |
|
179 | assert_nil Message.find_by_id(1) | |
180 | end |
|
180 | end | |
181 |
|
181 | |||
182 | def test_destroy_reply |
|
182 | def test_destroy_reply | |
183 | @request.session[:user_id] = 2 |
|
183 | @request.session[:user_id] = 2 | |
184 | assert_difference 'Message.count', -1 do |
|
184 | assert_difference 'Message.count', -1 do | |
185 | post :destroy, :board_id => 1, :id => 2 |
|
185 | post :destroy, :board_id => 1, :id => 2 | |
186 | end |
|
186 | end | |
187 | assert_redirected_to '/boards/1/topics/1?r=2' |
|
187 | assert_redirected_to '/boards/1/topics/1?r=2' | |
188 | assert_nil Message.find_by_id(2) |
|
188 | assert_nil Message.find_by_id(2) | |
189 | end |
|
189 | end | |
190 |
|
190 | |||
191 | def test_quote |
|
191 | def test_quote | |
192 | @request.session[:user_id] = 2 |
|
192 | @request.session[:user_id] = 2 | |
193 | xhr :get, :quote, :board_id => 1, :id => 3 |
|
193 | xhr :get, :quote, :board_id => 1, :id => 3 | |
194 | assert_response :success |
|
194 | assert_response :success | |
195 | assert_equal 'text/javascript', response.content_type |
|
195 | assert_equal 'text/javascript', response.content_type | |
196 | assert_template 'quote' |
|
196 | assert_template 'quote' | |
197 | assert_include 'RE: First post', response.body |
|
197 | assert_include 'RE: First post', response.body | |
198 | assert_include '> An other reply', response.body |
|
198 | assert_include '> An other reply', response.body | |
199 | end |
|
199 | end | |
200 |
|
200 | |||
201 | def test_preview_new |
|
201 | def test_preview_new | |
202 | @request.session[:user_id] = 2 |
|
202 | @request.session[:user_id] = 2 | |
203 | post :preview, |
|
203 | post :preview, | |
204 | :board_id => 1, |
|
204 | :board_id => 1, | |
205 | :message => {:subject => "", :content => "Previewed text"} |
|
205 | :message => {:subject => "", :content => "Previewed text"} | |
206 | assert_response :success |
|
206 | assert_response :success | |
207 | assert_template 'common/_preview' |
|
207 | assert_template 'common/_preview' | |
208 | end |
|
208 | end | |
209 |
|
209 | |||
210 | def test_preview_edit |
|
210 | def test_preview_edit | |
211 | @request.session[:user_id] = 2 |
|
211 | @request.session[:user_id] = 2 | |
212 | post :preview, |
|
212 | post :preview, | |
213 | :id => 4, |
|
213 | :id => 4, | |
214 | :board_id => 1, |
|
214 | :board_id => 1, | |
215 | :message => {:subject => "", :content => "Previewed text"} |
|
215 | :message => {:subject => "", :content => "Previewed text"} | |
216 | assert_response :success |
|
216 | assert_response :success | |
217 | assert_template 'common/_preview' |
|
217 | assert_template 'common/_preview' | |
218 | end |
|
218 | end | |
219 | end |
|
219 | end |
@@ -1,2748 +1,2748 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2016 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2016 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 IssueTest < ActiveSupport::TestCase |
|
20 | class IssueTest < ActiveSupport::TestCase | |
21 | fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, |
|
21 | fixtures :projects, :users, :email_addresses, :user_preferences, :members, :member_roles, :roles, | |
22 | :groups_users, |
|
22 | :groups_users, | |
23 | :trackers, :projects_trackers, |
|
23 | :trackers, :projects_trackers, | |
24 | :enabled_modules, |
|
24 | :enabled_modules, | |
25 | :versions, |
|
25 | :versions, | |
26 | :issue_statuses, :issue_categories, :issue_relations, :workflows, |
|
26 | :issue_statuses, :issue_categories, :issue_relations, :workflows, | |
27 | :enumerations, |
|
27 | :enumerations, | |
28 | :issues, :journals, :journal_details, |
|
28 | :issues, :journals, :journal_details, | |
29 | :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values, |
|
29 | :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values, | |
30 | :time_entries |
|
30 | :time_entries | |
31 |
|
31 | |||
32 | include Redmine::I18n |
|
32 | include Redmine::I18n | |
33 |
|
33 | |||
34 | def setup |
|
34 | def setup | |
35 | set_language_if_valid 'en' |
|
35 | set_language_if_valid 'en' | |
36 | end |
|
36 | end | |
37 |
|
37 | |||
38 | def teardown |
|
38 | def teardown | |
39 | User.current = nil |
|
39 | User.current = nil | |
40 | end |
|
40 | end | |
41 |
|
41 | |||
42 | def test_initialize |
|
42 | def test_initialize | |
43 | issue = Issue.new |
|
43 | issue = Issue.new | |
44 |
|
44 | |||
45 | assert_nil issue.project_id |
|
45 | assert_nil issue.project_id | |
46 | assert_nil issue.tracker_id |
|
46 | assert_nil issue.tracker_id | |
47 | assert_nil issue.status_id |
|
47 | assert_nil issue.status_id | |
48 | assert_nil issue.author_id |
|
48 | assert_nil issue.author_id | |
49 | assert_nil issue.assigned_to_id |
|
49 | assert_nil issue.assigned_to_id | |
50 | assert_nil issue.category_id |
|
50 | assert_nil issue.category_id | |
51 |
|
51 | |||
52 | assert_equal IssuePriority.default, issue.priority |
|
52 | assert_equal IssuePriority.default, issue.priority | |
53 | end |
|
53 | end | |
54 |
|
54 | |||
55 | def test_create |
|
55 | def test_create | |
56 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, |
|
56 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, | |
57 | :status_id => 1, :priority => IssuePriority.all.first, |
|
57 | :status_id => 1, :priority => IssuePriority.all.first, | |
58 | :subject => 'test_create', |
|
58 | :subject => 'test_create', | |
59 | :description => 'IssueTest#test_create', :estimated_hours => '1:30') |
|
59 | :description => 'IssueTest#test_create', :estimated_hours => '1:30') | |
60 | assert issue.save |
|
60 | assert issue.save | |
61 | issue.reload |
|
61 | issue.reload | |
62 | assert_equal 1.5, issue.estimated_hours |
|
62 | assert_equal 1.5, issue.estimated_hours | |
63 | end |
|
63 | end | |
64 |
|
64 | |||
65 | def test_create_minimal |
|
65 | def test_create_minimal | |
66 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create') |
|
66 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create') | |
67 | assert issue.save |
|
67 | assert issue.save | |
68 | assert_equal issue.tracker.default_status, issue.status |
|
68 | assert_equal issue.tracker.default_status, issue.status | |
69 | assert issue.description.nil? |
|
69 | assert issue.description.nil? | |
70 | assert_nil issue.estimated_hours |
|
70 | assert_nil issue.estimated_hours | |
71 | end |
|
71 | end | |
72 |
|
72 | |||
73 | def test_create_with_all_fields_disabled |
|
73 | def test_create_with_all_fields_disabled | |
74 | tracker = Tracker.find(1) |
|
74 | tracker = Tracker.find(1) | |
75 | tracker.core_fields = [] |
|
75 | tracker.core_fields = [] | |
76 | tracker.save! |
|
76 | tracker.save! | |
77 |
|
77 | |||
78 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create_with_all_fields_disabled') |
|
78 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create_with_all_fields_disabled') | |
79 | assert_save issue |
|
79 | assert_save issue | |
80 | end |
|
80 | end | |
81 |
|
81 | |||
82 | def test_start_date_format_should_be_validated |
|
82 | def test_start_date_format_should_be_validated | |
83 | set_language_if_valid 'en' |
|
83 | set_language_if_valid 'en' | |
84 | ['2012', 'ABC', '2012-15-20'].each do |invalid_date| |
|
84 | ['2012', 'ABC', '2012-15-20'].each do |invalid_date| | |
85 | issue = Issue.new(:start_date => invalid_date) |
|
85 | issue = Issue.new(:start_date => invalid_date) | |
86 | assert !issue.valid? |
|
86 | assert !issue.valid? | |
87 | assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}" |
|
87 | assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}" | |
88 | end |
|
88 | end | |
89 | end |
|
89 | end | |
90 |
|
90 | |||
91 | def test_due_date_format_should_be_validated |
|
91 | def test_due_date_format_should_be_validated | |
92 | set_language_if_valid 'en' |
|
92 | set_language_if_valid 'en' | |
93 | ['2012', 'ABC', '2012-15-20'].each do |invalid_date| |
|
93 | ['2012', 'ABC', '2012-15-20'].each do |invalid_date| | |
94 | issue = Issue.new(:due_date => invalid_date) |
|
94 | issue = Issue.new(:due_date => invalid_date) | |
95 | assert !issue.valid? |
|
95 | assert !issue.valid? | |
96 | assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}" |
|
96 | assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}" | |
97 | end |
|
97 | end | |
98 | end |
|
98 | end | |
99 |
|
99 | |||
100 | def test_due_date_lesser_than_start_date_should_not_validate |
|
100 | def test_due_date_lesser_than_start_date_should_not_validate | |
101 | set_language_if_valid 'en' |
|
101 | set_language_if_valid 'en' | |
102 | issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02') |
|
102 | issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02') | |
103 | assert !issue.valid? |
|
103 | assert !issue.valid? | |
104 | assert_include 'Due date must be greater than start date', issue.errors.full_messages |
|
104 | assert_include 'Due date must be greater than start date', issue.errors.full_messages | |
105 | end |
|
105 | end | |
106 |
|
106 | |||
107 | def test_start_date_lesser_than_soonest_start_should_not_validate_on_create |
|
107 | def test_start_date_lesser_than_soonest_start_should_not_validate_on_create | |
108 | issue = Issue.generate(:start_date => '2013-06-04') |
|
108 | issue = Issue.generate(:start_date => '2013-06-04') | |
109 | issue.stubs(:soonest_start).returns(Date.parse('2013-06-10')) |
|
109 | issue.stubs(:soonest_start).returns(Date.parse('2013-06-10')) | |
110 | assert !issue.valid? |
|
110 | assert !issue.valid? | |
111 | assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages |
|
111 | assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages | |
112 | end |
|
112 | end | |
113 |
|
113 | |||
114 | def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed |
|
114 | def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed | |
115 | issue = Issue.generate!(:start_date => '2013-06-04') |
|
115 | issue = Issue.generate!(:start_date => '2013-06-04') | |
116 | issue.stubs(:soonest_start).returns(Date.parse('2013-06-10')) |
|
116 | issue.stubs(:soonest_start).returns(Date.parse('2013-06-10')) | |
117 | issue.start_date = '2013-06-07' |
|
117 | issue.start_date = '2013-06-07' | |
118 | assert !issue.valid? |
|
118 | assert !issue.valid? | |
119 | assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages |
|
119 | assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages | |
120 | end |
|
120 | end | |
121 |
|
121 | |||
122 | def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged |
|
122 | def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged | |
123 | issue = Issue.generate!(:start_date => '2013-06-04') |
|
123 | issue = Issue.generate!(:start_date => '2013-06-04') | |
124 | issue.stubs(:soonest_start).returns(Date.parse('2013-06-10')) |
|
124 | issue.stubs(:soonest_start).returns(Date.parse('2013-06-10')) | |
125 | assert issue.valid? |
|
125 | assert issue.valid? | |
126 | end |
|
126 | end | |
127 |
|
127 | |||
128 | def test_estimated_hours_should_be_validated |
|
128 | def test_estimated_hours_should_be_validated | |
129 | set_language_if_valid 'en' |
|
129 | set_language_if_valid 'en' | |
130 | ['-2'].each do |invalid| |
|
130 | ['-2'].each do |invalid| | |
131 | issue = Issue.new(:estimated_hours => invalid) |
|
131 | issue = Issue.new(:estimated_hours => invalid) | |
132 | assert !issue.valid? |
|
132 | assert !issue.valid? | |
133 | assert_include 'Estimated time is invalid', issue.errors.full_messages |
|
133 | assert_include 'Estimated time is invalid', issue.errors.full_messages | |
134 | end |
|
134 | end | |
135 | end |
|
135 | end | |
136 |
|
136 | |||
137 | def test_create_with_required_custom_field |
|
137 | def test_create_with_required_custom_field | |
138 | set_language_if_valid 'en' |
|
138 | set_language_if_valid 'en' | |
139 | field = IssueCustomField.find_by_name('Database') |
|
139 | field = IssueCustomField.find_by_name('Database') | |
140 | field.update_attribute(:is_required, true) |
|
140 | field.update_attribute(:is_required, true) | |
141 |
|
141 | |||
142 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
142 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
143 | :status_id => 1, :subject => 'test_create', |
|
143 | :status_id => 1, :subject => 'test_create', | |
144 | :description => 'IssueTest#test_create_with_required_custom_field') |
|
144 | :description => 'IssueTest#test_create_with_required_custom_field') | |
145 | assert issue.available_custom_fields.include?(field) |
|
145 | assert issue.available_custom_fields.include?(field) | |
146 | # No value for the custom field |
|
146 | # No value for the custom field | |
147 | assert !issue.save |
|
147 | assert !issue.save | |
148 | assert_equal ["Database cannot be blank"], issue.errors.full_messages |
|
148 | assert_equal ["Database cannot be blank"], issue.errors.full_messages | |
149 | # Blank value |
|
149 | # Blank value | |
150 | issue.custom_field_values = { field.id => '' } |
|
150 | issue.custom_field_values = { field.id => '' } | |
151 | assert !issue.save |
|
151 | assert !issue.save | |
152 | assert_equal ["Database cannot be blank"], issue.errors.full_messages |
|
152 | assert_equal ["Database cannot be blank"], issue.errors.full_messages | |
153 | # Invalid value |
|
153 | # Invalid value | |
154 | issue.custom_field_values = { field.id => 'SQLServer' } |
|
154 | issue.custom_field_values = { field.id => 'SQLServer' } | |
155 | assert !issue.save |
|
155 | assert !issue.save | |
156 | assert_equal ["Database is not included in the list"], issue.errors.full_messages |
|
156 | assert_equal ["Database is not included in the list"], issue.errors.full_messages | |
157 | # Valid value |
|
157 | # Valid value | |
158 | issue.custom_field_values = { field.id => 'PostgreSQL' } |
|
158 | issue.custom_field_values = { field.id => 'PostgreSQL' } | |
159 | assert issue.save |
|
159 | assert issue.save | |
160 | issue.reload |
|
160 | issue.reload | |
161 | assert_equal 'PostgreSQL', issue.custom_value_for(field).value |
|
161 | assert_equal 'PostgreSQL', issue.custom_value_for(field).value | |
162 | end |
|
162 | end | |
163 |
|
163 | |||
164 | def test_create_with_group_assignment |
|
164 | def test_create_with_group_assignment | |
165 | with_settings :issue_group_assignment => '1' do |
|
165 | with_settings :issue_group_assignment => '1' do | |
166 | assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1, |
|
166 | assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1, | |
167 | :subject => 'Group assignment', |
|
167 | :subject => 'Group assignment', | |
168 | :assigned_to_id => 11).save |
|
168 | :assigned_to_id => 11).save | |
169 | issue = Issue.order('id DESC').first |
|
169 | issue = Issue.order('id DESC').first | |
170 | assert_kind_of Group, issue.assigned_to |
|
170 | assert_kind_of Group, issue.assigned_to | |
171 | assert_equal Group.find(11), issue.assigned_to |
|
171 | assert_equal Group.find(11), issue.assigned_to | |
172 | end |
|
172 | end | |
173 | end |
|
173 | end | |
174 |
|
174 | |||
175 | def test_create_with_parent_issue_id |
|
175 | def test_create_with_parent_issue_id | |
176 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
176 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
177 | :author_id => 1, :subject => 'Group assignment', |
|
177 | :author_id => 1, :subject => 'Group assignment', | |
178 | :parent_issue_id => 1) |
|
178 | :parent_issue_id => 1) | |
179 | assert_save issue |
|
179 | assert_save issue | |
180 | assert_equal 1, issue.parent_issue_id |
|
180 | assert_equal 1, issue.parent_issue_id | |
181 | assert_equal Issue.find(1), issue.parent |
|
181 | assert_equal Issue.find(1), issue.parent | |
182 | end |
|
182 | end | |
183 |
|
183 | |||
184 | def test_create_with_sharp_parent_issue_id |
|
184 | def test_create_with_sharp_parent_issue_id | |
185 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
185 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
186 | :author_id => 1, :subject => 'Group assignment', |
|
186 | :author_id => 1, :subject => 'Group assignment', | |
187 | :parent_issue_id => "#1") |
|
187 | :parent_issue_id => "#1") | |
188 | assert_save issue |
|
188 | assert_save issue | |
189 | assert_equal 1, issue.parent_issue_id |
|
189 | assert_equal 1, issue.parent_issue_id | |
190 | assert_equal Issue.find(1), issue.parent |
|
190 | assert_equal Issue.find(1), issue.parent | |
191 | end |
|
191 | end | |
192 |
|
192 | |||
193 | def test_create_with_invalid_parent_issue_id |
|
193 | def test_create_with_invalid_parent_issue_id | |
194 | set_language_if_valid 'en' |
|
194 | set_language_if_valid 'en' | |
195 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
195 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
196 | :author_id => 1, :subject => 'Group assignment', |
|
196 | :author_id => 1, :subject => 'Group assignment', | |
197 | :parent_issue_id => '01ABC') |
|
197 | :parent_issue_id => '01ABC') | |
198 | assert !issue.save |
|
198 | assert !issue.save | |
199 | assert_equal '01ABC', issue.parent_issue_id |
|
199 | assert_equal '01ABC', issue.parent_issue_id | |
200 | assert_include 'Parent task is invalid', issue.errors.full_messages |
|
200 | assert_include 'Parent task is invalid', issue.errors.full_messages | |
201 | end |
|
201 | end | |
202 |
|
202 | |||
203 | def test_create_with_invalid_sharp_parent_issue_id |
|
203 | def test_create_with_invalid_sharp_parent_issue_id | |
204 | set_language_if_valid 'en' |
|
204 | set_language_if_valid 'en' | |
205 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
205 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
206 | :author_id => 1, :subject => 'Group assignment', |
|
206 | :author_id => 1, :subject => 'Group assignment', | |
207 | :parent_issue_id => '#01ABC') |
|
207 | :parent_issue_id => '#01ABC') | |
208 | assert !issue.save |
|
208 | assert !issue.save | |
209 | assert_equal '#01ABC', issue.parent_issue_id |
|
209 | assert_equal '#01ABC', issue.parent_issue_id | |
210 | assert_include 'Parent task is invalid', issue.errors.full_messages |
|
210 | assert_include 'Parent task is invalid', issue.errors.full_messages | |
211 | end |
|
211 | end | |
212 |
|
212 | |||
213 | def assert_visibility_match(user, issues) |
|
213 | def assert_visibility_match(user, issues) | |
214 | assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort |
|
214 | assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort | |
215 | end |
|
215 | end | |
216 |
|
216 | |||
217 | def test_visible_scope_for_anonymous |
|
217 | def test_visible_scope_for_anonymous | |
218 | # Anonymous user should see issues of public projects only |
|
218 | # Anonymous user should see issues of public projects only | |
219 | issues = Issue.visible(User.anonymous).to_a |
|
219 | issues = Issue.visible(User.anonymous).to_a | |
220 | assert issues.any? |
|
220 | assert issues.any? | |
221 | assert_nil issues.detect {|issue| !issue.project.is_public?} |
|
221 | assert_nil issues.detect {|issue| !issue.project.is_public?} | |
222 | assert_nil issues.detect {|issue| issue.is_private?} |
|
222 | assert_nil issues.detect {|issue| issue.is_private?} | |
223 | assert_visibility_match User.anonymous, issues |
|
223 | assert_visibility_match User.anonymous, issues | |
224 | end |
|
224 | end | |
225 |
|
225 | |||
226 | def test_visible_scope_for_anonymous_without_view_issues_permissions |
|
226 | def test_visible_scope_for_anonymous_without_view_issues_permissions | |
227 | # Anonymous user should not see issues without permission |
|
227 | # Anonymous user should not see issues without permission | |
228 | Role.anonymous.remove_permission!(:view_issues) |
|
228 | Role.anonymous.remove_permission!(:view_issues) | |
229 | issues = Issue.visible(User.anonymous).to_a |
|
229 | issues = Issue.visible(User.anonymous).to_a | |
230 | assert issues.empty? |
|
230 | assert issues.empty? | |
231 | assert_visibility_match User.anonymous, issues |
|
231 | assert_visibility_match User.anonymous, issues | |
232 | end |
|
232 | end | |
233 |
|
233 | |||
234 | def test_visible_scope_for_anonymous_without_view_issues_permissions_and_membership |
|
234 | def test_visible_scope_for_anonymous_without_view_issues_permissions_and_membership | |
235 | Role.anonymous.remove_permission!(:view_issues) |
|
235 | Role.anonymous.remove_permission!(:view_issues) | |
236 | Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [2]) |
|
236 | Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [2]) | |
237 |
|
237 | |||
238 | issues = Issue.visible(User.anonymous).all |
|
238 | issues = Issue.visible(User.anonymous).all | |
239 | assert issues.any? |
|
239 | assert issues.any? | |
240 | assert_equal [1], issues.map(&:project_id).uniq.sort |
|
240 | assert_equal [1], issues.map(&:project_id).uniq.sort | |
241 | assert_visibility_match User.anonymous, issues |
|
241 | assert_visibility_match User.anonymous, issues | |
242 | end |
|
242 | end | |
243 |
|
243 | |||
244 | def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default |
|
244 | def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default | |
245 | assert Role.anonymous.update_attribute(:issues_visibility, 'default') |
|
245 | assert Role.anonymous.update_attribute(:issues_visibility, 'default') | |
246 | issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true) |
|
246 | issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true) | |
247 | assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first |
|
247 | assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first | |
248 | assert !issue.visible?(User.anonymous) |
|
248 | assert !issue.visible?(User.anonymous) | |
249 | end |
|
249 | end | |
250 |
|
250 | |||
251 | def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own |
|
251 | def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own | |
252 | assert Role.anonymous.update_attribute(:issues_visibility, 'own') |
|
252 | assert Role.anonymous.update_attribute(:issues_visibility, 'own') | |
253 | issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true) |
|
253 | issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true) | |
254 | assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first |
|
254 | assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first | |
255 | assert !issue.visible?(User.anonymous) |
|
255 | assert !issue.visible?(User.anonymous) | |
256 | end |
|
256 | end | |
257 |
|
257 | |||
258 | def test_visible_scope_for_non_member |
|
258 | def test_visible_scope_for_non_member | |
259 | user = User.find(9) |
|
259 | user = User.find(9) | |
260 | assert user.projects.empty? |
|
260 | assert user.projects.empty? | |
261 | # Non member user should see issues of public projects only |
|
261 | # Non member user should see issues of public projects only | |
262 | issues = Issue.visible(user).to_a |
|
262 | issues = Issue.visible(user).to_a | |
263 | assert issues.any? |
|
263 | assert issues.any? | |
264 | assert_nil issues.detect {|issue| !issue.project.is_public?} |
|
264 | assert_nil issues.detect {|issue| !issue.project.is_public?} | |
265 | assert_nil issues.detect {|issue| issue.is_private?} |
|
265 | assert_nil issues.detect {|issue| issue.is_private?} | |
266 | assert_visibility_match user, issues |
|
266 | assert_visibility_match user, issues | |
267 | end |
|
267 | end | |
268 |
|
268 | |||
269 | def test_visible_scope_for_non_member_with_own_issues_visibility |
|
269 | def test_visible_scope_for_non_member_with_own_issues_visibility | |
270 | Role.non_member.update_attribute :issues_visibility, 'own' |
|
270 | Role.non_member.update_attribute :issues_visibility, 'own' | |
271 | Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member') |
|
271 | Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member') | |
272 | user = User.find(9) |
|
272 | user = User.find(9) | |
273 |
|
273 | |||
274 | issues = Issue.visible(user).to_a |
|
274 | issues = Issue.visible(user).to_a | |
275 | assert issues.any? |
|
275 | assert issues.any? | |
276 | assert_nil issues.detect {|issue| issue.author != user} |
|
276 | assert_nil issues.detect {|issue| issue.author != user} | |
277 | assert_visibility_match user, issues |
|
277 | assert_visibility_match user, issues | |
278 | end |
|
278 | end | |
279 |
|
279 | |||
280 | def test_visible_scope_for_non_member_without_view_issues_permissions |
|
280 | def test_visible_scope_for_non_member_without_view_issues_permissions | |
281 | # Non member user should not see issues without permission |
|
281 | # Non member user should not see issues without permission | |
282 | Role.non_member.remove_permission!(:view_issues) |
|
282 | Role.non_member.remove_permission!(:view_issues) | |
283 | user = User.find(9) |
|
283 | user = User.find(9) | |
284 | assert user.projects.empty? |
|
284 | assert user.projects.empty? | |
285 | issues = Issue.visible(user).to_a |
|
285 | issues = Issue.visible(user).to_a | |
286 | assert issues.empty? |
|
286 | assert issues.empty? | |
287 | assert_visibility_match user, issues |
|
287 | assert_visibility_match user, issues | |
288 | end |
|
288 | end | |
289 |
|
289 | |||
290 | def test_visible_scope_for_non_member_without_view_issues_permissions_and_membership |
|
290 | def test_visible_scope_for_non_member_without_view_issues_permissions_and_membership | |
291 | Role.non_member.remove_permission!(:view_issues) |
|
291 | Role.non_member.remove_permission!(:view_issues) | |
292 | Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [2]) |
|
292 | Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [2]) | |
293 | user = User.find(9) |
|
293 | user = User.find(9) | |
294 |
|
294 | |||
295 | issues = Issue.visible(user).all |
|
295 | issues = Issue.visible(user).all | |
296 | assert issues.any? |
|
296 | assert issues.any? | |
297 | assert_equal [1], issues.map(&:project_id).uniq.sort |
|
297 | assert_equal [1], issues.map(&:project_id).uniq.sort | |
298 | assert_visibility_match user, issues |
|
298 | assert_visibility_match user, issues | |
299 | end |
|
299 | end | |
300 |
|
300 | |||
301 | def test_visible_scope_for_member |
|
301 | def test_visible_scope_for_member | |
302 | user = User.find(9) |
|
302 | user = User.find(9) | |
303 | # User should see issues of projects for which user has view_issues permissions only |
|
303 | # User should see issues of projects for which user has view_issues permissions only | |
304 | Role.non_member.remove_permission!(:view_issues) |
|
304 | Role.non_member.remove_permission!(:view_issues) | |
305 | Member.create!(:principal => user, :project_id => 3, :role_ids => [2]) |
|
305 | Member.create!(:principal => user, :project_id => 3, :role_ids => [2]) | |
306 | issues = Issue.visible(user).to_a |
|
306 | issues = Issue.visible(user).to_a | |
307 | assert issues.any? |
|
307 | assert issues.any? | |
308 | assert_nil issues.detect {|issue| issue.project_id != 3} |
|
308 | assert_nil issues.detect {|issue| issue.project_id != 3} | |
309 | assert_nil issues.detect {|issue| issue.is_private?} |
|
309 | assert_nil issues.detect {|issue| issue.is_private?} | |
310 | assert_visibility_match user, issues |
|
310 | assert_visibility_match user, issues | |
311 | end |
|
311 | end | |
312 |
|
312 | |||
313 | def test_visible_scope_for_member_without_view_issues_permission_and_non_member_role_having_the_permission |
|
313 | def test_visible_scope_for_member_without_view_issues_permission_and_non_member_role_having_the_permission | |
314 | Role.non_member.add_permission!(:view_issues) |
|
314 | Role.non_member.add_permission!(:view_issues) | |
315 | Role.find(1).remove_permission!(:view_issues) |
|
315 | Role.find(1).remove_permission!(:view_issues) | |
316 | user = User.find(2) |
|
316 | user = User.find(2) | |
317 |
|
317 | |||
318 | assert_equal 0, Issue.where(:project_id => 1).visible(user).count |
|
318 | assert_equal 0, Issue.where(:project_id => 1).visible(user).count | |
319 | assert_equal false, Issue.where(:project_id => 1).first.visible?(user) |
|
319 | assert_equal false, Issue.where(:project_id => 1).first.visible?(user) | |
320 | end |
|
320 | end | |
321 |
|
321 | |||
322 | def test_visible_scope_for_member_with_groups_should_return_assigned_issues |
|
322 | def test_visible_scope_for_member_with_groups_should_return_assigned_issues | |
323 | user = User.find(8) |
|
323 | user = User.find(8) | |
324 | assert user.groups.any? |
|
324 | assert user.groups.any? | |
325 | Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2]) |
|
325 | Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2]) | |
326 | Role.non_member.remove_permission!(:view_issues) |
|
326 | Role.non_member.remove_permission!(:view_issues) | |
327 |
|
327 | |||
328 | issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3, |
|
328 | issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3, | |
329 | :status_id => 1, :priority => IssuePriority.all.first, |
|
329 | :status_id => 1, :priority => IssuePriority.all.first, | |
330 | :subject => 'Assignment test', |
|
330 | :subject => 'Assignment test', | |
331 | :assigned_to => user.groups.first, |
|
331 | :assigned_to => user.groups.first, | |
332 | :is_private => true) |
|
332 | :is_private => true) | |
333 |
|
333 | |||
334 | Role.find(2).update_attribute :issues_visibility, 'default' |
|
334 | Role.find(2).update_attribute :issues_visibility, 'default' | |
335 | issues = Issue.visible(User.find(8)).to_a |
|
335 | issues = Issue.visible(User.find(8)).to_a | |
336 | assert issues.any? |
|
336 | assert issues.any? | |
337 | assert issues.include?(issue) |
|
337 | assert issues.include?(issue) | |
338 |
|
338 | |||
339 | Role.find(2).update_attribute :issues_visibility, 'own' |
|
339 | Role.find(2).update_attribute :issues_visibility, 'own' | |
340 | issues = Issue.visible(User.find(8)).to_a |
|
340 | issues = Issue.visible(User.find(8)).to_a | |
341 | assert issues.any? |
|
341 | assert issues.any? | |
342 | assert_include issue, issues |
|
342 | assert_include issue, issues | |
343 | end |
|
343 | end | |
344 |
|
344 | |||
345 | def test_visible_scope_for_admin |
|
345 | def test_visible_scope_for_admin | |
346 | user = User.find(1) |
|
346 | user = User.find(1) | |
347 | user.members.each(&:destroy) |
|
347 | user.members.each(&:destroy) | |
348 | assert user.projects.empty? |
|
348 | assert user.projects.empty? | |
349 | issues = Issue.visible(user).to_a |
|
349 | issues = Issue.visible(user).to_a | |
350 | assert issues.any? |
|
350 | assert issues.any? | |
351 | # Admin should see issues on private projects that admin does not belong to |
|
351 | # Admin should see issues on private projects that admin does not belong to | |
352 | assert issues.detect {|issue| !issue.project.is_public?} |
|
352 | assert issues.detect {|issue| !issue.project.is_public?} | |
353 | # Admin should see private issues of other users |
|
353 | # Admin should see private issues of other users | |
354 | assert issues.detect {|issue| issue.is_private? && issue.author != user} |
|
354 | assert issues.detect {|issue| issue.is_private? && issue.author != user} | |
355 | assert_visibility_match user, issues |
|
355 | assert_visibility_match user, issues | |
356 | end |
|
356 | end | |
357 |
|
357 | |||
358 | def test_visible_scope_with_project |
|
358 | def test_visible_scope_with_project | |
359 | project = Project.find(1) |
|
359 | project = Project.find(1) | |
360 | issues = Issue.visible(User.find(2), :project => project).to_a |
|
360 | issues = Issue.visible(User.find(2), :project => project).to_a | |
361 | projects = issues.collect(&:project).uniq |
|
361 | projects = issues.collect(&:project).uniq | |
362 | assert_equal 1, projects.size |
|
362 | assert_equal 1, projects.size | |
363 | assert_equal project, projects.first |
|
363 | assert_equal project, projects.first | |
364 | end |
|
364 | end | |
365 |
|
365 | |||
366 | def test_visible_scope_with_project_and_subprojects |
|
366 | def test_visible_scope_with_project_and_subprojects | |
367 | project = Project.find(1) |
|
367 | project = Project.find(1) | |
368 | issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a |
|
368 | issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a | |
369 | projects = issues.collect(&:project).uniq |
|
369 | projects = issues.collect(&:project).uniq | |
370 | assert projects.size > 1 |
|
370 | assert projects.size > 1 | |
371 | assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)} |
|
371 | assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)} | |
372 | end |
|
372 | end | |
373 |
|
373 | |||
374 | def test_visible_and_nested_set_scopes |
|
374 | def test_visible_and_nested_set_scopes | |
375 | user = User.generate! |
|
375 | user = User.generate! | |
376 | parent = Issue.generate!(:assigned_to => user) |
|
376 | parent = Issue.generate!(:assigned_to => user) | |
377 | assert parent.visible?(user) |
|
377 | assert parent.visible?(user) | |
378 | child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user) |
|
378 | child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user) | |
379 | child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user) |
|
379 | child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user) | |
380 | parent.reload |
|
380 | parent.reload | |
381 | child1.reload |
|
381 | child1.reload | |
382 | child2.reload |
|
382 | child2.reload | |
383 | assert child1.visible?(user) |
|
383 | assert child1.visible?(user) | |
384 | assert child2.visible?(user) |
|
384 | assert child2.visible?(user) | |
385 | assert_equal 2, parent.descendants.count |
|
385 | assert_equal 2, parent.descendants.count | |
386 | assert_equal 2, parent.descendants.visible(user).count |
|
386 | assert_equal 2, parent.descendants.visible(user).count | |
387 | # awesome_nested_set 2-1-stable branch has regression. |
|
387 | # awesome_nested_set 2-1-stable branch has regression. | |
388 | # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6 |
|
388 | # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6 | |
389 | # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft: |
|
389 | # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft: | |
390 | assert_equal 2, parent.descendants.collect{|i| i}.size |
|
390 | assert_equal 2, parent.descendants.collect{|i| i}.size | |
391 | assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size |
|
391 | assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size | |
392 | end |
|
392 | end | |
393 |
|
393 | |||
394 | def test_visible_scope_with_unsaved_user_should_not_raise_an_error |
|
394 | def test_visible_scope_with_unsaved_user_should_not_raise_an_error | |
395 | user = User.new |
|
395 | user = User.new | |
396 | assert_nothing_raised do |
|
396 | assert_nothing_raised do | |
397 | Issue.visible(user).to_a |
|
397 | Issue.visible(user).to_a | |
398 | end |
|
398 | end | |
399 | end |
|
399 | end | |
400 |
|
400 | |||
401 | def test_open_scope |
|
401 | def test_open_scope | |
402 | issues = Issue.open.to_a |
|
402 | issues = Issue.open.to_a | |
403 | assert_nil issues.detect(&:closed?) |
|
403 | assert_nil issues.detect(&:closed?) | |
404 | end |
|
404 | end | |
405 |
|
405 | |||
406 | def test_open_scope_with_arg |
|
406 | def test_open_scope_with_arg | |
407 | issues = Issue.open(false).to_a |
|
407 | issues = Issue.open(false).to_a | |
408 | assert_equal issues, issues.select(&:closed?) |
|
408 | assert_equal issues, issues.select(&:closed?) | |
409 | end |
|
409 | end | |
410 |
|
410 | |||
411 | def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues |
|
411 | def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues | |
412 | version = Version.find(2) |
|
412 | version = Version.find(2) | |
413 | assert version.fixed_issues.any? |
|
413 | assert version.fixed_issues.any? | |
414 | assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort |
|
414 | assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort | |
415 | end |
|
415 | end | |
416 |
|
416 | |||
417 | def test_fixed_version_scope_with_empty_array_should_return_no_result |
|
417 | def test_fixed_version_scope_with_empty_array_should_return_no_result | |
418 | assert_equal 0, Issue.fixed_version([]).count |
|
418 | assert_equal 0, Issue.fixed_version([]).count | |
419 | end |
|
419 | end | |
420 |
|
420 | |||
421 | def test_assigned_to_scope_should_return_issues_assigned_to_the_user |
|
421 | def test_assigned_to_scope_should_return_issues_assigned_to_the_user | |
422 | user = User.generate! |
|
422 | user = User.generate! | |
423 | issue = Issue.generate! |
|
423 | issue = Issue.generate! | |
424 | Issue.where(:id => issue.id).update_all :assigned_to_id => user.id |
|
424 | Issue.where(:id => issue.id).update_all :assigned_to_id => user.id | |
425 | assert_equal [issue], Issue.assigned_to(user).to_a |
|
425 | assert_equal [issue], Issue.assigned_to(user).to_a | |
426 | end |
|
426 | end | |
427 |
|
427 | |||
428 | def test_assigned_to_scope_should_return_issues_assigned_to_the_user_groups |
|
428 | def test_assigned_to_scope_should_return_issues_assigned_to_the_user_groups | |
429 | group = Group.generate! |
|
429 | group = Group.generate! | |
430 | user = User.generate! |
|
430 | user = User.generate! | |
431 | group.users << user |
|
431 | group.users << user | |
432 | issue = Issue.generate! |
|
432 | issue = Issue.generate! | |
433 | Issue.where(:id => issue.id).update_all :assigned_to_id => group.id |
|
433 | Issue.where(:id => issue.id).update_all :assigned_to_id => group.id | |
434 | assert_equal [issue], Issue.assigned_to(user).to_a |
|
434 | assert_equal [issue], Issue.assigned_to(user).to_a | |
435 | end |
|
435 | end | |
436 |
|
436 | |||
437 | def test_errors_full_messages_should_include_custom_fields_errors |
|
437 | def test_errors_full_messages_should_include_custom_fields_errors | |
438 | field = IssueCustomField.find_by_name('Database') |
|
438 | field = IssueCustomField.find_by_name('Database') | |
439 |
|
439 | |||
440 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
440 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
441 | :status_id => 1, :subject => 'test_create', |
|
441 | :status_id => 1, :subject => 'test_create', | |
442 | :description => 'IssueTest#test_create_with_required_custom_field') |
|
442 | :description => 'IssueTest#test_create_with_required_custom_field') | |
443 | assert issue.available_custom_fields.include?(field) |
|
443 | assert issue.available_custom_fields.include?(field) | |
444 | # Invalid value |
|
444 | # Invalid value | |
445 | issue.custom_field_values = { field.id => 'SQLServer' } |
|
445 | issue.custom_field_values = { field.id => 'SQLServer' } | |
446 |
|
446 | |||
447 | assert !issue.valid? |
|
447 | assert !issue.valid? | |
448 | assert_equal 1, issue.errors.full_messages.size |
|
448 | assert_equal 1, issue.errors.full_messages.size | |
449 | assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", |
|
449 | assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", | |
450 | issue.errors.full_messages.first |
|
450 | issue.errors.full_messages.first | |
451 | end |
|
451 | end | |
452 |
|
452 | |||
453 | def test_update_issue_with_required_custom_field |
|
453 | def test_update_issue_with_required_custom_field | |
454 | field = IssueCustomField.find_by_name('Database') |
|
454 | field = IssueCustomField.find_by_name('Database') | |
455 | field.update_attribute(:is_required, true) |
|
455 | field.update_attribute(:is_required, true) | |
456 |
|
456 | |||
457 | issue = Issue.find(1) |
|
457 | issue = Issue.find(1) | |
458 | assert_nil issue.custom_value_for(field) |
|
458 | assert_nil issue.custom_value_for(field) | |
459 | assert issue.available_custom_fields.include?(field) |
|
459 | assert issue.available_custom_fields.include?(field) | |
460 | # No change to custom values, issue can be saved |
|
460 | # No change to custom values, issue can be saved | |
461 | assert issue.save |
|
461 | assert issue.save | |
462 | # Blank value |
|
462 | # Blank value | |
463 | issue.custom_field_values = { field.id => '' } |
|
463 | issue.custom_field_values = { field.id => '' } | |
464 | assert !issue.save |
|
464 | assert !issue.save | |
465 | # Valid value |
|
465 | # Valid value | |
466 | issue.custom_field_values = { field.id => 'PostgreSQL' } |
|
466 | issue.custom_field_values = { field.id => 'PostgreSQL' } | |
467 | assert issue.save |
|
467 | assert issue.save | |
468 | issue.reload |
|
468 | issue.reload | |
469 | assert_equal 'PostgreSQL', issue.custom_value_for(field).value |
|
469 | assert_equal 'PostgreSQL', issue.custom_value_for(field).value | |
470 | end |
|
470 | end | |
471 |
|
471 | |||
472 | def test_should_not_update_attributes_if_custom_fields_validation_fails |
|
472 | def test_should_not_update_attributes_if_custom_fields_validation_fails | |
473 | issue = Issue.find(1) |
|
473 | issue = Issue.find(1) | |
474 | field = IssueCustomField.find_by_name('Database') |
|
474 | field = IssueCustomField.find_by_name('Database') | |
475 | assert issue.available_custom_fields.include?(field) |
|
475 | assert issue.available_custom_fields.include?(field) | |
476 |
|
476 | |||
477 | issue.custom_field_values = { field.id => 'Invalid' } |
|
477 | issue.custom_field_values = { field.id => 'Invalid' } | |
478 | issue.subject = 'Should be not be saved' |
|
478 | issue.subject = 'Should be not be saved' | |
479 | assert !issue.save |
|
479 | assert !issue.save | |
480 |
|
480 | |||
481 | issue.reload |
|
481 | issue.reload | |
482 | assert_equal "Cannot print recipes", issue.subject |
|
482 | assert_equal "Cannot print recipes", issue.subject | |
483 | end |
|
483 | end | |
484 |
|
484 | |||
485 | def test_should_not_recreate_custom_values_objects_on_update |
|
485 | def test_should_not_recreate_custom_values_objects_on_update | |
486 | field = IssueCustomField.find_by_name('Database') |
|
486 | field = IssueCustomField.find_by_name('Database') | |
487 |
|
487 | |||
488 | issue = Issue.find(1) |
|
488 | issue = Issue.find(1) | |
489 | issue.custom_field_values = { field.id => 'PostgreSQL' } |
|
489 | issue.custom_field_values = { field.id => 'PostgreSQL' } | |
490 | assert issue.save |
|
490 | assert issue.save | |
491 | custom_value = issue.custom_value_for(field) |
|
491 | custom_value = issue.custom_value_for(field) | |
492 | issue.reload |
|
492 | issue.reload | |
493 | issue.custom_field_values = { field.id => 'MySQL' } |
|
493 | issue.custom_field_values = { field.id => 'MySQL' } | |
494 | assert issue.save |
|
494 | assert issue.save | |
495 | issue.reload |
|
495 | issue.reload | |
496 | assert_equal custom_value.id, issue.custom_value_for(field).id |
|
496 | assert_equal custom_value.id, issue.custom_value_for(field).id | |
497 | end |
|
497 | end | |
498 |
|
498 | |||
499 | def test_setting_project_should_set_version_to_default_version |
|
499 | def test_setting_project_should_set_version_to_default_version | |
500 | version = Version.generate!(:project_id => 1) |
|
500 | version = Version.generate!(:project_id => 1) | |
501 | Project.find(1).update_attribute(:default_version_id, version.id) |
|
501 | Project.find(1).update_attribute(:default_version_id, version.id) | |
502 |
|
502 | |||
503 | issue = Issue.new(:project_id => 1) |
|
503 | issue = Issue.new(:project_id => 1) | |
504 | assert_equal version, issue.fixed_version |
|
504 | assert_equal version, issue.fixed_version | |
505 | end |
|
505 | end | |
506 |
|
506 | |||
507 | def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields |
|
507 | def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields | |
508 | issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
508 | issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
509 | :status_id => 1, :subject => 'Test', |
|
509 | :status_id => 1, :subject => 'Test', | |
510 | :custom_field_values => {'2' => 'Test'}) |
|
510 | :custom_field_values => {'2' => 'Test'}) | |
511 | assert !Tracker.find(2).custom_field_ids.include?(2) |
|
511 | assert !Tracker.find(2).custom_field_ids.include?(2) | |
512 |
|
512 | |||
513 | issue = Issue.find(issue.id) |
|
513 | issue = Issue.find(issue.id) | |
514 | issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}} |
|
514 | issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}} | |
515 |
|
515 | |||
516 | issue = Issue.find(issue.id) |
|
516 | issue = Issue.find(issue.id) | |
517 | custom_value = issue.custom_value_for(2) |
|
517 | custom_value = issue.custom_value_for(2) | |
518 | assert_not_nil custom_value |
|
518 | assert_not_nil custom_value | |
519 | assert_equal 'Test', custom_value.value |
|
519 | assert_equal 'Test', custom_value.value | |
520 | end |
|
520 | end | |
521 |
|
521 | |||
522 | def test_assigning_tracker_id_should_reload_custom_fields_values |
|
522 | def test_assigning_tracker_id_should_reload_custom_fields_values | |
523 | issue = Issue.new(:project => Project.find(1)) |
|
523 | issue = Issue.new(:project => Project.find(1)) | |
524 | assert issue.custom_field_values.empty? |
|
524 | assert issue.custom_field_values.empty? | |
525 | issue.tracker_id = 1 |
|
525 | issue.tracker_id = 1 | |
526 | assert issue.custom_field_values.any? |
|
526 | assert issue.custom_field_values.any? | |
527 | end |
|
527 | end | |
528 |
|
528 | |||
529 | def test_assigning_attributes_should_assign_project_and_tracker_first |
|
529 | def test_assigning_attributes_should_assign_project_and_tracker_first | |
530 | seq = sequence('seq') |
|
530 | seq = sequence('seq') | |
531 | issue = Issue.new |
|
531 | issue = Issue.new | |
532 | issue.expects(:project_id=).in_sequence(seq) |
|
532 | issue.expects(:project_id=).in_sequence(seq) | |
533 | issue.expects(:tracker_id=).in_sequence(seq) |
|
533 | issue.expects(:tracker_id=).in_sequence(seq) | |
534 | issue.expects(:subject=).in_sequence(seq) |
|
534 | issue.expects(:subject=).in_sequence(seq) | |
535 | issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'} |
|
535 | issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'} | |
536 | end |
|
536 | end | |
537 |
|
537 | |||
538 | def test_assigning_tracker_and_custom_fields_should_assign_custom_fields |
|
538 | def test_assigning_tracker_and_custom_fields_should_assign_custom_fields | |
539 | attributes = ActiveSupport::OrderedHash.new |
|
539 | attributes = ActiveSupport::OrderedHash.new | |
540 | attributes['custom_field_values'] = { '1' => 'MySQL' } |
|
540 | attributes['custom_field_values'] = { '1' => 'MySQL' } | |
541 | attributes['tracker_id'] = '1' |
|
541 | attributes['tracker_id'] = '1' | |
542 | issue = Issue.new(:project => Project.find(1)) |
|
542 | issue = Issue.new(:project => Project.find(1)) | |
543 | issue.attributes = attributes |
|
543 | issue.attributes = attributes | |
544 | assert_equal 'MySQL', issue.custom_field_value(1) |
|
544 | assert_equal 'MySQL', issue.custom_field_value(1) | |
545 | end |
|
545 | end | |
546 |
|
546 | |||
547 | def test_changing_tracker_should_clear_disabled_core_fields |
|
547 | def test_changing_tracker_should_clear_disabled_core_fields | |
548 | tracker = Tracker.find(2) |
|
548 | tracker = Tracker.find(2) | |
549 | tracker.core_fields = tracker.core_fields - %w(due_date) |
|
549 | tracker.core_fields = tracker.core_fields - %w(due_date) | |
550 | tracker.save! |
|
550 | tracker.save! | |
551 |
|
551 | |||
552 | issue = Issue.generate!(:tracker_id => 1, :start_date => Date.today, :due_date => Date.today) |
|
552 | issue = Issue.generate!(:tracker_id => 1, :start_date => Date.today, :due_date => Date.today) | |
553 | issue.save! |
|
553 | issue.save! | |
554 |
|
554 | |||
555 | issue.tracker_id = 2 |
|
555 | issue.tracker_id = 2 | |
556 | issue.save! |
|
556 | issue.save! | |
557 | assert_not_nil issue.start_date |
|
557 | assert_not_nil issue.start_date | |
558 | assert_nil issue.due_date |
|
558 | assert_nil issue.due_date | |
559 | end |
|
559 | end | |
560 |
|
560 | |||
561 | def test_changing_tracker_should_not_add_cleared_fields_to_journal |
|
561 | def test_changing_tracker_should_not_add_cleared_fields_to_journal | |
562 | tracker = Tracker.find(2) |
|
562 | tracker = Tracker.find(2) | |
563 | tracker.core_fields = tracker.core_fields - %w(due_date) |
|
563 | tracker.core_fields = tracker.core_fields - %w(due_date) | |
564 | tracker.save! |
|
564 | tracker.save! | |
565 |
|
565 | |||
566 | issue = Issue.generate!(:tracker_id => 1, :due_date => Date.today) |
|
566 | issue = Issue.generate!(:tracker_id => 1, :due_date => Date.today) | |
567 | issue.save! |
|
567 | issue.save! | |
568 |
|
568 | |||
569 | assert_difference 'Journal.count' do |
|
569 | assert_difference 'Journal.count' do | |
570 | issue.init_journal User.find(1) |
|
570 | issue.init_journal User.find(1) | |
571 | issue.tracker_id = 2 |
|
571 | issue.tracker_id = 2 | |
572 | issue.save! |
|
572 | issue.save! | |
573 | assert_nil issue.due_date |
|
573 | assert_nil issue.due_date | |
574 | end |
|
574 | end | |
575 | journal = Journal.order('id DESC').first |
|
575 | journal = Journal.order('id DESC').first | |
576 | assert_equal 1, journal.details.count |
|
576 | assert_equal 1, journal.details.count | |
577 | end |
|
577 | end | |
578 |
|
578 | |||
579 | def test_reload_should_reload_custom_field_values |
|
579 | def test_reload_should_reload_custom_field_values | |
580 | issue = Issue.generate! |
|
580 | issue = Issue.generate! | |
581 | issue.custom_field_values = {'2' => 'Foo'} |
|
581 | issue.custom_field_values = {'2' => 'Foo'} | |
582 | issue.save! |
|
582 | issue.save! | |
583 |
|
583 | |||
584 | issue = Issue.order('id desc').first |
|
584 | issue = Issue.order('id desc').first | |
585 | assert_equal 'Foo', issue.custom_field_value(2) |
|
585 | assert_equal 'Foo', issue.custom_field_value(2) | |
586 |
|
586 | |||
587 | issue.custom_field_values = {'2' => 'Bar'} |
|
587 | issue.custom_field_values = {'2' => 'Bar'} | |
588 | assert_equal 'Bar', issue.custom_field_value(2) |
|
588 | assert_equal 'Bar', issue.custom_field_value(2) | |
589 |
|
589 | |||
590 | issue.reload |
|
590 | issue.reload | |
591 | assert_equal 'Foo', issue.custom_field_value(2) |
|
591 | assert_equal 'Foo', issue.custom_field_value(2) | |
592 | end |
|
592 | end | |
593 |
|
593 | |||
594 | def test_should_update_issue_with_disabled_tracker |
|
594 | def test_should_update_issue_with_disabled_tracker | |
595 | p = Project.find(1) |
|
595 | p = Project.find(1) | |
596 | issue = Issue.find(1) |
|
596 | issue = Issue.find(1) | |
597 |
|
597 | |||
598 | p.trackers.delete(issue.tracker) |
|
598 | p.trackers.delete(issue.tracker) | |
599 | assert !p.trackers.include?(issue.tracker) |
|
599 | assert !p.trackers.include?(issue.tracker) | |
600 |
|
600 | |||
601 | issue.reload |
|
601 | issue.reload | |
602 | issue.subject = 'New subject' |
|
602 | issue.subject = 'New subject' | |
603 | assert issue.save |
|
603 | assert issue.save | |
604 | end |
|
604 | end | |
605 |
|
605 | |||
606 | def test_should_not_set_a_disabled_tracker |
|
606 | def test_should_not_set_a_disabled_tracker | |
607 | p = Project.find(1) |
|
607 | p = Project.find(1) | |
608 | p.trackers.delete(Tracker.find(2)) |
|
608 | p.trackers.delete(Tracker.find(2)) | |
609 |
|
609 | |||
610 | issue = Issue.find(1) |
|
610 | issue = Issue.find(1) | |
611 | issue.tracker_id = 2 |
|
611 | issue.tracker_id = 2 | |
612 | issue.subject = 'New subject' |
|
612 | issue.subject = 'New subject' | |
613 | assert !issue.save |
|
613 | assert !issue.save | |
614 | assert_not_equal [], issue.errors[:tracker_id] |
|
614 | assert_not_equal [], issue.errors[:tracker_id] | |
615 | end |
|
615 | end | |
616 |
|
616 | |||
617 | def test_category_based_assignment |
|
617 | def test_category_based_assignment | |
618 | issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, |
|
618 | issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, | |
619 | :status_id => 1, :priority => IssuePriority.all.first, |
|
619 | :status_id => 1, :priority => IssuePriority.all.first, | |
620 | :subject => 'Assignment test', |
|
620 | :subject => 'Assignment test', | |
621 | :description => 'Assignment test', :category_id => 1) |
|
621 | :description => 'Assignment test', :category_id => 1) | |
622 | assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to |
|
622 | assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to | |
623 | end |
|
623 | end | |
624 |
|
624 | |||
625 | def test_new_statuses_allowed_to |
|
625 | def test_new_statuses_allowed_to | |
626 | WorkflowTransition.delete_all |
|
626 | WorkflowTransition.delete_all | |
627 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
627 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, | |
628 | :old_status_id => 1, :new_status_id => 2, |
|
628 | :old_status_id => 1, :new_status_id => 2, | |
629 | :author => false, :assignee => false) |
|
629 | :author => false, :assignee => false) | |
630 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
630 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, | |
631 | :old_status_id => 1, :new_status_id => 3, |
|
631 | :old_status_id => 1, :new_status_id => 3, | |
632 | :author => true, :assignee => false) |
|
632 | :author => true, :assignee => false) | |
633 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
633 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, | |
634 | :old_status_id => 1, :new_status_id => 4, |
|
634 | :old_status_id => 1, :new_status_id => 4, | |
635 | :author => false, :assignee => true) |
|
635 | :author => false, :assignee => true) | |
636 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
636 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, | |
637 | :old_status_id => 1, :new_status_id => 5, |
|
637 | :old_status_id => 1, :new_status_id => 5, | |
638 | :author => true, :assignee => true) |
|
638 | :author => true, :assignee => true) | |
639 | status = IssueStatus.find(1) |
|
639 | status = IssueStatus.find(1) | |
640 | role = Role.find(1) |
|
640 | role = Role.find(1) | |
641 | tracker = Tracker.find(1) |
|
641 | tracker = Tracker.find(1) | |
642 | user = User.find(2) |
|
642 | user = User.find(2) | |
643 |
|
643 | |||
644 | issue = Issue.generate!(:tracker => tracker, :status => status, |
|
644 | issue = Issue.generate!(:tracker => tracker, :status => status, | |
645 | :project_id => 1, :author_id => 1) |
|
645 | :project_id => 1, :author_id => 1) | |
646 | assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id) |
|
646 | assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id) | |
647 |
|
647 | |||
648 | issue = Issue.generate!(:tracker => tracker, :status => status, |
|
648 | issue = Issue.generate!(:tracker => tracker, :status => status, | |
649 | :project_id => 1, :author => user) |
|
649 | :project_id => 1, :author => user) | |
650 | assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id) |
|
650 | assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id) | |
651 |
|
651 | |||
652 | issue = Issue.generate!(:tracker => tracker, :status => status, |
|
652 | issue = Issue.generate!(:tracker => tracker, :status => status, | |
653 | :project_id => 1, :author_id => 1, |
|
653 | :project_id => 1, :author_id => 1, | |
654 | :assigned_to => user) |
|
654 | :assigned_to => user) | |
655 | assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) |
|
655 | assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) | |
656 |
|
656 | |||
657 | issue = Issue.generate!(:tracker => tracker, :status => status, |
|
657 | issue = Issue.generate!(:tracker => tracker, :status => status, | |
658 | :project_id => 1, :author => user, |
|
658 | :project_id => 1, :author => user, | |
659 | :assigned_to => user) |
|
659 | :assigned_to => user) | |
660 | assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) |
|
660 | assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) | |
661 |
|
661 | |||
662 | group = Group.generate! |
|
662 | group = Group.generate! | |
663 | group.users << user |
|
663 | group.users << user | |
664 | issue = Issue.generate!(:tracker => tracker, :status => status, |
|
664 | issue = Issue.generate!(:tracker => tracker, :status => status, | |
665 | :project_id => 1, :author => user, |
|
665 | :project_id => 1, :author => user, | |
666 | :assigned_to => group) |
|
666 | :assigned_to => group) | |
667 | assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) |
|
667 | assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) | |
668 | end |
|
668 | end | |
669 |
|
669 | |||
670 | def test_new_statuses_allowed_to_should_consider_group_assignment |
|
670 | def test_new_statuses_allowed_to_should_consider_group_assignment | |
671 | WorkflowTransition.delete_all |
|
671 | WorkflowTransition.delete_all | |
672 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
672 | WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, | |
673 | :old_status_id => 1, :new_status_id => 4, |
|
673 | :old_status_id => 1, :new_status_id => 4, | |
674 | :author => false, :assignee => true) |
|
674 | :author => false, :assignee => true) | |
675 | user = User.find(2) |
|
675 | user = User.find(2) | |
676 | group = Group.generate! |
|
676 | group = Group.generate! | |
677 | group.users << user |
|
677 | group.users << user | |
678 |
|
678 | |||
679 | issue = Issue.generate!(:author_id => 1, :assigned_to => group) |
|
679 | issue = Issue.generate!(:author_id => 1, :assigned_to => group) | |
680 | assert_include 4, issue.new_statuses_allowed_to(user).map(&:id) |
|
680 | assert_include 4, issue.new_statuses_allowed_to(user).map(&:id) | |
681 | end |
|
681 | end | |
682 |
|
682 | |||
683 | def test_new_statuses_allowed_to_should_return_all_transitions_for_admin |
|
683 | def test_new_statuses_allowed_to_should_return_all_transitions_for_admin | |
684 | admin = User.find(1) |
|
684 | admin = User.find(1) | |
685 | issue = Issue.find(1) |
|
685 | issue = Issue.find(1) | |
686 | assert !admin.member_of?(issue.project) |
|
686 | assert !admin.member_of?(issue.project) | |
687 | expected_statuses = [issue.status] + |
|
687 | expected_statuses = [issue.status] + | |
688 | WorkflowTransition.where(:old_status_id => issue.status_id). |
|
688 | WorkflowTransition.where(:old_status_id => issue.status_id). | |
689 | map(&:new_status).uniq.sort |
|
689 | map(&:new_status).uniq.sort | |
690 | assert_equal expected_statuses, issue.new_statuses_allowed_to(admin) |
|
690 | assert_equal expected_statuses, issue.new_statuses_allowed_to(admin) | |
691 | end |
|
691 | end | |
692 |
|
692 | |||
693 | def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying |
|
693 | def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying | |
694 | issue = Issue.find(1).copy |
|
694 | issue = Issue.find(1).copy | |
695 | assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id) |
|
695 | assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id) | |
696 |
|
696 | |||
697 | issue = Issue.find(2).copy |
|
697 | issue = Issue.find(2).copy | |
698 | assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id) |
|
698 | assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id) | |
699 | end |
|
699 | end | |
700 |
|
700 | |||
701 | def test_safe_attributes_names_should_not_include_disabled_field |
|
701 | def test_safe_attributes_names_should_not_include_disabled_field | |
702 | tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id)) |
|
702 | tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id)) | |
703 |
|
703 | |||
704 | issue = Issue.new(:tracker => tracker) |
|
704 | issue = Issue.new(:tracker => tracker) | |
705 | assert_include 'tracker_id', issue.safe_attribute_names |
|
705 | assert_include 'tracker_id', issue.safe_attribute_names | |
706 | assert_include 'status_id', issue.safe_attribute_names |
|
706 | assert_include 'status_id', issue.safe_attribute_names | |
707 | assert_include 'subject', issue.safe_attribute_names |
|
707 | assert_include 'subject', issue.safe_attribute_names | |
708 | assert_include 'description', issue.safe_attribute_names |
|
708 | assert_include 'description', issue.safe_attribute_names | |
709 | assert_include 'custom_field_values', issue.safe_attribute_names |
|
709 | assert_include 'custom_field_values', issue.safe_attribute_names | |
710 | assert_include 'custom_fields', issue.safe_attribute_names |
|
710 | assert_include 'custom_fields', issue.safe_attribute_names | |
711 | assert_include 'lock_version', issue.safe_attribute_names |
|
711 | assert_include 'lock_version', issue.safe_attribute_names | |
712 |
|
712 | |||
713 | tracker.core_fields.each do |field| |
|
713 | tracker.core_fields.each do |field| | |
714 | assert_include field, issue.safe_attribute_names |
|
714 | assert_include field, issue.safe_attribute_names | |
715 | end |
|
715 | end | |
716 |
|
716 | |||
717 | tracker.disabled_core_fields.each do |field| |
|
717 | tracker.disabled_core_fields.each do |field| | |
718 | assert_not_include field, issue.safe_attribute_names |
|
718 | assert_not_include field, issue.safe_attribute_names | |
719 | end |
|
719 | end | |
720 | end |
|
720 | end | |
721 |
|
721 | |||
722 | def test_safe_attributes_should_ignore_disabled_fields |
|
722 | def test_safe_attributes_should_ignore_disabled_fields | |
723 | tracker = Tracker.find(1) |
|
723 | tracker = Tracker.find(1) | |
724 | tracker.core_fields = %w(assigned_to_id due_date) |
|
724 | tracker.core_fields = %w(assigned_to_id due_date) | |
725 | tracker.save! |
|
725 | tracker.save! | |
726 |
|
726 | |||
727 | issue = Issue.new(:tracker => tracker) |
|
727 | issue = Issue.new(:tracker => tracker) | |
728 | issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'} |
|
728 | issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'} | |
729 | assert_nil issue.start_date |
|
729 | assert_nil issue.start_date | |
730 | assert_equal Date.parse('2012-07-14'), issue.due_date |
|
730 | assert_equal Date.parse('2012-07-14'), issue.due_date | |
731 | end |
|
731 | end | |
732 |
|
732 | |||
733 | def test_safe_attributes_should_accept_target_tracker_enabled_fields |
|
733 | def test_safe_attributes_should_accept_target_tracker_enabled_fields | |
734 | source = Tracker.find(1) |
|
734 | source = Tracker.find(1) | |
735 | source.core_fields = [] |
|
735 | source.core_fields = [] | |
736 | source.save! |
|
736 | source.save! | |
737 | target = Tracker.find(2) |
|
737 | target = Tracker.find(2) | |
738 | target.core_fields = %w(assigned_to_id due_date) |
|
738 | target.core_fields = %w(assigned_to_id due_date) | |
739 | target.save! |
|
739 | target.save! | |
740 |
|
740 | |||
741 | issue = Issue.new(:tracker => source) |
|
741 | issue = Issue.new(:tracker => source) | |
742 | issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'} |
|
742 | issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'} | |
743 | assert_equal target, issue.tracker |
|
743 | assert_equal target, issue.tracker | |
744 | assert_equal Date.parse('2012-07-14'), issue.due_date |
|
744 | assert_equal Date.parse('2012-07-14'), issue.due_date | |
745 | end |
|
745 | end | |
746 |
|
746 | |||
747 | def test_safe_attributes_should_not_include_readonly_fields |
|
747 | def test_safe_attributes_should_not_include_readonly_fields | |
748 | WorkflowPermission.delete_all |
|
748 | WorkflowPermission.delete_all | |
749 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
749 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
750 | :role_id => 1, :field_name => 'due_date', |
|
750 | :role_id => 1, :field_name => 'due_date', | |
751 | :rule => 'readonly') |
|
751 | :rule => 'readonly') | |
752 | user = User.find(2) |
|
752 | user = User.find(2) | |
753 |
|
753 | |||
754 | issue = Issue.new(:project_id => 1, :tracker_id => 1) |
|
754 | issue = Issue.new(:project_id => 1, :tracker_id => 1) | |
755 | assert_equal %w(due_date), issue.read_only_attribute_names(user) |
|
755 | assert_equal %w(due_date), issue.read_only_attribute_names(user) | |
756 | assert_not_include 'due_date', issue.safe_attribute_names(user) |
|
756 | assert_not_include 'due_date', issue.safe_attribute_names(user) | |
757 |
|
757 | |||
758 | issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user |
|
758 | issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user | |
759 | assert_equal Date.parse('2012-07-14'), issue.start_date |
|
759 | assert_equal Date.parse('2012-07-14'), issue.start_date | |
760 | assert_nil issue.due_date |
|
760 | assert_nil issue.due_date | |
761 | end |
|
761 | end | |
762 |
|
762 | |||
763 | def test_safe_attributes_should_not_include_readonly_custom_fields |
|
763 | def test_safe_attributes_should_not_include_readonly_custom_fields | |
764 | cf1 = IssueCustomField.create!(:name => 'Writable field', |
|
764 | cf1 = IssueCustomField.create!(:name => 'Writable field', | |
765 | :field_format => 'string', |
|
765 | :field_format => 'string', | |
766 | :is_for_all => true, :tracker_ids => [1]) |
|
766 | :is_for_all => true, :tracker_ids => [1]) | |
767 | cf2 = IssueCustomField.create!(:name => 'Readonly field', |
|
767 | cf2 = IssueCustomField.create!(:name => 'Readonly field', | |
768 | :field_format => 'string', |
|
768 | :field_format => 'string', | |
769 | :is_for_all => true, :tracker_ids => [1]) |
|
769 | :is_for_all => true, :tracker_ids => [1]) | |
770 | WorkflowPermission.delete_all |
|
770 | WorkflowPermission.delete_all | |
771 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
771 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
772 | :role_id => 1, :field_name => cf2.id.to_s, |
|
772 | :role_id => 1, :field_name => cf2.id.to_s, | |
773 | :rule => 'readonly') |
|
773 | :rule => 'readonly') | |
774 | user = User.find(2) |
|
774 | user = User.find(2) | |
775 | issue = Issue.new(:project_id => 1, :tracker_id => 1) |
|
775 | issue = Issue.new(:project_id => 1, :tracker_id => 1) | |
776 | assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user) |
|
776 | assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user) | |
777 | assert_not_include cf2.id.to_s, issue.safe_attribute_names(user) |
|
777 | assert_not_include cf2.id.to_s, issue.safe_attribute_names(user) | |
778 |
|
778 | |||
779 | issue.send :safe_attributes=, {'custom_field_values' => { |
|
779 | issue.send :safe_attributes=, {'custom_field_values' => { | |
780 | cf1.id.to_s => 'value1', cf2.id.to_s => 'value2' |
|
780 | cf1.id.to_s => 'value1', cf2.id.to_s => 'value2' | |
781 | }}, user |
|
781 | }}, user | |
782 | assert_equal 'value1', issue.custom_field_value(cf1) |
|
782 | assert_equal 'value1', issue.custom_field_value(cf1) | |
783 | assert_nil issue.custom_field_value(cf2) |
|
783 | assert_nil issue.custom_field_value(cf2) | |
784 |
|
784 | |||
785 | issue.send :safe_attributes=, {'custom_fields' => [ |
|
785 | issue.send :safe_attributes=, {'custom_fields' => [ | |
786 | {'id' => cf1.id.to_s, 'value' => 'valuea'}, |
|
786 | {'id' => cf1.id.to_s, 'value' => 'valuea'}, | |
787 | {'id' => cf2.id.to_s, 'value' => 'valueb'} |
|
787 | {'id' => cf2.id.to_s, 'value' => 'valueb'} | |
788 | ]}, user |
|
788 | ]}, user | |
789 | assert_equal 'valuea', issue.custom_field_value(cf1) |
|
789 | assert_equal 'valuea', issue.custom_field_value(cf1) | |
790 | assert_nil issue.custom_field_value(cf2) |
|
790 | assert_nil issue.custom_field_value(cf2) | |
791 | end |
|
791 | end | |
792 |
|
792 | |||
793 | def test_safe_attributes_should_ignore_unassignable_assignee |
|
793 | def test_safe_attributes_should_ignore_unassignable_assignee | |
794 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, |
|
794 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, | |
795 | :status_id => 1, :priority => IssuePriority.all.first, |
|
795 | :status_id => 1, :priority => IssuePriority.all.first, | |
796 | :subject => 'test_create') |
|
796 | :subject => 'test_create') | |
797 | assert issue.valid? |
|
797 | assert issue.valid? | |
798 |
|
798 | |||
799 | # locked user, not allowed |
|
799 | # locked user, not allowed | |
800 | issue.safe_attributes=({'assigned_to_id' => '5'}) |
|
800 | issue.safe_attributes=({'assigned_to_id' => '5'}) | |
801 | assert_nil issue.assigned_to_id |
|
801 | assert_nil issue.assigned_to_id | |
802 | # no member |
|
802 | # no member | |
803 | issue.safe_attributes=({'assigned_to_id' => '1'}) |
|
803 | issue.safe_attributes=({'assigned_to_id' => '1'}) | |
804 | assert_nil issue.assigned_to_id |
|
804 | assert_nil issue.assigned_to_id | |
805 | # user 2 is ok |
|
805 | # user 2 is ok | |
806 | issue.safe_attributes=({'assigned_to_id' => '2'}) |
|
806 | issue.safe_attributes=({'assigned_to_id' => '2'}) | |
807 | assert_equal 2, issue.assigned_to_id |
|
807 | assert_equal 2, issue.assigned_to_id | |
808 | assert issue.save |
|
808 | assert issue.save | |
809 |
|
809 | |||
810 | issue.reload |
|
810 | issue.reload | |
811 | assert_equal 2, issue.assigned_to_id |
|
811 | assert_equal 2, issue.assigned_to_id | |
812 | issue.safe_attributes=({'assigned_to_id' => '5'}) |
|
812 | issue.safe_attributes=({'assigned_to_id' => '5'}) | |
813 | assert_equal 2, issue.assigned_to_id |
|
813 | assert_equal 2, issue.assigned_to_id | |
814 | issue.safe_attributes=({'assigned_to_id' => '1'}) |
|
814 | issue.safe_attributes=({'assigned_to_id' => '1'}) | |
815 | assert_equal 2, issue.assigned_to_id |
|
815 | assert_equal 2, issue.assigned_to_id | |
816 | # user 3 is also ok |
|
816 | # user 3 is also ok | |
817 | issue.safe_attributes=({'assigned_to_id' => '3'}) |
|
817 | issue.safe_attributes=({'assigned_to_id' => '3'}) | |
818 | assert_equal 3, issue.assigned_to_id |
|
818 | assert_equal 3, issue.assigned_to_id | |
819 | assert issue.save |
|
819 | assert issue.save | |
820 |
|
820 | |||
821 | # removal of assignee |
|
821 | # removal of assignee | |
822 | issue.safe_attributes=({'assigned_to_id' => ''}) |
|
822 | issue.safe_attributes=({'assigned_to_id' => ''}) | |
823 | assert_nil issue.assigned_to_id |
|
823 | assert_nil issue.assigned_to_id | |
824 | assert issue.save |
|
824 | assert issue.save | |
825 | end |
|
825 | end | |
826 |
|
826 | |||
827 | def test_editable_custom_field_values_should_return_non_readonly_custom_values |
|
827 | def test_editable_custom_field_values_should_return_non_readonly_custom_values | |
828 | cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string', |
|
828 | cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string', | |
829 | :is_for_all => true, :tracker_ids => [1, 2]) |
|
829 | :is_for_all => true, :tracker_ids => [1, 2]) | |
830 | cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string', |
|
830 | cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string', | |
831 | :is_for_all => true, :tracker_ids => [1, 2]) |
|
831 | :is_for_all => true, :tracker_ids => [1, 2]) | |
832 | WorkflowPermission.delete_all |
|
832 | WorkflowPermission.delete_all | |
833 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, |
|
833 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, | |
834 | :field_name => cf2.id.to_s, :rule => 'readonly') |
|
834 | :field_name => cf2.id.to_s, :rule => 'readonly') | |
835 | user = User.find(2) |
|
835 | user = User.find(2) | |
836 |
|
836 | |||
837 | issue = Issue.new(:project_id => 1, :tracker_id => 1) |
|
837 | issue = Issue.new(:project_id => 1, :tracker_id => 1) | |
838 | values = issue.editable_custom_field_values(user) |
|
838 | values = issue.editable_custom_field_values(user) | |
839 | assert values.detect {|value| value.custom_field == cf1} |
|
839 | assert values.detect {|value| value.custom_field == cf1} | |
840 | assert_nil values.detect {|value| value.custom_field == cf2} |
|
840 | assert_nil values.detect {|value| value.custom_field == cf2} | |
841 |
|
841 | |||
842 | issue.tracker_id = 2 |
|
842 | issue.tracker_id = 2 | |
843 | values = issue.editable_custom_field_values(user) |
|
843 | values = issue.editable_custom_field_values(user) | |
844 | assert values.detect {|value| value.custom_field == cf1} |
|
844 | assert values.detect {|value| value.custom_field == cf1} | |
845 | assert values.detect {|value| value.custom_field == cf2} |
|
845 | assert values.detect {|value| value.custom_field == cf2} | |
846 | end |
|
846 | end | |
847 |
|
847 | |||
848 | def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only |
|
848 | def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only | |
849 | enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2]) |
|
849 | enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2]) | |
850 | disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2]) |
|
850 | disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2]) | |
851 | user = User.find(2) |
|
851 | user = User.find(2) | |
852 | issue = Issue.new(:project_id => 1, :tracker_id => 1) |
|
852 | issue = Issue.new(:project_id => 1, :tracker_id => 1) | |
853 |
|
853 | |||
854 | assert_include enabled_cf, issue.editable_custom_fields(user) |
|
854 | assert_include enabled_cf, issue.editable_custom_fields(user) | |
855 | assert_not_include disabled_cf, issue.editable_custom_fields(user) |
|
855 | assert_not_include disabled_cf, issue.editable_custom_fields(user) | |
856 | end |
|
856 | end | |
857 |
|
857 | |||
858 | def test_safe_attributes_should_accept_target_tracker_writable_fields |
|
858 | def test_safe_attributes_should_accept_target_tracker_writable_fields | |
859 | WorkflowPermission.delete_all |
|
859 | WorkflowPermission.delete_all | |
860 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
860 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
861 | :role_id => 1, :field_name => 'due_date', |
|
861 | :role_id => 1, :field_name => 'due_date', | |
862 | :rule => 'readonly') |
|
862 | :rule => 'readonly') | |
863 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, |
|
863 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, | |
864 | :role_id => 1, :field_name => 'start_date', |
|
864 | :role_id => 1, :field_name => 'start_date', | |
865 | :rule => 'readonly') |
|
865 | :rule => 'readonly') | |
866 | user = User.find(2) |
|
866 | user = User.find(2) | |
867 |
|
867 | |||
868 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
868 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
869 |
|
869 | |||
870 | issue.send :safe_attributes=, {'start_date' => '2012-07-12', |
|
870 | issue.send :safe_attributes=, {'start_date' => '2012-07-12', | |
871 | 'due_date' => '2012-07-14'}, user |
|
871 | 'due_date' => '2012-07-14'}, user | |
872 | assert_equal Date.parse('2012-07-12'), issue.start_date |
|
872 | assert_equal Date.parse('2012-07-12'), issue.start_date | |
873 | assert_nil issue.due_date |
|
873 | assert_nil issue.due_date | |
874 |
|
874 | |||
875 | issue.send :safe_attributes=, {'start_date' => '2012-07-15', |
|
875 | issue.send :safe_attributes=, {'start_date' => '2012-07-15', | |
876 | 'due_date' => '2012-07-16', |
|
876 | 'due_date' => '2012-07-16', | |
877 | 'tracker_id' => 2}, user |
|
877 | 'tracker_id' => 2}, user | |
878 | assert_equal Date.parse('2012-07-12'), issue.start_date |
|
878 | assert_equal Date.parse('2012-07-12'), issue.start_date | |
879 | assert_equal Date.parse('2012-07-16'), issue.due_date |
|
879 | assert_equal Date.parse('2012-07-16'), issue.due_date | |
880 | end |
|
880 | end | |
881 |
|
881 | |||
882 | def test_safe_attributes_should_accept_target_status_writable_fields |
|
882 | def test_safe_attributes_should_accept_target_status_writable_fields | |
883 | WorkflowPermission.delete_all |
|
883 | WorkflowPermission.delete_all | |
884 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
884 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
885 | :role_id => 1, :field_name => 'due_date', |
|
885 | :role_id => 1, :field_name => 'due_date', | |
886 | :rule => 'readonly') |
|
886 | :rule => 'readonly') | |
887 | WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1, |
|
887 | WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1, | |
888 | :role_id => 1, :field_name => 'start_date', |
|
888 | :role_id => 1, :field_name => 'start_date', | |
889 | :rule => 'readonly') |
|
889 | :rule => 'readonly') | |
890 | user = User.find(2) |
|
890 | user = User.find(2) | |
891 |
|
891 | |||
892 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
892 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
893 |
|
893 | |||
894 | issue.send :safe_attributes=, {'start_date' => '2012-07-12', |
|
894 | issue.send :safe_attributes=, {'start_date' => '2012-07-12', | |
895 | 'due_date' => '2012-07-14'}, |
|
895 | 'due_date' => '2012-07-14'}, | |
896 | user |
|
896 | user | |
897 | assert_equal Date.parse('2012-07-12'), issue.start_date |
|
897 | assert_equal Date.parse('2012-07-12'), issue.start_date | |
898 | assert_nil issue.due_date |
|
898 | assert_nil issue.due_date | |
899 |
|
899 | |||
900 | issue.send :safe_attributes=, {'start_date' => '2012-07-15', |
|
900 | issue.send :safe_attributes=, {'start_date' => '2012-07-15', | |
901 | 'due_date' => '2012-07-16', |
|
901 | 'due_date' => '2012-07-16', | |
902 | 'status_id' => 2}, |
|
902 | 'status_id' => 2}, | |
903 | user |
|
903 | user | |
904 | assert_equal Date.parse('2012-07-12'), issue.start_date |
|
904 | assert_equal Date.parse('2012-07-12'), issue.start_date | |
905 | assert_equal Date.parse('2012-07-16'), issue.due_date |
|
905 | assert_equal Date.parse('2012-07-16'), issue.due_date | |
906 | end |
|
906 | end | |
907 |
|
907 | |||
908 | def test_required_attributes_should_be_validated |
|
908 | def test_required_attributes_should_be_validated | |
909 | cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', |
|
909 | cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', | |
910 | :is_for_all => true, :tracker_ids => [1, 2]) |
|
910 | :is_for_all => true, :tracker_ids => [1, 2]) | |
911 |
|
911 | |||
912 | WorkflowPermission.delete_all |
|
912 | WorkflowPermission.delete_all | |
913 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
913 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
914 | :role_id => 1, :field_name => 'due_date', |
|
914 | :role_id => 1, :field_name => 'due_date', | |
915 | :rule => 'required') |
|
915 | :rule => 'required') | |
916 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
916 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
917 | :role_id => 1, :field_name => 'category_id', |
|
917 | :role_id => 1, :field_name => 'category_id', | |
918 | :rule => 'required') |
|
918 | :rule => 'required') | |
919 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
919 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
920 | :role_id => 1, :field_name => cf.id.to_s, |
|
920 | :role_id => 1, :field_name => cf.id.to_s, | |
921 | :rule => 'required') |
|
921 | :rule => 'required') | |
922 |
|
922 | |||
923 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, |
|
923 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, | |
924 | :role_id => 1, :field_name => 'start_date', |
|
924 | :role_id => 1, :field_name => 'start_date', | |
925 | :rule => 'required') |
|
925 | :rule => 'required') | |
926 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, |
|
926 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, | |
927 | :role_id => 1, :field_name => cf.id.to_s, |
|
927 | :role_id => 1, :field_name => cf.id.to_s, | |
928 | :rule => 'required') |
|
928 | :rule => 'required') | |
929 | user = User.find(2) |
|
929 | user = User.find(2) | |
930 |
|
930 | |||
931 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
931 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
932 | :status_id => 1, :subject => 'Required fields', |
|
932 | :status_id => 1, :subject => 'Required fields', | |
933 | :author => user) |
|
933 | :author => user) | |
934 | assert_equal [cf.id.to_s, "category_id", "due_date"], |
|
934 | assert_equal [cf.id.to_s, "category_id", "due_date"], | |
935 | issue.required_attribute_names(user).sort |
|
935 | issue.required_attribute_names(user).sort | |
936 | assert !issue.save, "Issue was saved" |
|
936 | assert !issue.save, "Issue was saved" | |
937 | assert_equal ["Category cannot be blank", "Due date cannot be blank", "Foo cannot be blank"], |
|
937 | assert_equal ["Category cannot be blank", "Due date cannot be blank", "Foo cannot be blank"], | |
938 | issue.errors.full_messages.sort |
|
938 | issue.errors.full_messages.sort | |
939 |
|
939 | |||
940 | issue.tracker_id = 2 |
|
940 | issue.tracker_id = 2 | |
941 | assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort |
|
941 | assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort | |
942 | assert !issue.save, "Issue was saved" |
|
942 | assert !issue.save, "Issue was saved" | |
943 | assert_equal ["Foo cannot be blank", "Start date cannot be blank"], |
|
943 | assert_equal ["Foo cannot be blank", "Start date cannot be blank"], | |
944 | issue.errors.full_messages.sort |
|
944 | issue.errors.full_messages.sort | |
945 |
|
945 | |||
946 | issue.start_date = Date.today |
|
946 | issue.start_date = Date.today | |
947 | issue.custom_field_values = {cf.id.to_s => 'bar'} |
|
947 | issue.custom_field_values = {cf.id.to_s => 'bar'} | |
948 | assert issue.save |
|
948 | assert issue.save | |
949 | end |
|
949 | end | |
950 |
|
950 | |||
951 | def test_required_attribute_that_is_disabled_for_the_tracker_should_not_be_required |
|
951 | def test_required_attribute_that_is_disabled_for_the_tracker_should_not_be_required | |
952 | WorkflowPermission.delete_all |
|
952 | WorkflowPermission.delete_all | |
953 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
953 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
954 | :role_id => 1, :field_name => 'start_date', |
|
954 | :role_id => 1, :field_name => 'start_date', | |
955 | :rule => 'required') |
|
955 | :rule => 'required') | |
956 | user = User.find(2) |
|
956 | user = User.find(2) | |
957 |
|
957 | |||
958 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
958 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
959 | :subject => 'Required fields', :author => user) |
|
959 | :subject => 'Required fields', :author => user) | |
960 | assert !issue.save |
|
960 | assert !issue.save | |
961 | assert_include "Start date cannot be blank", issue.errors.full_messages |
|
961 | assert_include "Start date cannot be blank", issue.errors.full_messages | |
962 |
|
962 | |||
963 | tracker = Tracker.find(1) |
|
963 | tracker = Tracker.find(1) | |
964 | tracker.core_fields -= %w(start_date) |
|
964 | tracker.core_fields -= %w(start_date) | |
965 | tracker.save! |
|
965 | tracker.save! | |
966 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
966 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
967 | :subject => 'Required fields', :author => user) |
|
967 | :subject => 'Required fields', :author => user) | |
968 | assert issue.save |
|
968 | assert issue.save | |
969 | end |
|
969 | end | |
970 |
|
970 | |||
971 | def test_category_should_not_be_required_if_project_has_no_categories |
|
971 | def test_category_should_not_be_required_if_project_has_no_categories | |
972 | Project.find(1).issue_categories.delete_all |
|
972 | Project.find(1).issue_categories.delete_all | |
973 | WorkflowPermission.delete_all |
|
973 | WorkflowPermission.delete_all | |
974 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
974 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
975 | :role_id => 1, :field_name => 'category_id',:rule => 'required') |
|
975 | :role_id => 1, :field_name => 'category_id',:rule => 'required') | |
976 | user = User.find(2) |
|
976 | user = User.find(2) | |
977 |
|
977 | |||
978 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
978 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
979 | :subject => 'Required fields', :author => user) |
|
979 | :subject => 'Required fields', :author => user) | |
980 | assert_save issue |
|
980 | assert_save issue | |
981 | end |
|
981 | end | |
982 |
|
982 | |||
983 | def test_fixed_version_should_not_be_required_no_assignable_versions |
|
983 | def test_fixed_version_should_not_be_required_no_assignable_versions | |
984 | Version.delete_all |
|
984 | Version.delete_all | |
985 | WorkflowPermission.delete_all |
|
985 | WorkflowPermission.delete_all | |
986 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
986 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
987 | :role_id => 1, :field_name => 'fixed_version_id',:rule => 'required') |
|
987 | :role_id => 1, :field_name => 'fixed_version_id',:rule => 'required') | |
988 | user = User.find(2) |
|
988 | user = User.find(2) | |
989 |
|
989 | |||
990 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
990 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
991 | :subject => 'Required fields', :author => user) |
|
991 | :subject => 'Required fields', :author => user) | |
992 | assert_save issue |
|
992 | assert_save issue | |
993 | end |
|
993 | end | |
994 |
|
994 | |||
995 | def test_required_custom_field_that_is_not_visible_for_the_user_should_not_be_required |
|
995 | def test_required_custom_field_that_is_not_visible_for_the_user_should_not_be_required | |
996 | CustomField.delete_all |
|
996 | CustomField.delete_all | |
997 | field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true) |
|
997 | field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true) | |
998 | user = User.generate! |
|
998 | user = User.generate! | |
999 | User.add_to_project(user, Project.find(1), Role.find(2)) |
|
999 | User.add_to_project(user, Project.find(1), Role.find(2)) | |
1000 |
|
1000 | |||
1001 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
1001 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
1002 | :subject => 'Required fields', :author => user) |
|
1002 | :subject => 'Required fields', :author => user) | |
1003 | assert_save issue |
|
1003 | assert_save issue | |
1004 | end |
|
1004 | end | |
1005 |
|
1005 | |||
1006 | def test_required_custom_field_that_is_visible_for_the_user_should_be_required |
|
1006 | def test_required_custom_field_that_is_visible_for_the_user_should_be_required | |
1007 | CustomField.delete_all |
|
1007 | CustomField.delete_all | |
1008 | field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true) |
|
1008 | field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true) | |
1009 | user = User.generate! |
|
1009 | user = User.generate! | |
1010 | User.add_to_project(user, Project.find(1), Role.find(1)) |
|
1010 | User.add_to_project(user, Project.find(1), Role.find(1)) | |
1011 |
|
1011 | |||
1012 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
1012 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
1013 | :subject => 'Required fields', :author => user) |
|
1013 | :subject => 'Required fields', :author => user) | |
1014 | assert !issue.save |
|
1014 | assert !issue.save | |
1015 | assert_include "#{field.name} cannot be blank", issue.errors.full_messages |
|
1015 | assert_include "#{field.name} cannot be blank", issue.errors.full_messages | |
1016 | end |
|
1016 | end | |
1017 |
|
1017 | |||
1018 | def test_required_attribute_names_for_multiple_roles_should_intersect_rules |
|
1018 | def test_required_attribute_names_for_multiple_roles_should_intersect_rules | |
1019 | WorkflowPermission.delete_all |
|
1019 | WorkflowPermission.delete_all | |
1020 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1020 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1021 | :role_id => 1, :field_name => 'due_date', |
|
1021 | :role_id => 1, :field_name => 'due_date', | |
1022 | :rule => 'required') |
|
1022 | :rule => 'required') | |
1023 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1023 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1024 | :role_id => 1, :field_name => 'start_date', |
|
1024 | :role_id => 1, :field_name => 'start_date', | |
1025 | :rule => 'required') |
|
1025 | :rule => 'required') | |
1026 | user = User.find(2) |
|
1026 | user = User.find(2) | |
1027 | member = Member.find(1) |
|
1027 | member = Member.find(1) | |
1028 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
1028 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
1029 |
|
1029 | |||
1030 | assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort |
|
1030 | assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort | |
1031 |
|
1031 | |||
1032 | member.role_ids = [1, 2] |
|
1032 | member.role_ids = [1, 2] | |
1033 | member.save! |
|
1033 | member.save! | |
1034 | assert_equal [], issue.required_attribute_names(user.reload) |
|
1034 | assert_equal [], issue.required_attribute_names(user.reload) | |
1035 |
|
1035 | |||
1036 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1036 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1037 | :role_id => 2, :field_name => 'due_date', |
|
1037 | :role_id => 2, :field_name => 'due_date', | |
1038 | :rule => 'required') |
|
1038 | :rule => 'required') | |
1039 | assert_equal %w(due_date), issue.required_attribute_names(user) |
|
1039 | assert_equal %w(due_date), issue.required_attribute_names(user) | |
1040 |
|
1040 | |||
1041 | member.role_ids = [1, 2, 3] |
|
1041 | member.role_ids = [1, 2, 3] | |
1042 | member.save! |
|
1042 | member.save! | |
1043 | assert_equal [], issue.required_attribute_names(user.reload) |
|
1043 | assert_equal [], issue.required_attribute_names(user.reload) | |
1044 |
|
1044 | |||
1045 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1045 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1046 | :role_id => 3, :field_name => 'due_date', |
|
1046 | :role_id => 3, :field_name => 'due_date', | |
1047 | :rule => 'readonly') |
|
1047 | :rule => 'readonly') | |
1048 | # required + readonly => required |
|
1048 | # required + readonly => required | |
1049 | assert_equal %w(due_date), issue.required_attribute_names(user) |
|
1049 | assert_equal %w(due_date), issue.required_attribute_names(user) | |
1050 | end |
|
1050 | end | |
1051 |
|
1051 | |||
1052 | def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules |
|
1052 | def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules | |
1053 | WorkflowPermission.delete_all |
|
1053 | WorkflowPermission.delete_all | |
1054 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1054 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1055 | :role_id => 1, :field_name => 'due_date', |
|
1055 | :role_id => 1, :field_name => 'due_date', | |
1056 | :rule => 'readonly') |
|
1056 | :rule => 'readonly') | |
1057 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1057 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1058 | :role_id => 1, :field_name => 'start_date', |
|
1058 | :role_id => 1, :field_name => 'start_date', | |
1059 | :rule => 'readonly') |
|
1059 | :rule => 'readonly') | |
1060 | user = User.find(2) |
|
1060 | user = User.find(2) | |
1061 | member = Member.find(1) |
|
1061 | member = Member.find(1) | |
1062 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
1062 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
1063 |
|
1063 | |||
1064 | assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort |
|
1064 | assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort | |
1065 |
|
1065 | |||
1066 | member.role_ids = [1, 2] |
|
1066 | member.role_ids = [1, 2] | |
1067 | member.save! |
|
1067 | member.save! | |
1068 | assert_equal [], issue.read_only_attribute_names(user.reload) |
|
1068 | assert_equal [], issue.read_only_attribute_names(user.reload) | |
1069 |
|
1069 | |||
1070 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1070 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1071 | :role_id => 2, :field_name => 'due_date', |
|
1071 | :role_id => 2, :field_name => 'due_date', | |
1072 | :rule => 'readonly') |
|
1072 | :rule => 'readonly') | |
1073 | assert_equal %w(due_date), issue.read_only_attribute_names(user) |
|
1073 | assert_equal %w(due_date), issue.read_only_attribute_names(user) | |
1074 | end |
|
1074 | end | |
1075 |
|
1075 | |||
1076 | # A field that is not visible by role 2 and readonly by role 1 should be readonly for user with role 1 and 2 |
|
1076 | # A field that is not visible by role 2 and readonly by role 1 should be readonly for user with role 1 and 2 | |
1077 | def test_read_only_attribute_names_should_include_custom_fields_that_combine_readonly_and_not_visible_for_roles |
|
1077 | def test_read_only_attribute_names_should_include_custom_fields_that_combine_readonly_and_not_visible_for_roles | |
1078 | field = IssueCustomField.generate!( |
|
1078 | field = IssueCustomField.generate!( | |
1079 | :is_for_all => true, :trackers => Tracker.all, :visible => false, :role_ids => [1] |
|
1079 | :is_for_all => true, :trackers => Tracker.all, :visible => false, :role_ids => [1] | |
1080 | ) |
|
1080 | ) | |
1081 | WorkflowPermission.delete_all |
|
1081 | WorkflowPermission.delete_all | |
1082 | WorkflowPermission.create!( |
|
1082 | WorkflowPermission.create!( | |
1083 | :old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => field.id, :rule => 'readonly' |
|
1083 | :old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => field.id, :rule => 'readonly' | |
1084 | ) |
|
1084 | ) | |
1085 | user = User.generate! |
|
1085 | user = User.generate! | |
1086 | project = Project.find(1) |
|
1086 | project = Project.find(1) | |
1087 | User.add_to_project(user, project, Role.where(:id => [1, 2])) |
|
1087 | User.add_to_project(user, project, Role.where(:id => [1, 2])) | |
1088 |
|
1088 | |||
1089 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
1089 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
1090 | assert_equal [field.id.to_s], issue.read_only_attribute_names(user) |
|
1090 | assert_equal [field.id.to_s], issue.read_only_attribute_names(user) | |
1091 | end |
|
1091 | end | |
1092 |
|
1092 | |||
1093 | def test_workflow_rules_should_ignore_roles_without_issue_permissions |
|
1093 | def test_workflow_rules_should_ignore_roles_without_issue_permissions | |
1094 | role = Role.generate! :permissions => [:view_issues, :edit_issues] |
|
1094 | role = Role.generate! :permissions => [:view_issues, :edit_issues] | |
1095 | ignored_role = Role.generate! :permissions => [:view_issues] |
|
1095 | ignored_role = Role.generate! :permissions => [:view_issues] | |
1096 |
|
1096 | |||
1097 | WorkflowPermission.delete_all |
|
1097 | WorkflowPermission.delete_all | |
1098 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1098 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1099 | :role => role, :field_name => 'due_date', |
|
1099 | :role => role, :field_name => 'due_date', | |
1100 | :rule => 'required') |
|
1100 | :rule => 'required') | |
1101 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1101 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1102 | :role => role, :field_name => 'start_date', |
|
1102 | :role => role, :field_name => 'start_date', | |
1103 | :rule => 'readonly') |
|
1103 | :rule => 'readonly') | |
1104 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1104 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1105 | :role => role, :field_name => 'done_ratio', |
|
1105 | :role => role, :field_name => 'done_ratio', | |
1106 | :rule => 'readonly') |
|
1106 | :rule => 'readonly') | |
1107 | user = User.generate! |
|
1107 | user = User.generate! | |
1108 | User.add_to_project user, Project.find(1), [role, ignored_role] |
|
1108 | User.add_to_project user, Project.find(1), [role, ignored_role] | |
1109 |
|
1109 | |||
1110 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
1110 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
1111 |
|
1111 | |||
1112 | assert_equal %w(due_date), issue.required_attribute_names(user) |
|
1112 | assert_equal %w(due_date), issue.required_attribute_names(user) | |
1113 | assert_equal %w(done_ratio start_date), issue.read_only_attribute_names(user).sort |
|
1113 | assert_equal %w(done_ratio start_date), issue.read_only_attribute_names(user).sort | |
1114 | end |
|
1114 | end | |
1115 |
|
1115 | |||
1116 | def test_workflow_rules_should_work_for_member_with_duplicate_role |
|
1116 | def test_workflow_rules_should_work_for_member_with_duplicate_role | |
1117 | WorkflowPermission.delete_all |
|
1117 | WorkflowPermission.delete_all | |
1118 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1118 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1119 | :role_id => 1, :field_name => 'due_date', |
|
1119 | :role_id => 1, :field_name => 'due_date', | |
1120 | :rule => 'required') |
|
1120 | :rule => 'required') | |
1121 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, |
|
1121 | WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, | |
1122 | :role_id => 1, :field_name => 'start_date', |
|
1122 | :role_id => 1, :field_name => 'start_date', | |
1123 | :rule => 'readonly') |
|
1123 | :rule => 'readonly') | |
1124 |
|
1124 | |||
1125 | user = User.generate! |
|
1125 | user = User.generate! | |
1126 | m = Member.new(:user_id => user.id, :project_id => 1) |
|
1126 | m = Member.new(:user_id => user.id, :project_id => 1) | |
1127 | m.member_roles.build(:role_id => 1) |
|
1127 | m.member_roles.build(:role_id => 1) | |
1128 | m.member_roles.build(:role_id => 1) |
|
1128 | m.member_roles.build(:role_id => 1) | |
1129 | m.save! |
|
1129 | m.save! | |
1130 |
|
1130 | |||
1131 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) |
|
1131 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1) | |
1132 |
|
1132 | |||
1133 | assert_equal %w(due_date), issue.required_attribute_names(user) |
|
1133 | assert_equal %w(due_date), issue.required_attribute_names(user) | |
1134 | assert_equal %w(start_date), issue.read_only_attribute_names(user) |
|
1134 | assert_equal %w(start_date), issue.read_only_attribute_names(user) | |
1135 | end |
|
1135 | end | |
1136 |
|
1136 | |||
1137 | def test_copy |
|
1137 | def test_copy | |
1138 | issue = Issue.new.copy_from(1) |
|
1138 | issue = Issue.new.copy_from(1) | |
1139 | assert issue.copy? |
|
1139 | assert issue.copy? | |
1140 | assert issue.save |
|
1140 | assert issue.save | |
1141 | issue.reload |
|
1141 | issue.reload | |
1142 | orig = Issue.find(1) |
|
1142 | orig = Issue.find(1) | |
1143 | assert_equal orig.subject, issue.subject |
|
1143 | assert_equal orig.subject, issue.subject | |
1144 | assert_equal orig.tracker, issue.tracker |
|
1144 | assert_equal orig.tracker, issue.tracker | |
1145 | assert_equal "125", issue.custom_value_for(2).value |
|
1145 | assert_equal "125", issue.custom_value_for(2).value | |
1146 | end |
|
1146 | end | |
1147 |
|
1147 | |||
1148 | def test_copy_should_copy_status |
|
1148 | def test_copy_should_copy_status | |
1149 | orig = Issue.find(8) |
|
1149 | orig = Issue.find(8) | |
1150 | assert orig.status != orig.default_status |
|
1150 | assert orig.status != orig.default_status | |
1151 |
|
1151 | |||
1152 | issue = Issue.new.copy_from(orig) |
|
1152 | issue = Issue.new.copy_from(orig) | |
1153 | assert issue.save |
|
1153 | assert issue.save | |
1154 | issue.reload |
|
1154 | issue.reload | |
1155 | assert_equal orig.status, issue.status |
|
1155 | assert_equal orig.status, issue.status | |
1156 | end |
|
1156 | end | |
1157 |
|
1157 | |||
1158 | def test_copy_should_add_relation_with_copied_issue |
|
1158 | def test_copy_should_add_relation_with_copied_issue | |
1159 | copied = Issue.find(1) |
|
1159 | copied = Issue.find(1) | |
1160 | issue = Issue.new.copy_from(copied) |
|
1160 | issue = Issue.new.copy_from(copied) | |
1161 | assert issue.save |
|
1161 | assert issue.save | |
1162 | issue.reload |
|
1162 | issue.reload | |
1163 |
|
1163 | |||
1164 | assert_equal 1, issue.relations.size |
|
1164 | assert_equal 1, issue.relations.size | |
1165 | relation = issue.relations.first |
|
1165 | relation = issue.relations.first | |
1166 | assert_equal 'copied_to', relation.relation_type |
|
1166 | assert_equal 'copied_to', relation.relation_type | |
1167 | assert_equal copied, relation.issue_from |
|
1167 | assert_equal copied, relation.issue_from | |
1168 | assert_equal issue, relation.issue_to |
|
1168 | assert_equal issue, relation.issue_to | |
1169 | end |
|
1169 | end | |
1170 |
|
1170 | |||
1171 | def test_copy_should_copy_subtasks |
|
1171 | def test_copy_should_copy_subtasks | |
1172 | issue = Issue.generate_with_descendants! |
|
1172 | issue = Issue.generate_with_descendants! | |
1173 |
|
1173 | |||
1174 | copy = issue.reload.copy |
|
1174 | copy = issue.reload.copy | |
1175 | copy.author = User.find(7) |
|
1175 | copy.author = User.find(7) | |
1176 | assert_difference 'Issue.count', 1+issue.descendants.count do |
|
1176 | assert_difference 'Issue.count', 1+issue.descendants.count do | |
1177 | assert copy.save |
|
1177 | assert copy.save | |
1178 | end |
|
1178 | end | |
1179 | copy.reload |
|
1179 | copy.reload | |
1180 | assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort |
|
1180 | assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort | |
1181 | child_copy = copy.children.detect {|c| c.subject == 'Child1'} |
|
1181 | child_copy = copy.children.detect {|c| c.subject == 'Child1'} | |
1182 | assert_equal %w(Child11), child_copy.children.map(&:subject).sort |
|
1182 | assert_equal %w(Child11), child_copy.children.map(&:subject).sort | |
1183 | assert_equal copy.author, child_copy.author |
|
1183 | assert_equal copy.author, child_copy.author | |
1184 | end |
|
1184 | end | |
1185 |
|
1185 | |||
1186 | def test_copy_as_a_child_of_copied_issue_should_not_copy_itself |
|
1186 | def test_copy_as_a_child_of_copied_issue_should_not_copy_itself | |
1187 | parent = Issue.generate! |
|
1187 | parent = Issue.generate! | |
1188 | child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1') |
|
1188 | child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1') | |
1189 | child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2') |
|
1189 | child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2') | |
1190 |
|
1190 | |||
1191 | copy = parent.reload.copy |
|
1191 | copy = parent.reload.copy | |
1192 | copy.parent_issue_id = parent.id |
|
1192 | copy.parent_issue_id = parent.id | |
1193 | copy.author = User.find(7) |
|
1193 | copy.author = User.find(7) | |
1194 | assert_difference 'Issue.count', 3 do |
|
1194 | assert_difference 'Issue.count', 3 do | |
1195 | assert copy.save |
|
1195 | assert copy.save | |
1196 | end |
|
1196 | end | |
1197 | parent.reload |
|
1197 | parent.reload | |
1198 | copy.reload |
|
1198 | copy.reload | |
1199 | assert_equal parent, copy.parent |
|
1199 | assert_equal parent, copy.parent | |
1200 | assert_equal 3, parent.children.count |
|
1200 | assert_equal 3, parent.children.count | |
1201 | assert_equal 5, parent.descendants.count |
|
1201 | assert_equal 5, parent.descendants.count | |
1202 | assert_equal 2, copy.children.count |
|
1202 | assert_equal 2, copy.children.count | |
1203 | assert_equal 2, copy.descendants.count |
|
1203 | assert_equal 2, copy.descendants.count | |
1204 | end |
|
1204 | end | |
1205 |
|
1205 | |||
1206 | def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself |
|
1206 | def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself | |
1207 | parent = Issue.generate! |
|
1207 | parent = Issue.generate! | |
1208 | child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1') |
|
1208 | child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1') | |
1209 | child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2') |
|
1209 | child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2') | |
1210 |
|
1210 | |||
1211 | copy = parent.reload.copy |
|
1211 | copy = parent.reload.copy | |
1212 | copy.parent_issue_id = child1.id |
|
1212 | copy.parent_issue_id = child1.id | |
1213 | copy.author = User.find(7) |
|
1213 | copy.author = User.find(7) | |
1214 | assert_difference 'Issue.count', 3 do |
|
1214 | assert_difference 'Issue.count', 3 do | |
1215 | assert copy.save |
|
1215 | assert copy.save | |
1216 | end |
|
1216 | end | |
1217 | parent.reload |
|
1217 | parent.reload | |
1218 | child1.reload |
|
1218 | child1.reload | |
1219 | copy.reload |
|
1219 | copy.reload | |
1220 | assert_equal child1, copy.parent |
|
1220 | assert_equal child1, copy.parent | |
1221 | assert_equal 2, parent.children.count |
|
1221 | assert_equal 2, parent.children.count | |
1222 | assert_equal 5, parent.descendants.count |
|
1222 | assert_equal 5, parent.descendants.count | |
1223 | assert_equal 1, child1.children.count |
|
1223 | assert_equal 1, child1.children.count | |
1224 | assert_equal 3, child1.descendants.count |
|
1224 | assert_equal 3, child1.descendants.count | |
1225 | assert_equal 2, copy.children.count |
|
1225 | assert_equal 2, copy.children.count | |
1226 | assert_equal 2, copy.descendants.count |
|
1226 | assert_equal 2, copy.descendants.count | |
1227 | end |
|
1227 | end | |
1228 |
|
1228 | |||
1229 | def test_copy_should_copy_subtasks_to_target_project |
|
1229 | def test_copy_should_copy_subtasks_to_target_project | |
1230 | issue = Issue.generate_with_descendants! |
|
1230 | issue = Issue.generate_with_descendants! | |
1231 |
|
1231 | |||
1232 | copy = issue.copy(:project_id => 3) |
|
1232 | copy = issue.copy(:project_id => 3) | |
1233 | assert_difference 'Issue.count', 1+issue.descendants.count do |
|
1233 | assert_difference 'Issue.count', 1+issue.descendants.count do | |
1234 | assert copy.save |
|
1234 | assert copy.save | |
1235 | end |
|
1235 | end | |
1236 | assert_equal [3], copy.reload.descendants.map(&:project_id).uniq |
|
1236 | assert_equal [3], copy.reload.descendants.map(&:project_id).uniq | |
1237 | end |
|
1237 | end | |
1238 |
|
1238 | |||
1239 | def test_copy_should_not_copy_subtasks_twice_when_saving_twice |
|
1239 | def test_copy_should_not_copy_subtasks_twice_when_saving_twice | |
1240 | issue = Issue.generate_with_descendants! |
|
1240 | issue = Issue.generate_with_descendants! | |
1241 |
|
1241 | |||
1242 | copy = issue.reload.copy |
|
1242 | copy = issue.reload.copy | |
1243 | assert_difference 'Issue.count', 1+issue.descendants.count do |
|
1243 | assert_difference 'Issue.count', 1+issue.descendants.count do | |
1244 | assert copy.save |
|
1244 | assert copy.save | |
1245 | assert copy.save |
|
1245 | assert copy.save | |
1246 | end |
|
1246 | end | |
1247 | end |
|
1247 | end | |
1248 |
|
1248 | |||
1249 | def test_should_not_call_after_project_change_on_creation |
|
1249 | def test_should_not_call_after_project_change_on_creation | |
1250 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, |
|
1250 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, | |
1251 | :subject => 'Test', :author_id => 1) |
|
1251 | :subject => 'Test', :author_id => 1) | |
1252 | issue.expects(:after_project_change).never |
|
1252 | issue.expects(:after_project_change).never | |
1253 | issue.save! |
|
1253 | issue.save! | |
1254 | end |
|
1254 | end | |
1255 |
|
1255 | |||
1256 | def test_should_not_call_after_project_change_on_update |
|
1256 | def test_should_not_call_after_project_change_on_update | |
1257 | issue = Issue.find(1) |
|
1257 | issue = Issue.find(1) | |
1258 | issue.project = Project.find(1) |
|
1258 | issue.project = Project.find(1) | |
1259 | issue.subject = 'No project change' |
|
1259 | issue.subject = 'No project change' | |
1260 | issue.expects(:after_project_change).never |
|
1260 | issue.expects(:after_project_change).never | |
1261 | issue.save! |
|
1261 | issue.save! | |
1262 | end |
|
1262 | end | |
1263 |
|
1263 | |||
1264 | def test_should_call_after_project_change_on_project_change |
|
1264 | def test_should_call_after_project_change_on_project_change | |
1265 | issue = Issue.find(1) |
|
1265 | issue = Issue.find(1) | |
1266 | issue.project = Project.find(2) |
|
1266 | issue.project = Project.find(2) | |
1267 | issue.expects(:after_project_change).once |
|
1267 | issue.expects(:after_project_change).once | |
1268 | issue.save! |
|
1268 | issue.save! | |
1269 | end |
|
1269 | end | |
1270 |
|
1270 | |||
1271 | def test_adding_journal_should_update_timestamp |
|
1271 | def test_adding_journal_should_update_timestamp | |
1272 | issue = Issue.find(1) |
|
1272 | issue = Issue.find(1) | |
1273 | updated_on_was = issue.updated_on |
|
1273 | updated_on_was = issue.updated_on | |
1274 |
|
1274 | |||
1275 | issue.init_journal(User.first, "Adding notes") |
|
1275 | issue.init_journal(User.first, "Adding notes") | |
1276 | assert_difference 'Journal.count' do |
|
1276 | assert_difference 'Journal.count' do | |
1277 | assert issue.save |
|
1277 | assert issue.save | |
1278 | end |
|
1278 | end | |
1279 | issue.reload |
|
1279 | issue.reload | |
1280 |
|
1280 | |||
1281 | assert_not_equal updated_on_was, issue.updated_on |
|
1281 | assert_not_equal updated_on_was, issue.updated_on | |
1282 | end |
|
1282 | end | |
1283 |
|
1283 | |||
1284 | def test_should_close_duplicates |
|
1284 | def test_should_close_duplicates | |
1285 | # Create 3 issues |
|
1285 | # Create 3 issues | |
1286 | issue1 = Issue.generate! |
|
1286 | issue1 = Issue.generate! | |
1287 | issue2 = Issue.generate! |
|
1287 | issue2 = Issue.generate! | |
1288 | issue3 = Issue.generate! |
|
1288 | issue3 = Issue.generate! | |
1289 |
|
1289 | |||
1290 | # 2 is a dupe of 1 |
|
1290 | # 2 is a dupe of 1 | |
1291 | IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, |
|
1291 | IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, | |
1292 | :relation_type => IssueRelation::TYPE_DUPLICATES) |
|
1292 | :relation_type => IssueRelation::TYPE_DUPLICATES) | |
1293 | # And 3 is a dupe of 2 |
|
1293 | # And 3 is a dupe of 2 | |
1294 | # IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, |
|
1294 | # IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, | |
1295 | # :relation_type => IssueRelation::TYPE_DUPLICATES) |
|
1295 | # :relation_type => IssueRelation::TYPE_DUPLICATES) | |
1296 | # And 3 is a dupe of 1 (circular duplicates) |
|
1296 | # And 3 is a dupe of 1 (circular duplicates) | |
1297 | IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, |
|
1297 | IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, | |
1298 | :relation_type => IssueRelation::TYPE_DUPLICATES) |
|
1298 | :relation_type => IssueRelation::TYPE_DUPLICATES) | |
1299 |
|
1299 | |||
1300 | assert issue1.reload.duplicates.include?(issue2) |
|
1300 | assert issue1.reload.duplicates.include?(issue2) | |
1301 |
|
1301 | |||
1302 | # Closing issue 1 |
|
1302 | # Closing issue 1 | |
1303 | issue1.init_journal(User.first, "Closing issue1") |
|
1303 | issue1.init_journal(User.first, "Closing issue1") | |
1304 | issue1.status = IssueStatus.where(:is_closed => true).first |
|
1304 | issue1.status = IssueStatus.where(:is_closed => true).first | |
1305 | assert issue1.save |
|
1305 | assert issue1.save | |
1306 | # 2 and 3 should be also closed |
|
1306 | # 2 and 3 should be also closed | |
1307 | assert issue2.reload.closed? |
|
1307 | assert issue2.reload.closed? | |
1308 | assert issue3.reload.closed? |
|
1308 | assert issue3.reload.closed? | |
1309 | end |
|
1309 | end | |
1310 |
|
1310 | |||
1311 | def test_should_close_duplicates_with_private_notes |
|
1311 | def test_should_close_duplicates_with_private_notes | |
1312 | issue = Issue.generate! |
|
1312 | issue = Issue.generate! | |
1313 | duplicate = Issue.generate! |
|
1313 | duplicate = Issue.generate! | |
1314 | IssueRelation.create!(:issue_from => duplicate, :issue_to => issue, |
|
1314 | IssueRelation.create!(:issue_from => duplicate, :issue_to => issue, | |
1315 | :relation_type => IssueRelation::TYPE_DUPLICATES) |
|
1315 | :relation_type => IssueRelation::TYPE_DUPLICATES) | |
1316 | assert issue.reload.duplicates.include?(duplicate) |
|
1316 | assert issue.reload.duplicates.include?(duplicate) | |
1317 |
|
1317 | |||
1318 | # Closing issue with private notes |
|
1318 | # Closing issue with private notes | |
1319 | issue.init_journal(User.first, "Private notes") |
|
1319 | issue.init_journal(User.first, "Private notes") | |
1320 | issue.private_notes = true |
|
1320 | issue.private_notes = true | |
1321 | issue.status = IssueStatus.where(:is_closed => true).first |
|
1321 | issue.status = IssueStatus.where(:is_closed => true).first | |
1322 | assert_save issue |
|
1322 | assert_save issue | |
1323 |
|
1323 | |||
1324 | duplicate.reload |
|
1324 | duplicate.reload | |
1325 | assert journal = duplicate.journals.detect {|journal| journal.notes == "Private notes"} |
|
1325 | assert journal = duplicate.journals.detect {|journal| journal.notes == "Private notes"} | |
1326 | assert_equal true, journal.private_notes |
|
1326 | assert_equal true, journal.private_notes | |
1327 | end |
|
1327 | end | |
1328 |
|
1328 | |||
1329 | def test_should_not_close_duplicated_issue |
|
1329 | def test_should_not_close_duplicated_issue | |
1330 | issue1 = Issue.generate! |
|
1330 | issue1 = Issue.generate! | |
1331 | issue2 = Issue.generate! |
|
1331 | issue2 = Issue.generate! | |
1332 |
|
1332 | |||
1333 | # 2 is a dupe of 1 |
|
1333 | # 2 is a dupe of 1 | |
1334 | IssueRelation.create(:issue_from => issue2, :issue_to => issue1, |
|
1334 | IssueRelation.create(:issue_from => issue2, :issue_to => issue1, | |
1335 | :relation_type => IssueRelation::TYPE_DUPLICATES) |
|
1335 | :relation_type => IssueRelation::TYPE_DUPLICATES) | |
1336 | # 2 is a dup of 1 but 1 is not a duplicate of 2 |
|
1336 | # 2 is a dup of 1 but 1 is not a duplicate of 2 | |
1337 | assert !issue2.reload.duplicates.include?(issue1) |
|
1337 | assert !issue2.reload.duplicates.include?(issue1) | |
1338 |
|
1338 | |||
1339 | # Closing issue 2 |
|
1339 | # Closing issue 2 | |
1340 | issue2.init_journal(User.first, "Closing issue2") |
|
1340 | issue2.init_journal(User.first, "Closing issue2") | |
1341 | issue2.status = IssueStatus.where(:is_closed => true).first |
|
1341 | issue2.status = IssueStatus.where(:is_closed => true).first | |
1342 | assert issue2.save |
|
1342 | assert issue2.save | |
1343 | # 1 should not be also closed |
|
1343 | # 1 should not be also closed | |
1344 | assert !issue1.reload.closed? |
|
1344 | assert !issue1.reload.closed? | |
1345 | end |
|
1345 | end | |
1346 |
|
1346 | |||
1347 | def test_assignable_versions |
|
1347 | def test_assignable_versions | |
1348 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
1348 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
1349 | :status_id => 1, :fixed_version_id => 1, |
|
1349 | :status_id => 1, :fixed_version_id => 1, | |
1350 | :subject => 'New issue') |
|
1350 | :subject => 'New issue') | |
1351 | assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq |
|
1351 | assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq | |
1352 | end |
|
1352 | end | |
1353 |
|
1353 | |||
1354 | def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version |
|
1354 | def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version | |
1355 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
1355 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
1356 | :status_id => 1, :fixed_version_id => 1, |
|
1356 | :status_id => 1, :fixed_version_id => 1, | |
1357 | :subject => 'New issue') |
|
1357 | :subject => 'New issue') | |
1358 | assert !issue.save |
|
1358 | assert !issue.save | |
1359 | assert_not_equal [], issue.errors[:fixed_version_id] |
|
1359 | assert_not_equal [], issue.errors[:fixed_version_id] | |
1360 | end |
|
1360 | end | |
1361 |
|
1361 | |||
1362 | def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version |
|
1362 | def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version | |
1363 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
1363 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
1364 | :status_id => 1, :fixed_version_id => 2, |
|
1364 | :status_id => 1, :fixed_version_id => 2, | |
1365 | :subject => 'New issue') |
|
1365 | :subject => 'New issue') | |
1366 | assert !issue.save |
|
1366 | assert !issue.save | |
1367 | assert_not_equal [], issue.errors[:fixed_version_id] |
|
1367 | assert_not_equal [], issue.errors[:fixed_version_id] | |
1368 | end |
|
1368 | end | |
1369 |
|
1369 | |||
1370 | def test_should_be_able_to_assign_a_new_issue_to_an_open_version |
|
1370 | def test_should_be_able_to_assign_a_new_issue_to_an_open_version | |
1371 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, |
|
1371 | issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, | |
1372 | :status_id => 1, :fixed_version_id => 3, |
|
1372 | :status_id => 1, :fixed_version_id => 3, | |
1373 | :subject => 'New issue') |
|
1373 | :subject => 'New issue') | |
1374 | assert issue.save |
|
1374 | assert issue.save | |
1375 | end |
|
1375 | end | |
1376 |
|
1376 | |||
1377 | def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version |
|
1377 | def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version | |
1378 | issue = Issue.find(11) |
|
1378 | issue = Issue.find(11) | |
1379 | assert_equal 'closed', issue.fixed_version.status |
|
1379 | assert_equal 'closed', issue.fixed_version.status | |
1380 | issue.subject = 'Subject changed' |
|
1380 | issue.subject = 'Subject changed' | |
1381 | assert issue.save |
|
1381 | assert issue.save | |
1382 | end |
|
1382 | end | |
1383 |
|
1383 | |||
1384 | def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version |
|
1384 | def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version | |
1385 | issue = Issue.find(11) |
|
1385 | issue = Issue.find(11) | |
1386 | issue.status_id = 1 |
|
1386 | issue.status_id = 1 | |
1387 | assert !issue.save |
|
1387 | assert !issue.save | |
1388 | assert_not_equal [], issue.errors[:base] |
|
1388 | assert_not_equal [], issue.errors[:base] | |
1389 | end |
|
1389 | end | |
1390 |
|
1390 | |||
1391 | def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version |
|
1391 | def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version | |
1392 | issue = Issue.find(11) |
|
1392 | issue = Issue.find(11) | |
1393 | issue.status_id = 1 |
|
1393 | issue.status_id = 1 | |
1394 | issue.fixed_version_id = 3 |
|
1394 | issue.fixed_version_id = 3 | |
1395 | assert issue.save |
|
1395 | assert issue.save | |
1396 | end |
|
1396 | end | |
1397 |
|
1397 | |||
1398 | def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version |
|
1398 | def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version | |
1399 | issue = Issue.find(12) |
|
1399 | issue = Issue.find(12) | |
1400 | assert_equal 'locked', issue.fixed_version.status |
|
1400 | assert_equal 'locked', issue.fixed_version.status | |
1401 | issue.status_id = 1 |
|
1401 | issue.status_id = 1 | |
1402 | assert issue.save |
|
1402 | assert issue.save | |
1403 | end |
|
1403 | end | |
1404 |
|
1404 | |||
1405 | def test_should_not_be_able_to_keep_unshared_version_when_changing_project |
|
1405 | def test_should_not_be_able_to_keep_unshared_version_when_changing_project | |
1406 | issue = Issue.find(2) |
|
1406 | issue = Issue.find(2) | |
1407 | assert_equal 2, issue.fixed_version_id |
|
1407 | assert_equal 2, issue.fixed_version_id | |
1408 | issue.project_id = 3 |
|
1408 | issue.project_id = 3 | |
1409 | assert_nil issue.fixed_version_id |
|
1409 | assert_nil issue.fixed_version_id | |
1410 | issue.fixed_version_id = 2 |
|
1410 | issue.fixed_version_id = 2 | |
1411 | assert !issue.save |
|
1411 | assert !issue.save | |
1412 | assert_include 'Target version is not included in the list', issue.errors.full_messages |
|
1412 | assert_include 'Target version is not included in the list', issue.errors.full_messages | |
1413 | end |
|
1413 | end | |
1414 |
|
1414 | |||
1415 | def test_should_keep_shared_version_when_changing_project |
|
1415 | def test_should_keep_shared_version_when_changing_project | |
1416 | Version.find(2).update_attribute :sharing, 'tree' |
|
1416 | Version.find(2).update_attribute :sharing, 'tree' | |
1417 |
|
1417 | |||
1418 | issue = Issue.find(2) |
|
1418 | issue = Issue.find(2) | |
1419 | assert_equal 2, issue.fixed_version_id |
|
1419 | assert_equal 2, issue.fixed_version_id | |
1420 | issue.project_id = 3 |
|
1420 | issue.project_id = 3 | |
1421 | assert_equal 2, issue.fixed_version_id |
|
1421 | assert_equal 2, issue.fixed_version_id | |
1422 | assert issue.save |
|
1422 | assert issue.save | |
1423 | end |
|
1423 | end | |
1424 |
|
1424 | |||
1425 | def test_allowed_target_projects_should_include_projects_with_issue_tracking_enabled |
|
1425 | def test_allowed_target_projects_should_include_projects_with_issue_tracking_enabled | |
1426 | assert_include Project.find(2), Issue.allowed_target_projects(User.find(2)) |
|
1426 | assert_include Project.find(2), Issue.allowed_target_projects(User.find(2)) | |
1427 | end |
|
1427 | end | |
1428 |
|
1428 | |||
1429 | def test_allowed_target_projects_should_not_include_projects_with_issue_tracking_disabled |
|
1429 | def test_allowed_target_projects_should_not_include_projects_with_issue_tracking_disabled | |
1430 | Project.find(2).disable_module! :issue_tracking |
|
1430 | Project.find(2).disable_module! :issue_tracking | |
1431 | assert_not_include Project.find(2), Issue.allowed_target_projects(User.find(2)) |
|
1431 | assert_not_include Project.find(2), Issue.allowed_target_projects(User.find(2)) | |
1432 | end |
|
1432 | end | |
1433 |
|
1433 | |||
1434 | def test_allowed_target_projects_should_not_include_projects_without_trackers |
|
1434 | def test_allowed_target_projects_should_not_include_projects_without_trackers | |
1435 | project = Project.generate!(:tracker_ids => []) |
|
1435 | project = Project.generate!(:tracker_ids => []) | |
1436 | assert project.trackers.empty? |
|
1436 | assert project.trackers.empty? | |
1437 | assert_not_include project, Issue.allowed_target_projects(User.find(1)) |
|
1437 | assert_not_include project, Issue.allowed_target_projects(User.find(1)) | |
1438 | end |
|
1438 | end | |
1439 |
|
1439 | |||
1440 | def test_move_to_another_project_with_same_category |
|
1440 | def test_move_to_another_project_with_same_category | |
1441 | issue = Issue.find(1) |
|
1441 | issue = Issue.find(1) | |
1442 | issue.project = Project.find(2) |
|
1442 | issue.project = Project.find(2) | |
1443 | assert issue.save |
|
1443 | assert issue.save | |
1444 | issue.reload |
|
1444 | issue.reload | |
1445 | assert_equal 2, issue.project_id |
|
1445 | assert_equal 2, issue.project_id | |
1446 | # Category changes |
|
1446 | # Category changes | |
1447 | assert_equal 4, issue.category_id |
|
1447 | assert_equal 4, issue.category_id | |
1448 | # Make sure time entries were move to the target project |
|
1448 | # Make sure time entries were move to the target project | |
1449 | assert_equal 2, issue.time_entries.first.project_id |
|
1449 | assert_equal 2, issue.time_entries.first.project_id | |
1450 | end |
|
1450 | end | |
1451 |
|
1451 | |||
1452 | def test_move_to_another_project_without_same_category |
|
1452 | def test_move_to_another_project_without_same_category | |
1453 | issue = Issue.find(2) |
|
1453 | issue = Issue.find(2) | |
1454 | issue.project = Project.find(2) |
|
1454 | issue.project = Project.find(2) | |
1455 | assert issue.save |
|
1455 | assert issue.save | |
1456 | issue.reload |
|
1456 | issue.reload | |
1457 | assert_equal 2, issue.project_id |
|
1457 | assert_equal 2, issue.project_id | |
1458 | # Category cleared |
|
1458 | # Category cleared | |
1459 | assert_nil issue.category_id |
|
1459 | assert_nil issue.category_id | |
1460 | end |
|
1460 | end | |
1461 |
|
1461 | |||
1462 | def test_move_to_another_project_should_clear_fixed_version_when_not_shared |
|
1462 | def test_move_to_another_project_should_clear_fixed_version_when_not_shared | |
1463 | issue = Issue.find(1) |
|
1463 | issue = Issue.find(1) | |
1464 | issue.update_attribute(:fixed_version_id, 1) |
|
1464 | issue.update_attribute(:fixed_version_id, 1) | |
1465 | issue.project = Project.find(2) |
|
1465 | issue.project = Project.find(2) | |
1466 | assert issue.save |
|
1466 | assert issue.save | |
1467 | issue.reload |
|
1467 | issue.reload | |
1468 | assert_equal 2, issue.project_id |
|
1468 | assert_equal 2, issue.project_id | |
1469 | # Cleared fixed_version |
|
1469 | # Cleared fixed_version | |
1470 | assert_equal nil, issue.fixed_version |
|
1470 | assert_equal nil, issue.fixed_version | |
1471 | end |
|
1471 | end | |
1472 |
|
1472 | |||
1473 | def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project |
|
1473 | def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project | |
1474 | issue = Issue.find(1) |
|
1474 | issue = Issue.find(1) | |
1475 | issue.update_attribute(:fixed_version_id, 4) |
|
1475 | issue.update_attribute(:fixed_version_id, 4) | |
1476 | issue.project = Project.find(5) |
|
1476 | issue.project = Project.find(5) | |
1477 | assert issue.save |
|
1477 | assert issue.save | |
1478 | issue.reload |
|
1478 | issue.reload | |
1479 | assert_equal 5, issue.project_id |
|
1479 | assert_equal 5, issue.project_id | |
1480 | # Keep fixed_version |
|
1480 | # Keep fixed_version | |
1481 | assert_equal 4, issue.fixed_version_id |
|
1481 | assert_equal 4, issue.fixed_version_id | |
1482 | end |
|
1482 | end | |
1483 |
|
1483 | |||
1484 | def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project |
|
1484 | def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project | |
1485 | issue = Issue.find(1) |
|
1485 | issue = Issue.find(1) | |
1486 | issue.update_attribute(:fixed_version_id, 1) |
|
1486 | issue.update_attribute(:fixed_version_id, 1) | |
1487 | issue.project = Project.find(5) |
|
1487 | issue.project = Project.find(5) | |
1488 | assert issue.save |
|
1488 | assert issue.save | |
1489 | issue.reload |
|
1489 | issue.reload | |
1490 | assert_equal 5, issue.project_id |
|
1490 | assert_equal 5, issue.project_id | |
1491 | # Cleared fixed_version |
|
1491 | # Cleared fixed_version | |
1492 | assert_equal nil, issue.fixed_version |
|
1492 | assert_equal nil, issue.fixed_version | |
1493 | end |
|
1493 | end | |
1494 |
|
1494 | |||
1495 | def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide |
|
1495 | def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide | |
1496 | issue = Issue.find(1) |
|
1496 | issue = Issue.find(1) | |
1497 | issue.update_attribute(:fixed_version_id, 7) |
|
1497 | issue.update_attribute(:fixed_version_id, 7) | |
1498 | issue.project = Project.find(2) |
|
1498 | issue.project = Project.find(2) | |
1499 | assert issue.save |
|
1499 | assert issue.save | |
1500 | issue.reload |
|
1500 | issue.reload | |
1501 | assert_equal 2, issue.project_id |
|
1501 | assert_equal 2, issue.project_id | |
1502 | # Keep fixed_version |
|
1502 | # Keep fixed_version | |
1503 | assert_equal 7, issue.fixed_version_id |
|
1503 | assert_equal 7, issue.fixed_version_id | |
1504 | end |
|
1504 | end | |
1505 |
|
1505 | |||
1506 | def test_move_to_another_project_should_keep_parent_if_valid |
|
1506 | def test_move_to_another_project_should_keep_parent_if_valid | |
1507 | issue = Issue.find(1) |
|
1507 | issue = Issue.find(1) | |
1508 | issue.update_attribute(:parent_issue_id, 2) |
|
1508 | issue.update_attribute(:parent_issue_id, 2) | |
1509 | issue.project = Project.find(3) |
|
1509 | issue.project = Project.find(3) | |
1510 | assert issue.save |
|
1510 | assert issue.save | |
1511 | issue.reload |
|
1511 | issue.reload | |
1512 | assert_equal 2, issue.parent_id |
|
1512 | assert_equal 2, issue.parent_id | |
1513 | end |
|
1513 | end | |
1514 |
|
1514 | |||
1515 | def test_move_to_another_project_should_clear_parent_if_not_valid |
|
1515 | def test_move_to_another_project_should_clear_parent_if_not_valid | |
1516 | issue = Issue.find(1) |
|
1516 | issue = Issue.find(1) | |
1517 | issue.update_attribute(:parent_issue_id, 2) |
|
1517 | issue.update_attribute(:parent_issue_id, 2) | |
1518 | issue.project = Project.find(2) |
|
1518 | issue.project = Project.find(2) | |
1519 | assert issue.save |
|
1519 | assert issue.save | |
1520 | issue.reload |
|
1520 | issue.reload | |
1521 | assert_nil issue.parent_id |
|
1521 | assert_nil issue.parent_id | |
1522 | end |
|
1522 | end | |
1523 |
|
1523 | |||
1524 | def test_move_to_another_project_with_disabled_tracker |
|
1524 | def test_move_to_another_project_with_disabled_tracker | |
1525 | issue = Issue.find(1) |
|
1525 | issue = Issue.find(1) | |
1526 | target = Project.find(2) |
|
1526 | target = Project.find(2) | |
1527 | target.tracker_ids = [3] |
|
1527 | target.tracker_ids = [3] | |
1528 | target.save |
|
1528 | target.save | |
1529 | issue.project = target |
|
1529 | issue.project = target | |
1530 | assert issue.save |
|
1530 | assert issue.save | |
1531 | issue.reload |
|
1531 | issue.reload | |
1532 | assert_equal 2, issue.project_id |
|
1532 | assert_equal 2, issue.project_id | |
1533 | assert_equal 3, issue.tracker_id |
|
1533 | assert_equal 3, issue.tracker_id | |
1534 | end |
|
1534 | end | |
1535 |
|
1535 | |||
1536 | def test_copy_to_the_same_project |
|
1536 | def test_copy_to_the_same_project | |
1537 | issue = Issue.find(1) |
|
1537 | issue = Issue.find(1) | |
1538 | copy = issue.copy |
|
1538 | copy = issue.copy | |
1539 | assert_difference 'Issue.count' do |
|
1539 | assert_difference 'Issue.count' do | |
1540 | copy.save! |
|
1540 | copy.save! | |
1541 | end |
|
1541 | end | |
1542 | assert_kind_of Issue, copy |
|
1542 | assert_kind_of Issue, copy | |
1543 | assert_equal issue.project, copy.project |
|
1543 | assert_equal issue.project, copy.project | |
1544 | assert_equal "125", copy.custom_value_for(2).value |
|
1544 | assert_equal "125", copy.custom_value_for(2).value | |
1545 | end |
|
1545 | end | |
1546 |
|
1546 | |||
1547 | def test_copy_to_another_project_and_tracker |
|
1547 | def test_copy_to_another_project_and_tracker | |
1548 | issue = Issue.find(1) |
|
1548 | issue = Issue.find(1) | |
1549 | copy = issue.copy(:project_id => 3, :tracker_id => 2) |
|
1549 | copy = issue.copy(:project_id => 3, :tracker_id => 2) | |
1550 | assert_difference 'Issue.count' do |
|
1550 | assert_difference 'Issue.count' do | |
1551 | copy.save! |
|
1551 | copy.save! | |
1552 | end |
|
1552 | end | |
1553 | copy.reload |
|
1553 | copy.reload | |
1554 | assert_kind_of Issue, copy |
|
1554 | assert_kind_of Issue, copy | |
1555 | assert_equal Project.find(3), copy.project |
|
1555 | assert_equal Project.find(3), copy.project | |
1556 | assert_equal Tracker.find(2), copy.tracker |
|
1556 | assert_equal Tracker.find(2), copy.tracker | |
1557 | # Custom field #2 is not associated with target tracker |
|
1557 | # Custom field #2 is not associated with target tracker | |
1558 | assert_nil copy.custom_value_for(2) |
|
1558 | assert_nil copy.custom_value_for(2) | |
1559 | end |
|
1559 | end | |
1560 |
|
1560 | |||
1561 | test "#copy should not create a journal" do |
|
1561 | test "#copy should not create a journal" do | |
1562 | copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false) |
|
1562 | copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false) | |
1563 | copy.save! |
|
1563 | copy.save! | |
1564 | assert_equal 0, copy.reload.journals.size |
|
1564 | assert_equal 0, copy.reload.journals.size | |
1565 | end |
|
1565 | end | |
1566 |
|
1566 | |||
1567 | test "#copy should allow assigned_to changes" do |
|
1567 | test "#copy should allow assigned_to changes" do | |
1568 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3) |
|
1568 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3) | |
1569 | assert_equal 3, copy.assigned_to_id |
|
1569 | assert_equal 3, copy.assigned_to_id | |
1570 | end |
|
1570 | end | |
1571 |
|
1571 | |||
1572 | test "#copy should allow status changes" do |
|
1572 | test "#copy should allow status changes" do | |
1573 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2) |
|
1573 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2) | |
1574 | assert_equal 2, copy.status_id |
|
1574 | assert_equal 2, copy.status_id | |
1575 | end |
|
1575 | end | |
1576 |
|
1576 | |||
1577 | test "#copy should allow start date changes" do |
|
1577 | test "#copy should allow start date changes" do | |
1578 | date = Date.today |
|
1578 | date = Date.today | |
1579 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date) |
|
1579 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date) | |
1580 | assert_equal date, copy.start_date |
|
1580 | assert_equal date, copy.start_date | |
1581 | end |
|
1581 | end | |
1582 |
|
1582 | |||
1583 | test "#copy should allow due date changes" do |
|
1583 | test "#copy should allow due date changes" do | |
1584 | date = Date.today |
|
1584 | date = Date.today | |
1585 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date) |
|
1585 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date) | |
1586 | assert_equal date, copy.due_date |
|
1586 | assert_equal date, copy.due_date | |
1587 | end |
|
1587 | end | |
1588 |
|
1588 | |||
1589 | test "#copy should set current user as author" do |
|
1589 | test "#copy should set current user as author" do | |
1590 | User.current = User.find(9) |
|
1590 | User.current = User.find(9) | |
1591 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2) |
|
1591 | copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2) | |
1592 | assert_equal User.current, copy.author |
|
1592 | assert_equal User.current, copy.author | |
1593 | end |
|
1593 | end | |
1594 |
|
1594 | |||
1595 | test "#copy should create a journal with notes" do |
|
1595 | test "#copy should create a journal with notes" do | |
1596 | date = Date.today |
|
1596 | date = Date.today | |
1597 | notes = "Notes added when copying" |
|
1597 | notes = "Notes added when copying" | |
1598 | copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false) |
|
1598 | copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false) | |
1599 | copy.init_journal(User.current, notes) |
|
1599 | copy.init_journal(User.current, notes) | |
1600 | copy.save! |
|
1600 | copy.save! | |
1601 |
|
1601 | |||
1602 | assert_equal 1, copy.journals.size |
|
1602 | assert_equal 1, copy.journals.size | |
1603 | journal = copy.journals.first |
|
1603 | journal = copy.journals.first | |
1604 | assert_equal 0, journal.details.size |
|
1604 | assert_equal 0, journal.details.size | |
1605 | assert_equal notes, journal.notes |
|
1605 | assert_equal notes, journal.notes | |
1606 | end |
|
1606 | end | |
1607 |
|
1607 | |||
1608 | def test_valid_parent_project |
|
1608 | def test_valid_parent_project | |
1609 | issue = Issue.find(1) |
|
1609 | issue = Issue.find(1) | |
1610 | issue_in_same_project = Issue.find(2) |
|
1610 | issue_in_same_project = Issue.find(2) | |
1611 | issue_in_child_project = Issue.find(5) |
|
1611 | issue_in_child_project = Issue.find(5) | |
1612 | issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1) |
|
1612 | issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1) | |
1613 | issue_in_other_child_project = Issue.find(6) |
|
1613 | issue_in_other_child_project = Issue.find(6) | |
1614 | issue_in_different_tree = Issue.find(4) |
|
1614 | issue_in_different_tree = Issue.find(4) | |
1615 |
|
1615 | |||
1616 | with_settings :cross_project_subtasks => '' do |
|
1616 | with_settings :cross_project_subtasks => '' do | |
1617 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) |
|
1617 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) | |
1618 | assert_equal false, issue.valid_parent_project?(issue_in_child_project) |
|
1618 | assert_equal false, issue.valid_parent_project?(issue_in_child_project) | |
1619 | assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project) |
|
1619 | assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project) | |
1620 | assert_equal false, issue.valid_parent_project?(issue_in_different_tree) |
|
1620 | assert_equal false, issue.valid_parent_project?(issue_in_different_tree) | |
1621 | end |
|
1621 | end | |
1622 |
|
1622 | |||
1623 | with_settings :cross_project_subtasks => 'system' do |
|
1623 | with_settings :cross_project_subtasks => 'system' do | |
1624 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) |
|
1624 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) | |
1625 | assert_equal true, issue.valid_parent_project?(issue_in_child_project) |
|
1625 | assert_equal true, issue.valid_parent_project?(issue_in_child_project) | |
1626 | assert_equal true, issue.valid_parent_project?(issue_in_different_tree) |
|
1626 | assert_equal true, issue.valid_parent_project?(issue_in_different_tree) | |
1627 | end |
|
1627 | end | |
1628 |
|
1628 | |||
1629 | with_settings :cross_project_subtasks => 'tree' do |
|
1629 | with_settings :cross_project_subtasks => 'tree' do | |
1630 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) |
|
1630 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) | |
1631 | assert_equal true, issue.valid_parent_project?(issue_in_child_project) |
|
1631 | assert_equal true, issue.valid_parent_project?(issue_in_child_project) | |
1632 | assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project) |
|
1632 | assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project) | |
1633 | assert_equal false, issue.valid_parent_project?(issue_in_different_tree) |
|
1633 | assert_equal false, issue.valid_parent_project?(issue_in_different_tree) | |
1634 |
|
1634 | |||
1635 | assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project) |
|
1635 | assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project) | |
1636 | assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project) |
|
1636 | assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project) | |
1637 | end |
|
1637 | end | |
1638 |
|
1638 | |||
1639 | with_settings :cross_project_subtasks => 'descendants' do |
|
1639 | with_settings :cross_project_subtasks => 'descendants' do | |
1640 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) |
|
1640 | assert_equal true, issue.valid_parent_project?(issue_in_same_project) | |
1641 | assert_equal false, issue.valid_parent_project?(issue_in_child_project) |
|
1641 | assert_equal false, issue.valid_parent_project?(issue_in_child_project) | |
1642 | assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project) |
|
1642 | assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project) | |
1643 | assert_equal false, issue.valid_parent_project?(issue_in_different_tree) |
|
1643 | assert_equal false, issue.valid_parent_project?(issue_in_different_tree) | |
1644 |
|
1644 | |||
1645 | assert_equal true, issue_in_child_project.valid_parent_project?(issue) |
|
1645 | assert_equal true, issue_in_child_project.valid_parent_project?(issue) | |
1646 | assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project) |
|
1646 | assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project) | |
1647 | end |
|
1647 | end | |
1648 | end |
|
1648 | end | |
1649 |
|
1649 | |||
1650 | def test_recipients_should_include_previous_assignee |
|
1650 | def test_recipients_should_include_previous_assignee | |
1651 | user = User.find(3) |
|
1651 | user = User.find(3) | |
1652 | user.members.update_all ["mail_notification = ?", false] |
|
1652 | user.members.update_all ["mail_notification = ?", false] | |
1653 | user.update_attribute :mail_notification, 'only_assigned' |
|
1653 | user.update_attribute :mail_notification, 'only_assigned' | |
1654 |
|
1654 | |||
1655 | issue = Issue.find(2) |
|
1655 | issue = Issue.find(2) | |
1656 | issue.assigned_to = nil |
|
1656 | issue.assigned_to = nil | |
1657 | assert_include user.mail, issue.recipients |
|
1657 | assert_include user.mail, issue.recipients | |
1658 | issue.save! |
|
1658 | issue.save! | |
1659 | assert !issue.recipients.include?(user.mail) |
|
1659 | assert !issue.recipients.include?(user.mail) | |
1660 | end |
|
1660 | end | |
1661 |
|
1661 | |||
1662 | def test_recipients_should_not_include_users_that_cannot_view_the_issue |
|
1662 | def test_recipients_should_not_include_users_that_cannot_view_the_issue | |
1663 | issue = Issue.find(12) |
|
1663 | issue = Issue.find(12) | |
1664 | assert issue.recipients.include?(issue.author.mail) |
|
1664 | assert issue.recipients.include?(issue.author.mail) | |
1665 | # copy the issue to a private project |
|
1665 | # copy the issue to a private project | |
1666 | copy = issue.copy(:project_id => 5, :tracker_id => 2) |
|
1666 | copy = issue.copy(:project_id => 5, :tracker_id => 2) | |
1667 | # author is not a member of project anymore |
|
1667 | # author is not a member of project anymore | |
1668 | assert !copy.recipients.include?(copy.author.mail) |
|
1668 | assert !copy.recipients.include?(copy.author.mail) | |
1669 | end |
|
1669 | end | |
1670 |
|
1670 | |||
1671 | def test_recipients_should_include_the_assigned_group_members |
|
1671 | def test_recipients_should_include_the_assigned_group_members | |
1672 | group_member = User.generate! |
|
1672 | group_member = User.generate! | |
1673 | group = Group.generate! |
|
1673 | group = Group.generate! | |
1674 | group.users << group_member |
|
1674 | group.users << group_member | |
1675 |
|
1675 | |||
1676 | issue = Issue.find(12) |
|
1676 | issue = Issue.find(12) | |
1677 | issue.assigned_to = group |
|
1677 | issue.assigned_to = group | |
1678 | assert issue.recipients.include?(group_member.mail) |
|
1678 | assert issue.recipients.include?(group_member.mail) | |
1679 | end |
|
1679 | end | |
1680 |
|
1680 | |||
1681 | def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue |
|
1681 | def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue | |
1682 | user = User.find(3) |
|
1682 | user = User.find(3) | |
1683 | issue = Issue.find(9) |
|
1683 | issue = Issue.find(9) | |
1684 | Watcher.create!(:user => user, :watchable => issue) |
|
1684 | Watcher.create!(:user => user, :watchable => issue) | |
1685 | assert issue.watched_by?(user) |
|
1685 | assert issue.watched_by?(user) | |
1686 | assert !issue.watcher_recipients.include?(user.mail) |
|
1686 | assert !issue.watcher_recipients.include?(user.mail) | |
1687 | end |
|
1687 | end | |
1688 |
|
1688 | |||
1689 | def test_issue_destroy |
|
1689 | def test_issue_destroy | |
1690 | Issue.find(1).destroy |
|
1690 | Issue.find(1).destroy | |
1691 | assert_nil Issue.find_by_id(1) |
|
1691 | assert_nil Issue.find_by_id(1) | |
1692 | assert_nil TimeEntry.find_by_issue_id(1) |
|
1692 | assert_nil TimeEntry.find_by_issue_id(1) | |
1693 | end |
|
1693 | end | |
1694 |
|
1694 | |||
1695 | def test_destroy_should_delete_time_entries_custom_values |
|
1695 | def test_destroy_should_delete_time_entries_custom_values | |
1696 | issue = Issue.generate! |
|
1696 | issue = Issue.generate! | |
1697 | time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'}) |
|
1697 | time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'}) | |
1698 |
|
1698 | |||
1699 | assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do |
|
1699 | assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do | |
1700 | assert issue.destroy |
|
1700 | assert issue.destroy | |
1701 | end |
|
1701 | end | |
1702 | end |
|
1702 | end | |
1703 |
|
1703 | |||
1704 | def test_destroying_a_deleted_issue_should_not_raise_an_error |
|
1704 | def test_destroying_a_deleted_issue_should_not_raise_an_error | |
1705 | issue = Issue.find(1) |
|
1705 | issue = Issue.find(1) | |
1706 | Issue.find(1).destroy |
|
1706 | Issue.find(1).destroy | |
1707 |
|
1707 | |||
1708 | assert_nothing_raised do |
|
1708 | assert_nothing_raised do | |
1709 | assert_no_difference 'Issue.count' do |
|
1709 | assert_no_difference 'Issue.count' do | |
1710 | issue.destroy |
|
1710 | issue.destroy | |
1711 | end |
|
1711 | end | |
1712 | assert issue.destroyed? |
|
1712 | assert issue.destroyed? | |
1713 | end |
|
1713 | end | |
1714 | end |
|
1714 | end | |
1715 |
|
1715 | |||
1716 | def test_destroying_a_stale_issue_should_not_raise_an_error |
|
1716 | def test_destroying_a_stale_issue_should_not_raise_an_error | |
1717 | issue = Issue.find(1) |
|
1717 | issue = Issue.find(1) | |
1718 | Issue.find(1).update_attribute :subject, "Updated" |
|
1718 | Issue.find(1).update_attribute :subject, "Updated" | |
1719 |
|
1719 | |||
1720 | assert_nothing_raised do |
|
1720 | assert_nothing_raised do | |
1721 | assert_difference 'Issue.count', -1 do |
|
1721 | assert_difference 'Issue.count', -1 do | |
1722 | issue.destroy |
|
1722 | issue.destroy | |
1723 | end |
|
1723 | end | |
1724 | assert issue.destroyed? |
|
1724 | assert issue.destroyed? | |
1725 | end |
|
1725 | end | |
1726 | end |
|
1726 | end | |
1727 |
|
1727 | |||
1728 | def test_blocked |
|
1728 | def test_blocked | |
1729 | blocked_issue = Issue.find(9) |
|
1729 | blocked_issue = Issue.find(9) | |
1730 | blocking_issue = Issue.find(10) |
|
1730 | blocking_issue = Issue.find(10) | |
1731 |
|
1731 | |||
1732 | assert blocked_issue.blocked? |
|
1732 | assert blocked_issue.blocked? | |
1733 | assert !blocking_issue.blocked? |
|
1733 | assert !blocking_issue.blocked? | |
1734 | end |
|
1734 | end | |
1735 |
|
1735 | |||
1736 | def test_blocked_issues_dont_allow_closed_statuses |
|
1736 | def test_blocked_issues_dont_allow_closed_statuses | |
1737 | blocked_issue = Issue.find(9) |
|
1737 | blocked_issue = Issue.find(9) | |
1738 |
|
1738 | |||
1739 | allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002)) |
|
1739 | allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002)) | |
1740 | assert !allowed_statuses.empty? |
|
1740 | assert !allowed_statuses.empty? | |
1741 | closed_statuses = allowed_statuses.select {|st| st.is_closed?} |
|
1741 | closed_statuses = allowed_statuses.select {|st| st.is_closed?} | |
1742 | assert closed_statuses.empty? |
|
1742 | assert closed_statuses.empty? | |
1743 | end |
|
1743 | end | |
1744 |
|
1744 | |||
1745 | def test_unblocked_issues_allow_closed_statuses |
|
1745 | def test_unblocked_issues_allow_closed_statuses | |
1746 | blocking_issue = Issue.find(10) |
|
1746 | blocking_issue = Issue.find(10) | |
1747 |
|
1747 | |||
1748 | allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002)) |
|
1748 | allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002)) | |
1749 | assert !allowed_statuses.empty? |
|
1749 | assert !allowed_statuses.empty? | |
1750 | closed_statuses = allowed_statuses.select {|st| st.is_closed?} |
|
1750 | closed_statuses = allowed_statuses.select {|st| st.is_closed?} | |
1751 | assert !closed_statuses.empty? |
|
1751 | assert !closed_statuses.empty? | |
1752 | end |
|
1752 | end | |
1753 |
|
1753 | |||
1754 | def test_reschedule_an_issue_without_dates |
|
1754 | def test_reschedule_an_issue_without_dates | |
1755 | with_settings :non_working_week_days => [] do |
|
1755 | with_settings :non_working_week_days => [] do | |
1756 | issue = Issue.new(:start_date => nil, :due_date => nil) |
|
1756 | issue = Issue.new(:start_date => nil, :due_date => nil) | |
1757 | issue.reschedule_on '2012-10-09'.to_date |
|
1757 | issue.reschedule_on '2012-10-09'.to_date | |
1758 | assert_equal '2012-10-09'.to_date, issue.start_date |
|
1758 | assert_equal '2012-10-09'.to_date, issue.start_date | |
1759 | assert_equal '2012-10-09'.to_date, issue.due_date |
|
1759 | assert_equal '2012-10-09'.to_date, issue.due_date | |
1760 | end |
|
1760 | end | |
1761 |
|
1761 | |||
1762 | with_settings :non_working_week_days => %w(6 7) do |
|
1762 | with_settings :non_working_week_days => %w(6 7) do | |
1763 | issue = Issue.new(:start_date => nil, :due_date => nil) |
|
1763 | issue = Issue.new(:start_date => nil, :due_date => nil) | |
1764 | issue.reschedule_on '2012-10-09'.to_date |
|
1764 | issue.reschedule_on '2012-10-09'.to_date | |
1765 | assert_equal '2012-10-09'.to_date, issue.start_date |
|
1765 | assert_equal '2012-10-09'.to_date, issue.start_date | |
1766 | assert_equal '2012-10-09'.to_date, issue.due_date |
|
1766 | assert_equal '2012-10-09'.to_date, issue.due_date | |
1767 |
|
1767 | |||
1768 | issue = Issue.new(:start_date => nil, :due_date => nil) |
|
1768 | issue = Issue.new(:start_date => nil, :due_date => nil) | |
1769 | issue.reschedule_on '2012-10-13'.to_date |
|
1769 | issue.reschedule_on '2012-10-13'.to_date | |
1770 | assert_equal '2012-10-15'.to_date, issue.start_date |
|
1770 | assert_equal '2012-10-15'.to_date, issue.start_date | |
1771 | assert_equal '2012-10-15'.to_date, issue.due_date |
|
1771 | assert_equal '2012-10-15'.to_date, issue.due_date | |
1772 | end |
|
1772 | end | |
1773 | end |
|
1773 | end | |
1774 |
|
1774 | |||
1775 | def test_reschedule_an_issue_with_start_date |
|
1775 | def test_reschedule_an_issue_with_start_date | |
1776 | with_settings :non_working_week_days => [] do |
|
1776 | with_settings :non_working_week_days => [] do | |
1777 | issue = Issue.new(:start_date => '2012-10-09', :due_date => nil) |
|
1777 | issue = Issue.new(:start_date => '2012-10-09', :due_date => nil) | |
1778 | issue.reschedule_on '2012-10-13'.to_date |
|
1778 | issue.reschedule_on '2012-10-13'.to_date | |
1779 | assert_equal '2012-10-13'.to_date, issue.start_date |
|
1779 | assert_equal '2012-10-13'.to_date, issue.start_date | |
1780 | assert_equal '2012-10-13'.to_date, issue.due_date |
|
1780 | assert_equal '2012-10-13'.to_date, issue.due_date | |
1781 | end |
|
1781 | end | |
1782 |
|
1782 | |||
1783 | with_settings :non_working_week_days => %w(6 7) do |
|
1783 | with_settings :non_working_week_days => %w(6 7) do | |
1784 | issue = Issue.new(:start_date => '2012-10-09', :due_date => nil) |
|
1784 | issue = Issue.new(:start_date => '2012-10-09', :due_date => nil) | |
1785 | issue.reschedule_on '2012-10-11'.to_date |
|
1785 | issue.reschedule_on '2012-10-11'.to_date | |
1786 | assert_equal '2012-10-11'.to_date, issue.start_date |
|
1786 | assert_equal '2012-10-11'.to_date, issue.start_date | |
1787 | assert_equal '2012-10-11'.to_date, issue.due_date |
|
1787 | assert_equal '2012-10-11'.to_date, issue.due_date | |
1788 |
|
1788 | |||
1789 | issue = Issue.new(:start_date => '2012-10-09', :due_date => nil) |
|
1789 | issue = Issue.new(:start_date => '2012-10-09', :due_date => nil) | |
1790 | issue.reschedule_on '2012-10-13'.to_date |
|
1790 | issue.reschedule_on '2012-10-13'.to_date | |
1791 | assert_equal '2012-10-15'.to_date, issue.start_date |
|
1791 | assert_equal '2012-10-15'.to_date, issue.start_date | |
1792 | assert_equal '2012-10-15'.to_date, issue.due_date |
|
1792 | assert_equal '2012-10-15'.to_date, issue.due_date | |
1793 | end |
|
1793 | end | |
1794 | end |
|
1794 | end | |
1795 |
|
1795 | |||
1796 | def test_reschedule_an_issue_with_start_and_due_dates |
|
1796 | def test_reschedule_an_issue_with_start_and_due_dates | |
1797 | with_settings :non_working_week_days => [] do |
|
1797 | with_settings :non_working_week_days => [] do | |
1798 | issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15') |
|
1798 | issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15') | |
1799 | issue.reschedule_on '2012-10-13'.to_date |
|
1799 | issue.reschedule_on '2012-10-13'.to_date | |
1800 | assert_equal '2012-10-13'.to_date, issue.start_date |
|
1800 | assert_equal '2012-10-13'.to_date, issue.start_date | |
1801 | assert_equal '2012-10-19'.to_date, issue.due_date |
|
1801 | assert_equal '2012-10-19'.to_date, issue.due_date | |
1802 | end |
|
1802 | end | |
1803 |
|
1803 | |||
1804 | with_settings :non_working_week_days => %w(6 7) do |
|
1804 | with_settings :non_working_week_days => %w(6 7) do | |
1805 | issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days |
|
1805 | issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days | |
1806 | issue.reschedule_on '2012-10-11'.to_date |
|
1806 | issue.reschedule_on '2012-10-11'.to_date | |
1807 | assert_equal '2012-10-11'.to_date, issue.start_date |
|
1807 | assert_equal '2012-10-11'.to_date, issue.start_date | |
1808 | assert_equal '2012-10-23'.to_date, issue.due_date |
|
1808 | assert_equal '2012-10-23'.to_date, issue.due_date | |
1809 |
|
1809 | |||
1810 | issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') |
|
1810 | issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') | |
1811 | issue.reschedule_on '2012-10-13'.to_date |
|
1811 | issue.reschedule_on '2012-10-13'.to_date | |
1812 | assert_equal '2012-10-15'.to_date, issue.start_date |
|
1812 | assert_equal '2012-10-15'.to_date, issue.start_date | |
1813 | assert_equal '2012-10-25'.to_date, issue.due_date |
|
1813 | assert_equal '2012-10-25'.to_date, issue.due_date | |
1814 | end |
|
1814 | end | |
1815 | end |
|
1815 | end | |
1816 |
|
1816 | |||
1817 | def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue |
|
1817 | def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue | |
1818 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1818 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1819 | issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1819 | issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1820 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, |
|
1820 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, | |
1821 | :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1821 | :relation_type => IssueRelation::TYPE_PRECEDES) | |
1822 | assert_equal Date.parse('2012-10-18'), issue2.reload.start_date |
|
1822 | assert_equal Date.parse('2012-10-18'), issue2.reload.start_date | |
1823 |
|
1823 | |||
1824 | issue1.reload |
|
1824 | issue1.reload | |
1825 | issue1.due_date = '2012-10-23' |
|
1825 | issue1.due_date = '2012-10-23' | |
1826 | issue1.save! |
|
1826 | issue1.save! | |
1827 | issue2.reload |
|
1827 | issue2.reload | |
1828 | assert_equal Date.parse('2012-10-24'), issue2.start_date |
|
1828 | assert_equal Date.parse('2012-10-24'), issue2.start_date | |
1829 | assert_equal Date.parse('2012-10-26'), issue2.due_date |
|
1829 | assert_equal Date.parse('2012-10-26'), issue2.due_date | |
1830 | end |
|
1830 | end | |
1831 |
|
1831 | |||
1832 | def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue |
|
1832 | def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue | |
1833 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1833 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1834 | issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1834 | issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1835 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, |
|
1835 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, | |
1836 | :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1836 | :relation_type => IssueRelation::TYPE_PRECEDES) | |
1837 | assert_equal Date.parse('2012-10-18'), issue2.reload.start_date |
|
1837 | assert_equal Date.parse('2012-10-18'), issue2.reload.start_date | |
1838 |
|
1838 | |||
1839 | issue1.reload |
|
1839 | issue1.reload | |
1840 | issue1.start_date = '2012-09-17' |
|
1840 | issue1.start_date = '2012-09-17' | |
1841 | issue1.due_date = '2012-09-18' |
|
1841 | issue1.due_date = '2012-09-18' | |
1842 | issue1.save! |
|
1842 | issue1.save! | |
1843 | issue2.reload |
|
1843 | issue2.reload | |
1844 | assert_equal Date.parse('2012-09-19'), issue2.start_date |
|
1844 | assert_equal Date.parse('2012-09-19'), issue2.start_date | |
1845 | assert_equal Date.parse('2012-09-21'), issue2.due_date |
|
1845 | assert_equal Date.parse('2012-09-21'), issue2.due_date | |
1846 | end |
|
1846 | end | |
1847 |
|
1847 | |||
1848 | def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues |
|
1848 | def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues | |
1849 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1849 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1850 | issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1850 | issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1851 | issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02') |
|
1851 | issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02') | |
1852 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, |
|
1852 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, | |
1853 | :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1853 | :relation_type => IssueRelation::TYPE_PRECEDES) | |
1854 | IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, |
|
1854 | IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, | |
1855 | :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1855 | :relation_type => IssueRelation::TYPE_PRECEDES) | |
1856 | assert_equal Date.parse('2012-10-18'), issue2.reload.start_date |
|
1856 | assert_equal Date.parse('2012-10-18'), issue2.reload.start_date | |
1857 |
|
1857 | |||
1858 | issue1.reload |
|
1858 | issue1.reload | |
1859 | issue1.start_date = '2012-09-17' |
|
1859 | issue1.start_date = '2012-09-17' | |
1860 | issue1.due_date = '2012-09-18' |
|
1860 | issue1.due_date = '2012-09-18' | |
1861 | issue1.save! |
|
1861 | issue1.save! | |
1862 | issue2.reload |
|
1862 | issue2.reload | |
1863 | # Issue 2 must start after Issue 3 |
|
1863 | # Issue 2 must start after Issue 3 | |
1864 | assert_equal Date.parse('2012-10-03'), issue2.start_date |
|
1864 | assert_equal Date.parse('2012-10-03'), issue2.start_date | |
1865 | assert_equal Date.parse('2012-10-05'), issue2.due_date |
|
1865 | assert_equal Date.parse('2012-10-05'), issue2.due_date | |
1866 | end |
|
1866 | end | |
1867 |
|
1867 | |||
1868 | def test_rescheduling_a_stale_issue_should_not_raise_an_error |
|
1868 | def test_rescheduling_a_stale_issue_should_not_raise_an_error | |
1869 | with_settings :non_working_week_days => [] do |
|
1869 | with_settings :non_working_week_days => [] do | |
1870 | stale = Issue.find(1) |
|
1870 | stale = Issue.find(1) | |
1871 | issue = Issue.find(1) |
|
1871 | issue = Issue.find(1) | |
1872 | issue.subject = "Updated" |
|
1872 | issue.subject = "Updated" | |
1873 | issue.save! |
|
1873 | issue.save! | |
1874 | date = 10.days.from_now.to_date |
|
1874 | date = 10.days.from_now.to_date | |
1875 | assert_nothing_raised do |
|
1875 | assert_nothing_raised do | |
1876 | stale.reschedule_on!(date) |
|
1876 | stale.reschedule_on!(date) | |
1877 | end |
|
1877 | end | |
1878 | assert_equal date, stale.reload.start_date |
|
1878 | assert_equal date, stale.reload.start_date | |
1879 | end |
|
1879 | end | |
1880 | end |
|
1880 | end | |
1881 |
|
1881 | |||
1882 | def test_child_issue_should_consider_parent_soonest_start_on_create |
|
1882 | def test_child_issue_should_consider_parent_soonest_start_on_create | |
1883 | set_language_if_valid 'en' |
|
1883 | set_language_if_valid 'en' | |
1884 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') |
|
1884 | issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') | |
1885 | issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20') |
|
1885 | issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20') | |
1886 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, |
|
1886 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, | |
1887 | :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1887 | :relation_type => IssueRelation::TYPE_PRECEDES) | |
1888 | issue1.reload |
|
1888 | issue1.reload | |
1889 | issue2.reload |
|
1889 | issue2.reload | |
1890 | assert_equal Date.parse('2012-10-18'), issue2.start_date |
|
1890 | assert_equal Date.parse('2012-10-18'), issue2.start_date | |
1891 |
|
1891 | |||
1892 | with_settings :date_format => '%m/%d/%Y' do |
|
1892 | with_settings :date_format => '%m/%d/%Y' do | |
1893 | child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16', |
|
1893 | child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16', | |
1894 | :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1) |
|
1894 | :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1) | |
1895 | assert !child.valid? |
|
1895 | assert !child.valid? | |
1896 | assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages |
|
1896 | assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages | |
1897 | assert_equal Date.parse('2012-10-18'), child.soonest_start |
|
1897 | assert_equal Date.parse('2012-10-18'), child.soonest_start | |
1898 | child.start_date = '2012-10-18' |
|
1898 | child.start_date = '2012-10-18' | |
1899 | assert child.save |
|
1899 | assert child.save | |
1900 | end |
|
1900 | end | |
1901 | end |
|
1901 | end | |
1902 |
|
1902 | |||
1903 | def test_setting_parent_to_a_an_issue_that_precedes_should_not_validate |
|
1903 | def test_setting_parent_to_a_an_issue_that_precedes_should_not_validate | |
1904 | # tests that 3 cannot have 1 as parent: |
|
1904 | # tests that 3 cannot have 1 as parent: | |
1905 | # |
|
1905 | # | |
1906 | # 1 -> 2 -> 3 |
|
1906 | # 1 -> 2 -> 3 | |
1907 | # |
|
1907 | # | |
1908 | set_language_if_valid 'en' |
|
1908 | set_language_if_valid 'en' | |
1909 | issue1 = Issue.generate! |
|
1909 | issue1 = Issue.generate! | |
1910 | issue2 = Issue.generate! |
|
1910 | issue2 = Issue.generate! | |
1911 | issue3 = Issue.generate! |
|
1911 | issue3 = Issue.generate! | |
1912 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1912 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1913 | IssueRelation.create!(:issue_from => issue2, :issue_to => issue3, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1913 | IssueRelation.create!(:issue_from => issue2, :issue_to => issue3, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1914 | issue3.reload |
|
1914 | issue3.reload | |
1915 | issue3.parent_issue_id = issue1.id |
|
1915 | issue3.parent_issue_id = issue1.id | |
1916 | assert !issue3.valid? |
|
1916 | assert !issue3.valid? | |
1917 | assert_include 'Parent task is invalid', issue3.errors.full_messages |
|
1917 | assert_include 'Parent task is invalid', issue3.errors.full_messages | |
1918 | end |
|
1918 | end | |
1919 |
|
1919 | |||
1920 | def test_setting_parent_to_a_an_issue_that_follows_should_not_validate |
|
1920 | def test_setting_parent_to_a_an_issue_that_follows_should_not_validate | |
1921 | # tests that 1 cannot have 3 as parent: |
|
1921 | # tests that 1 cannot have 3 as parent: | |
1922 | # |
|
1922 | # | |
1923 | # 1 -> 2 -> 3 |
|
1923 | # 1 -> 2 -> 3 | |
1924 | # |
|
1924 | # | |
1925 | set_language_if_valid 'en' |
|
1925 | set_language_if_valid 'en' | |
1926 | issue1 = Issue.generate! |
|
1926 | issue1 = Issue.generate! | |
1927 | issue2 = Issue.generate! |
|
1927 | issue2 = Issue.generate! | |
1928 | issue3 = Issue.generate! |
|
1928 | issue3 = Issue.generate! | |
1929 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1929 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1930 | IssueRelation.create!(:issue_from => issue2, :issue_to => issue3, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1930 | IssueRelation.create!(:issue_from => issue2, :issue_to => issue3, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1931 | issue1.reload |
|
1931 | issue1.reload | |
1932 | issue1.parent_issue_id = issue3.id |
|
1932 | issue1.parent_issue_id = issue3.id | |
1933 | assert !issue1.valid? |
|
1933 | assert !issue1.valid? | |
1934 | assert_include 'Parent task is invalid', issue1.errors.full_messages |
|
1934 | assert_include 'Parent task is invalid', issue1.errors.full_messages | |
1935 | end |
|
1935 | end | |
1936 |
|
1936 | |||
1937 | def test_setting_parent_to_a_an_issue_that_precedes_through_hierarchy_should_not_validate |
|
1937 | def test_setting_parent_to_a_an_issue_that_precedes_through_hierarchy_should_not_validate | |
1938 | # tests that 4 cannot have 1 as parent: |
|
1938 | # tests that 4 cannot have 1 as parent: | |
1939 | # changing the due date of 4 would update the end date of 1 which would reschedule 2 |
|
1939 | # changing the due date of 4 would update the end date of 1 which would reschedule 2 | |
1940 | # which would change the end date of 3 which would reschedule 4 and so on... |
|
1940 | # which would change the end date of 3 which would reschedule 4 and so on... | |
1941 | # |
|
1941 | # | |
1942 | # 3 -> 4 |
|
1942 | # 3 -> 4 | |
1943 | # ^ |
|
1943 | # ^ | |
1944 | # 1 -> 2 |
|
1944 | # 1 -> 2 | |
1945 | # |
|
1945 | # | |
1946 | set_language_if_valid 'en' |
|
1946 | set_language_if_valid 'en' | |
1947 | issue1 = Issue.generate! |
|
1947 | issue1 = Issue.generate! | |
1948 | issue2 = Issue.generate! |
|
1948 | issue2 = Issue.generate! | |
1949 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1949 | IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1950 | issue3 = Issue.generate! |
|
1950 | issue3 = Issue.generate! | |
1951 | issue2.reload |
|
1951 | issue2.reload | |
1952 | issue2.parent_issue_id = issue3.id |
|
1952 | issue2.parent_issue_id = issue3.id | |
1953 | issue2.save! |
|
1953 | issue2.save! | |
1954 | issue4 = Issue.generate! |
|
1954 | issue4 = Issue.generate! | |
1955 | IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1955 | IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1956 | issue4.reload |
|
1956 | issue4.reload | |
1957 | issue4.parent_issue_id = issue1.id |
|
1957 | issue4.parent_issue_id = issue1.id | |
1958 | assert !issue4.valid? |
|
1958 | assert !issue4.valid? | |
1959 | assert_include 'Parent task is invalid', issue4.errors.full_messages |
|
1959 | assert_include 'Parent task is invalid', issue4.errors.full_messages | |
1960 | end |
|
1960 | end | |
1961 |
|
1961 | |||
1962 | def test_issue_and_following_issue_should_be_able_to_be_moved_to_the_same_parent |
|
1962 | def test_issue_and_following_issue_should_be_able_to_be_moved_to_the_same_parent | |
1963 | set_language_if_valid 'en' |
|
1963 | set_language_if_valid 'en' | |
1964 | issue1 = Issue.generate! |
|
1964 | issue1 = Issue.generate! | |
1965 | issue2 = Issue.generate! |
|
1965 | issue2 = Issue.generate! | |
1966 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_FOLLOWS) |
|
1966 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_FOLLOWS) | |
1967 | parent = Issue.generate! |
|
1967 | parent = Issue.generate! | |
1968 | issue1.reload.parent_issue_id = parent.id |
|
1968 | issue1.reload.parent_issue_id = parent.id | |
1969 | assert_save issue1 |
|
1969 | assert_save issue1 | |
1970 | parent.reload |
|
1970 | parent.reload | |
1971 | issue2.reload.parent_issue_id = parent.id |
|
1971 | issue2.reload.parent_issue_id = parent.id | |
1972 | assert_save issue2 |
|
1972 | assert_save issue2 | |
1973 | assert IssueRelation.exists?(relation.id) |
|
1973 | assert IssueRelation.exists?(relation.id) | |
1974 | end |
|
1974 | end | |
1975 |
|
1975 | |||
1976 | def test_issue_and_preceding_issue_should_be_able_to_be_moved_to_the_same_parent |
|
1976 | def test_issue_and_preceding_issue_should_be_able_to_be_moved_to_the_same_parent | |
1977 | set_language_if_valid 'en' |
|
1977 | set_language_if_valid 'en' | |
1978 | issue1 = Issue.generate! |
|
1978 | issue1 = Issue.generate! | |
1979 | issue2 = Issue.generate! |
|
1979 | issue2 = Issue.generate! | |
1980 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES) |
|
1980 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES) | |
1981 | parent = Issue.generate! |
|
1981 | parent = Issue.generate! | |
1982 | issue1.reload.parent_issue_id = parent.id |
|
1982 | issue1.reload.parent_issue_id = parent.id | |
1983 | assert_save issue1 |
|
1983 | assert_save issue1 | |
1984 | parent.reload |
|
1984 | parent.reload | |
1985 | issue2.reload.parent_issue_id = parent.id |
|
1985 | issue2.reload.parent_issue_id = parent.id | |
1986 | assert_save issue2 |
|
1986 | assert_save issue2 | |
1987 | assert IssueRelation.exists?(relation.id) |
|
1987 | assert IssueRelation.exists?(relation.id) | |
1988 | end |
|
1988 | end | |
1989 |
|
1989 | |||
1990 | def test_issue_and_blocked_issue_should_be_able_to_be_moved_to_the_same_parent |
|
1990 | def test_issue_and_blocked_issue_should_be_able_to_be_moved_to_the_same_parent | |
1991 | set_language_if_valid 'en' |
|
1991 | set_language_if_valid 'en' | |
1992 | issue1 = Issue.generate! |
|
1992 | issue1 = Issue.generate! | |
1993 | issue2 = Issue.generate! |
|
1993 | issue2 = Issue.generate! | |
1994 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_BLOCKED) |
|
1994 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_BLOCKED) | |
1995 | parent = Issue.generate! |
|
1995 | parent = Issue.generate! | |
1996 | issue1.reload.parent_issue_id = parent.id |
|
1996 | issue1.reload.parent_issue_id = parent.id | |
1997 | assert_save issue1 |
|
1997 | assert_save issue1 | |
1998 | parent.reload |
|
1998 | parent.reload | |
1999 | issue2.reload.parent_issue_id = parent.id |
|
1999 | issue2.reload.parent_issue_id = parent.id | |
2000 | assert_save issue2 |
|
2000 | assert_save issue2 | |
2001 | assert IssueRelation.exists?(relation.id) |
|
2001 | assert IssueRelation.exists?(relation.id) | |
2002 | end |
|
2002 | end | |
2003 |
|
2003 | |||
2004 | def test_issue_and_blocking_issue_should_be_able_to_be_moved_to_the_same_parent |
|
2004 | def test_issue_and_blocking_issue_should_be_able_to_be_moved_to_the_same_parent | |
2005 | set_language_if_valid 'en' |
|
2005 | set_language_if_valid 'en' | |
2006 | issue1 = Issue.generate! |
|
2006 | issue1 = Issue.generate! | |
2007 | issue2 = Issue.generate! |
|
2007 | issue2 = Issue.generate! | |
2008 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_BLOCKS) |
|
2008 | relation = IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_BLOCKS) | |
2009 | parent = Issue.generate! |
|
2009 | parent = Issue.generate! | |
2010 | issue1.reload.parent_issue_id = parent.id |
|
2010 | issue1.reload.parent_issue_id = parent.id | |
2011 | assert_save issue1 |
|
2011 | assert_save issue1 | |
2012 | parent.reload |
|
2012 | parent.reload | |
2013 | issue2.reload.parent_issue_id = parent.id |
|
2013 | issue2.reload.parent_issue_id = parent.id | |
2014 | assert_save issue2 |
|
2014 | assert_save issue2 | |
2015 | assert IssueRelation.exists?(relation.id) |
|
2015 | assert IssueRelation.exists?(relation.id) | |
2016 | end |
|
2016 | end | |
2017 |
|
2017 | |||
2018 | def test_issue_copy_should_be_able_to_be_moved_to_the_same_parent_as_copied_issue |
|
2018 | def test_issue_copy_should_be_able_to_be_moved_to_the_same_parent_as_copied_issue | |
2019 | issue = Issue.generate! |
|
2019 | issue = Issue.generate! | |
2020 | parent = Issue.generate! |
|
2020 | parent = Issue.generate! | |
2021 | issue.parent_issue_id = parent.id |
|
2021 | issue.parent_issue_id = parent.id | |
2022 | issue.save! |
|
2022 | issue.save! | |
2023 | issue.reload |
|
2023 | issue.reload | |
2024 |
|
2024 | |||
2025 | copy = Issue.new.copy_from(issue, :link => true) |
|
2025 | copy = Issue.new.copy_from(issue, :link => true) | |
2026 | relation = new_record(IssueRelation) do |
|
2026 | relation = new_record(IssueRelation) do | |
2027 | copy.save! |
|
2027 | copy.save! | |
2028 | end |
|
2028 | end | |
2029 |
|
2029 | |||
2030 | copy.parent_issue_id = parent.id |
|
2030 | copy.parent_issue_id = parent.id | |
2031 | assert_save copy |
|
2031 | assert_save copy | |
2032 | assert IssueRelation.exists?(relation.id) |
|
2032 | assert IssueRelation.exists?(relation.id) | |
2033 | end |
|
2033 | end | |
2034 |
|
2034 | |||
2035 | def test_overdue |
|
2035 | def test_overdue | |
2036 | assert Issue.new(:due_date => 1.day.ago.to_date).overdue? |
|
2036 | assert Issue.new(:due_date => 1.day.ago.to_date).overdue? | |
2037 | assert !Issue.new(:due_date => Date.today).overdue? |
|
2037 | assert !Issue.new(:due_date => Date.today).overdue? | |
2038 | assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue? |
|
2038 | assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue? | |
2039 | assert !Issue.new(:due_date => nil).overdue? |
|
2039 | assert !Issue.new(:due_date => nil).overdue? | |
2040 | assert !Issue.new(:due_date => 1.day.ago.to_date, |
|
2040 | assert !Issue.new(:due_date => 1.day.ago.to_date, | |
2041 | :status => IssueStatus.where(:is_closed => true).first |
|
2041 | :status => IssueStatus.where(:is_closed => true).first | |
2042 | ).overdue? |
|
2042 | ).overdue? | |
2043 | end |
|
2043 | end | |
2044 |
|
2044 | |||
2045 | test "#behind_schedule? should be false if the issue has no start_date" do |
|
2045 | test "#behind_schedule? should be false if the issue has no start_date" do | |
2046 | assert !Issue.new(:start_date => nil, |
|
2046 | assert !Issue.new(:start_date => nil, | |
2047 | :due_date => 1.day.from_now.to_date, |
|
2047 | :due_date => 1.day.from_now.to_date, | |
2048 | :done_ratio => 0).behind_schedule? |
|
2048 | :done_ratio => 0).behind_schedule? | |
2049 | end |
|
2049 | end | |
2050 |
|
2050 | |||
2051 | test "#behind_schedule? should be false if the issue has no end_date" do |
|
2051 | test "#behind_schedule? should be false if the issue has no end_date" do | |
2052 | assert !Issue.new(:start_date => 1.day.from_now.to_date, |
|
2052 | assert !Issue.new(:start_date => 1.day.from_now.to_date, | |
2053 | :due_date => nil, |
|
2053 | :due_date => nil, | |
2054 | :done_ratio => 0).behind_schedule? |
|
2054 | :done_ratio => 0).behind_schedule? | |
2055 | end |
|
2055 | end | |
2056 |
|
2056 | |||
2057 | test "#behind_schedule? should be false if the issue has more done than it's calendar time" do |
|
2057 | test "#behind_schedule? should be false if the issue has more done than it's calendar time" do | |
2058 | assert !Issue.new(:start_date => 50.days.ago.to_date, |
|
2058 | assert !Issue.new(:start_date => 50.days.ago.to_date, | |
2059 | :due_date => 50.days.from_now.to_date, |
|
2059 | :due_date => 50.days.from_now.to_date, | |
2060 | :done_ratio => 90).behind_schedule? |
|
2060 | :done_ratio => 90).behind_schedule? | |
2061 | end |
|
2061 | end | |
2062 |
|
2062 | |||
2063 | test "#behind_schedule? should be true if the issue hasn't been started at all" do |
|
2063 | test "#behind_schedule? should be true if the issue hasn't been started at all" do | |
2064 | assert Issue.new(:start_date => 1.day.ago.to_date, |
|
2064 | assert Issue.new(:start_date => 1.day.ago.to_date, | |
2065 | :due_date => 1.day.from_now.to_date, |
|
2065 | :due_date => 1.day.from_now.to_date, | |
2066 | :done_ratio => 0).behind_schedule? |
|
2066 | :done_ratio => 0).behind_schedule? | |
2067 | end |
|
2067 | end | |
2068 |
|
2068 | |||
2069 | test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do |
|
2069 | test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do | |
2070 | assert Issue.new(:start_date => 100.days.ago.to_date, |
|
2070 | assert Issue.new(:start_date => 100.days.ago.to_date, | |
2071 | :due_date => Date.today, |
|
2071 | :due_date => Date.today, | |
2072 | :done_ratio => 90).behind_schedule? |
|
2072 | :done_ratio => 90).behind_schedule? | |
2073 | end |
|
2073 | end | |
2074 |
|
2074 | |||
2075 | test "#assignable_users should be Users" do |
|
2075 | test "#assignable_users should be Users" do | |
2076 | assert_kind_of User, Issue.find(1).assignable_users.first |
|
2076 | assert_kind_of User, Issue.find(1).assignable_users.first | |
2077 | end |
|
2077 | end | |
2078 |
|
2078 | |||
2079 | test "#assignable_users should include the issue author" do |
|
2079 | test "#assignable_users should include the issue author" do | |
2080 | non_project_member = User.generate! |
|
2080 | non_project_member = User.generate! | |
2081 | issue = Issue.generate!(:author => non_project_member) |
|
2081 | issue = Issue.generate!(:author => non_project_member) | |
2082 |
|
2082 | |||
2083 | assert issue.assignable_users.include?(non_project_member) |
|
2083 | assert issue.assignable_users.include?(non_project_member) | |
2084 | end |
|
2084 | end | |
2085 |
|
2085 | |||
2086 | def test_assignable_users_should_not_include_anonymous_user |
|
2086 | def test_assignable_users_should_not_include_anonymous_user | |
2087 | issue = Issue.generate!(:author => User.anonymous) |
|
2087 | issue = Issue.generate!(:author => User.anonymous) | |
2088 |
|
2088 | |||
2089 | assert !issue.assignable_users.include?(User.anonymous) |
|
2089 | assert !issue.assignable_users.include?(User.anonymous) | |
2090 | end |
|
2090 | end | |
2091 |
|
2091 | |||
2092 | def test_assignable_users_should_not_include_locked_user |
|
2092 | def test_assignable_users_should_not_include_locked_user | |
2093 | user = User.generate! |
|
2093 | user = User.generate! | |
2094 | issue = Issue.generate!(:author => user) |
|
2094 | issue = Issue.generate!(:author => user) | |
2095 | user.lock! |
|
2095 | user.lock! | |
2096 |
|
2096 | |||
2097 | assert !issue.assignable_users.include?(user) |
|
2097 | assert !issue.assignable_users.include?(user) | |
2098 | end |
|
2098 | end | |
2099 |
|
2099 | |||
2100 | test "#assignable_users should include the current assignee" do |
|
2100 | test "#assignable_users should include the current assignee" do | |
2101 | user = User.generate! |
|
2101 | user = User.generate! | |
2102 | issue = Issue.generate!(:assigned_to => user) |
|
2102 | issue = Issue.generate!(:assigned_to => user) | |
2103 | user.lock! |
|
2103 | user.lock! | |
2104 |
|
2104 | |||
2105 | assert Issue.find(issue.id).assignable_users.include?(user) |
|
2105 | assert Issue.find(issue.id).assignable_users.include?(user) | |
2106 | end |
|
2106 | end | |
2107 |
|
2107 | |||
2108 | test "#assignable_users should not show the issue author twice" do |
|
2108 | test "#assignable_users should not show the issue author twice" do | |
2109 | assignable_user_ids = Issue.find(1).assignable_users.collect(&:id) |
|
2109 | assignable_user_ids = Issue.find(1).assignable_users.collect(&:id) | |
2110 | assert_equal 2, assignable_user_ids.length |
|
2110 | assert_equal 2, assignable_user_ids.length | |
2111 |
|
2111 | |||
2112 | assignable_user_ids.each do |user_id| |
|
2112 | assignable_user_ids.each do |user_id| | |
2113 | assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, |
|
2113 | assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, | |
2114 | "User #{user_id} appears more or less than once" |
|
2114 | "User #{user_id} appears more or less than once" | |
2115 | end |
|
2115 | end | |
2116 | end |
|
2116 | end | |
2117 |
|
2117 | |||
2118 | test "#assignable_users with issue_group_assignment should include groups" do |
|
2118 | test "#assignable_users with issue_group_assignment should include groups" do | |
2119 | issue = Issue.new(:project => Project.find(2)) |
|
2119 | issue = Issue.new(:project => Project.find(2)) | |
2120 |
|
2120 | |||
2121 | with_settings :issue_group_assignment => '1' do |
|
2121 | with_settings :issue_group_assignment => '1' do | |
2122 | assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort |
|
2122 | assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort | |
2123 | assert issue.assignable_users.include?(Group.find(11)) |
|
2123 | assert issue.assignable_users.include?(Group.find(11)) | |
2124 | end |
|
2124 | end | |
2125 | end |
|
2125 | end | |
2126 |
|
2126 | |||
2127 | test "#assignable_users without issue_group_assignment should not include groups" do |
|
2127 | test "#assignable_users without issue_group_assignment should not include groups" do | |
2128 | issue = Issue.new(:project => Project.find(2)) |
|
2128 | issue = Issue.new(:project => Project.find(2)) | |
2129 |
|
2129 | |||
2130 | with_settings :issue_group_assignment => '0' do |
|
2130 | with_settings :issue_group_assignment => '0' do | |
2131 | assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort |
|
2131 | assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort | |
2132 | assert !issue.assignable_users.include?(Group.find(11)) |
|
2132 | assert !issue.assignable_users.include?(Group.find(11)) | |
2133 | end |
|
2133 | end | |
2134 | end |
|
2134 | end | |
2135 |
|
2135 | |||
2136 | def test_assignable_users_should_not_include_builtin_groups |
|
2136 | def test_assignable_users_should_not_include_builtin_groups | |
2137 | Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [1]) |
|
2137 | Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [1]) | |
2138 | Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [1]) |
|
2138 | Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [1]) | |
2139 | issue = Issue.new(:project => Project.find(1)) |
|
2139 | issue = Issue.new(:project => Project.find(1)) | |
2140 |
|
2140 | |||
2141 | with_settings :issue_group_assignment => '1' do |
|
2141 | with_settings :issue_group_assignment => '1' do | |
2142 | assert_nil issue.assignable_users.detect {|u| u.is_a?(GroupBuiltin)} |
|
2142 | assert_nil issue.assignable_users.detect {|u| u.is_a?(GroupBuiltin)} | |
2143 | end |
|
2143 | end | |
2144 | end |
|
2144 | end | |
2145 |
|
2145 | |||
2146 | def test_create_should_send_email_notification |
|
2146 | def test_create_should_send_email_notification | |
2147 | ActionMailer::Base.deliveries.clear |
|
2147 | ActionMailer::Base.deliveries.clear | |
2148 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
2148 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
2149 | :author_id => 3, :status_id => 1, |
|
2149 | :author_id => 3, :status_id => 1, | |
2150 | :priority => IssuePriority.all.first, |
|
2150 | :priority => IssuePriority.all.first, | |
2151 | :subject => 'test_create', :estimated_hours => '1:30') |
|
2151 | :subject => 'test_create', :estimated_hours => '1:30') | |
2152 | with_settings :notified_events => %w(issue_added) do |
|
2152 | with_settings :notified_events => %w(issue_added) do | |
2153 | assert issue.save |
|
2153 | assert issue.save | |
2154 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
2154 | assert_equal 1, ActionMailer::Base.deliveries.size | |
2155 | end |
|
2155 | end | |
2156 | end |
|
2156 | end | |
2157 |
|
2157 | |||
2158 | def test_create_should_send_one_email_notification_with_both_settings |
|
2158 | def test_create_should_send_one_email_notification_with_both_settings | |
2159 | ActionMailer::Base.deliveries.clear |
|
2159 | ActionMailer::Base.deliveries.clear | |
2160 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
2160 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
2161 | :author_id => 3, :status_id => 1, |
|
2161 | :author_id => 3, :status_id => 1, | |
2162 | :priority => IssuePriority.all.first, |
|
2162 | :priority => IssuePriority.all.first, | |
2163 | :subject => 'test_create', :estimated_hours => '1:30') |
|
2163 | :subject => 'test_create', :estimated_hours => '1:30') | |
2164 | with_settings :notified_events => %w(issue_added issue_updated) do |
|
2164 | with_settings :notified_events => %w(issue_added issue_updated) do | |
2165 | assert issue.save |
|
2165 | assert issue.save | |
2166 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
2166 | assert_equal 1, ActionMailer::Base.deliveries.size | |
2167 | end |
|
2167 | end | |
2168 | end |
|
2168 | end | |
2169 |
|
2169 | |||
2170 | def test_create_should_not_send_email_notification_with_no_setting |
|
2170 | def test_create_should_not_send_email_notification_with_no_setting | |
2171 | ActionMailer::Base.deliveries.clear |
|
2171 | ActionMailer::Base.deliveries.clear | |
2172 | issue = Issue.new(:project_id => 1, :tracker_id => 1, |
|
2172 | issue = Issue.new(:project_id => 1, :tracker_id => 1, | |
2173 | :author_id => 3, :status_id => 1, |
|
2173 | :author_id => 3, :status_id => 1, | |
2174 | :priority => IssuePriority.all.first, |
|
2174 | :priority => IssuePriority.all.first, | |
2175 | :subject => 'test_create', :estimated_hours => '1:30') |
|
2175 | :subject => 'test_create', :estimated_hours => '1:30') | |
2176 | with_settings :notified_events => [] do |
|
2176 | with_settings :notified_events => [] do | |
2177 | assert issue.save |
|
2177 | assert issue.save | |
2178 | assert_equal 0, ActionMailer::Base.deliveries.size |
|
2178 | assert_equal 0, ActionMailer::Base.deliveries.size | |
2179 | end |
|
2179 | end | |
2180 | end |
|
2180 | end | |
2181 |
|
2181 | |||
2182 | def test_update_should_notify_previous_assignee |
|
2182 | def test_update_should_notify_previous_assignee | |
2183 | ActionMailer::Base.deliveries.clear |
|
2183 | ActionMailer::Base.deliveries.clear | |
2184 | user = User.find(3) |
|
2184 | user = User.find(3) | |
2185 | user.members.update_all ["mail_notification = ?", false] |
|
2185 | user.members.update_all ["mail_notification = ?", false] | |
2186 | user.update_attribute :mail_notification, 'only_assigned' |
|
2186 | user.update_attribute :mail_notification, 'only_assigned' | |
2187 |
|
2187 | |||
2188 | with_settings :notified_events => %w(issue_updated) do |
|
2188 | with_settings :notified_events => %w(issue_updated) do | |
2189 | issue = Issue.find(2) |
|
2189 | issue = Issue.find(2) | |
2190 | issue.init_journal User.find(1) |
|
2190 | issue.init_journal User.find(1) | |
2191 | issue.assigned_to = nil |
|
2191 | issue.assigned_to = nil | |
2192 | issue.save! |
|
2192 | issue.save! | |
2193 | assert_include user.mail, ActionMailer::Base.deliveries.last.bcc |
|
2193 | assert_include user.mail, ActionMailer::Base.deliveries.last.bcc | |
2194 | end |
|
2194 | end | |
2195 | end |
|
2195 | end | |
2196 |
|
2196 | |||
2197 | def test_stale_issue_should_not_send_email_notification |
|
2197 | def test_stale_issue_should_not_send_email_notification | |
2198 | ActionMailer::Base.deliveries.clear |
|
2198 | ActionMailer::Base.deliveries.clear | |
2199 | issue = Issue.find(1) |
|
2199 | issue = Issue.find(1) | |
2200 | stale = Issue.find(1) |
|
2200 | stale = Issue.find(1) | |
2201 |
|
2201 | |||
2202 | issue.init_journal(User.find(1)) |
|
2202 | issue.init_journal(User.find(1)) | |
2203 | issue.subject = 'Subjet update' |
|
2203 | issue.subject = 'Subjet update' | |
2204 | with_settings :notified_events => %w(issue_updated) do |
|
2204 | with_settings :notified_events => %w(issue_updated) do | |
2205 | assert issue.save |
|
2205 | assert issue.save | |
2206 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
2206 | assert_equal 1, ActionMailer::Base.deliveries.size | |
2207 | ActionMailer::Base.deliveries.clear |
|
2207 | ActionMailer::Base.deliveries.clear | |
2208 |
|
2208 | |||
2209 | stale.init_journal(User.find(1)) |
|
2209 | stale.init_journal(User.find(1)) | |
2210 | stale.subject = 'Another subjet update' |
|
2210 | stale.subject = 'Another subjet update' | |
2211 | assert_raise ActiveRecord::StaleObjectError do |
|
2211 | assert_raise ActiveRecord::StaleObjectError do | |
2212 | stale.save |
|
2212 | stale.save | |
2213 | end |
|
2213 | end | |
2214 | assert ActionMailer::Base.deliveries.empty? |
|
2214 | assert ActionMailer::Base.deliveries.empty? | |
2215 | end |
|
2215 | end | |
2216 | end |
|
2216 | end | |
2217 |
|
2217 | |||
2218 | def test_journalized_description |
|
2218 | def test_journalized_description | |
2219 | IssueCustomField.delete_all |
|
2219 | IssueCustomField.delete_all | |
2220 |
|
2220 | |||
2221 | i = Issue.first |
|
2221 | i = Issue.first | |
2222 | old_description = i.description |
|
2222 | old_description = i.description | |
2223 | new_description = "This is the new description" |
|
2223 | new_description = "This is the new description" | |
2224 |
|
2224 | |||
2225 | i.init_journal(User.find(2)) |
|
2225 | i.init_journal(User.find(2)) | |
2226 | i.description = new_description |
|
2226 | i.description = new_description | |
2227 | assert_difference 'Journal.count', 1 do |
|
2227 | assert_difference 'Journal.count', 1 do | |
2228 | assert_difference 'JournalDetail.count', 1 do |
|
2228 | assert_difference 'JournalDetail.count', 1 do | |
2229 | i.save! |
|
2229 | i.save! | |
2230 | end |
|
2230 | end | |
2231 | end |
|
2231 | end | |
2232 |
|
2232 | |||
2233 | detail = JournalDetail.order('id DESC').first |
|
2233 | detail = JournalDetail.order('id DESC').first | |
2234 | assert_equal i, detail.journal.journalized |
|
2234 | assert_equal i, detail.journal.journalized | |
2235 | assert_equal 'attr', detail.property |
|
2235 | assert_equal 'attr', detail.property | |
2236 | assert_equal 'description', detail.prop_key |
|
2236 | assert_equal 'description', detail.prop_key | |
2237 | assert_equal old_description, detail.old_value |
|
2237 | assert_equal old_description, detail.old_value | |
2238 | assert_equal new_description, detail.value |
|
2238 | assert_equal new_description, detail.value | |
2239 | end |
|
2239 | end | |
2240 |
|
2240 | |||
2241 | def test_blank_descriptions_should_not_be_journalized |
|
2241 | def test_blank_descriptions_should_not_be_journalized | |
2242 | IssueCustomField.delete_all |
|
2242 | IssueCustomField.delete_all | |
2243 | Issue.where(:id => 1).update_all("description = NULL") |
|
2243 | Issue.where(:id => 1).update_all("description = NULL") | |
2244 |
|
2244 | |||
2245 | i = Issue.find(1) |
|
2245 | i = Issue.find(1) | |
2246 | i.init_journal(User.find(2)) |
|
2246 | i.init_journal(User.find(2)) | |
2247 | i.subject = "blank description" |
|
2247 | i.subject = "blank description" | |
2248 | i.description = "\r\n" |
|
2248 | i.description = "\r\n" | |
2249 |
|
2249 | |||
2250 | assert_difference 'Journal.count', 1 do |
|
2250 | assert_difference 'Journal.count', 1 do | |
2251 | assert_difference 'JournalDetail.count', 1 do |
|
2251 | assert_difference 'JournalDetail.count', 1 do | |
2252 | i.save! |
|
2252 | i.save! | |
2253 | end |
|
2253 | end | |
2254 | end |
|
2254 | end | |
2255 | end |
|
2255 | end | |
2256 |
|
2256 | |||
2257 | def test_journalized_multi_custom_field |
|
2257 | def test_journalized_multi_custom_field | |
2258 | field = IssueCustomField.create!(:name => 'filter', :field_format => 'list', |
|
2258 | field = IssueCustomField.create!(:name => 'filter', :field_format => 'list', | |
2259 | :is_filter => true, :is_for_all => true, |
|
2259 | :is_filter => true, :is_for_all => true, | |
2260 | :tracker_ids => [1], |
|
2260 | :tracker_ids => [1], | |
2261 | :possible_values => ['value1', 'value2', 'value3'], |
|
2261 | :possible_values => ['value1', 'value2', 'value3'], | |
2262 | :multiple => true) |
|
2262 | :multiple => true) | |
2263 |
|
2263 | |||
2264 | issue = Issue.create!(:project_id => 1, :tracker_id => 1, |
|
2264 | issue = Issue.create!(:project_id => 1, :tracker_id => 1, | |
2265 | :subject => 'Test', :author_id => 1) |
|
2265 | :subject => 'Test', :author_id => 1) | |
2266 |
|
2266 | |||
2267 | assert_difference 'Journal.count' do |
|
2267 | assert_difference 'Journal.count' do | |
2268 | assert_difference 'JournalDetail.count' do |
|
2268 | assert_difference 'JournalDetail.count' do | |
2269 | issue.init_journal(User.first) |
|
2269 | issue.init_journal(User.first) | |
2270 | issue.custom_field_values = {field.id => ['value1']} |
|
2270 | issue.custom_field_values = {field.id => ['value1']} | |
2271 | issue.save! |
|
2271 | issue.save! | |
2272 | end |
|
2272 | end | |
2273 | assert_difference 'JournalDetail.count' do |
|
2273 | assert_difference 'JournalDetail.count' do | |
2274 | issue.init_journal(User.first) |
|
2274 | issue.init_journal(User.first) | |
2275 | issue.custom_field_values = {field.id => ['value1', 'value2']} |
|
2275 | issue.custom_field_values = {field.id => ['value1', 'value2']} | |
2276 | issue.save! |
|
2276 | issue.save! | |
2277 | end |
|
2277 | end | |
2278 | assert_difference 'JournalDetail.count', 2 do |
|
2278 | assert_difference 'JournalDetail.count', 2 do | |
2279 | issue.init_journal(User.first) |
|
2279 | issue.init_journal(User.first) | |
2280 | issue.custom_field_values = {field.id => ['value3', 'value2']} |
|
2280 | issue.custom_field_values = {field.id => ['value3', 'value2']} | |
2281 | issue.save! |
|
2281 | issue.save! | |
2282 | end |
|
2282 | end | |
2283 | assert_difference 'JournalDetail.count', 2 do |
|
2283 | assert_difference 'JournalDetail.count', 2 do | |
2284 | issue.init_journal(User.first) |
|
2284 | issue.init_journal(User.first) | |
2285 | issue.custom_field_values = {field.id => nil} |
|
2285 | issue.custom_field_values = {field.id => nil} | |
2286 | issue.save! |
|
2286 | issue.save! | |
2287 | end |
|
2287 | end | |
2288 | end |
|
2288 | end | |
2289 | end |
|
2289 | end | |
2290 |
|
2290 | |||
2291 | def test_description_eol_should_be_normalized |
|
2291 | def test_description_eol_should_be_normalized | |
2292 | i = Issue.new(:description => "CR \r LF \n CRLF \r\n") |
|
2292 | i = Issue.new(:description => "CR \r LF \n CRLF \r\n") | |
2293 | assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description |
|
2293 | assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description | |
2294 | end |
|
2294 | end | |
2295 |
|
2295 | |||
2296 | def test_saving_twice_should_not_duplicate_journal_details |
|
2296 | def test_saving_twice_should_not_duplicate_journal_details | |
2297 | i = Issue.first |
|
2297 | i = Issue.first | |
2298 | i.init_journal(User.find(2), 'Some notes') |
|
2298 | i.init_journal(User.find(2), 'Some notes') | |
2299 | # initial changes |
|
2299 | # initial changes | |
2300 | i.subject = 'New subject' |
|
2300 | i.subject = 'New subject' | |
2301 | i.done_ratio = i.done_ratio + 10 |
|
2301 | i.done_ratio = i.done_ratio + 10 | |
2302 | assert_difference 'Journal.count' do |
|
2302 | assert_difference 'Journal.count' do | |
2303 | assert i.save |
|
2303 | assert i.save | |
2304 | end |
|
2304 | end | |
2305 | # 1 more change |
|
2305 | # 1 more change | |
2306 | i.priority = IssuePriority.where("id <> ?", i.priority_id).first |
|
2306 | i.priority = IssuePriority.where("id <> ?", i.priority_id).first | |
2307 | assert_no_difference 'Journal.count' do |
|
2307 | assert_no_difference 'Journal.count' do | |
2308 | assert_difference 'JournalDetail.count', 1 do |
|
2308 | assert_difference 'JournalDetail.count', 1 do | |
2309 | i.save |
|
2309 | i.save | |
2310 | end |
|
2310 | end | |
2311 | end |
|
2311 | end | |
2312 | # no more change |
|
2312 | # no more change | |
2313 | assert_no_difference 'Journal.count' do |
|
2313 | assert_no_difference 'Journal.count' do | |
2314 | assert_no_difference 'JournalDetail.count' do |
|
2314 | assert_no_difference 'JournalDetail.count' do | |
2315 | i.save |
|
2315 | i.save | |
2316 | end |
|
2316 | end | |
2317 | end |
|
2317 | end | |
2318 | end |
|
2318 | end | |
2319 |
|
2319 | |||
2320 | test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do |
|
2320 | test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do | |
2321 | @issue = Issue.find(1) |
|
2321 | @issue = Issue.find(1) | |
2322 | @issue_status = IssueStatus.find(1) |
|
2322 | @issue_status = IssueStatus.find(1) | |
2323 | @issue_status.update_attribute(:default_done_ratio, 50) |
|
2323 | @issue_status.update_attribute(:default_done_ratio, 50) | |
2324 | @issue2 = Issue.find(2) |
|
2324 | @issue2 = Issue.find(2) | |
2325 | @issue_status2 = IssueStatus.find(2) |
|
2325 | @issue_status2 = IssueStatus.find(2) | |
2326 | @issue_status2.update_attribute(:default_done_ratio, 0) |
|
2326 | @issue_status2.update_attribute(:default_done_ratio, 0) | |
2327 |
|
2327 | |||
2328 | with_settings :issue_done_ratio => 'issue_field' do |
|
2328 | with_settings :issue_done_ratio => 'issue_field' do | |
2329 | assert_equal 0, @issue.done_ratio |
|
2329 | assert_equal 0, @issue.done_ratio | |
2330 | assert_equal 30, @issue2.done_ratio |
|
2330 | assert_equal 30, @issue2.done_ratio | |
2331 | end |
|
2331 | end | |
2332 |
|
2332 | |||
2333 | with_settings :issue_done_ratio => 'issue_status' do |
|
2333 | with_settings :issue_done_ratio => 'issue_status' do | |
2334 | assert_equal 50, @issue.done_ratio |
|
2334 | assert_equal 50, @issue.done_ratio | |
2335 | assert_equal 0, @issue2.done_ratio |
|
2335 | assert_equal 0, @issue2.done_ratio | |
2336 | end |
|
2336 | end | |
2337 | end |
|
2337 | end | |
2338 |
|
2338 | |||
2339 | test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do |
|
2339 | test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do | |
2340 | @issue = Issue.find(1) |
|
2340 | @issue = Issue.find(1) | |
2341 | @issue_status = IssueStatus.find(1) |
|
2341 | @issue_status = IssueStatus.find(1) | |
2342 | @issue_status.update_attribute(:default_done_ratio, 50) |
|
2342 | @issue_status.update_attribute(:default_done_ratio, 50) | |
2343 | @issue2 = Issue.find(2) |
|
2343 | @issue2 = Issue.find(2) | |
2344 | @issue_status2 = IssueStatus.find(2) |
|
2344 | @issue_status2 = IssueStatus.find(2) | |
2345 | @issue_status2.update_attribute(:default_done_ratio, 0) |
|
2345 | @issue_status2.update_attribute(:default_done_ratio, 0) | |
2346 |
|
2346 | |||
2347 | with_settings :issue_done_ratio => 'issue_field' do |
|
2347 | with_settings :issue_done_ratio => 'issue_field' do | |
2348 | @issue.update_done_ratio_from_issue_status |
|
2348 | @issue.update_done_ratio_from_issue_status | |
2349 | @issue2.update_done_ratio_from_issue_status |
|
2349 | @issue2.update_done_ratio_from_issue_status | |
2350 |
|
2350 | |||
2351 | assert_equal 0, @issue.read_attribute(:done_ratio) |
|
2351 | assert_equal 0, @issue.read_attribute(:done_ratio) | |
2352 | assert_equal 30, @issue2.read_attribute(:done_ratio) |
|
2352 | assert_equal 30, @issue2.read_attribute(:done_ratio) | |
2353 | end |
|
2353 | end | |
2354 |
|
2354 | |||
2355 | with_settings :issue_done_ratio => 'issue_status' do |
|
2355 | with_settings :issue_done_ratio => 'issue_status' do | |
2356 | @issue.update_done_ratio_from_issue_status |
|
2356 | @issue.update_done_ratio_from_issue_status | |
2357 | @issue2.update_done_ratio_from_issue_status |
|
2357 | @issue2.update_done_ratio_from_issue_status | |
2358 |
|
2358 | |||
2359 | assert_equal 50, @issue.read_attribute(:done_ratio) |
|
2359 | assert_equal 50, @issue.read_attribute(:done_ratio) | |
2360 | assert_equal 0, @issue2.read_attribute(:done_ratio) |
|
2360 | assert_equal 0, @issue2.read_attribute(:done_ratio) | |
2361 | end |
|
2361 | end | |
2362 | end |
|
2362 | end | |
2363 |
|
2363 | |||
2364 | test "#by_tracker" do |
|
2364 | test "#by_tracker" do | |
2365 | User.current = User.anonymous |
|
2365 | User.current = User.anonymous | |
2366 | groups = Issue.by_tracker(Project.find(1)) |
|
2366 | groups = Issue.by_tracker(Project.find(1)) | |
2367 | assert_equal 3, groups.count |
|
2367 | assert_equal 3, groups.count | |
2368 | assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2368 | assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2369 | end |
|
2369 | end | |
2370 |
|
2370 | |||
2371 | test "#by_version" do |
|
2371 | test "#by_version" do | |
2372 | User.current = User.anonymous |
|
2372 | User.current = User.anonymous | |
2373 | groups = Issue.by_version(Project.find(1)) |
|
2373 | groups = Issue.by_version(Project.find(1)) | |
2374 | assert_equal 3, groups.count |
|
2374 | assert_equal 3, groups.count | |
2375 | assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2375 | assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2376 | end |
|
2376 | end | |
2377 |
|
2377 | |||
2378 | test "#by_priority" do |
|
2378 | test "#by_priority" do | |
2379 | User.current = User.anonymous |
|
2379 | User.current = User.anonymous | |
2380 | groups = Issue.by_priority(Project.find(1)) |
|
2380 | groups = Issue.by_priority(Project.find(1)) | |
2381 | assert_equal 4, groups.count |
|
2381 | assert_equal 4, groups.count | |
2382 | assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2382 | assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2383 | end |
|
2383 | end | |
2384 |
|
2384 | |||
2385 | test "#by_category" do |
|
2385 | test "#by_category" do | |
2386 | User.current = User.anonymous |
|
2386 | User.current = User.anonymous | |
2387 | groups = Issue.by_category(Project.find(1)) |
|
2387 | groups = Issue.by_category(Project.find(1)) | |
2388 | assert_equal 2, groups.count |
|
2388 | assert_equal 2, groups.count | |
2389 | assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2389 | assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2390 | end |
|
2390 | end | |
2391 |
|
2391 | |||
2392 | test "#by_assigned_to" do |
|
2392 | test "#by_assigned_to" do | |
2393 | User.current = User.anonymous |
|
2393 | User.current = User.anonymous | |
2394 | groups = Issue.by_assigned_to(Project.find(1)) |
|
2394 | groups = Issue.by_assigned_to(Project.find(1)) | |
2395 | assert_equal 2, groups.count |
|
2395 | assert_equal 2, groups.count | |
2396 | assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2396 | assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2397 | end |
|
2397 | end | |
2398 |
|
2398 | |||
2399 | test "#by_author" do |
|
2399 | test "#by_author" do | |
2400 | User.current = User.anonymous |
|
2400 | User.current = User.anonymous | |
2401 | groups = Issue.by_author(Project.find(1)) |
|
2401 | groups = Issue.by_author(Project.find(1)) | |
2402 | assert_equal 4, groups.count |
|
2402 | assert_equal 4, groups.count | |
2403 | assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2403 | assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2404 | end |
|
2404 | end | |
2405 |
|
2405 | |||
2406 | test "#by_subproject" do |
|
2406 | test "#by_subproject" do | |
2407 | User.current = User.anonymous |
|
2407 | User.current = User.anonymous | |
2408 | groups = Issue.by_subproject(Project.find(1)) |
|
2408 | groups = Issue.by_subproject(Project.find(1)) | |
2409 | # Private descendant not visible |
|
2409 | # Private descendant not visible | |
2410 | assert_equal 1, groups.count |
|
2410 | assert_equal 1, groups.count | |
2411 | assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} |
|
2411 | assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} | |
2412 | end |
|
2412 | end | |
2413 |
|
2413 | |||
2414 | def test_recently_updated_scope |
|
2414 | def test_recently_updated_scope | |
2415 | #should return the last updated issue |
|
2415 | #should return the last updated issue | |
2416 | assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first |
|
2416 | assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first | |
2417 | end |
|
2417 | end | |
2418 |
|
2418 | |||
2419 | def test_on_active_projects_scope |
|
2419 | def test_on_active_projects_scope | |
2420 | assert Project.find(2).archive |
|
2420 | assert Project.find(2).archive | |
2421 |
|
2421 | |||
2422 | before = Issue.on_active_project.length |
|
2422 | before = Issue.on_active_project.length | |
2423 | # test inclusion to results |
|
2423 | # test inclusion to results | |
2424 | issue = Issue.generate!(:tracker => Project.find(2).trackers.first) |
|
2424 | issue = Issue.generate!(:tracker => Project.find(2).trackers.first) | |
2425 | assert_equal before + 1, Issue.on_active_project.length |
|
2425 | assert_equal before + 1, Issue.on_active_project.length | |
2426 |
|
2426 | |||
2427 | # Move to an archived project |
|
2427 | # Move to an archived project | |
2428 | issue.project = Project.find(2) |
|
2428 | issue.project = Project.find(2) | |
2429 | assert issue.save |
|
2429 | assert issue.save | |
2430 | assert_equal before, Issue.on_active_project.length |
|
2430 | assert_equal before, Issue.on_active_project.length | |
2431 | end |
|
2431 | end | |
2432 |
|
2432 | |||
2433 | test "Issue#recipients should include project recipients" do |
|
2433 | test "Issue#recipients should include project recipients" do | |
2434 | issue = Issue.generate! |
|
2434 | issue = Issue.generate! | |
2435 | assert issue.project.recipients.present? |
|
2435 | assert issue.project.recipients.present? | |
2436 | issue.project.recipients.each do |project_recipient| |
|
2436 | issue.project.recipients.each do |project_recipient| | |
2437 | assert issue.recipients.include?(project_recipient) |
|
2437 | assert issue.recipients.include?(project_recipient) | |
2438 | end |
|
2438 | end | |
2439 | end |
|
2439 | end | |
2440 |
|
2440 | |||
2441 | test "Issue#recipients should include the author if the author is active" do |
|
2441 | test "Issue#recipients should include the author if the author is active" do | |
2442 | issue = Issue.generate!(:author => User.generate!) |
|
2442 | issue = Issue.generate!(:author => User.generate!) | |
2443 | assert issue.author, "No author set for Issue" |
|
2443 | assert issue.author, "No author set for Issue" | |
2444 | assert issue.recipients.include?(issue.author.mail) |
|
2444 | assert issue.recipients.include?(issue.author.mail) | |
2445 | end |
|
2445 | end | |
2446 |
|
2446 | |||
2447 | test "Issue#recipients should include the assigned to user if the assigned to user is active" do |
|
2447 | test "Issue#recipients should include the assigned to user if the assigned to user is active" do | |
2448 | issue = Issue.generate!(:assigned_to => User.generate!) |
|
2448 | issue = Issue.generate!(:assigned_to => User.generate!) | |
2449 | assert issue.assigned_to, "No assigned_to set for Issue" |
|
2449 | assert issue.assigned_to, "No assigned_to set for Issue" | |
2450 | assert issue.recipients.include?(issue.assigned_to.mail) |
|
2450 | assert issue.recipients.include?(issue.assigned_to.mail) | |
2451 | end |
|
2451 | end | |
2452 |
|
2452 | |||
2453 | test "Issue#recipients should not include users who opt out of all email" do |
|
2453 | test "Issue#recipients should not include users who opt out of all email" do | |
2454 | issue = Issue.generate!(:author => User.generate!) |
|
2454 | issue = Issue.generate!(:author => User.generate!) | |
2455 | issue.author.update_attribute(:mail_notification, :none) |
|
2455 | issue.author.update_attribute(:mail_notification, :none) | |
2456 | assert !issue.recipients.include?(issue.author.mail) |
|
2456 | assert !issue.recipients.include?(issue.author.mail) | |
2457 | end |
|
2457 | end | |
2458 |
|
2458 | |||
2459 | test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do |
|
2459 | test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do | |
2460 | issue = Issue.generate!(:author => User.generate!) |
|
2460 | issue = Issue.generate!(:author => User.generate!) | |
2461 | issue.author.update_attribute(:mail_notification, :only_assigned) |
|
2461 | issue.author.update_attribute(:mail_notification, :only_assigned) | |
2462 | assert !issue.recipients.include?(issue.author.mail) |
|
2462 | assert !issue.recipients.include?(issue.author.mail) | |
2463 | end |
|
2463 | end | |
2464 |
|
2464 | |||
2465 | test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do |
|
2465 | test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do | |
2466 | issue = Issue.generate!(:assigned_to => User.generate!) |
|
2466 | issue = Issue.generate!(:assigned_to => User.generate!) | |
2467 | issue.assigned_to.update_attribute(:mail_notification, :only_owner) |
|
2467 | issue.assigned_to.update_attribute(:mail_notification, :only_owner) | |
2468 | assert !issue.recipients.include?(issue.assigned_to.mail) |
|
2468 | assert !issue.recipients.include?(issue.assigned_to.mail) | |
2469 | end |
|
2469 | end | |
2470 |
|
2470 | |||
2471 | def test_last_journal_id_with_journals_should_return_the_journal_id |
|
2471 | def test_last_journal_id_with_journals_should_return_the_journal_id | |
2472 | assert_equal 2, Issue.find(1).last_journal_id |
|
2472 | assert_equal 2, Issue.find(1).last_journal_id | |
2473 | end |
|
2473 | end | |
2474 |
|
2474 | |||
2475 | def test_last_journal_id_without_journals_should_return_nil |
|
2475 | def test_last_journal_id_without_journals_should_return_nil | |
2476 | assert_nil Issue.find(3).last_journal_id |
|
2476 | assert_nil Issue.find(3).last_journal_id | |
2477 | end |
|
2477 | end | |
2478 |
|
2478 | |||
2479 | def test_journals_after_should_return_journals_with_greater_id |
|
2479 | def test_journals_after_should_return_journals_with_greater_id | |
2480 | assert_equal [Journal.find(2)], Issue.find(1).journals_after('1') |
|
2480 | assert_equal [Journal.find(2)], Issue.find(1).journals_after('1') | |
2481 | assert_equal [], Issue.find(1).journals_after('2') |
|
2481 | assert_equal [], Issue.find(1).journals_after('2') | |
2482 | end |
|
2482 | end | |
2483 |
|
2483 | |||
2484 | def test_journals_after_with_blank_arg_should_return_all_journals |
|
2484 | def test_journals_after_with_blank_arg_should_return_all_journals | |
2485 | assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('') |
|
2485 | assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('') | |
2486 | end |
|
2486 | end | |
2487 |
|
2487 | |||
2488 | def test_css_classes_should_include_tracker |
|
2488 | def test_css_classes_should_include_tracker | |
2489 | issue = Issue.new(:tracker => Tracker.find(2)) |
|
2489 | issue = Issue.new(:tracker => Tracker.find(2)) | |
2490 | classes = issue.css_classes.split(' ') |
|
2490 | classes = issue.css_classes.split(' ') | |
2491 | assert_include 'tracker-2', classes |
|
2491 | assert_include 'tracker-2', classes | |
2492 | end |
|
2492 | end | |
2493 |
|
2493 | |||
2494 | def test_css_classes_should_include_priority |
|
2494 | def test_css_classes_should_include_priority | |
2495 | issue = Issue.new(:priority => IssuePriority.find(8)) |
|
2495 | issue = Issue.new(:priority => IssuePriority.find(8)) | |
2496 | classes = issue.css_classes.split(' ') |
|
2496 | classes = issue.css_classes.split(' ') | |
2497 | assert_include 'priority-8', classes |
|
2497 | assert_include 'priority-8', classes | |
2498 | assert_include 'priority-highest', classes |
|
2498 | assert_include 'priority-highest', classes | |
2499 | end |
|
2499 | end | |
2500 |
|
2500 | |||
2501 | def test_css_classes_should_include_user_and_group_assignment |
|
2501 | def test_css_classes_should_include_user_and_group_assignment | |
2502 | project = Project.first |
|
2502 | project = Project.first | |
2503 | user = User.generate! |
|
2503 | user = User.generate! | |
2504 | group = Group.generate! |
|
2504 | group = Group.generate! | |
2505 | Member.create!(:principal => group, :project => project, :role_ids => [1, 2]) |
|
2505 | Member.create!(:principal => group, :project => project, :role_ids => [1, 2]) | |
2506 | group.users << user |
|
2506 | group.users << user | |
2507 | assert user.member_of?(project) |
|
2507 | assert user.member_of?(project) | |
2508 | issue1 = Issue.generate(:assigned_to_id => group.id) |
|
2508 | issue1 = Issue.generate(:assigned_to_id => group.id) | |
2509 | assert_include 'assigned-to-my-group', issue1.css_classes(user) |
|
2509 | assert_include 'assigned-to-my-group', issue1.css_classes(user) | |
2510 | assert_not_include 'assigned-to-me', issue1.css_classes(user) |
|
2510 | assert_not_include 'assigned-to-me', issue1.css_classes(user) | |
2511 | issue2 = Issue.generate(:assigned_to_id => user.id) |
|
2511 | issue2 = Issue.generate(:assigned_to_id => user.id) | |
2512 | assert_not_include 'assigned-to-my-group', issue2.css_classes(user) |
|
2512 | assert_not_include 'assigned-to-my-group', issue2.css_classes(user) | |
2513 | assert_include 'assigned-to-me', issue2.css_classes(user) |
|
2513 | assert_include 'assigned-to-me', issue2.css_classes(user) | |
2514 | end |
|
2514 | end | |
2515 |
|
2515 | |||
2516 | def test_save_attachments_with_hash_should_save_attachments_in_keys_order |
|
2516 | def test_save_attachments_with_hash_should_save_attachments_in_keys_order | |
2517 | set_tmp_attachments_directory |
|
2517 | set_tmp_attachments_directory | |
2518 | issue = Issue.generate! |
|
2518 | issue = Issue.generate! | |
2519 | issue.save_attachments({ |
|
2519 | issue.save_attachments({ | |
2520 | 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')}, |
|
2520 | 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')}, | |
2521 | '3' => {'file' => mock_file_with_options(:original_filename => 'bar')}, |
|
2521 | '3' => {'file' => mock_file_with_options(:original_filename => 'bar')}, | |
2522 | '1' => {'file' => mock_file_with_options(:original_filename => 'foo')} |
|
2522 | '1' => {'file' => mock_file_with_options(:original_filename => 'foo')} | |
2523 | }) |
|
2523 | }) | |
2524 | issue.attach_saved_attachments |
|
2524 | issue.attach_saved_attachments | |
2525 |
|
2525 | |||
2526 | assert_equal 3, issue.reload.attachments.count |
|
2526 | assert_equal 3, issue.reload.attachments.count | |
2527 | assert_equal %w(upload foo bar), issue.attachments.map(&:filename) |
|
2527 | assert_equal %w(upload foo bar), issue.attachments.map(&:filename) | |
2528 | end |
|
2528 | end | |
2529 |
|
2529 | |||
2530 | def test_closed_on_should_be_nil_when_creating_an_open_issue |
|
2530 | def test_closed_on_should_be_nil_when_creating_an_open_issue | |
2531 | issue = Issue.generate!(:status_id => 1).reload |
|
2531 | issue = Issue.generate!(:status_id => 1).reload | |
2532 | assert !issue.closed? |
|
2532 | assert !issue.closed? | |
2533 | assert_nil issue.closed_on |
|
2533 | assert_nil issue.closed_on | |
2534 | end |
|
2534 | end | |
2535 |
|
2535 | |||
2536 | def test_closed_on_should_be_set_when_creating_a_closed_issue |
|
2536 | def test_closed_on_should_be_set_when_creating_a_closed_issue | |
2537 | issue = Issue.generate!(:status_id => 5).reload |
|
2537 | issue = Issue.generate!(:status_id => 5).reload | |
2538 | assert issue.closed? |
|
2538 | assert issue.closed? | |
2539 | assert_not_nil issue.closed_on |
|
2539 | assert_not_nil issue.closed_on | |
2540 | assert_equal issue.updated_on, issue.closed_on |
|
2540 | assert_equal issue.updated_on, issue.closed_on | |
2541 | assert_equal issue.created_on, issue.closed_on |
|
2541 | assert_equal issue.created_on, issue.closed_on | |
2542 | end |
|
2542 | end | |
2543 |
|
2543 | |||
2544 | def test_closed_on_should_be_nil_when_updating_an_open_issue |
|
2544 | def test_closed_on_should_be_nil_when_updating_an_open_issue | |
2545 | issue = Issue.find(1) |
|
2545 | issue = Issue.find(1) | |
2546 | issue.subject = 'Not closed yet' |
|
2546 | issue.subject = 'Not closed yet' | |
2547 | issue.save! |
|
2547 | issue.save! | |
2548 | issue.reload |
|
2548 | issue.reload | |
2549 | assert_nil issue.closed_on |
|
2549 | assert_nil issue.closed_on | |
2550 | end |
|
2550 | end | |
2551 |
|
2551 | |||
2552 | def test_closed_on_should_be_set_when_closing_an_open_issue |
|
2552 | def test_closed_on_should_be_set_when_closing_an_open_issue | |
2553 | issue = Issue.find(1) |
|
2553 | issue = Issue.find(1) | |
2554 | issue.subject = 'Now closed' |
|
2554 | issue.subject = 'Now closed' | |
2555 | issue.status_id = 5 |
|
2555 | issue.status_id = 5 | |
2556 | issue.save! |
|
2556 | issue.save! | |
2557 | issue.reload |
|
2557 | issue.reload | |
2558 | assert_not_nil issue.closed_on |
|
2558 | assert_not_nil issue.closed_on | |
2559 | assert_equal issue.updated_on, issue.closed_on |
|
2559 | assert_equal issue.updated_on, issue.closed_on | |
2560 | end |
|
2560 | end | |
2561 |
|
2561 | |||
2562 | def test_closed_on_should_not_be_updated_when_updating_a_closed_issue |
|
2562 | def test_closed_on_should_not_be_updated_when_updating_a_closed_issue | |
2563 | issue = Issue.open(false).first |
|
2563 | issue = Issue.open(false).first | |
2564 | was_closed_on = issue.closed_on |
|
2564 | was_closed_on = issue.closed_on | |
2565 | assert_not_nil was_closed_on |
|
2565 | assert_not_nil was_closed_on | |
2566 | issue.subject = 'Updating a closed issue' |
|
2566 | issue.subject = 'Updating a closed issue' | |
2567 | issue.save! |
|
2567 | issue.save! | |
2568 | issue.reload |
|
2568 | issue.reload | |
2569 | assert_equal was_closed_on, issue.closed_on |
|
2569 | assert_equal was_closed_on, issue.closed_on | |
2570 | end |
|
2570 | end | |
2571 |
|
2571 | |||
2572 | def test_closed_on_should_be_preserved_when_reopening_a_closed_issue |
|
2572 | def test_closed_on_should_be_preserved_when_reopening_a_closed_issue | |
2573 | issue = Issue.open(false).first |
|
2573 | issue = Issue.open(false).first | |
2574 | was_closed_on = issue.closed_on |
|
2574 | was_closed_on = issue.closed_on | |
2575 | assert_not_nil was_closed_on |
|
2575 | assert_not_nil was_closed_on | |
2576 | issue.subject = 'Reopening a closed issue' |
|
2576 | issue.subject = 'Reopening a closed issue' | |
2577 | issue.status_id = 1 |
|
2577 | issue.status_id = 1 | |
2578 | issue.save! |
|
2578 | issue.save! | |
2579 | issue.reload |
|
2579 | issue.reload | |
2580 | assert !issue.closed? |
|
2580 | assert !issue.closed? | |
2581 | assert_equal was_closed_on, issue.closed_on |
|
2581 | assert_equal was_closed_on, issue.closed_on | |
2582 | end |
|
2582 | end | |
2583 |
|
2583 | |||
2584 | def test_status_was_should_return_nil_for_new_issue |
|
2584 | def test_status_was_should_return_nil_for_new_issue | |
2585 | issue = Issue.new |
|
2585 | issue = Issue.new | |
2586 | assert_nil issue.status_was |
|
2586 | assert_nil issue.status_was | |
2587 | end |
|
2587 | end | |
2588 |
|
2588 | |||
2589 | def test_status_was_should_return_status_before_change |
|
2589 | def test_status_was_should_return_status_before_change | |
2590 | issue = Issue.find(1) |
|
2590 | issue = Issue.find(1) | |
2591 | issue.status = IssueStatus.find(2) |
|
2591 | issue.status = IssueStatus.find(2) | |
2592 | assert_equal IssueStatus.find(1), issue.status_was |
|
2592 | assert_equal IssueStatus.find(1), issue.status_was | |
2593 | end |
|
2593 | end | |
2594 |
|
2594 | |||
2595 | def test_status_was_should_return_status_before_change_with_status_id |
|
2595 | def test_status_was_should_return_status_before_change_with_status_id | |
2596 | issue = Issue.find(1) |
|
2596 | issue = Issue.find(1) | |
2597 | assert_equal IssueStatus.find(1), issue.status |
|
2597 | assert_equal IssueStatus.find(1), issue.status | |
2598 | issue.status_id = 2 |
|
2598 | issue.status_id = 2 | |
2599 | assert_equal IssueStatus.find(1), issue.status_was |
|
2599 | assert_equal IssueStatus.find(1), issue.status_was | |
2600 | end |
|
2600 | end | |
2601 |
|
2601 | |||
2602 | def test_status_was_should_be_reset_on_save |
|
2602 | def test_status_was_should_be_reset_on_save | |
2603 | issue = Issue.find(1) |
|
2603 | issue = Issue.find(1) | |
2604 | issue.status = IssueStatus.find(2) |
|
2604 | issue.status = IssueStatus.find(2) | |
2605 | assert_equal IssueStatus.find(1), issue.status_was |
|
2605 | assert_equal IssueStatus.find(1), issue.status_was | |
2606 | assert issue.save! |
|
2606 | assert issue.save! | |
2607 | assert_equal IssueStatus.find(2), issue.status_was |
|
2607 | assert_equal IssueStatus.find(2), issue.status_was | |
2608 | end |
|
2608 | end | |
2609 |
|
2609 | |||
2610 | def test_closing_should_return_true_when_closing_an_issue |
|
2610 | def test_closing_should_return_true_when_closing_an_issue | |
2611 | issue = Issue.find(1) |
|
2611 | issue = Issue.find(1) | |
2612 | issue.status = IssueStatus.find(2) |
|
2612 | issue.status = IssueStatus.find(2) | |
2613 | assert_equal false, issue.closing? |
|
2613 | assert_equal false, issue.closing? | |
2614 | issue.status = IssueStatus.find(5) |
|
2614 | issue.status = IssueStatus.find(5) | |
2615 | assert_equal true, issue.closing? |
|
2615 | assert_equal true, issue.closing? | |
2616 | end |
|
2616 | end | |
2617 |
|
2617 | |||
2618 | def test_closing_should_return_true_when_closing_an_issue_with_status_id |
|
2618 | def test_closing_should_return_true_when_closing_an_issue_with_status_id | |
2619 | issue = Issue.find(1) |
|
2619 | issue = Issue.find(1) | |
2620 | issue.status_id = 2 |
|
2620 | issue.status_id = 2 | |
2621 | assert_equal false, issue.closing? |
|
2621 | assert_equal false, issue.closing? | |
2622 | issue.status_id = 5 |
|
2622 | issue.status_id = 5 | |
2623 | assert_equal true, issue.closing? |
|
2623 | assert_equal true, issue.closing? | |
2624 | end |
|
2624 | end | |
2625 |
|
2625 | |||
2626 | def test_closing_should_return_true_for_new_closed_issue |
|
2626 | def test_closing_should_return_true_for_new_closed_issue | |
2627 | issue = Issue.new |
|
2627 | issue = Issue.new | |
2628 | assert_equal false, issue.closing? |
|
2628 | assert_equal false, issue.closing? | |
2629 | issue.status = IssueStatus.find(5) |
|
2629 | issue.status = IssueStatus.find(5) | |
2630 | assert_equal true, issue.closing? |
|
2630 | assert_equal true, issue.closing? | |
2631 | end |
|
2631 | end | |
2632 |
|
2632 | |||
2633 | def test_closing_should_return_true_for_new_closed_issue_with_status_id |
|
2633 | def test_closing_should_return_true_for_new_closed_issue_with_status_id | |
2634 | issue = Issue.new |
|
2634 | issue = Issue.new | |
2635 | assert_equal false, issue.closing? |
|
2635 | assert_equal false, issue.closing? | |
2636 | issue.status_id = 5 |
|
2636 | issue.status_id = 5 | |
2637 | assert_equal true, issue.closing? |
|
2637 | assert_equal true, issue.closing? | |
2638 | end |
|
2638 | end | |
2639 |
|
2639 | |||
2640 | def test_closing_should_be_reset_after_save |
|
2640 | def test_closing_should_be_reset_after_save | |
2641 | issue = Issue.find(1) |
|
2641 | issue = Issue.find(1) | |
2642 | issue.status_id = 5 |
|
2642 | issue.status_id = 5 | |
2643 | assert_equal true, issue.closing? |
|
2643 | assert_equal true, issue.closing? | |
2644 | issue.save! |
|
2644 | issue.save! | |
2645 | assert_equal false, issue.closing? |
|
2645 | assert_equal false, issue.closing? | |
2646 | end |
|
2646 | end | |
2647 |
|
2647 | |||
2648 | def test_reopening_should_return_true_when_reopening_an_issue |
|
2648 | def test_reopening_should_return_true_when_reopening_an_issue | |
2649 | issue = Issue.find(8) |
|
2649 | issue = Issue.find(8) | |
2650 | issue.status = IssueStatus.find(6) |
|
2650 | issue.status = IssueStatus.find(6) | |
2651 | assert_equal false, issue.reopening? |
|
2651 | assert_equal false, issue.reopening? | |
2652 | issue.status = IssueStatus.find(2) |
|
2652 | issue.status = IssueStatus.find(2) | |
2653 | assert_equal true, issue.reopening? |
|
2653 | assert_equal true, issue.reopening? | |
2654 | end |
|
2654 | end | |
2655 |
|
2655 | |||
2656 | def test_reopening_should_return_true_when_reopening_an_issue_with_status_id |
|
2656 | def test_reopening_should_return_true_when_reopening_an_issue_with_status_id | |
2657 | issue = Issue.find(8) |
|
2657 | issue = Issue.find(8) | |
2658 | issue.status_id = 6 |
|
2658 | issue.status_id = 6 | |
2659 | assert_equal false, issue.reopening? |
|
2659 | assert_equal false, issue.reopening? | |
2660 | issue.status_id = 2 |
|
2660 | issue.status_id = 2 | |
2661 | assert_equal true, issue.reopening? |
|
2661 | assert_equal true, issue.reopening? | |
2662 | end |
|
2662 | end | |
2663 |
|
2663 | |||
2664 | def test_reopening_should_return_false_for_new_open_issue |
|
2664 | def test_reopening_should_return_false_for_new_open_issue | |
2665 | issue = Issue.new |
|
2665 | issue = Issue.new | |
2666 | issue.status = IssueStatus.find(1) |
|
2666 | issue.status = IssueStatus.find(1) | |
2667 | assert_equal false, issue.reopening? |
|
2667 | assert_equal false, issue.reopening? | |
2668 | end |
|
2668 | end | |
2669 |
|
2669 | |||
2670 | def test_reopening_should_be_reset_after_save |
|
2670 | def test_reopening_should_be_reset_after_save | |
2671 | issue = Issue.find(8) |
|
2671 | issue = Issue.find(8) | |
2672 | issue.status_id = 2 |
|
2672 | issue.status_id = 2 | |
2673 | assert_equal true, issue.reopening? |
|
2673 | assert_equal true, issue.reopening? | |
2674 | issue.save! |
|
2674 | issue.save! | |
2675 | assert_equal false, issue.reopening? |
|
2675 | assert_equal false, issue.reopening? | |
2676 | end |
|
2676 | end | |
2677 |
|
2677 | |||
2678 | def test_default_status_without_tracker_should_be_nil |
|
2678 | def test_default_status_without_tracker_should_be_nil | |
2679 | issue = Issue.new |
|
2679 | issue = Issue.new | |
2680 | assert_nil issue.tracker |
|
2680 | assert_nil issue.tracker | |
2681 | assert_nil issue.default_status |
|
2681 | assert_nil issue.default_status | |
2682 | end |
|
2682 | end | |
2683 |
|
2683 | |||
2684 | def test_default_status_should_be_tracker_default_status |
|
2684 | def test_default_status_should_be_tracker_default_status | |
2685 | issue = Issue.new(:tracker_id => 1) |
|
2685 | issue = Issue.new(:tracker_id => 1) | |
2686 | assert_not_nil issue.status |
|
2686 | assert_not_nil issue.status | |
2687 | assert_equal issue.tracker.default_status, issue.default_status |
|
2687 | assert_equal issue.tracker.default_status, issue.default_status | |
2688 | end |
|
2688 | end | |
2689 |
|
2689 | |||
2690 | def test_initializing_with_tracker_should_set_default_status |
|
2690 | def test_initializing_with_tracker_should_set_default_status | |
2691 | issue = Issue.new(:tracker => Tracker.find(1)) |
|
2691 | issue = Issue.new(:tracker => Tracker.find(1)) | |
2692 | assert_not_nil issue.status |
|
2692 | assert_not_nil issue.status | |
2693 | assert_equal issue.default_status, issue.status |
|
2693 | assert_equal issue.default_status, issue.status | |
2694 | end |
|
2694 | end | |
2695 |
|
2695 | |||
2696 | def test_initializing_with_tracker_id_should_set_default_status |
|
2696 | def test_initializing_with_tracker_id_should_set_default_status | |
2697 | issue = Issue.new(:tracker_id => 1) |
|
2697 | issue = Issue.new(:tracker_id => 1) | |
2698 | assert_not_nil issue.status |
|
2698 | assert_not_nil issue.status | |
2699 | assert_equal issue.default_status, issue.status |
|
2699 | assert_equal issue.default_status, issue.status | |
2700 | end |
|
2700 | end | |
2701 |
|
2701 | |||
2702 | def test_setting_tracker_should_set_default_status |
|
2702 | def test_setting_tracker_should_set_default_status | |
2703 | issue = Issue.new |
|
2703 | issue = Issue.new | |
2704 | issue.tracker = Tracker.find(1) |
|
2704 | issue.tracker = Tracker.find(1) | |
2705 | assert_not_nil issue.status |
|
2705 | assert_not_nil issue.status | |
2706 | assert_equal issue.default_status, issue.status |
|
2706 | assert_equal issue.default_status, issue.status | |
2707 | end |
|
2707 | end | |
2708 |
|
2708 | |||
2709 | def test_changing_tracker_should_set_default_status_if_status_was_default |
|
2709 | def test_changing_tracker_should_set_default_status_if_status_was_default | |
2710 | WorkflowTransition.delete_all |
|
2710 | WorkflowTransition.delete_all | |
2711 | WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1 |
|
2711 | WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1 | |
2712 | Tracker.find(2).update! :default_status_id => 2 |
|
2712 | Tracker.find(2).update! :default_status_id => 2 | |
2713 |
|
2713 | |||
2714 | issue = Issue.new(:tracker_id => 1, :status_id => 1) |
|
2714 | issue = Issue.new(:tracker_id => 1, :status_id => 1) | |
2715 | assert_equal IssueStatus.find(1), issue.status |
|
2715 | assert_equal IssueStatus.find(1), issue.status | |
2716 | issue.tracker = Tracker.find(2) |
|
2716 | issue.tracker = Tracker.find(2) | |
2717 | assert_equal IssueStatus.find(2), issue.status |
|
2717 | assert_equal IssueStatus.find(2), issue.status | |
2718 | end |
|
2718 | end | |
2719 |
|
2719 | |||
2720 | def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker |
|
2720 | def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker | |
2721 | WorkflowTransition.delete_all |
|
2721 | WorkflowTransition.delete_all | |
2722 | Tracker.find(2).update! :default_status_id => 2 |
|
2722 | Tracker.find(2).update! :default_status_id => 2 | |
2723 |
|
2723 | |||
2724 | issue = Issue.new(:tracker_id => 1, :status_id => 3) |
|
2724 | issue = Issue.new(:tracker_id => 1, :status_id => 3) | |
2725 | assert_equal IssueStatus.find(3), issue.status |
|
2725 | assert_equal IssueStatus.find(3), issue.status | |
2726 | issue.tracker = Tracker.find(2) |
|
2726 | issue.tracker = Tracker.find(2) | |
2727 | assert_equal IssueStatus.find(2), issue.status |
|
2727 | assert_equal IssueStatus.find(2), issue.status | |
2728 | end |
|
2728 | end | |
2729 |
|
2729 | |||
2730 | def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker |
|
2730 | def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker | |
2731 | WorkflowTransition.delete_all |
|
2731 | WorkflowTransition.delete_all | |
2732 | WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3 |
|
2732 | WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3 | |
2733 | Tracker.find(2).update! :default_status_id => 2 |
|
2733 | Tracker.find(2).update! :default_status_id => 2 | |
2734 |
|
2734 | |||
2735 | issue = Issue.new(:tracker_id => 1, :status_id => 3) |
|
2735 | issue = Issue.new(:tracker_id => 1, :status_id => 3) | |
2736 | assert_equal IssueStatus.find(3), issue.status |
|
2736 | assert_equal IssueStatus.find(3), issue.status | |
2737 | issue.tracker = Tracker.find(2) |
|
2737 | issue.tracker = Tracker.find(2) | |
2738 | assert_equal IssueStatus.find(3), issue.status |
|
2738 | assert_equal IssueStatus.find(3), issue.status | |
2739 | end |
|
2739 | end | |
2740 |
|
2740 | |||
2741 | def test_assigned_to_was_with_a_group |
|
2741 | def test_assigned_to_was_with_a_group | |
2742 | group = Group.find(10) |
|
2742 | group = Group.find(10) | |
2743 |
|
2743 | |||
2744 | issue = Issue.generate!(:assigned_to => group) |
|
2744 | issue = Issue.generate!(:assigned_to => group) | |
2745 | issue.reload.assigned_to = nil |
|
2745 | issue.reload.assigned_to = nil | |
2746 | assert_equal group, issue.assigned_to_was |
|
2746 | assert_equal group, issue.assigned_to_was | |
2747 | end |
|
2747 | end | |
2748 | end |
|
2748 | end |
@@ -1,1084 +1,1084 | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | # |
|
2 | # | |
3 | # Redmine - project management software |
|
3 | # Redmine - project management software | |
4 | # Copyright (C) 2006-2016 Jean-Philippe Lang |
|
4 | # Copyright (C) 2006-2016 Jean-Philippe Lang | |
5 | # |
|
5 | # | |
6 | # This program is free software; you can redistribute it and/or |
|
6 | # This program is free software; you can redistribute it and/or | |
7 | # modify it under the terms of the GNU General Public License |
|
7 | # modify it under the terms of the GNU General Public License | |
8 | # as published by the Free Software Foundation; either version 2 |
|
8 | # as published by the Free Software Foundation; either version 2 | |
9 | # of the License, or (at your option) any later version. |
|
9 | # of the License, or (at your option) any later version. | |
10 | # |
|
10 | # | |
11 | # This program is distributed in the hope that it will be useful, |
|
11 | # This program is distributed in the hope that it will be useful, | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | # GNU General Public License for more details. |
|
14 | # GNU General Public License for more details. | |
15 | # |
|
15 | # | |
16 | # You should have received a copy of the GNU General Public License |
|
16 | # You should have received a copy of the GNU General Public License | |
17 | # along with this program; if not, write to the Free Software |
|
17 | # along with this program; if not, write to the Free Software | |
18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 |
|
19 | |||
20 | require File.expand_path('../../test_helper', __FILE__) |
|
20 | require File.expand_path('../../test_helper', __FILE__) | |
21 |
|
21 | |||
22 | class MailHandlerTest < ActiveSupport::TestCase |
|
22 | class MailHandlerTest < ActiveSupport::TestCase | |
23 | fixtures :users, :projects, :enabled_modules, :roles, |
|
23 | fixtures :users, :projects, :enabled_modules, :roles, | |
24 | :members, :member_roles, :users, |
|
24 | :members, :member_roles, :users, | |
25 | :email_addresses, |
|
25 | :email_addresses, :user_preferences, | |
26 | :issues, :issue_statuses, |
|
26 | :issues, :issue_statuses, | |
27 | :workflows, :trackers, :projects_trackers, |
|
27 | :workflows, :trackers, :projects_trackers, | |
28 | :versions, :enumerations, :issue_categories, |
|
28 | :versions, :enumerations, :issue_categories, | |
29 | :custom_fields, :custom_fields_trackers, :custom_fields_projects, |
|
29 | :custom_fields, :custom_fields_trackers, :custom_fields_projects, | |
30 | :boards, :messages |
|
30 | :boards, :messages | |
31 |
|
31 | |||
32 | FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler' |
|
32 | FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler' | |
33 |
|
33 | |||
34 | def setup |
|
34 | def setup | |
35 | ActionMailer::Base.deliveries.clear |
|
35 | ActionMailer::Base.deliveries.clear | |
36 | Setting.notified_events = Redmine::Notifiable.all.collect(&:name) |
|
36 | Setting.notified_events = Redmine::Notifiable.all.collect(&:name) | |
37 | end |
|
37 | end | |
38 |
|
38 | |||
39 | def teardown |
|
39 | def teardown | |
40 | Setting.clear_cache |
|
40 | Setting.clear_cache | |
41 | end |
|
41 | end | |
42 |
|
42 | |||
43 | def test_add_issue_with_specific_overrides |
|
43 | def test_add_issue_with_specific_overrides | |
44 | issue = submit_email('ticket_on_given_project.eml', |
|
44 | issue = submit_email('ticket_on_given_project.eml', | |
45 | :allow_override => ['status', 'start_date', 'due_date', 'assigned_to', 'fixed_version', 'estimated_hours', 'done_ratio'] |
|
45 | :allow_override => ['status', 'start_date', 'due_date', 'assigned_to', 'fixed_version', 'estimated_hours', 'done_ratio'] | |
46 | ) |
|
46 | ) | |
47 | assert issue.is_a?(Issue) |
|
47 | assert issue.is_a?(Issue) | |
48 | assert !issue.new_record? |
|
48 | assert !issue.new_record? | |
49 | issue.reload |
|
49 | issue.reload | |
50 | assert_equal Project.find(2), issue.project |
|
50 | assert_equal Project.find(2), issue.project | |
51 | assert_equal issue.project.trackers.first, issue.tracker |
|
51 | assert_equal issue.project.trackers.first, issue.tracker | |
52 | assert_equal 'New ticket on a given project', issue.subject |
|
52 | assert_equal 'New ticket on a given project', issue.subject | |
53 | assert_equal User.find_by_login('jsmith'), issue.author |
|
53 | assert_equal User.find_by_login('jsmith'), issue.author | |
54 | assert_equal IssueStatus.find_by_name('Resolved'), issue.status |
|
54 | assert_equal IssueStatus.find_by_name('Resolved'), issue.status | |
55 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
55 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
56 | assert_equal '2010-01-01', issue.start_date.to_s |
|
56 | assert_equal '2010-01-01', issue.start_date.to_s | |
57 | assert_equal '2010-12-31', issue.due_date.to_s |
|
57 | assert_equal '2010-12-31', issue.due_date.to_s | |
58 | assert_equal User.find_by_login('jsmith'), issue.assigned_to |
|
58 | assert_equal User.find_by_login('jsmith'), issue.assigned_to | |
59 | assert_equal Version.find_by_name('Alpha'), issue.fixed_version |
|
59 | assert_equal Version.find_by_name('Alpha'), issue.fixed_version | |
60 | assert_equal 2.5, issue.estimated_hours |
|
60 | assert_equal 2.5, issue.estimated_hours | |
61 | assert_equal 30, issue.done_ratio |
|
61 | assert_equal 30, issue.done_ratio | |
62 | # keywords should be removed from the email body |
|
62 | # keywords should be removed from the email body | |
63 | assert !issue.description.match(/^Project:/i) |
|
63 | assert !issue.description.match(/^Project:/i) | |
64 | assert !issue.description.match(/^Status:/i) |
|
64 | assert !issue.description.match(/^Status:/i) | |
65 | assert !issue.description.match(/^Start Date:/i) |
|
65 | assert !issue.description.match(/^Start Date:/i) | |
66 | end |
|
66 | end | |
67 |
|
67 | |||
68 | def test_add_issue_with_all_overrides |
|
68 | def test_add_issue_with_all_overrides | |
69 | issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all') |
|
69 | issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all') | |
70 | assert issue.is_a?(Issue) |
|
70 | assert issue.is_a?(Issue) | |
71 | assert !issue.new_record? |
|
71 | assert !issue.new_record? | |
72 | issue.reload |
|
72 | issue.reload | |
73 | assert_equal Project.find(2), issue.project |
|
73 | assert_equal Project.find(2), issue.project | |
74 | assert_equal issue.project.trackers.first, issue.tracker |
|
74 | assert_equal issue.project.trackers.first, issue.tracker | |
75 | assert_equal IssueStatus.find_by_name('Resolved'), issue.status |
|
75 | assert_equal IssueStatus.find_by_name('Resolved'), issue.status | |
76 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
76 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
77 | assert_equal '2010-01-01', issue.start_date.to_s |
|
77 | assert_equal '2010-01-01', issue.start_date.to_s | |
78 | assert_equal '2010-12-31', issue.due_date.to_s |
|
78 | assert_equal '2010-12-31', issue.due_date.to_s | |
79 | assert_equal User.find_by_login('jsmith'), issue.assigned_to |
|
79 | assert_equal User.find_by_login('jsmith'), issue.assigned_to | |
80 | assert_equal Version.find_by_name('Alpha'), issue.fixed_version |
|
80 | assert_equal Version.find_by_name('Alpha'), issue.fixed_version | |
81 | assert_equal 2.5, issue.estimated_hours |
|
81 | assert_equal 2.5, issue.estimated_hours | |
82 | assert_equal 30, issue.done_ratio |
|
82 | assert_equal 30, issue.done_ratio | |
83 | end |
|
83 | end | |
84 |
|
84 | |||
85 | def test_add_issue_without_overrides_should_ignore_attributes |
|
85 | def test_add_issue_without_overrides_should_ignore_attributes | |
86 | WorkflowRule.delete_all |
|
86 | WorkflowRule.delete_all | |
87 | issue = submit_email('ticket_on_given_project.eml') |
|
87 | issue = submit_email('ticket_on_given_project.eml') | |
88 | assert issue.is_a?(Issue) |
|
88 | assert issue.is_a?(Issue) | |
89 | assert !issue.new_record? |
|
89 | assert !issue.new_record? | |
90 | issue.reload |
|
90 | issue.reload | |
91 | assert_equal Project.find(2), issue.project |
|
91 | assert_equal Project.find(2), issue.project | |
92 | assert_equal 'New ticket on a given project', issue.subject |
|
92 | assert_equal 'New ticket on a given project', issue.subject | |
93 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
93 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
94 | assert_equal User.find_by_login('jsmith'), issue.author |
|
94 | assert_equal User.find_by_login('jsmith'), issue.author | |
95 |
|
95 | |||
96 | assert_equal issue.project.trackers.first, issue.tracker |
|
96 | assert_equal issue.project.trackers.first, issue.tracker | |
97 | assert_equal 'New', issue.status.name |
|
97 | assert_equal 'New', issue.status.name | |
98 | assert_not_equal '2010-01-01', issue.start_date.to_s |
|
98 | assert_not_equal '2010-01-01', issue.start_date.to_s | |
99 | assert_nil issue.due_date |
|
99 | assert_nil issue.due_date | |
100 | assert_nil issue.assigned_to |
|
100 | assert_nil issue.assigned_to | |
101 | assert_nil issue.fixed_version |
|
101 | assert_nil issue.fixed_version | |
102 | assert_nil issue.estimated_hours |
|
102 | assert_nil issue.estimated_hours | |
103 | assert_equal 0, issue.done_ratio |
|
103 | assert_equal 0, issue.done_ratio | |
104 | end |
|
104 | end | |
105 |
|
105 | |||
106 | def test_add_issue_to_project_specified_by_subaddress |
|
106 | def test_add_issue_to_project_specified_by_subaddress | |
107 | # This email has redmine+onlinestore@somenet.foo as 'To' header |
|
107 | # This email has redmine+onlinestore@somenet.foo as 'To' header | |
108 | issue = submit_email( |
|
108 | issue = submit_email( | |
109 | 'ticket_on_project_given_by_to_header.eml', |
|
109 | 'ticket_on_project_given_by_to_header.eml', | |
110 | :issue => {:tracker => 'Support request'}, |
|
110 | :issue => {:tracker => 'Support request'}, | |
111 | :project_from_subaddress => 'redmine@somenet.foo' |
|
111 | :project_from_subaddress => 'redmine@somenet.foo' | |
112 | ) |
|
112 | ) | |
113 | assert issue.is_a?(Issue) |
|
113 | assert issue.is_a?(Issue) | |
114 | assert !issue.new_record? |
|
114 | assert !issue.new_record? | |
115 | issue.reload |
|
115 | issue.reload | |
116 | assert_equal 'onlinestore', issue.project.identifier |
|
116 | assert_equal 'onlinestore', issue.project.identifier | |
117 | assert_equal 'Support request', issue.tracker.name |
|
117 | assert_equal 'Support request', issue.tracker.name | |
118 | end |
|
118 | end | |
119 |
|
119 | |||
120 | def test_add_issue_with_default_tracker |
|
120 | def test_add_issue_with_default_tracker | |
121 | # This email contains: 'Project: onlinestore' |
|
121 | # This email contains: 'Project: onlinestore' | |
122 | issue = submit_email( |
|
122 | issue = submit_email( | |
123 | 'ticket_on_given_project.eml', |
|
123 | 'ticket_on_given_project.eml', | |
124 | :issue => {:tracker => 'Support request'} |
|
124 | :issue => {:tracker => 'Support request'} | |
125 | ) |
|
125 | ) | |
126 | assert issue.is_a?(Issue) |
|
126 | assert issue.is_a?(Issue) | |
127 | assert !issue.new_record? |
|
127 | assert !issue.new_record? | |
128 | issue.reload |
|
128 | issue.reload | |
129 | assert_equal 'Support request', issue.tracker.name |
|
129 | assert_equal 'Support request', issue.tracker.name | |
130 | end |
|
130 | end | |
131 |
|
131 | |||
132 | def test_add_issue_with_default_version |
|
132 | def test_add_issue_with_default_version | |
133 | # This email contains: 'Project: onlinestore' |
|
133 | # This email contains: 'Project: onlinestore' | |
134 | issue = submit_email( |
|
134 | issue = submit_email( | |
135 | 'ticket_on_given_project.eml', |
|
135 | 'ticket_on_given_project.eml', | |
136 | :issue => {:fixed_version => 'Alpha'} |
|
136 | :issue => {:fixed_version => 'Alpha'} | |
137 | ) |
|
137 | ) | |
138 | assert issue.is_a?(Issue) |
|
138 | assert issue.is_a?(Issue) | |
139 | assert !issue.new_record? |
|
139 | assert !issue.new_record? | |
140 | assert_equal 'Alpha', issue.reload.fixed_version.name |
|
140 | assert_equal 'Alpha', issue.reload.fixed_version.name | |
141 | end |
|
141 | end | |
142 |
|
142 | |||
143 | def test_add_issue_with_status_override |
|
143 | def test_add_issue_with_status_override | |
144 | # This email contains: 'Project: onlinestore' and 'Status: Resolved' |
|
144 | # This email contains: 'Project: onlinestore' and 'Status: Resolved' | |
145 | issue = submit_email('ticket_on_given_project.eml', :allow_override => ['status']) |
|
145 | issue = submit_email('ticket_on_given_project.eml', :allow_override => ['status']) | |
146 | assert issue.is_a?(Issue) |
|
146 | assert issue.is_a?(Issue) | |
147 | assert !issue.new_record? |
|
147 | assert !issue.new_record? | |
148 | issue.reload |
|
148 | issue.reload | |
149 | assert_equal Project.find(2), issue.project |
|
149 | assert_equal Project.find(2), issue.project | |
150 | assert_equal IssueStatus.find_by_name("Resolved"), issue.status |
|
150 | assert_equal IssueStatus.find_by_name("Resolved"), issue.status | |
151 | end |
|
151 | end | |
152 |
|
152 | |||
153 | def test_add_issue_should_accept_is_private_attribute |
|
153 | def test_add_issue_should_accept_is_private_attribute | |
154 | issue = submit_email('ticket_on_given_project.eml', :issue => {:is_private => '1'}) |
|
154 | issue = submit_email('ticket_on_given_project.eml', :issue => {:is_private => '1'}) | |
155 | assert issue.is_a?(Issue) |
|
155 | assert issue.is_a?(Issue) | |
156 | assert !issue.new_record? |
|
156 | assert !issue.new_record? | |
157 | assert_equal true, issue.reload.is_private |
|
157 | assert_equal true, issue.reload.is_private | |
158 | end |
|
158 | end | |
159 |
|
159 | |||
160 | def test_add_issue_with_group_assignment |
|
160 | def test_add_issue_with_group_assignment | |
161 | with_settings :issue_group_assignment => '1' do |
|
161 | with_settings :issue_group_assignment => '1' do | |
162 | issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email| |
|
162 | issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email| | |
163 | email.gsub!('Assigned to: John Smith', 'Assigned to: B Team') |
|
163 | email.gsub!('Assigned to: John Smith', 'Assigned to: B Team') | |
164 | end |
|
164 | end | |
165 | assert issue.is_a?(Issue) |
|
165 | assert issue.is_a?(Issue) | |
166 | assert !issue.new_record? |
|
166 | assert !issue.new_record? | |
167 | issue.reload |
|
167 | issue.reload | |
168 | assert_equal Group.find(11), issue.assigned_to |
|
168 | assert_equal Group.find(11), issue.assigned_to | |
169 | end |
|
169 | end | |
170 | end |
|
170 | end | |
171 |
|
171 | |||
172 | def test_add_issue_with_partial_attributes_override |
|
172 | def test_add_issue_with_partial_attributes_override | |
173 | issue = submit_email( |
|
173 | issue = submit_email( | |
174 | 'ticket_with_attributes.eml', |
|
174 | 'ticket_with_attributes.eml', | |
175 | :issue => {:priority => 'High'}, |
|
175 | :issue => {:priority => 'High'}, | |
176 | :allow_override => ['tracker'] |
|
176 | :allow_override => ['tracker'] | |
177 | ) |
|
177 | ) | |
178 | assert issue.is_a?(Issue) |
|
178 | assert issue.is_a?(Issue) | |
179 | assert !issue.new_record? |
|
179 | assert !issue.new_record? | |
180 | issue.reload |
|
180 | issue.reload | |
181 | assert_equal 'New ticket on a given project', issue.subject |
|
181 | assert_equal 'New ticket on a given project', issue.subject | |
182 | assert_equal User.find_by_login('jsmith'), issue.author |
|
182 | assert_equal User.find_by_login('jsmith'), issue.author | |
183 | assert_equal Project.find(2), issue.project |
|
183 | assert_equal Project.find(2), issue.project | |
184 | assert_equal 'Feature request', issue.tracker.to_s |
|
184 | assert_equal 'Feature request', issue.tracker.to_s | |
185 | assert_nil issue.category |
|
185 | assert_nil issue.category | |
186 | assert_equal 'High', issue.priority.to_s |
|
186 | assert_equal 'High', issue.priority.to_s | |
187 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
187 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
188 | end |
|
188 | end | |
189 |
|
189 | |||
190 | def test_add_issue_with_spaces_between_attribute_and_separator |
|
190 | def test_add_issue_with_spaces_between_attribute_and_separator | |
191 | issue = submit_email( |
|
191 | issue = submit_email( | |
192 | 'ticket_with_spaces_between_attribute_and_separator.eml', |
|
192 | 'ticket_with_spaces_between_attribute_and_separator.eml', | |
193 | :allow_override => 'tracker,category,priority' |
|
193 | :allow_override => 'tracker,category,priority' | |
194 | ) |
|
194 | ) | |
195 | assert issue.is_a?(Issue) |
|
195 | assert issue.is_a?(Issue) | |
196 | assert !issue.new_record? |
|
196 | assert !issue.new_record? | |
197 | issue.reload |
|
197 | issue.reload | |
198 | assert_equal 'New ticket on a given project', issue.subject |
|
198 | assert_equal 'New ticket on a given project', issue.subject | |
199 | assert_equal User.find_by_login('jsmith'), issue.author |
|
199 | assert_equal User.find_by_login('jsmith'), issue.author | |
200 | assert_equal Project.find(2), issue.project |
|
200 | assert_equal Project.find(2), issue.project | |
201 | assert_equal 'Feature request', issue.tracker.to_s |
|
201 | assert_equal 'Feature request', issue.tracker.to_s | |
202 | assert_equal 'Stock management', issue.category.to_s |
|
202 | assert_equal 'Stock management', issue.category.to_s | |
203 | assert_equal 'Urgent', issue.priority.to_s |
|
203 | assert_equal 'Urgent', issue.priority.to_s | |
204 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
204 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
205 | end |
|
205 | end | |
206 |
|
206 | |||
207 | def test_add_issue_with_attachment_to_specific_project |
|
207 | def test_add_issue_with_attachment_to_specific_project | |
208 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) |
|
208 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) | |
209 | assert issue.is_a?(Issue) |
|
209 | assert issue.is_a?(Issue) | |
210 | assert !issue.new_record? |
|
210 | assert !issue.new_record? | |
211 | issue.reload |
|
211 | issue.reload | |
212 | assert_equal 'Ticket created by email with attachment', issue.subject |
|
212 | assert_equal 'Ticket created by email with attachment', issue.subject | |
213 | assert_equal User.find_by_login('jsmith'), issue.author |
|
213 | assert_equal User.find_by_login('jsmith'), issue.author | |
214 | assert_equal Project.find(2), issue.project |
|
214 | assert_equal Project.find(2), issue.project | |
215 | assert_equal 'This is a new ticket with attachments', issue.description |
|
215 | assert_equal 'This is a new ticket with attachments', issue.description | |
216 | # Attachment properties |
|
216 | # Attachment properties | |
217 | assert_equal 1, issue.attachments.size |
|
217 | assert_equal 1, issue.attachments.size | |
218 | assert_equal 'Paella.jpg', issue.attachments.first.filename |
|
218 | assert_equal 'Paella.jpg', issue.attachments.first.filename | |
219 | assert_equal 'image/jpeg', issue.attachments.first.content_type |
|
219 | assert_equal 'image/jpeg', issue.attachments.first.content_type | |
220 | assert_equal 10790, issue.attachments.first.filesize |
|
220 | assert_equal 10790, issue.attachments.first.filesize | |
221 | end |
|
221 | end | |
222 |
|
222 | |||
223 | def test_add_issue_with_custom_fields |
|
223 | def test_add_issue_with_custom_fields | |
224 | issue = submit_email('ticket_with_custom_fields.eml', |
|
224 | issue = submit_email('ticket_with_custom_fields.eml', | |
225 | :issue => {:project => 'onlinestore'}, :allow_override => ['database', 'Searchable_field'] |
|
225 | :issue => {:project => 'onlinestore'}, :allow_override => ['database', 'Searchable_field'] | |
226 | ) |
|
226 | ) | |
227 | assert issue.is_a?(Issue) |
|
227 | assert issue.is_a?(Issue) | |
228 | assert !issue.new_record? |
|
228 | assert !issue.new_record? | |
229 | issue.reload |
|
229 | issue.reload | |
230 | assert_equal 'New ticket with custom field values', issue.subject |
|
230 | assert_equal 'New ticket with custom field values', issue.subject | |
231 | assert_equal 'PostgreSQL', issue.custom_field_value(1) |
|
231 | assert_equal 'PostgreSQL', issue.custom_field_value(1) | |
232 | assert_equal 'Value for a custom field', issue.custom_field_value(2) |
|
232 | assert_equal 'Value for a custom field', issue.custom_field_value(2) | |
233 | assert !issue.description.match(/^searchable field:/i) |
|
233 | assert !issue.description.match(/^searchable field:/i) | |
234 | end |
|
234 | end | |
235 |
|
235 | |||
236 | def test_add_issue_with_version_custom_fields |
|
236 | def test_add_issue_with_version_custom_fields | |
237 | field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3]) |
|
237 | field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3]) | |
238 |
|
238 | |||
239 | issue = submit_email('ticket_with_custom_fields.eml', |
|
239 | issue = submit_email('ticket_with_custom_fields.eml', | |
240 | :issue => {:project => 'ecookbook'}, :allow_override => ['affected version'] |
|
240 | :issue => {:project => 'ecookbook'}, :allow_override => ['affected version'] | |
241 | ) do |email| |
|
241 | ) do |email| | |
242 | email << "Affected version: 1.0\n" |
|
242 | email << "Affected version: 1.0\n" | |
243 | end |
|
243 | end | |
244 | assert issue.is_a?(Issue) |
|
244 | assert issue.is_a?(Issue) | |
245 | assert !issue.new_record? |
|
245 | assert !issue.new_record? | |
246 | issue.reload |
|
246 | issue.reload | |
247 | assert_equal '2', issue.custom_field_value(field) |
|
247 | assert_equal '2', issue.custom_field_value(field) | |
248 | end |
|
248 | end | |
249 |
|
249 | |||
250 | def test_add_issue_should_match_assignee_on_display_name |
|
250 | def test_add_issue_should_match_assignee_on_display_name | |
251 | user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz') |
|
251 | user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz') | |
252 | User.add_to_project(user, Project.find(2)) |
|
252 | User.add_to_project(user, Project.find(2)) | |
253 | issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email| |
|
253 | issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email| | |
254 | email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz') |
|
254 | email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz') | |
255 | end |
|
255 | end | |
256 | assert issue.is_a?(Issue) |
|
256 | assert issue.is_a?(Issue) | |
257 | assert_equal user, issue.assigned_to |
|
257 | assert_equal user, issue.assigned_to | |
258 | end |
|
258 | end | |
259 |
|
259 | |||
260 | def test_add_issue_should_set_default_start_date |
|
260 | def test_add_issue_should_set_default_start_date | |
261 | with_settings :default_issue_start_date_to_creation_date => '1' do |
|
261 | with_settings :default_issue_start_date_to_creation_date => '1' do | |
262 | issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'}) |
|
262 | issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'}) | |
263 | assert issue.is_a?(Issue) |
|
263 | assert issue.is_a?(Issue) | |
264 | assert_equal Date.today, issue.start_date |
|
264 | assert_equal Date.today, issue.start_date | |
265 | end |
|
265 | end | |
266 | end |
|
266 | end | |
267 |
|
267 | |||
268 | def test_add_issue_should_add_cc_as_watchers |
|
268 | def test_add_issue_should_add_cc_as_watchers | |
269 | issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'}) |
|
269 | issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'}) | |
270 | assert issue.is_a?(Issue) |
|
270 | assert issue.is_a?(Issue) | |
271 | assert !issue.new_record? |
|
271 | assert !issue.new_record? | |
272 | issue.reload |
|
272 | issue.reload | |
273 | assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo')) |
|
273 | assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo')) | |
274 | assert_equal 1, issue.watcher_user_ids.size |
|
274 | assert_equal 1, issue.watcher_user_ids.size | |
275 | end |
|
275 | end | |
276 |
|
276 | |||
277 | def test_add_issue_from_additional_email_address |
|
277 | def test_add_issue_from_additional_email_address | |
278 | user = User.find(2) |
|
278 | user = User.find(2) | |
279 | user.mail = 'mainaddress@somenet.foo' |
|
279 | user.mail = 'mainaddress@somenet.foo' | |
280 | user.save! |
|
280 | user.save! | |
281 | EmailAddress.create!(:user => user, :address => 'jsmith@somenet.foo') |
|
281 | EmailAddress.create!(:user => user, :address => 'jsmith@somenet.foo') | |
282 |
|
282 | |||
283 | issue = submit_email('ticket_on_given_project.eml') |
|
283 | issue = submit_email('ticket_on_given_project.eml') | |
284 | assert issue |
|
284 | assert issue | |
285 | assert_equal user, issue.author |
|
285 | assert_equal user, issue.author | |
286 | end |
|
286 | end | |
287 |
|
287 | |||
288 | def test_add_issue_by_unknown_user |
|
288 | def test_add_issue_by_unknown_user | |
289 | assert_no_difference 'User.count' do |
|
289 | assert_no_difference 'User.count' do | |
290 | assert_equal false, |
|
290 | assert_equal false, | |
291 | submit_email( |
|
291 | submit_email( | |
292 | 'ticket_by_unknown_user.eml', |
|
292 | 'ticket_by_unknown_user.eml', | |
293 | :issue => {:project => 'ecookbook'} |
|
293 | :issue => {:project => 'ecookbook'} | |
294 | ) |
|
294 | ) | |
295 | end |
|
295 | end | |
296 | end |
|
296 | end | |
297 |
|
297 | |||
298 | def test_add_issue_by_anonymous_user |
|
298 | def test_add_issue_by_anonymous_user | |
299 | Role.anonymous.add_permission!(:add_issues) |
|
299 | Role.anonymous.add_permission!(:add_issues) | |
300 | assert_no_difference 'User.count' do |
|
300 | assert_no_difference 'User.count' do | |
301 | issue = submit_email( |
|
301 | issue = submit_email( | |
302 | 'ticket_by_unknown_user.eml', |
|
302 | 'ticket_by_unknown_user.eml', | |
303 | :issue => {:project => 'ecookbook'}, |
|
303 | :issue => {:project => 'ecookbook'}, | |
304 | :unknown_user => 'accept' |
|
304 | :unknown_user => 'accept' | |
305 | ) |
|
305 | ) | |
306 | assert issue.is_a?(Issue) |
|
306 | assert issue.is_a?(Issue) | |
307 | assert issue.author.anonymous? |
|
307 | assert issue.author.anonymous? | |
308 | end |
|
308 | end | |
309 | end |
|
309 | end | |
310 |
|
310 | |||
311 | def test_add_issue_by_anonymous_user_with_no_from_address |
|
311 | def test_add_issue_by_anonymous_user_with_no_from_address | |
312 | Role.anonymous.add_permission!(:add_issues) |
|
312 | Role.anonymous.add_permission!(:add_issues) | |
313 | assert_no_difference 'User.count' do |
|
313 | assert_no_difference 'User.count' do | |
314 | issue = submit_email( |
|
314 | issue = submit_email( | |
315 | 'ticket_by_empty_user.eml', |
|
315 | 'ticket_by_empty_user.eml', | |
316 | :issue => {:project => 'ecookbook'}, |
|
316 | :issue => {:project => 'ecookbook'}, | |
317 | :unknown_user => 'accept' |
|
317 | :unknown_user => 'accept' | |
318 | ) |
|
318 | ) | |
319 | assert issue.is_a?(Issue) |
|
319 | assert issue.is_a?(Issue) | |
320 | assert issue.author.anonymous? |
|
320 | assert issue.author.anonymous? | |
321 | end |
|
321 | end | |
322 | end |
|
322 | end | |
323 |
|
323 | |||
324 | def test_add_issue_by_anonymous_user_on_private_project |
|
324 | def test_add_issue_by_anonymous_user_on_private_project | |
325 | Role.anonymous.add_permission!(:add_issues) |
|
325 | Role.anonymous.add_permission!(:add_issues) | |
326 | assert_no_difference 'User.count' do |
|
326 | assert_no_difference 'User.count' do | |
327 | assert_no_difference 'Issue.count' do |
|
327 | assert_no_difference 'Issue.count' do | |
328 | assert_equal false, |
|
328 | assert_equal false, | |
329 | submit_email( |
|
329 | submit_email( | |
330 | 'ticket_by_unknown_user.eml', |
|
330 | 'ticket_by_unknown_user.eml', | |
331 | :issue => {:project => 'onlinestore'}, |
|
331 | :issue => {:project => 'onlinestore'}, | |
332 | :unknown_user => 'accept' |
|
332 | :unknown_user => 'accept' | |
333 | ) |
|
333 | ) | |
334 | end |
|
334 | end | |
335 | end |
|
335 | end | |
336 | end |
|
336 | end | |
337 |
|
337 | |||
338 | def test_add_issue_by_anonymous_user_on_private_project_without_permission_check |
|
338 | def test_add_issue_by_anonymous_user_on_private_project_without_permission_check | |
339 | assert_no_difference 'User.count' do |
|
339 | assert_no_difference 'User.count' do | |
340 | assert_difference 'Issue.count' do |
|
340 | assert_difference 'Issue.count' do | |
341 | issue = submit_email( |
|
341 | issue = submit_email( | |
342 | 'ticket_by_unknown_user.eml', |
|
342 | 'ticket_by_unknown_user.eml', | |
343 | :issue => {:project => 'onlinestore'}, |
|
343 | :issue => {:project => 'onlinestore'}, | |
344 | :no_permission_check => '1', |
|
344 | :no_permission_check => '1', | |
345 | :unknown_user => 'accept' |
|
345 | :unknown_user => 'accept' | |
346 | ) |
|
346 | ) | |
347 | assert issue.is_a?(Issue) |
|
347 | assert issue.is_a?(Issue) | |
348 | assert issue.author.anonymous? |
|
348 | assert issue.author.anonymous? | |
349 | assert !issue.project.is_public? |
|
349 | assert !issue.project.is_public? | |
350 | end |
|
350 | end | |
351 | end |
|
351 | end | |
352 | end |
|
352 | end | |
353 |
|
353 | |||
354 | def test_add_issue_by_created_user |
|
354 | def test_add_issue_by_created_user | |
355 | Setting.default_language = 'en' |
|
355 | Setting.default_language = 'en' | |
356 | assert_difference 'User.count' do |
|
356 | assert_difference 'User.count' do | |
357 | issue = submit_email( |
|
357 | issue = submit_email( | |
358 | 'ticket_by_unknown_user.eml', |
|
358 | 'ticket_by_unknown_user.eml', | |
359 | :issue => {:project => 'ecookbook'}, |
|
359 | :issue => {:project => 'ecookbook'}, | |
360 | :unknown_user => 'create' |
|
360 | :unknown_user => 'create' | |
361 | ) |
|
361 | ) | |
362 | assert issue.is_a?(Issue) |
|
362 | assert issue.is_a?(Issue) | |
363 | assert issue.author.active? |
|
363 | assert issue.author.active? | |
364 | assert_equal 'john.doe@somenet.foo', issue.author.mail |
|
364 | assert_equal 'john.doe@somenet.foo', issue.author.mail | |
365 | assert_equal 'John', issue.author.firstname |
|
365 | assert_equal 'John', issue.author.firstname | |
366 | assert_equal 'Doe', issue.author.lastname |
|
366 | assert_equal 'Doe', issue.author.lastname | |
367 |
|
367 | |||
368 | # account information |
|
368 | # account information | |
369 | email = ActionMailer::Base.deliveries.first |
|
369 | email = ActionMailer::Base.deliveries.first | |
370 | assert_not_nil email |
|
370 | assert_not_nil email | |
371 | assert email.subject.include?('account activation') |
|
371 | assert email.subject.include?('account activation') | |
372 | login = mail_body(email).match(/\* Login: (.*)$/)[1].strip |
|
372 | login = mail_body(email).match(/\* Login: (.*)$/)[1].strip | |
373 | password = mail_body(email).match(/\* Password: (.*)$/)[1].strip |
|
373 | password = mail_body(email).match(/\* Password: (.*)$/)[1].strip | |
374 | assert_equal issue.author, User.try_to_login(login, password) |
|
374 | assert_equal issue.author, User.try_to_login(login, password) | |
375 | end |
|
375 | end | |
376 | end |
|
376 | end | |
377 |
|
377 | |||
378 | def test_add_issue_should_send_notification |
|
378 | def test_add_issue_should_send_notification | |
379 | issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all') |
|
379 | issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all') | |
380 | assert issue.is_a?(Issue) |
|
380 | assert issue.is_a?(Issue) | |
381 | assert !issue.new_record? |
|
381 | assert !issue.new_record? | |
382 |
|
382 | |||
383 | mail = ActionMailer::Base.deliveries.last |
|
383 | mail = ActionMailer::Base.deliveries.last | |
384 | assert_not_nil mail |
|
384 | assert_not_nil mail | |
385 | assert mail.subject.include?("##{issue.id}") |
|
385 | assert mail.subject.include?("##{issue.id}") | |
386 | assert mail.subject.include?('New ticket on a given project') |
|
386 | assert mail.subject.include?('New ticket on a given project') | |
387 | end |
|
387 | end | |
388 |
|
388 | |||
389 | def test_created_user_should_be_added_to_groups |
|
389 | def test_created_user_should_be_added_to_groups | |
390 | group1 = Group.generate! |
|
390 | group1 = Group.generate! | |
391 | group2 = Group.generate! |
|
391 | group2 = Group.generate! | |
392 |
|
392 | |||
393 | assert_difference 'User.count' do |
|
393 | assert_difference 'User.count' do | |
394 | submit_email( |
|
394 | submit_email( | |
395 | 'ticket_by_unknown_user.eml', |
|
395 | 'ticket_by_unknown_user.eml', | |
396 | :issue => {:project => 'ecookbook'}, |
|
396 | :issue => {:project => 'ecookbook'}, | |
397 | :unknown_user => 'create', |
|
397 | :unknown_user => 'create', | |
398 | :default_group => "#{group1.name},#{group2.name}" |
|
398 | :default_group => "#{group1.name},#{group2.name}" | |
399 | ) |
|
399 | ) | |
400 | end |
|
400 | end | |
401 | user = User.order('id DESC').first |
|
401 | user = User.order('id DESC').first | |
402 | assert_equal [group1, group2].sort, user.groups.sort |
|
402 | assert_equal [group1, group2].sort, user.groups.sort | |
403 | end |
|
403 | end | |
404 |
|
404 | |||
405 | def test_created_user_should_not_receive_account_information_with_no_account_info_option |
|
405 | def test_created_user_should_not_receive_account_information_with_no_account_info_option | |
406 | assert_difference 'User.count' do |
|
406 | assert_difference 'User.count' do | |
407 | submit_email( |
|
407 | submit_email( | |
408 | 'ticket_by_unknown_user.eml', |
|
408 | 'ticket_by_unknown_user.eml', | |
409 | :issue => {:project => 'ecookbook'}, |
|
409 | :issue => {:project => 'ecookbook'}, | |
410 | :unknown_user => 'create', |
|
410 | :unknown_user => 'create', | |
411 | :no_account_notice => '1' |
|
411 | :no_account_notice => '1' | |
412 | ) |
|
412 | ) | |
413 | end |
|
413 | end | |
414 |
|
414 | |||
415 | # only 1 email for the new issue notification |
|
415 | # only 1 email for the new issue notification | |
416 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
416 | assert_equal 1, ActionMailer::Base.deliveries.size | |
417 | email = ActionMailer::Base.deliveries.first |
|
417 | email = ActionMailer::Base.deliveries.first | |
418 | assert_include 'Ticket by unknown user', email.subject |
|
418 | assert_include 'Ticket by unknown user', email.subject | |
419 | end |
|
419 | end | |
420 |
|
420 | |||
421 | def test_created_user_should_have_mail_notification_to_none_with_no_notification_option |
|
421 | def test_created_user_should_have_mail_notification_to_none_with_no_notification_option | |
422 | assert_difference 'User.count' do |
|
422 | assert_difference 'User.count' do | |
423 | submit_email( |
|
423 | submit_email( | |
424 | 'ticket_by_unknown_user.eml', |
|
424 | 'ticket_by_unknown_user.eml', | |
425 | :issue => {:project => 'ecookbook'}, |
|
425 | :issue => {:project => 'ecookbook'}, | |
426 | :unknown_user => 'create', |
|
426 | :unknown_user => 'create', | |
427 | :no_notification => '1' |
|
427 | :no_notification => '1' | |
428 | ) |
|
428 | ) | |
429 | end |
|
429 | end | |
430 | user = User.order('id DESC').first |
|
430 | user = User.order('id DESC').first | |
431 | assert_equal 'none', user.mail_notification |
|
431 | assert_equal 'none', user.mail_notification | |
432 | end |
|
432 | end | |
433 |
|
433 | |||
434 | def test_add_issue_without_from_header |
|
434 | def test_add_issue_without_from_header | |
435 | Role.anonymous.add_permission!(:add_issues) |
|
435 | Role.anonymous.add_permission!(:add_issues) | |
436 | assert_equal false, submit_email('ticket_without_from_header.eml') |
|
436 | assert_equal false, submit_email('ticket_without_from_header.eml') | |
437 | end |
|
437 | end | |
438 |
|
438 | |||
439 | def test_add_issue_with_invalid_attributes |
|
439 | def test_add_issue_with_invalid_attributes | |
440 | with_settings :default_issue_start_date_to_creation_date => '0' do |
|
440 | with_settings :default_issue_start_date_to_creation_date => '0' do | |
441 | issue = submit_email( |
|
441 | issue = submit_email( | |
442 | 'ticket_with_invalid_attributes.eml', |
|
442 | 'ticket_with_invalid_attributes.eml', | |
443 | :allow_override => 'tracker,category,priority' |
|
443 | :allow_override => 'tracker,category,priority' | |
444 | ) |
|
444 | ) | |
445 | assert issue.is_a?(Issue) |
|
445 | assert issue.is_a?(Issue) | |
446 | assert !issue.new_record? |
|
446 | assert !issue.new_record? | |
447 | issue.reload |
|
447 | issue.reload | |
448 | assert_nil issue.assigned_to |
|
448 | assert_nil issue.assigned_to | |
449 | assert_nil issue.start_date |
|
449 | assert_nil issue.start_date | |
450 | assert_nil issue.due_date |
|
450 | assert_nil issue.due_date | |
451 | assert_equal 0, issue.done_ratio |
|
451 | assert_equal 0, issue.done_ratio | |
452 | assert_equal 'Normal', issue.priority.to_s |
|
452 | assert_equal 'Normal', issue.priority.to_s | |
453 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
453 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
454 | end |
|
454 | end | |
455 | end |
|
455 | end | |
456 |
|
456 | |||
457 | def test_add_issue_with_invalid_project_should_be_assigned_to_default_project |
|
457 | def test_add_issue_with_invalid_project_should_be_assigned_to_default_project | |
458 | issue = submit_email('ticket_on_given_project.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'project') do |email| |
|
458 | issue = submit_email('ticket_on_given_project.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'project') do |email| | |
459 | email.gsub!(/^Project:.+$/, 'Project: invalid') |
|
459 | email.gsub!(/^Project:.+$/, 'Project: invalid') | |
460 | end |
|
460 | end | |
461 | assert issue.is_a?(Issue) |
|
461 | assert issue.is_a?(Issue) | |
462 | assert !issue.new_record? |
|
462 | assert !issue.new_record? | |
463 | assert_equal 'ecookbook', issue.project.identifier |
|
463 | assert_equal 'ecookbook', issue.project.identifier | |
464 | end |
|
464 | end | |
465 |
|
465 | |||
466 | def test_add_issue_with_localized_attributes |
|
466 | def test_add_issue_with_localized_attributes | |
467 | User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr' |
|
467 | User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr' | |
468 | issue = submit_email( |
|
468 | issue = submit_email( | |
469 | 'ticket_with_localized_attributes.eml', |
|
469 | 'ticket_with_localized_attributes.eml', | |
470 | :allow_override => 'tracker,category,priority' |
|
470 | :allow_override => 'tracker,category,priority' | |
471 | ) |
|
471 | ) | |
472 | assert issue.is_a?(Issue) |
|
472 | assert issue.is_a?(Issue) | |
473 | assert !issue.new_record? |
|
473 | assert !issue.new_record? | |
474 | issue.reload |
|
474 | issue.reload | |
475 | assert_equal 'New ticket on a given project', issue.subject |
|
475 | assert_equal 'New ticket on a given project', issue.subject | |
476 | assert_equal User.find_by_login('jsmith'), issue.author |
|
476 | assert_equal User.find_by_login('jsmith'), issue.author | |
477 | assert_equal Project.find(2), issue.project |
|
477 | assert_equal Project.find(2), issue.project | |
478 | assert_equal 'Feature request', issue.tracker.to_s |
|
478 | assert_equal 'Feature request', issue.tracker.to_s | |
479 | assert_equal 'Stock management', issue.category.to_s |
|
479 | assert_equal 'Stock management', issue.category.to_s | |
480 | assert_equal 'Urgent', issue.priority.to_s |
|
480 | assert_equal 'Urgent', issue.priority.to_s | |
481 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
481 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') | |
482 | end |
|
482 | end | |
483 |
|
483 | |||
484 | def test_add_issue_with_japanese_keywords |
|
484 | def test_add_issue_with_japanese_keywords | |
485 | ja_dev = "\xe9\x96\x8b\xe7\x99\xba".force_encoding('UTF-8') |
|
485 | ja_dev = "\xe9\x96\x8b\xe7\x99\xba".force_encoding('UTF-8') | |
486 | tracker = Tracker.generate!(:name => ja_dev) |
|
486 | tracker = Tracker.generate!(:name => ja_dev) | |
487 | Project.find(1).trackers << tracker |
|
487 | Project.find(1).trackers << tracker | |
488 | issue = submit_email( |
|
488 | issue = submit_email( | |
489 | 'japanese_keywords_iso_2022_jp.eml', |
|
489 | 'japanese_keywords_iso_2022_jp.eml', | |
490 | :issue => {:project => 'ecookbook'}, |
|
490 | :issue => {:project => 'ecookbook'}, | |
491 | :allow_override => 'tracker' |
|
491 | :allow_override => 'tracker' | |
492 | ) |
|
492 | ) | |
493 | assert_kind_of Issue, issue |
|
493 | assert_kind_of Issue, issue | |
494 | assert_equal tracker, issue.tracker |
|
494 | assert_equal tracker, issue.tracker | |
495 | end |
|
495 | end | |
496 |
|
496 | |||
497 | def test_add_issue_from_apple_mail |
|
497 | def test_add_issue_from_apple_mail | |
498 | issue = submit_email( |
|
498 | issue = submit_email( | |
499 | 'apple_mail_with_attachment.eml', |
|
499 | 'apple_mail_with_attachment.eml', | |
500 | :issue => {:project => 'ecookbook'} |
|
500 | :issue => {:project => 'ecookbook'} | |
501 | ) |
|
501 | ) | |
502 | assert_kind_of Issue, issue |
|
502 | assert_kind_of Issue, issue | |
503 | assert_equal 1, issue.attachments.size |
|
503 | assert_equal 1, issue.attachments.size | |
504 |
|
504 | |||
505 | attachment = issue.attachments.first |
|
505 | attachment = issue.attachments.first | |
506 | assert_equal 'paella.jpg', attachment.filename |
|
506 | assert_equal 'paella.jpg', attachment.filename | |
507 | assert_equal 10790, attachment.filesize |
|
507 | assert_equal 10790, attachment.filesize | |
508 | assert File.exist?(attachment.diskfile) |
|
508 | assert File.exist?(attachment.diskfile) | |
509 | assert_equal 10790, File.size(attachment.diskfile) |
|
509 | assert_equal 10790, File.size(attachment.diskfile) | |
510 | assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest |
|
510 | assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest | |
511 | end |
|
511 | end | |
512 |
|
512 | |||
513 | def test_thunderbird_with_attachment_ja |
|
513 | def test_thunderbird_with_attachment_ja | |
514 | issue = submit_email( |
|
514 | issue = submit_email( | |
515 | 'thunderbird_with_attachment_ja.eml', |
|
515 | 'thunderbird_with_attachment_ja.eml', | |
516 | :issue => {:project => 'ecookbook'} |
|
516 | :issue => {:project => 'ecookbook'} | |
517 | ) |
|
517 | ) | |
518 | assert_kind_of Issue, issue |
|
518 | assert_kind_of Issue, issue | |
519 | assert_equal 1, issue.attachments.size |
|
519 | assert_equal 1, issue.attachments.size | |
520 | ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8') |
|
520 | ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8') | |
521 | attachment = issue.attachments.first |
|
521 | attachment = issue.attachments.first | |
522 | assert_equal ja, attachment.filename |
|
522 | assert_equal ja, attachment.filename | |
523 | assert_equal 5, attachment.filesize |
|
523 | assert_equal 5, attachment.filesize | |
524 | assert File.exist?(attachment.diskfile) |
|
524 | assert File.exist?(attachment.diskfile) | |
525 | assert_equal 5, File.size(attachment.diskfile) |
|
525 | assert_equal 5, File.size(attachment.diskfile) | |
526 | assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest |
|
526 | assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest | |
527 | end |
|
527 | end | |
528 |
|
528 | |||
529 | def test_gmail_with_attachment_ja |
|
529 | def test_gmail_with_attachment_ja | |
530 | issue = submit_email( |
|
530 | issue = submit_email( | |
531 | 'gmail_with_attachment_ja.eml', |
|
531 | 'gmail_with_attachment_ja.eml', | |
532 | :issue => {:project => 'ecookbook'} |
|
532 | :issue => {:project => 'ecookbook'} | |
533 | ) |
|
533 | ) | |
534 | assert_kind_of Issue, issue |
|
534 | assert_kind_of Issue, issue | |
535 | assert_equal 1, issue.attachments.size |
|
535 | assert_equal 1, issue.attachments.size | |
536 | ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8') |
|
536 | ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8') | |
537 | attachment = issue.attachments.first |
|
537 | attachment = issue.attachments.first | |
538 | assert_equal ja, attachment.filename |
|
538 | assert_equal ja, attachment.filename | |
539 | assert_equal 5, attachment.filesize |
|
539 | assert_equal 5, attachment.filesize | |
540 | assert File.exist?(attachment.diskfile) |
|
540 | assert File.exist?(attachment.diskfile) | |
541 | assert_equal 5, File.size(attachment.diskfile) |
|
541 | assert_equal 5, File.size(attachment.diskfile) | |
542 | assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest |
|
542 | assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest | |
543 | end |
|
543 | end | |
544 |
|
544 | |||
545 | def test_thunderbird_with_attachment_latin1 |
|
545 | def test_thunderbird_with_attachment_latin1 | |
546 | issue = submit_email( |
|
546 | issue = submit_email( | |
547 | 'thunderbird_with_attachment_iso-8859-1.eml', |
|
547 | 'thunderbird_with_attachment_iso-8859-1.eml', | |
548 | :issue => {:project => 'ecookbook'} |
|
548 | :issue => {:project => 'ecookbook'} | |
549 | ) |
|
549 | ) | |
550 | assert_kind_of Issue, issue |
|
550 | assert_kind_of Issue, issue | |
551 | assert_equal 1, issue.attachments.size |
|
551 | assert_equal 1, issue.attachments.size | |
552 | u = "".force_encoding('UTF-8') |
|
552 | u = "".force_encoding('UTF-8') | |
553 | u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8') |
|
553 | u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8') | |
554 | 11.times { u << u1 } |
|
554 | 11.times { u << u1 } | |
555 | attachment = issue.attachments.first |
|
555 | attachment = issue.attachments.first | |
556 | assert_equal "#{u}.png", attachment.filename |
|
556 | assert_equal "#{u}.png", attachment.filename | |
557 | assert_equal 130, attachment.filesize |
|
557 | assert_equal 130, attachment.filesize | |
558 | assert File.exist?(attachment.diskfile) |
|
558 | assert File.exist?(attachment.diskfile) | |
559 | assert_equal 130, File.size(attachment.diskfile) |
|
559 | assert_equal 130, File.size(attachment.diskfile) | |
560 | assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest |
|
560 | assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest | |
561 | end |
|
561 | end | |
562 |
|
562 | |||
563 | def test_gmail_with_attachment_latin1 |
|
563 | def test_gmail_with_attachment_latin1 | |
564 | issue = submit_email( |
|
564 | issue = submit_email( | |
565 | 'gmail_with_attachment_iso-8859-1.eml', |
|
565 | 'gmail_with_attachment_iso-8859-1.eml', | |
566 | :issue => {:project => 'ecookbook'} |
|
566 | :issue => {:project => 'ecookbook'} | |
567 | ) |
|
567 | ) | |
568 | assert_kind_of Issue, issue |
|
568 | assert_kind_of Issue, issue | |
569 | assert_equal 1, issue.attachments.size |
|
569 | assert_equal 1, issue.attachments.size | |
570 | u = "".force_encoding('UTF-8') |
|
570 | u = "".force_encoding('UTF-8') | |
571 | u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8') |
|
571 | u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8') | |
572 | 11.times { u << u1 } |
|
572 | 11.times { u << u1 } | |
573 | attachment = issue.attachments.first |
|
573 | attachment = issue.attachments.first | |
574 | assert_equal "#{u}.txt", attachment.filename |
|
574 | assert_equal "#{u}.txt", attachment.filename | |
575 | assert_equal 5, attachment.filesize |
|
575 | assert_equal 5, attachment.filesize | |
576 | assert File.exist?(attachment.diskfile) |
|
576 | assert File.exist?(attachment.diskfile) | |
577 | assert_equal 5, File.size(attachment.diskfile) |
|
577 | assert_equal 5, File.size(attachment.diskfile) | |
578 | assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest |
|
578 | assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest | |
579 | end |
|
579 | end | |
580 |
|
580 | |||
581 | def test_mail_with_attachment_latin2 |
|
581 | def test_mail_with_attachment_latin2 | |
582 | issue = submit_email( |
|
582 | issue = submit_email( | |
583 | 'ticket_with_text_attachment_iso-8859-2.eml', |
|
583 | 'ticket_with_text_attachment_iso-8859-2.eml', | |
584 | :issue => {:project => 'ecookbook'} |
|
584 | :issue => {:project => 'ecookbook'} | |
585 | ) |
|
585 | ) | |
586 | assert_kind_of Issue, issue |
|
586 | assert_kind_of Issue, issue | |
587 | assert_equal 1, issue.attachments.size |
|
587 | assert_equal 1, issue.attachments.size | |
588 | attachment = issue.attachments.first |
|
588 | attachment = issue.attachments.first | |
589 | assert_equal 'latin2.txt', attachment.filename |
|
589 | assert_equal 'latin2.txt', attachment.filename | |
590 | assert_equal 19, attachment.filesize |
|
590 | assert_equal 19, attachment.filesize | |
591 | assert File.exist?(attachment.diskfile) |
|
591 | assert File.exist?(attachment.diskfile) | |
592 | assert_equal 19, File.size(attachment.diskfile) |
|
592 | assert_equal 19, File.size(attachment.diskfile) | |
593 | content = "p\xF8\xEDli\xB9 \xBEluou\xE8k\xFD k\xF9n".force_encoding('CP852') |
|
593 | content = "p\xF8\xEDli\xB9 \xBEluou\xE8k\xFD k\xF9n".force_encoding('CP852') | |
594 | assert_equal content, File.read(attachment.diskfile).force_encoding('CP852') |
|
594 | assert_equal content, File.read(attachment.diskfile).force_encoding('CP852') | |
595 | end |
|
595 | end | |
596 |
|
596 | |||
597 | def test_multiple_inline_text_parts_should_be_appended_to_issue_description |
|
597 | def test_multiple_inline_text_parts_should_be_appended_to_issue_description | |
598 | issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'}) |
|
598 | issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'}) | |
599 | assert_include 'first', issue.description |
|
599 | assert_include 'first', issue.description | |
600 | assert_include 'second', issue.description |
|
600 | assert_include 'second', issue.description | |
601 | assert_include 'third', issue.description |
|
601 | assert_include 'third', issue.description | |
602 | end |
|
602 | end | |
603 |
|
603 | |||
604 | def test_attachment_text_part_should_be_added_as_issue_attachment |
|
604 | def test_attachment_text_part_should_be_added_as_issue_attachment | |
605 | issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'}) |
|
605 | issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'}) | |
606 | assert_not_include 'Plain text attachment', issue.description |
|
606 | assert_not_include 'Plain text attachment', issue.description | |
607 | attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'} |
|
607 | attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'} | |
608 | assert_not_nil attachment |
|
608 | assert_not_nil attachment | |
609 | assert_include 'Plain text attachment', File.read(attachment.diskfile) |
|
609 | assert_include 'Plain text attachment', File.read(attachment.diskfile) | |
610 | end |
|
610 | end | |
611 |
|
611 | |||
612 | def test_add_issue_with_iso_8859_1_subject |
|
612 | def test_add_issue_with_iso_8859_1_subject | |
613 | issue = submit_email( |
|
613 | issue = submit_email( | |
614 | 'subject_as_iso-8859-1.eml', |
|
614 | 'subject_as_iso-8859-1.eml', | |
615 | :issue => {:project => 'ecookbook'} |
|
615 | :issue => {:project => 'ecookbook'} | |
616 | ) |
|
616 | ) | |
617 | str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc...".force_encoding('UTF-8') |
|
617 | str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc...".force_encoding('UTF-8') | |
618 | assert_kind_of Issue, issue |
|
618 | assert_kind_of Issue, issue | |
619 | assert_equal str, issue.subject |
|
619 | assert_equal str, issue.subject | |
620 | end |
|
620 | end | |
621 |
|
621 | |||
622 | def test_quoted_printable_utf8 |
|
622 | def test_quoted_printable_utf8 | |
623 | issue = submit_email( |
|
623 | issue = submit_email( | |
624 | 'quoted_printable_utf8.eml', |
|
624 | 'quoted_printable_utf8.eml', | |
625 | :issue => {:project => 'ecookbook'} |
|
625 | :issue => {:project => 'ecookbook'} | |
626 | ) |
|
626 | ) | |
627 | assert_kind_of Issue, issue |
|
627 | assert_kind_of Issue, issue | |
628 | str = "Freundliche Gr\xc3\xbcsse".force_encoding('UTF-8') |
|
628 | str = "Freundliche Gr\xc3\xbcsse".force_encoding('UTF-8') | |
629 | assert_equal str, issue.description |
|
629 | assert_equal str, issue.description | |
630 | end |
|
630 | end | |
631 |
|
631 | |||
632 | def test_gmail_iso8859_2 |
|
632 | def test_gmail_iso8859_2 | |
633 | issue = submit_email( |
|
633 | issue = submit_email( | |
634 | 'gmail-iso8859-2.eml', |
|
634 | 'gmail-iso8859-2.eml', | |
635 | :issue => {:project => 'ecookbook'} |
|
635 | :issue => {:project => 'ecookbook'} | |
636 | ) |
|
636 | ) | |
637 | assert_kind_of Issue, issue |
|
637 | assert_kind_of Issue, issue | |
638 | str = "Na \xc5\xa1triku se su\xc5\xa1i \xc5\xa1osi\xc4\x87.".force_encoding('UTF-8') |
|
638 | str = "Na \xc5\xa1triku se su\xc5\xa1i \xc5\xa1osi\xc4\x87.".force_encoding('UTF-8') | |
639 | assert issue.description.include?(str) |
|
639 | assert issue.description.include?(str) | |
640 | end |
|
640 | end | |
641 |
|
641 | |||
642 | def test_add_issue_with_japanese_subject |
|
642 | def test_add_issue_with_japanese_subject | |
643 | issue = submit_email( |
|
643 | issue = submit_email( | |
644 | 'subject_japanese_1.eml', |
|
644 | 'subject_japanese_1.eml', | |
645 | :issue => {:project => 'ecookbook'} |
|
645 | :issue => {:project => 'ecookbook'} | |
646 | ) |
|
646 | ) | |
647 | assert_kind_of Issue, issue |
|
647 | assert_kind_of Issue, issue | |
648 | ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8') |
|
648 | ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8') | |
649 | assert_equal ja, issue.subject |
|
649 | assert_equal ja, issue.subject | |
650 | end |
|
650 | end | |
651 |
|
651 | |||
652 | def test_add_issue_with_korean_body |
|
652 | def test_add_issue_with_korean_body | |
653 | # Make sure mail bodies with a charset unknown to Ruby |
|
653 | # Make sure mail bodies with a charset unknown to Ruby | |
654 | # but known to the Mail gem 2.5.4 are handled correctly |
|
654 | # but known to the Mail gem 2.5.4 are handled correctly | |
655 | kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4.".force_encoding('UTF-8') |
|
655 | kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4.".force_encoding('UTF-8') | |
656 | issue = submit_email( |
|
656 | issue = submit_email( | |
657 | 'body_ks_c_5601-1987.eml', |
|
657 | 'body_ks_c_5601-1987.eml', | |
658 | :issue => {:project => 'ecookbook'} |
|
658 | :issue => {:project => 'ecookbook'} | |
659 | ) |
|
659 | ) | |
660 | assert_kind_of Issue, issue |
|
660 | assert_kind_of Issue, issue | |
661 | assert_equal kr, issue.description |
|
661 | assert_equal kr, issue.description | |
662 | end |
|
662 | end | |
663 |
|
663 | |||
664 | def test_add_issue_with_no_subject_header |
|
664 | def test_add_issue_with_no_subject_header | |
665 | issue = submit_email( |
|
665 | issue = submit_email( | |
666 | 'no_subject_header.eml', |
|
666 | 'no_subject_header.eml', | |
667 | :issue => {:project => 'ecookbook'} |
|
667 | :issue => {:project => 'ecookbook'} | |
668 | ) |
|
668 | ) | |
669 | assert_kind_of Issue, issue |
|
669 | assert_kind_of Issue, issue | |
670 | assert_equal '(no subject)', issue.subject |
|
670 | assert_equal '(no subject)', issue.subject | |
671 | end |
|
671 | end | |
672 |
|
672 | |||
673 | def test_add_issue_with_mixed_japanese_subject |
|
673 | def test_add_issue_with_mixed_japanese_subject | |
674 | issue = submit_email( |
|
674 | issue = submit_email( | |
675 | 'subject_japanese_2.eml', |
|
675 | 'subject_japanese_2.eml', | |
676 | :issue => {:project => 'ecookbook'} |
|
676 | :issue => {:project => 'ecookbook'} | |
677 | ) |
|
677 | ) | |
678 | assert_kind_of Issue, issue |
|
678 | assert_kind_of Issue, issue | |
679 | ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8') |
|
679 | ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8') | |
680 | assert_equal ja, issue.subject |
|
680 | assert_equal ja, issue.subject | |
681 | end |
|
681 | end | |
682 |
|
682 | |||
683 | def test_should_ignore_emails_from_locked_users |
|
683 | def test_should_ignore_emails_from_locked_users | |
684 | User.find(2).lock! |
|
684 | User.find(2).lock! | |
685 |
|
685 | |||
686 | MailHandler.any_instance.expects(:dispatch).never |
|
686 | MailHandler.any_instance.expects(:dispatch).never | |
687 | assert_no_difference 'Issue.count' do |
|
687 | assert_no_difference 'Issue.count' do | |
688 | assert_equal false, submit_email('ticket_on_given_project.eml') |
|
688 | assert_equal false, submit_email('ticket_on_given_project.eml') | |
689 | end |
|
689 | end | |
690 | end |
|
690 | end | |
691 |
|
691 | |||
692 | def test_should_ignore_emails_from_emission_address |
|
692 | def test_should_ignore_emails_from_emission_address | |
693 | Role.anonymous.add_permission!(:add_issues) |
|
693 | Role.anonymous.add_permission!(:add_issues) | |
694 | assert_no_difference 'User.count' do |
|
694 | assert_no_difference 'User.count' do | |
695 | assert_equal false, |
|
695 | assert_equal false, | |
696 | submit_email( |
|
696 | submit_email( | |
697 | 'ticket_from_emission_address.eml', |
|
697 | 'ticket_from_emission_address.eml', | |
698 | :issue => {:project => 'ecookbook'}, |
|
698 | :issue => {:project => 'ecookbook'}, | |
699 | :unknown_user => 'create' |
|
699 | :unknown_user => 'create' | |
700 | ) |
|
700 | ) | |
701 | end |
|
701 | end | |
702 | end |
|
702 | end | |
703 |
|
703 | |||
704 | def test_should_ignore_auto_replied_emails |
|
704 | def test_should_ignore_auto_replied_emails | |
705 | MailHandler.any_instance.expects(:dispatch).never |
|
705 | MailHandler.any_instance.expects(:dispatch).never | |
706 | [ |
|
706 | [ | |
707 | "Auto-Submitted: auto-replied", |
|
707 | "Auto-Submitted: auto-replied", | |
708 | "Auto-Submitted: Auto-Replied", |
|
708 | "Auto-Submitted: Auto-Replied", | |
709 | "Auto-Submitted: auto-generated", |
|
709 | "Auto-Submitted: auto-generated", | |
710 | 'X-Autoreply: yes' |
|
710 | 'X-Autoreply: yes' | |
711 | ].each do |header| |
|
711 | ].each do |header| | |
712 | raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml')) |
|
712 | raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml')) | |
713 | raw = header + "\n" + raw |
|
713 | raw = header + "\n" + raw | |
714 |
|
714 | |||
715 | assert_no_difference 'Issue.count' do |
|
715 | assert_no_difference 'Issue.count' do | |
716 | assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored" |
|
716 | assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored" | |
717 | end |
|
717 | end | |
718 | end |
|
718 | end | |
719 | end |
|
719 | end | |
720 |
|
720 | |||
721 | test "should not ignore Auto-Submitted headers not defined in RFC3834" do |
|
721 | test "should not ignore Auto-Submitted headers not defined in RFC3834" do | |
722 | [ |
|
722 | [ | |
723 | "Auto-Submitted: auto-forwarded" |
|
723 | "Auto-Submitted: auto-forwarded" | |
724 | ].each do |header| |
|
724 | ].each do |header| | |
725 | raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml')) |
|
725 | raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml')) | |
726 | raw = header + "\n" + raw |
|
726 | raw = header + "\n" + raw | |
727 |
|
727 | |||
728 | assert_difference 'Issue.count', 1 do |
|
728 | assert_difference 'Issue.count', 1 do | |
729 | assert_not_nil MailHandler.receive(raw), "email with #{header} header was ignored" |
|
729 | assert_not_nil MailHandler.receive(raw), "email with #{header} header was ignored" | |
730 | end |
|
730 | end | |
731 | end |
|
731 | end | |
732 | end |
|
732 | end | |
733 |
|
733 | |||
734 | def test_add_issue_should_send_email_notification |
|
734 | def test_add_issue_should_send_email_notification | |
735 | Setting.notified_events = ['issue_added'] |
|
735 | Setting.notified_events = ['issue_added'] | |
736 | # This email contains: 'Project: onlinestore' |
|
736 | # This email contains: 'Project: onlinestore' | |
737 | issue = submit_email('ticket_on_given_project.eml') |
|
737 | issue = submit_email('ticket_on_given_project.eml') | |
738 | assert issue.is_a?(Issue) |
|
738 | assert issue.is_a?(Issue) | |
739 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
739 | assert_equal 1, ActionMailer::Base.deliveries.size | |
740 | end |
|
740 | end | |
741 |
|
741 | |||
742 | def test_update_issue |
|
742 | def test_update_issue | |
743 | journal = submit_email('ticket_reply.eml') |
|
743 | journal = submit_email('ticket_reply.eml') | |
744 | assert journal.is_a?(Journal) |
|
744 | assert journal.is_a?(Journal) | |
745 | assert_equal User.find_by_login('jsmith'), journal.user |
|
745 | assert_equal User.find_by_login('jsmith'), journal.user | |
746 | assert_equal Issue.find(2), journal.journalized |
|
746 | assert_equal Issue.find(2), journal.journalized | |
747 | assert_match /This is reply/, journal.notes |
|
747 | assert_match /This is reply/, journal.notes | |
748 | assert_equal false, journal.private_notes |
|
748 | assert_equal false, journal.private_notes | |
749 | assert_equal 'Feature request', journal.issue.tracker.name |
|
749 | assert_equal 'Feature request', journal.issue.tracker.name | |
750 | end |
|
750 | end | |
751 |
|
751 | |||
752 | def test_update_issue_should_accept_issue_id_after_space_inside_brackets |
|
752 | def test_update_issue_should_accept_issue_id_after_space_inside_brackets | |
753 | journal = submit_email('ticket_reply_with_status.eml') do |email| |
|
753 | journal = submit_email('ticket_reply_with_status.eml') do |email| | |
754 | assert email.sub!(/^Subject:.*$/, "Subject: Re: [Feature request #2] Add ingredients categories") |
|
754 | assert email.sub!(/^Subject:.*$/, "Subject: Re: [Feature request #2] Add ingredients categories") | |
755 | end |
|
755 | end | |
756 | assert journal.is_a?(Journal) |
|
756 | assert journal.is_a?(Journal) | |
757 | assert_equal Issue.find(2), journal.journalized |
|
757 | assert_equal Issue.find(2), journal.journalized | |
758 | end |
|
758 | end | |
759 |
|
759 | |||
760 | def test_update_issue_should_accept_issue_id_inside_brackets |
|
760 | def test_update_issue_should_accept_issue_id_inside_brackets | |
761 | journal = submit_email('ticket_reply_with_status.eml') do |email| |
|
761 | journal = submit_email('ticket_reply_with_status.eml') do |email| | |
762 | assert email.sub!(/^Subject:.*$/, "Subject: Re: [#2] Add ingredients categories") |
|
762 | assert email.sub!(/^Subject:.*$/, "Subject: Re: [#2] Add ingredients categories") | |
763 | end |
|
763 | end | |
764 | assert journal.is_a?(Journal) |
|
764 | assert journal.is_a?(Journal) | |
765 | assert_equal Issue.find(2), journal.journalized |
|
765 | assert_equal Issue.find(2), journal.journalized | |
766 | end |
|
766 | end | |
767 |
|
767 | |||
768 | def test_update_issue_should_ignore_bogus_issue_ids_in_subject |
|
768 | def test_update_issue_should_ignore_bogus_issue_ids_in_subject | |
769 | journal = submit_email('ticket_reply_with_status.eml') do |email| |
|
769 | journal = submit_email('ticket_reply_with_status.eml') do |email| | |
770 | assert email.sub!(/^Subject:.*$/, "Subject: Re: [12345#1][bogus#1][Feature request #2] Add ingredients categories") |
|
770 | assert email.sub!(/^Subject:.*$/, "Subject: Re: [12345#1][bogus#1][Feature request #2] Add ingredients categories") | |
771 | end |
|
771 | end | |
772 | assert journal.is_a?(Journal) |
|
772 | assert journal.is_a?(Journal) | |
773 | assert_equal Issue.find(2), journal.journalized |
|
773 | assert_equal Issue.find(2), journal.journalized | |
774 | end |
|
774 | end | |
775 |
|
775 | |||
776 | def test_update_issue_with_attribute_changes |
|
776 | def test_update_issue_with_attribute_changes | |
777 | journal = submit_email('ticket_reply_with_status.eml', :allow_override => ['status','assigned_to','start_date','due_date', 'float field']) |
|
777 | journal = submit_email('ticket_reply_with_status.eml', :allow_override => ['status','assigned_to','start_date','due_date', 'float field']) | |
778 | assert journal.is_a?(Journal) |
|
778 | assert journal.is_a?(Journal) | |
779 | issue = Issue.find(journal.issue.id) |
|
779 | issue = Issue.find(journal.issue.id) | |
780 | assert_equal User.find_by_login('jsmith'), journal.user |
|
780 | assert_equal User.find_by_login('jsmith'), journal.user | |
781 | assert_equal Issue.find(2), journal.journalized |
|
781 | assert_equal Issue.find(2), journal.journalized | |
782 | assert_match /This is reply/, journal.notes |
|
782 | assert_match /This is reply/, journal.notes | |
783 | assert_equal 'Feature request', journal.issue.tracker.name |
|
783 | assert_equal 'Feature request', journal.issue.tracker.name | |
784 | assert_equal IssueStatus.find_by_name("Resolved"), issue.status |
|
784 | assert_equal IssueStatus.find_by_name("Resolved"), issue.status | |
785 | assert_equal '2010-01-01', issue.start_date.to_s |
|
785 | assert_equal '2010-01-01', issue.start_date.to_s | |
786 | assert_equal '2010-12-31', issue.due_date.to_s |
|
786 | assert_equal '2010-12-31', issue.due_date.to_s | |
787 | assert_equal User.find_by_login('jsmith'), issue.assigned_to |
|
787 | assert_equal User.find_by_login('jsmith'), issue.assigned_to | |
788 | assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value |
|
788 | assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value | |
789 | # keywords should be removed from the email body |
|
789 | # keywords should be removed from the email body | |
790 | assert !journal.notes.match(/^Status:/i) |
|
790 | assert !journal.notes.match(/^Status:/i) | |
791 | assert !journal.notes.match(/^Start Date:/i) |
|
791 | assert !journal.notes.match(/^Start Date:/i) | |
792 | end |
|
792 | end | |
793 |
|
793 | |||
794 | def test_update_issue_with_attachment |
|
794 | def test_update_issue_with_attachment | |
795 | assert_difference 'Journal.count' do |
|
795 | assert_difference 'Journal.count' do | |
796 | assert_difference 'JournalDetail.count' do |
|
796 | assert_difference 'JournalDetail.count' do | |
797 | assert_difference 'Attachment.count' do |
|
797 | assert_difference 'Attachment.count' do | |
798 | assert_no_difference 'Issue.count' do |
|
798 | assert_no_difference 'Issue.count' do | |
799 | journal = submit_email('ticket_with_attachment.eml') do |raw| |
|
799 | journal = submit_email('ticket_with_attachment.eml') do |raw| | |
800 | raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories' |
|
800 | raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories' | |
801 | end |
|
801 | end | |
802 | end |
|
802 | end | |
803 | end |
|
803 | end | |
804 | end |
|
804 | end | |
805 | end |
|
805 | end | |
806 | journal = Journal.order('id DESC').first |
|
806 | journal = Journal.order('id DESC').first | |
807 | assert_equal Issue.find(2), journal.journalized |
|
807 | assert_equal Issue.find(2), journal.journalized | |
808 | assert_equal 1, journal.details.size |
|
808 | assert_equal 1, journal.details.size | |
809 |
|
809 | |||
810 | detail = journal.details.first |
|
810 | detail = journal.details.first | |
811 | assert_equal 'attachment', detail.property |
|
811 | assert_equal 'attachment', detail.property | |
812 | assert_equal 'Paella.jpg', detail.value |
|
812 | assert_equal 'Paella.jpg', detail.value | |
813 | end |
|
813 | end | |
814 |
|
814 | |||
815 | def test_update_issue_should_send_email_notification |
|
815 | def test_update_issue_should_send_email_notification | |
816 | journal = submit_email('ticket_reply.eml') |
|
816 | journal = submit_email('ticket_reply.eml') | |
817 | assert journal.is_a?(Journal) |
|
817 | assert journal.is_a?(Journal) | |
818 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
818 | assert_equal 1, ActionMailer::Base.deliveries.size | |
819 | end |
|
819 | end | |
820 |
|
820 | |||
821 | def test_update_issue_should_not_set_defaults |
|
821 | def test_update_issue_should_not_set_defaults | |
822 | journal = submit_email( |
|
822 | journal = submit_email( | |
823 | 'ticket_reply.eml', |
|
823 | 'ticket_reply.eml', | |
824 | :issue => {:tracker => 'Support request', :priority => 'High'} |
|
824 | :issue => {:tracker => 'Support request', :priority => 'High'} | |
825 | ) |
|
825 | ) | |
826 | assert journal.is_a?(Journal) |
|
826 | assert journal.is_a?(Journal) | |
827 | assert_match /This is reply/, journal.notes |
|
827 | assert_match /This is reply/, journal.notes | |
828 | assert_equal 'Feature request', journal.issue.tracker.name |
|
828 | assert_equal 'Feature request', journal.issue.tracker.name | |
829 | assert_equal 'Normal', journal.issue.priority.name |
|
829 | assert_equal 'Normal', journal.issue.priority.name | |
830 | end |
|
830 | end | |
831 |
|
831 | |||
832 | def test_update_issue_should_add_cc_as_watchers |
|
832 | def test_update_issue_should_add_cc_as_watchers | |
833 | Watcher.delete_all |
|
833 | Watcher.delete_all | |
834 | issue = Issue.find(2) |
|
834 | issue = Issue.find(2) | |
835 |
|
835 | |||
836 | assert_difference 'Watcher.count' do |
|
836 | assert_difference 'Watcher.count' do | |
837 | assert submit_email('issue_update_with_cc.eml') |
|
837 | assert submit_email('issue_update_with_cc.eml') | |
838 | end |
|
838 | end | |
839 | issue.reload |
|
839 | issue.reload | |
840 | assert_equal 1, issue.watcher_user_ids.size |
|
840 | assert_equal 1, issue.watcher_user_ids.size | |
841 | assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo')) |
|
841 | assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo')) | |
842 | end |
|
842 | end | |
843 |
|
843 | |||
844 | def test_update_issue_should_not_add_cc_as_watchers_if_already_watching |
|
844 | def test_update_issue_should_not_add_cc_as_watchers_if_already_watching | |
845 | Watcher.delete_all |
|
845 | Watcher.delete_all | |
846 | issue = Issue.find(2) |
|
846 | issue = Issue.find(2) | |
847 | Watcher.create!(:watchable => issue, :user => User.find_by_mail('dlopper@somenet.foo')) |
|
847 | Watcher.create!(:watchable => issue, :user => User.find_by_mail('dlopper@somenet.foo')) | |
848 |
|
848 | |||
849 | assert_no_difference 'Watcher.count' do |
|
849 | assert_no_difference 'Watcher.count' do | |
850 | assert submit_email('issue_update_with_cc.eml') |
|
850 | assert submit_email('issue_update_with_cc.eml') | |
851 | end |
|
851 | end | |
852 | end |
|
852 | end | |
853 |
|
853 | |||
854 | def test_replying_to_a_private_note_should_add_reply_as_private |
|
854 | def test_replying_to_a_private_note_should_add_reply_as_private | |
855 | private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2) |
|
855 | private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2) | |
856 |
|
856 | |||
857 | assert_difference 'Journal.count' do |
|
857 | assert_difference 'Journal.count' do | |
858 | journal = submit_email('ticket_reply.eml') do |email| |
|
858 | journal = submit_email('ticket_reply.eml') do |email| | |
859 | email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>" |
|
859 | email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>" | |
860 | end |
|
860 | end | |
861 |
|
861 | |||
862 | assert_kind_of Journal, journal |
|
862 | assert_kind_of Journal, journal | |
863 | assert_match /This is reply/, journal.notes |
|
863 | assert_match /This is reply/, journal.notes | |
864 | assert_equal true, journal.private_notes |
|
864 | assert_equal true, journal.private_notes | |
865 | end |
|
865 | end | |
866 | end |
|
866 | end | |
867 |
|
867 | |||
868 | def test_reply_to_a_message |
|
868 | def test_reply_to_a_message | |
869 | m = submit_email('message_reply.eml') |
|
869 | m = submit_email('message_reply.eml') | |
870 | assert m.is_a?(Message) |
|
870 | assert m.is_a?(Message) | |
871 | assert !m.new_record? |
|
871 | assert !m.new_record? | |
872 | m.reload |
|
872 | m.reload | |
873 | assert_equal 'Reply via email', m.subject |
|
873 | assert_equal 'Reply via email', m.subject | |
874 | # The email replies to message #2 which is part of the thread of message #1 |
|
874 | # The email replies to message #2 which is part of the thread of message #1 | |
875 | assert_equal Message.find(1), m.parent |
|
875 | assert_equal Message.find(1), m.parent | |
876 | end |
|
876 | end | |
877 |
|
877 | |||
878 | def test_reply_to_a_message_by_subject |
|
878 | def test_reply_to_a_message_by_subject | |
879 | m = submit_email('message_reply_by_subject.eml') |
|
879 | m = submit_email('message_reply_by_subject.eml') | |
880 | assert m.is_a?(Message) |
|
880 | assert m.is_a?(Message) | |
881 | assert !m.new_record? |
|
881 | assert !m.new_record? | |
882 | m.reload |
|
882 | m.reload | |
883 | assert_equal 'Reply to the first post', m.subject |
|
883 | assert_equal 'Reply to the first post', m.subject | |
884 | assert_equal Message.find(1), m.parent |
|
884 | assert_equal Message.find(1), m.parent | |
885 | end |
|
885 | end | |
886 |
|
886 | |||
887 | def test_should_convert_tags_of_html_only_emails |
|
887 | def test_should_convert_tags_of_html_only_emails | |
888 | with_settings :text_formatting => 'textile' do |
|
888 | with_settings :text_formatting => 'textile' do | |
889 | issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'}) |
|
889 | issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'}) | |
890 | assert issue.is_a?(Issue) |
|
890 | assert issue.is_a?(Issue) | |
891 | assert !issue.new_record? |
|
891 | assert !issue.new_record? | |
892 | issue.reload |
|
892 | issue.reload | |
893 | assert_equal 'HTML email', issue.subject |
|
893 | assert_equal 'HTML email', issue.subject | |
894 | assert_equal "This is a *html-only* email.\r\n\r\nh1. With a title\r\n\r\nand a paragraph.", issue.description |
|
894 | assert_equal "This is a *html-only* email.\r\n\r\nh1. With a title\r\n\r\nand a paragraph.", issue.description | |
895 | end |
|
895 | end | |
896 | end |
|
896 | end | |
897 |
|
897 | |||
898 | def test_should_handle_outlook_web_access_2010_html_only |
|
898 | def test_should_handle_outlook_web_access_2010_html_only | |
899 | issue = submit_email('outlook_web_access_2010_html_only.eml', :issue => {:project => 'ecookbook'}) |
|
899 | issue = submit_email('outlook_web_access_2010_html_only.eml', :issue => {:project => 'ecookbook'}) | |
900 | assert issue.is_a?(Issue) |
|
900 | assert issue.is_a?(Issue) | |
901 | issue.reload |
|
901 | issue.reload | |
902 | assert_equal 'Upgrade Redmine to 3.0.x', issue.subject |
|
902 | assert_equal 'Upgrade Redmine to 3.0.x', issue.subject | |
903 | assert_equal "A mess.\r\n\r\n--Geoff Maciolek\r\nMYCOMPANYNAME, LLC", issue.description |
|
903 | assert_equal "A mess.\r\n\r\n--Geoff Maciolek\r\nMYCOMPANYNAME, LLC", issue.description | |
904 | end |
|
904 | end | |
905 |
|
905 | |||
906 | def test_should_handle_outlook_2010_html_only |
|
906 | def test_should_handle_outlook_2010_html_only | |
907 | issue = submit_email('outlook_2010_html_only.eml', :issue => {:project => 'ecookbook'}) |
|
907 | issue = submit_email('outlook_2010_html_only.eml', :issue => {:project => 'ecookbook'}) | |
908 | assert issue.is_a?(Issue) |
|
908 | assert issue.is_a?(Issue) | |
909 | issue.reload |
|
909 | issue.reload | |
910 | assert_equal 'Test email', issue.subject |
|
910 | assert_equal 'Test email', issue.subject | |
911 | assert_equal "Simple, unadorned test email generated by Outlook 2010. It is in HTML format, but" + |
|
911 | assert_equal "Simple, unadorned test email generated by Outlook 2010. It is in HTML format, but" + | |
912 | " no special formatting has been chosen. Iβm going to save this as a draft and then manually" + |
|
912 | " no special formatting has been chosen. Iβm going to save this as a draft and then manually" + | |
913 | " drop it into the Inbox for scraping by Redmine 3.0.2.", issue.description |
|
913 | " drop it into the Inbox for scraping by Redmine 3.0.2.", issue.description | |
914 | end |
|
914 | end | |
915 |
|
915 | |||
916 | test "truncate emails with no setting should add the entire email into the issue" do |
|
916 | test "truncate emails with no setting should add the entire email into the issue" do | |
917 | with_settings :mail_handler_body_delimiters => '' do |
|
917 | with_settings :mail_handler_body_delimiters => '' do | |
918 | issue = submit_email('ticket_on_given_project.eml') |
|
918 | issue = submit_email('ticket_on_given_project.eml') | |
919 | assert_issue_created(issue) |
|
919 | assert_issue_created(issue) | |
920 | assert issue.description.include?('---') |
|
920 | assert issue.description.include?('---') | |
921 | assert issue.description.include?('This paragraph is after the delimiter') |
|
921 | assert issue.description.include?('This paragraph is after the delimiter') | |
922 | end |
|
922 | end | |
923 | end |
|
923 | end | |
924 |
|
924 | |||
925 | test "truncate emails with a single string should truncate the email at the delimiter for the issue" do |
|
925 | test "truncate emails with a single string should truncate the email at the delimiter for the issue" do | |
926 | with_settings :mail_handler_body_delimiters => '---' do |
|
926 | with_settings :mail_handler_body_delimiters => '---' do | |
927 | issue = submit_email('ticket_on_given_project.eml') |
|
927 | issue = submit_email('ticket_on_given_project.eml') | |
928 | assert_issue_created(issue) |
|
928 | assert_issue_created(issue) | |
929 | assert issue.description.include?('This paragraph is before delimiters') |
|
929 | assert issue.description.include?('This paragraph is before delimiters') | |
930 | assert issue.description.include?('--- This line starts with a delimiter') |
|
930 | assert issue.description.include?('--- This line starts with a delimiter') | |
931 | assert !issue.description.match(/^---$/) |
|
931 | assert !issue.description.match(/^---$/) | |
932 | assert !issue.description.include?('This paragraph is after the delimiter') |
|
932 | assert !issue.description.include?('This paragraph is after the delimiter') | |
933 | end |
|
933 | end | |
934 | end |
|
934 | end | |
935 |
|
935 | |||
936 | test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do |
|
936 | test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do | |
937 | with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do |
|
937 | with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do | |
938 | journal = submit_email('issue_update_with_quoted_reply_above.eml') |
|
938 | journal = submit_email('issue_update_with_quoted_reply_above.eml') | |
939 | assert journal.is_a?(Journal) |
|
939 | assert journal.is_a?(Journal) | |
940 | assert journal.notes.include?('An update to the issue by the sender.') |
|
940 | assert journal.notes.include?('An update to the issue by the sender.') | |
941 | assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---")) |
|
941 | assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---")) | |
942 | assert !journal.notes.include?('Looks like the JSON api for projects was missed.') |
|
942 | assert !journal.notes.include?('Looks like the JSON api for projects was missed.') | |
943 | end |
|
943 | end | |
944 | end |
|
944 | end | |
945 |
|
945 | |||
946 | test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do |
|
946 | test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do | |
947 | with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do |
|
947 | with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do | |
948 | journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml') |
|
948 | journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml') | |
949 | assert journal.is_a?(Journal) |
|
949 | assert journal.is_a?(Journal) | |
950 | assert journal.notes.include?('An update to the issue by the sender.') |
|
950 | assert journal.notes.include?('An update to the issue by the sender.') | |
951 | assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---")) |
|
951 | assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---")) | |
952 | assert !journal.notes.include?('Looks like the JSON api for projects was missed.') |
|
952 | assert !journal.notes.include?('Looks like the JSON api for projects was missed.') | |
953 | end |
|
953 | end | |
954 | end |
|
954 | end | |
955 |
|
955 | |||
956 | test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do |
|
956 | test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do | |
957 | with_settings :mail_handler_body_delimiters => "---\nBREAK" do |
|
957 | with_settings :mail_handler_body_delimiters => "---\nBREAK" do | |
958 | issue = submit_email('ticket_on_given_project.eml') |
|
958 | issue = submit_email('ticket_on_given_project.eml') | |
959 | assert_issue_created(issue) |
|
959 | assert_issue_created(issue) | |
960 | assert issue.description.include?('This paragraph is before delimiters') |
|
960 | assert issue.description.include?('This paragraph is before delimiters') | |
961 | assert !issue.description.include?('BREAK') |
|
961 | assert !issue.description.include?('BREAK') | |
962 | assert !issue.description.include?('This paragraph is between delimiters') |
|
962 | assert !issue.description.include?('This paragraph is between delimiters') | |
963 | assert !issue.description.match(/^---$/) |
|
963 | assert !issue.description.match(/^---$/) | |
964 | assert !issue.description.include?('This paragraph is after the delimiter') |
|
964 | assert !issue.description.include?('This paragraph is after the delimiter') | |
965 | end |
|
965 | end | |
966 | end |
|
966 | end | |
967 |
|
967 | |||
968 | def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored |
|
968 | def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored | |
969 | with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do |
|
969 | with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do | |
970 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) |
|
970 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) | |
971 | assert issue.is_a?(Issue) |
|
971 | assert issue.is_a?(Issue) | |
972 | assert !issue.new_record? |
|
972 | assert !issue.new_record? | |
973 | assert_equal 0, issue.reload.attachments.size |
|
973 | assert_equal 0, issue.reload.attachments.size | |
974 | end |
|
974 | end | |
975 | end |
|
975 | end | |
976 |
|
976 | |||
977 | def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached |
|
977 | def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached | |
978 | with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do |
|
978 | with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do | |
979 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) |
|
979 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) | |
980 | assert issue.is_a?(Issue) |
|
980 | assert issue.is_a?(Issue) | |
981 | assert !issue.new_record? |
|
981 | assert !issue.new_record? | |
982 | assert_equal 1, issue.reload.attachments.size |
|
982 | assert_equal 1, issue.reload.attachments.size | |
983 | end |
|
983 | end | |
984 | end |
|
984 | end | |
985 |
|
985 | |||
986 | def test_email_with_long_subject_line |
|
986 | def test_email_with_long_subject_line | |
987 | issue = submit_email('ticket_with_long_subject.eml') |
|
987 | issue = submit_email('ticket_with_long_subject.eml') | |
988 | assert issue.is_a?(Issue) |
|
988 | assert issue.is_a?(Issue) | |
989 | assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255] |
|
989 | assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255] | |
990 | end |
|
990 | end | |
991 |
|
991 | |||
992 | def test_first_keyword_should_be_matched |
|
992 | def test_first_keyword_should_be_matched | |
993 | issue = submit_email('ticket_with_duplicate_keyword.eml', :allow_override => 'priority') |
|
993 | issue = submit_email('ticket_with_duplicate_keyword.eml', :allow_override => 'priority') | |
994 | assert issue.is_a?(Issue) |
|
994 | assert issue.is_a?(Issue) | |
995 | assert_equal 'High', issue.priority.name |
|
995 | assert_equal 'High', issue.priority.name | |
996 | end |
|
996 | end | |
997 |
|
997 | |||
998 | def test_keyword_after_delimiter_should_be_ignored |
|
998 | def test_keyword_after_delimiter_should_be_ignored | |
999 | with_settings :mail_handler_body_delimiters => "== DELIMITER ==" do |
|
999 | with_settings :mail_handler_body_delimiters => "== DELIMITER ==" do | |
1000 | issue = submit_email('ticket_with_keyword_after_delimiter.eml', :allow_override => 'priority') |
|
1000 | issue = submit_email('ticket_with_keyword_after_delimiter.eml', :allow_override => 'priority') | |
1001 | assert issue.is_a?(Issue) |
|
1001 | assert issue.is_a?(Issue) | |
1002 | assert_equal 'Normal', issue.priority.name |
|
1002 | assert_equal 'Normal', issue.priority.name | |
1003 | end |
|
1003 | end | |
1004 | end |
|
1004 | end | |
1005 |
|
1005 | |||
1006 | def test_new_user_from_attributes_should_return_valid_user |
|
1006 | def test_new_user_from_attributes_should_return_valid_user | |
1007 | to_test = { |
|
1007 | to_test = { | |
1008 | # [address, name] => [login, firstname, lastname] |
|
1008 | # [address, name] => [login, firstname, lastname] | |
1009 | ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'], |
|
1009 | ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'], | |
1010 | ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'], |
|
1010 | ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'], | |
1011 | ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'], |
|
1011 | ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'], | |
1012 | ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'], |
|
1012 | ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'], | |
1013 | ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'], |
|
1013 | ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'], | |
1014 | ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh'] |
|
1014 | ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh'] | |
1015 | } |
|
1015 | } | |
1016 |
|
1016 | |||
1017 | to_test.each do |attrs, expected| |
|
1017 | to_test.each do |attrs, expected| | |
1018 | user = MailHandler.new_user_from_attributes(attrs.first, attrs.last) |
|
1018 | user = MailHandler.new_user_from_attributes(attrs.first, attrs.last) | |
1019 |
|
1019 | |||
1020 | assert user.valid?, user.errors.full_messages.to_s |
|
1020 | assert user.valid?, user.errors.full_messages.to_s | |
1021 | assert_equal attrs.first, user.mail |
|
1021 | assert_equal attrs.first, user.mail | |
1022 | assert_equal expected[0], user.login |
|
1022 | assert_equal expected[0], user.login | |
1023 | assert_equal expected[1], user.firstname |
|
1023 | assert_equal expected[1], user.firstname | |
1024 | assert_equal expected[2], user.lastname |
|
1024 | assert_equal expected[2], user.lastname | |
1025 | assert_equal 'only_my_events', user.mail_notification |
|
1025 | assert_equal 'only_my_events', user.mail_notification | |
1026 | end |
|
1026 | end | |
1027 | end |
|
1027 | end | |
1028 |
|
1028 | |||
1029 | def test_new_user_from_attributes_should_use_default_login_if_invalid |
|
1029 | def test_new_user_from_attributes_should_use_default_login_if_invalid | |
1030 | user = MailHandler.new_user_from_attributes('foo+bar@example.net') |
|
1030 | user = MailHandler.new_user_from_attributes('foo+bar@example.net') | |
1031 | assert user.valid? |
|
1031 | assert user.valid? | |
1032 | assert user.login =~ /^user[a-f0-9]+$/ |
|
1032 | assert user.login =~ /^user[a-f0-9]+$/ | |
1033 | assert_equal 'foo+bar@example.net', user.mail |
|
1033 | assert_equal 'foo+bar@example.net', user.mail | |
1034 | end |
|
1034 | end | |
1035 |
|
1035 | |||
1036 | def test_new_user_with_utf8_encoded_fullname_should_be_decoded |
|
1036 | def test_new_user_with_utf8_encoded_fullname_should_be_decoded | |
1037 | assert_difference 'User.count' do |
|
1037 | assert_difference 'User.count' do | |
1038 | issue = submit_email( |
|
1038 | issue = submit_email( | |
1039 | 'fullname_of_sender_as_utf8_encoded.eml', |
|
1039 | 'fullname_of_sender_as_utf8_encoded.eml', | |
1040 | :issue => {:project => 'ecookbook'}, |
|
1040 | :issue => {:project => 'ecookbook'}, | |
1041 | :unknown_user => 'create' |
|
1041 | :unknown_user => 'create' | |
1042 | ) |
|
1042 | ) | |
1043 | end |
|
1043 | end | |
1044 | user = User.order('id DESC').first |
|
1044 | user = User.order('id DESC').first | |
1045 | assert_equal "foo@example.org", user.mail |
|
1045 | assert_equal "foo@example.org", user.mail | |
1046 | str1 = "\xc3\x84\xc3\xa4".force_encoding('UTF-8') |
|
1046 | str1 = "\xc3\x84\xc3\xa4".force_encoding('UTF-8') | |
1047 | str2 = "\xc3\x96\xc3\xb6".force_encoding('UTF-8') |
|
1047 | str2 = "\xc3\x96\xc3\xb6".force_encoding('UTF-8') | |
1048 | assert_equal str1, user.firstname |
|
1048 | assert_equal str1, user.firstname | |
1049 | assert_equal str2, user.lastname |
|
1049 | assert_equal str2, user.lastname | |
1050 | end |
|
1050 | end | |
1051 |
|
1051 | |||
1052 | def test_extract_options_from_env_should_return_options |
|
1052 | def test_extract_options_from_env_should_return_options | |
1053 | options = MailHandler.extract_options_from_env({ |
|
1053 | options = MailHandler.extract_options_from_env({ | |
1054 | 'tracker' => 'defect', |
|
1054 | 'tracker' => 'defect', | |
1055 | 'project' => 'foo', |
|
1055 | 'project' => 'foo', | |
1056 | 'unknown_user' => 'create' |
|
1056 | 'unknown_user' => 'create' | |
1057 | }) |
|
1057 | }) | |
1058 |
|
1058 | |||
1059 | assert_equal({ |
|
1059 | assert_equal({ | |
1060 | :issue => {:tracker => 'defect', :project => 'foo'}, |
|
1060 | :issue => {:tracker => 'defect', :project => 'foo'}, | |
1061 | :unknown_user => 'create' |
|
1061 | :unknown_user => 'create' | |
1062 | }, options) |
|
1062 | }, options) | |
1063 | end |
|
1063 | end | |
1064 |
|
1064 | |||
1065 | def test_safe_receive_should_rescue_exceptions_and_return_false |
|
1065 | def test_safe_receive_should_rescue_exceptions_and_return_false | |
1066 | MailHandler.stubs(:receive).raises(Exception.new "Something went wrong") |
|
1066 | MailHandler.stubs(:receive).raises(Exception.new "Something went wrong") | |
1067 |
|
1067 | |||
1068 | assert_equal false, MailHandler.safe_receive |
|
1068 | assert_equal false, MailHandler.safe_receive | |
1069 | end |
|
1069 | end | |
1070 |
|
1070 | |||
1071 | private |
|
1071 | private | |
1072 |
|
1072 | |||
1073 | def submit_email(filename, options={}) |
|
1073 | def submit_email(filename, options={}) | |
1074 | raw = IO.read(File.join(FIXTURES_PATH, filename)) |
|
1074 | raw = IO.read(File.join(FIXTURES_PATH, filename)) | |
1075 | yield raw if block_given? |
|
1075 | yield raw if block_given? | |
1076 | MailHandler.receive(raw, options) |
|
1076 | MailHandler.receive(raw, options) | |
1077 | end |
|
1077 | end | |
1078 |
|
1078 | |||
1079 | def assert_issue_created(issue) |
|
1079 | def assert_issue_created(issue) | |
1080 | assert issue.is_a?(Issue) |
|
1080 | assert issue.is_a?(Issue) | |
1081 | assert !issue.new_record? |
|
1081 | assert !issue.new_record? | |
1082 | issue.reload |
|
1082 | issue.reload | |
1083 | end |
|
1083 | end | |
1084 | end |
|
1084 | end |
@@ -1,89 +1,89 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2016 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2016 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 UserPreferenceTest < ActiveSupport::TestCase |
|
20 | class UserPreferenceTest < ActiveSupport::TestCase | |
21 | fixtures :users, :user_preferences |
|
21 | fixtures :users, :user_preferences | |
22 |
|
22 | |||
23 | def test_hide_mail_should_default_to_true |
|
23 | def test_hide_mail_should_default_to_true | |
24 | preference = UserPreference.new |
|
24 | preference = UserPreference.new | |
25 | assert_equal true, preference.hide_mail |
|
25 | assert_equal true, preference.hide_mail | |
26 | end |
|
26 | end | |
27 |
|
27 | |||
28 | def test_hide_mail_should_default_to_false_with_setting |
|
28 | def test_hide_mail_should_default_to_false_with_setting | |
29 | with_settings :default_users_hide_mail => '0' do |
|
29 | with_settings :default_users_hide_mail => '0' do | |
30 | preference = UserPreference.new |
|
30 | preference = UserPreference.new | |
31 | assert_equal false, preference.hide_mail |
|
31 | assert_equal false, preference.hide_mail | |
32 | end |
|
32 | end | |
33 | end |
|
33 | end | |
34 |
|
34 | |||
|
35 | def test_no_self_notified_should_default_to_true | |||
|
36 | preference = UserPreference.new | |||
|
37 | assert_equal true, preference.no_self_notified | |||
|
38 | end | |||
|
39 | ||||
35 | def test_create |
|
40 | def test_create | |
36 | user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo") |
|
41 | user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo") | |
37 | user.login = "newuser" |
|
42 | user.login = "newuser" | |
38 | user.password, user.password_confirmation = "password", "password" |
|
43 | user.password, user.password_confirmation = "password", "password" | |
39 | assert user.save |
|
44 | assert user.save | |
40 |
|
45 | |||
41 | assert_kind_of UserPreference, user.pref |
|
46 | assert_kind_of UserPreference, user.pref | |
42 | assert_kind_of Hash, user.pref.others |
|
47 | assert_kind_of Hash, user.pref.others | |
43 | assert user.pref.save |
|
48 | assert user.pref.save | |
44 | end |
|
49 | end | |
45 |
|
50 | |||
46 | def test_update |
|
51 | def test_update | |
47 | user = User.find(1) |
|
52 | user = User.find(1) | |
48 | assert_equal true, user.pref.hide_mail |
|
53 | assert_equal true, user.pref.hide_mail | |
49 | user.pref['preftest'] = 'value' |
|
54 | user.pref['preftest'] = 'value' | |
50 | assert user.pref.save |
|
55 | assert user.pref.save | |
51 |
|
56 | |||
52 | user.reload |
|
57 | user.reload | |
53 | assert_equal 'value', user.pref['preftest'] |
|
58 | assert_equal 'value', user.pref['preftest'] | |
54 | end |
|
59 | end | |
55 |
|
60 | |||
56 | def test_others_hash |
|
61 | def test_others_hash | |
57 | user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo") |
|
62 | user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo") | |
58 | user.login = "newuser" |
|
63 | user.login = "newuser" | |
59 | user.password, user.password_confirmation = "password", "password" |
|
64 | user.password, user.password_confirmation = "password", "password" | |
60 | assert user.save |
|
65 | assert user.save | |
61 | assert_nil user.preference |
|
66 | assert_nil user.preference | |
62 | up = UserPreference.new(:user => user) |
|
67 | up = UserPreference.new(:user => user) | |
63 | assert_kind_of Hash, up.others |
|
68 | assert_kind_of Hash, up.others | |
64 | up.others = nil |
|
69 | up.others = nil | |
65 | assert_nil up.others |
|
70 | assert_nil up.others | |
66 | assert up.save |
|
71 | assert up.save | |
67 | assert_kind_of Hash, up.others |
|
72 | assert_kind_of Hash, up.others | |
68 | end |
|
73 | end | |
69 |
|
74 | |||
70 | def test_others_should_be_blank_after_initialization |
|
|||
71 | pref = User.new.pref |
|
|||
72 | assert_equal({}, pref.others) |
|
|||
73 | end |
|
|||
74 |
|
||||
75 | def test_reading_value_from_nil_others_hash |
|
75 | def test_reading_value_from_nil_others_hash | |
76 | up = UserPreference.new(:user => User.new) |
|
76 | up = UserPreference.new(:user => User.new) | |
77 | up.others = nil |
|
77 | up.others = nil | |
78 | assert_nil up.others |
|
78 | assert_nil up.others | |
79 | assert_nil up[:foo] |
|
79 | assert_nil up[:foo] | |
80 | end |
|
80 | end | |
81 |
|
81 | |||
82 | def test_writing_value_to_nil_others_hash |
|
82 | def test_writing_value_to_nil_others_hash | |
83 | up = UserPreference.new(:user => User.new) |
|
83 | up = UserPreference.new(:user => User.new) | |
84 | up.others = nil |
|
84 | up.others = nil | |
85 | assert_nil up.others |
|
85 | assert_nil up.others | |
86 | up[:foo] = 'bar' |
|
86 | up[:foo] = 'bar' | |
87 | assert_equal 'bar', up[:foo] |
|
87 | assert_equal 'bar', up[:foo] | |
88 | end |
|
88 | end | |
89 | end |
|
89 | end |
General Comments 0
You need to be logged in to leave comments.
Login now