##// END OF EJS Templates
Include url helpers in helper tests....
Jean-Philippe Lang -
r15304:ff50094d3e45
parent child
Show More
@@ -1,42 +1,43
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 GroupsHelperTest < Redmine::HelperTest
20 class GroupsHelperTest < Redmine::HelperTest
21 include Redmine::I18n
21 include Redmine::I18n
22 include ERB::Util
22 include ERB::Util
23 include GroupsHelper
23 include GroupsHelper
24 include Rails.application.routes.url_helpers
24
25
25 fixtures :users
26 fixtures :users
26
27
27 def test_render_principals_for_new_group_users
28 def test_render_principals_for_new_group_users
28 group = Group.generate!
29 group = Group.generate!
29
30
30 result = render_principals_for_new_group_users(group)
31 result = render_principals_for_new_group_users(group)
31 assert_select_in result, 'input[name=?][value="2"]', 'user_ids[]'
32 assert_select_in result, 'input[name=?][value="2"]', 'user_ids[]'
32 end
33 end
33
34
34 def test_render_principals_for_new_group_users_with_limited_results_should_paginate
35 def test_render_principals_for_new_group_users_with_limited_results_should_paginate
35 group = Group.generate!
36 group = Group.generate!
36
37
37 result = render_principals_for_new_group_users(group, 3)
38 result = render_principals_for_new_group_users(group, 3)
38 assert_select_in result, 'span.pagination'
39 assert_select_in result, 'span.pagination'
39 assert_select_in result, 'span.pagination li.current span', :text => '1'
40 assert_select_in result, 'span.pagination li.current span', :text => '1'
40 assert_select_in result, 'a[href=?]', "/groups/#{group.id}/autocomplete_for_user.js?page=2", :text => '2'
41 assert_select_in result, 'a[href=?]', "/groups/#{group.id}/autocomplete_for_user.js?page=2", :text => '2'
41 end
42 end
42 end
43 end
@@ -1,339 +1,339
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 IssuesHelperTest < Redmine::HelperTest
20 class IssuesHelperTest < Redmine::HelperTest
21 include Redmine::I18n
21 include Redmine::I18n
22 include IssuesHelper
22 include IssuesHelper
23 include CustomFieldsHelper
23 include CustomFieldsHelper
24 include ERB::Util
24 include ERB::Util
25 include Rails.application.routes.url_helpers
25 include Rails.application.routes.url_helpers
26
26
27 fixtures :projects, :trackers, :issue_statuses, :issues,
27 fixtures :projects, :trackers, :issue_statuses, :issues,
28 :enumerations, :users, :issue_categories,
28 :enumerations, :users, :issue_categories,
29 :projects_trackers,
29 :projects_trackers,
30 :roles,
30 :roles,
31 :member_roles,
31 :member_roles,
32 :members,
32 :members,
33 :enabled_modules,
33 :enabled_modules,
34 :custom_fields,
34 :custom_fields,
35 :attachments,
35 :attachments,
36 :versions
36 :versions
37
37
38 def setup
38 def setup
39 super
39 super
40 set_language_if_valid('en')
40 set_language_if_valid('en')
41 User.current = nil
41 User.current = nil
42 end
42 end
43
43
44 def test_issue_heading
44 def test_issue_heading
45 assert_equal "Bug #1", issue_heading(Issue.find(1))
45 assert_equal "Bug #1", issue_heading(Issue.find(1))
46 end
46 end
47
47
48 def test_issues_destroy_confirmation_message_with_one_root_issue
48 def test_issues_destroy_confirmation_message_with_one_root_issue
49 assert_equal l(:text_issues_destroy_confirmation),
49 assert_equal l(:text_issues_destroy_confirmation),
50 issues_destroy_confirmation_message(Issue.find(1))
50 issues_destroy_confirmation_message(Issue.find(1))
51 end
51 end
52
52
53 def test_issues_destroy_confirmation_message_with_an_arrayt_of_root_issues
53 def test_issues_destroy_confirmation_message_with_an_arrayt_of_root_issues
54 assert_equal l(:text_issues_destroy_confirmation),
54 assert_equal l(:text_issues_destroy_confirmation),
55 issues_destroy_confirmation_message(Issue.find([1, 2]))
55 issues_destroy_confirmation_message(Issue.find([1, 2]))
56 end
56 end
57
57
58 def test_issues_destroy_confirmation_message_with_one_parent_issue
58 def test_issues_destroy_confirmation_message_with_one_parent_issue
59 Issue.find(2).update_attribute :parent_issue_id, 1
59 Issue.find(2).update! :parent_issue_id => 1
60 assert_equal l(:text_issues_destroy_confirmation) + "\n" +
60 assert_equal l(:text_issues_destroy_confirmation) + "\n" +
61 l(:text_issues_destroy_descendants_confirmation, :count => 1),
61 l(:text_issues_destroy_descendants_confirmation, :count => 1),
62 issues_destroy_confirmation_message(Issue.find(1))
62 issues_destroy_confirmation_message(Issue.find(1))
63 end
63 end
64
64
65 def test_issues_destroy_confirmation_message_with_one_parent_issue_and_its_child
65 def test_issues_destroy_confirmation_message_with_one_parent_issue_and_its_child
66 Issue.find(2).update_attribute :parent_issue_id, 1
66 Issue.find(2).update! :parent_issue_id => 1
67 assert_equal l(:text_issues_destroy_confirmation),
67 assert_equal l(:text_issues_destroy_confirmation),
68 issues_destroy_confirmation_message(Issue.find([1, 2]))
68 issues_destroy_confirmation_message(Issue.find([1, 2]))
69 end
69 end
70
70
71 def test_issues_destroy_confirmation_message_with_issues_that_share_descendants
71 def test_issues_destroy_confirmation_message_with_issues_that_share_descendants
72 root = Issue.generate!
72 root = Issue.generate!
73 child = Issue.generate!(:parent_issue_id => root.id)
73 child = Issue.generate!(:parent_issue_id => root.id)
74 Issue.generate!(:parent_issue_id => child.id)
74 Issue.generate!(:parent_issue_id => child.id)
75
75
76 assert_equal l(:text_issues_destroy_confirmation) + "\n" +
76 assert_equal l(:text_issues_destroy_confirmation) + "\n" +
77 l(:text_issues_destroy_descendants_confirmation, :count => 1),
77 l(:text_issues_destroy_descendants_confirmation, :count => 1),
78 issues_destroy_confirmation_message([root.reload, child.reload])
78 issues_destroy_confirmation_message([root.reload, child.reload])
79 end
79 end
80
80
81 test 'show_detail with no_html should show a changing attribute' do
81 test 'show_detail with no_html should show a changing attribute' do
82 detail = JournalDetail.new(:property => 'attr', :old_value => '40',
82 detail = JournalDetail.new(:property => 'attr', :old_value => '40',
83 :value => '100', :prop_key => 'done_ratio')
83 :value => '100', :prop_key => 'done_ratio')
84 assert_equal "% Done changed from 40 to 100", show_detail(detail, true)
84 assert_equal "% Done changed from 40 to 100", show_detail(detail, true)
85 end
85 end
86
86
87 test 'show_detail with no_html should show a new attribute' do
87 test 'show_detail with no_html should show a new attribute' do
88 detail = JournalDetail.new(:property => 'attr', :old_value => nil,
88 detail = JournalDetail.new(:property => 'attr', :old_value => nil,
89 :value => '100', :prop_key => 'done_ratio')
89 :value => '100', :prop_key => 'done_ratio')
90 assert_equal "% Done set to 100", show_detail(detail, true)
90 assert_equal "% Done set to 100", show_detail(detail, true)
91 end
91 end
92
92
93 test 'show_detail with no_html should show a deleted attribute' do
93 test 'show_detail with no_html should show a deleted attribute' do
94 detail = JournalDetail.new(:property => 'attr', :old_value => '50',
94 detail = JournalDetail.new(:property => 'attr', :old_value => '50',
95 :value => nil, :prop_key => 'done_ratio')
95 :value => nil, :prop_key => 'done_ratio')
96 assert_equal "% Done deleted (50)", show_detail(detail, true)
96 assert_equal "% Done deleted (50)", show_detail(detail, true)
97 end
97 end
98
98
99 test 'show_detail with html should show a changing attribute with HTML highlights' do
99 test 'show_detail with html should show a changing attribute with HTML highlights' do
100 detail = JournalDetail.new(:property => 'attr', :old_value => '40',
100 detail = JournalDetail.new(:property => 'attr', :old_value => '40',
101 :value => '100', :prop_key => 'done_ratio')
101 :value => '100', :prop_key => 'done_ratio')
102 html = show_detail(detail, false)
102 html = show_detail(detail, false)
103 assert_include '<strong>% Done</strong>', html
103 assert_include '<strong>% Done</strong>', html
104 assert_include '<i>40</i>', html
104 assert_include '<i>40</i>', html
105 assert_include '<i>100</i>', html
105 assert_include '<i>100</i>', html
106 end
106 end
107
107
108 test 'show_detail with html should show a new attribute with HTML highlights' do
108 test 'show_detail with html should show a new attribute with HTML highlights' do
109 detail = JournalDetail.new(:property => 'attr', :old_value => nil,
109 detail = JournalDetail.new(:property => 'attr', :old_value => nil,
110 :value => '100', :prop_key => 'done_ratio')
110 :value => '100', :prop_key => 'done_ratio')
111 html = show_detail(detail, false)
111 html = show_detail(detail, false)
112 assert_include '<strong>% Done</strong>', html
112 assert_include '<strong>% Done</strong>', html
113 assert_include '<i>100</i>', html
113 assert_include '<i>100</i>', html
114 end
114 end
115
115
116 test 'show_detail with html should show a deleted attribute with HTML highlights' do
116 test 'show_detail with html should show a deleted attribute with HTML highlights' do
117 detail = JournalDetail.new(:property => 'attr', :old_value => '50',
117 detail = JournalDetail.new(:property => 'attr', :old_value => '50',
118 :value => nil, :prop_key => 'done_ratio')
118 :value => nil, :prop_key => 'done_ratio')
119 html = show_detail(detail, false)
119 html = show_detail(detail, false)
120 assert_include '<strong>% Done</strong>', html
120 assert_include '<strong>% Done</strong>', html
121 assert_include '<del><i>50</i></del>', html
121 assert_include '<del><i>50</i></del>', html
122 end
122 end
123
123
124 test 'show_detail with a start_date attribute should format the dates' do
124 test 'show_detail with a start_date attribute should format the dates' do
125 detail = JournalDetail.new(
125 detail = JournalDetail.new(
126 :property => 'attr',
126 :property => 'attr',
127 :old_value => '2010-01-01',
127 :old_value => '2010-01-01',
128 :value => '2010-01-31',
128 :value => '2010-01-31',
129 :prop_key => 'start_date'
129 :prop_key => 'start_date'
130 )
130 )
131 with_settings :date_format => '%m/%d/%Y' do
131 with_settings :date_format => '%m/%d/%Y' do
132 assert_match "01/31/2010", show_detail(detail, true)
132 assert_match "01/31/2010", show_detail(detail, true)
133 assert_match "01/01/2010", show_detail(detail, true)
133 assert_match "01/01/2010", show_detail(detail, true)
134 end
134 end
135 end
135 end
136
136
137 test 'show_detail with a due_date attribute should format the dates' do
137 test 'show_detail with a due_date attribute should format the dates' do
138 detail = JournalDetail.new(
138 detail = JournalDetail.new(
139 :property => 'attr',
139 :property => 'attr',
140 :old_value => '2010-01-01',
140 :old_value => '2010-01-01',
141 :value => '2010-01-31',
141 :value => '2010-01-31',
142 :prop_key => 'due_date'
142 :prop_key => 'due_date'
143 )
143 )
144 with_settings :date_format => '%m/%d/%Y' do
144 with_settings :date_format => '%m/%d/%Y' do
145 assert_match "01/31/2010", show_detail(detail, true)
145 assert_match "01/31/2010", show_detail(detail, true)
146 assert_match "01/01/2010", show_detail(detail, true)
146 assert_match "01/01/2010", show_detail(detail, true)
147 end
147 end
148 end
148 end
149
149
150 test 'show_detail should show old and new values with a project attribute' do
150 test 'show_detail should show old and new values with a project attribute' do
151 detail = JournalDetail.new(:property => 'attr', :prop_key => 'project_id',
151 detail = JournalDetail.new(:property => 'attr', :prop_key => 'project_id',
152 :old_value => 1, :value => 2)
152 :old_value => 1, :value => 2)
153 assert_match 'eCookbook', show_detail(detail, true)
153 assert_match 'eCookbook', show_detail(detail, true)
154 assert_match 'OnlineStore', show_detail(detail, true)
154 assert_match 'OnlineStore', show_detail(detail, true)
155 end
155 end
156
156
157 test 'show_detail should show old and new values with a issue status attribute' do
157 test 'show_detail should show old and new values with a issue status attribute' do
158 detail = JournalDetail.new(:property => 'attr', :prop_key => 'status_id',
158 detail = JournalDetail.new(:property => 'attr', :prop_key => 'status_id',
159 :old_value => 1, :value => 2)
159 :old_value => 1, :value => 2)
160 assert_match 'New', show_detail(detail, true)
160 assert_match 'New', show_detail(detail, true)
161 assert_match 'Assigned', show_detail(detail, true)
161 assert_match 'Assigned', show_detail(detail, true)
162 end
162 end
163
163
164 test 'show_detail should show old and new values with a tracker attribute' do
164 test 'show_detail should show old and new values with a tracker attribute' do
165 detail = JournalDetail.new(:property => 'attr', :prop_key => 'tracker_id',
165 detail = JournalDetail.new(:property => 'attr', :prop_key => 'tracker_id',
166 :old_value => 1, :value => 2)
166 :old_value => 1, :value => 2)
167 assert_match 'Bug', show_detail(detail, true)
167 assert_match 'Bug', show_detail(detail, true)
168 assert_match 'Feature request', show_detail(detail, true)
168 assert_match 'Feature request', show_detail(detail, true)
169 end
169 end
170
170
171 test 'show_detail should show old and new values with a assigned to attribute' do
171 test 'show_detail should show old and new values with a assigned to attribute' do
172 detail = JournalDetail.new(:property => 'attr', :prop_key => 'assigned_to_id',
172 detail = JournalDetail.new(:property => 'attr', :prop_key => 'assigned_to_id',
173 :old_value => 1, :value => 2)
173 :old_value => 1, :value => 2)
174 assert_match 'Redmine Admin', show_detail(detail, true)
174 assert_match 'Redmine Admin', show_detail(detail, true)
175 assert_match 'John Smith', show_detail(detail, true)
175 assert_match 'John Smith', show_detail(detail, true)
176 end
176 end
177
177
178 test 'show_detail should show old and new values with a priority attribute' do
178 test 'show_detail should show old and new values with a priority attribute' do
179 detail = JournalDetail.new(:property => 'attr', :prop_key => 'priority_id',
179 detail = JournalDetail.new(:property => 'attr', :prop_key => 'priority_id',
180 :old_value => 4, :value => 5)
180 :old_value => 4, :value => 5)
181 assert_match 'Low', show_detail(detail, true)
181 assert_match 'Low', show_detail(detail, true)
182 assert_match 'Normal', show_detail(detail, true)
182 assert_match 'Normal', show_detail(detail, true)
183 end
183 end
184
184
185 test 'show_detail should show old and new values with a category attribute' do
185 test 'show_detail should show old and new values with a category attribute' do
186 detail = JournalDetail.new(:property => 'attr', :prop_key => 'category_id',
186 detail = JournalDetail.new(:property => 'attr', :prop_key => 'category_id',
187 :old_value => 1, :value => 2)
187 :old_value => 1, :value => 2)
188 assert_match 'Printing', show_detail(detail, true)
188 assert_match 'Printing', show_detail(detail, true)
189 assert_match 'Recipes', show_detail(detail, true)
189 assert_match 'Recipes', show_detail(detail, true)
190 end
190 end
191
191
192 test 'show_detail should show old and new values with a fixed version attribute' do
192 test 'show_detail should show old and new values with a fixed version attribute' do
193 detail = JournalDetail.new(:property => 'attr', :prop_key => 'fixed_version_id',
193 detail = JournalDetail.new(:property => 'attr', :prop_key => 'fixed_version_id',
194 :old_value => 1, :value => 2)
194 :old_value => 1, :value => 2)
195 assert_match '0.1', show_detail(detail, true)
195 assert_match '0.1', show_detail(detail, true)
196 assert_match '1.0', show_detail(detail, true)
196 assert_match '1.0', show_detail(detail, true)
197 end
197 end
198
198
199 test 'show_detail should show old and new values with a estimated hours attribute' do
199 test 'show_detail should show old and new values with a estimated hours attribute' do
200 detail = JournalDetail.new(:property => 'attr', :prop_key => 'estimated_hours',
200 detail = JournalDetail.new(:property => 'attr', :prop_key => 'estimated_hours',
201 :old_value => '5', :value => '6.3')
201 :old_value => '5', :value => '6.3')
202 assert_match '5.00', show_detail(detail, true)
202 assert_match '5.00', show_detail(detail, true)
203 assert_match '6.30', show_detail(detail, true)
203 assert_match '6.30', show_detail(detail, true)
204 end
204 end
205
205
206 test 'show_detail should not show values with a description attribute' do
206 test 'show_detail should not show values with a description attribute' do
207 detail = JournalDetail.new(:property => 'attr', :prop_key => 'description',
207 detail = JournalDetail.new(:property => 'attr', :prop_key => 'description',
208 :old_value => 'Foo', :value => 'Bar')
208 :old_value => 'Foo', :value => 'Bar')
209 assert_equal 'Description updated', show_detail(detail, true)
209 assert_equal 'Description updated', show_detail(detail, true)
210 end
210 end
211
211
212 test 'show_detail should show old and new values with a custom field' do
212 test 'show_detail should show old and new values with a custom field' do
213 detail = JournalDetail.new(:property => 'cf', :prop_key => '1',
213 detail = JournalDetail.new(:property => 'cf', :prop_key => '1',
214 :old_value => 'MySQL', :value => 'PostgreSQL')
214 :old_value => 'MySQL', :value => 'PostgreSQL')
215 assert_equal 'Database changed from MySQL to PostgreSQL', show_detail(detail, true)
215 assert_equal 'Database changed from MySQL to PostgreSQL', show_detail(detail, true)
216 end
216 end
217
217
218 test 'show_detail should not show values with a long text custom field' do
218 test 'show_detail should not show values with a long text custom field' do
219 field = IssueCustomField.create!(:name => "Long field", :field_format => 'text')
219 field = IssueCustomField.create!(:name => "Long field", :field_format => 'text')
220 detail = JournalDetail.new(:property => 'cf', :prop_key => field.id,
220 detail = JournalDetail.new(:property => 'cf', :prop_key => field.id,
221 :old_value => 'Foo', :value => 'Bar')
221 :old_value => 'Foo', :value => 'Bar')
222 assert_equal 'Long field updated', show_detail(detail, true)
222 assert_equal 'Long field updated', show_detail(detail, true)
223 end
223 end
224
224
225 test 'show_detail should show added file' do
225 test 'show_detail should show added file' do
226 detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
226 detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
227 :old_value => nil, :value => 'error281.txt')
227 :old_value => nil, :value => 'error281.txt')
228 assert_match 'error281.txt', show_detail(detail, true)
228 assert_match 'error281.txt', show_detail(detail, true)
229 end
229 end
230
230
231 test 'show_detail should show removed file' do
231 test 'show_detail should show removed file' do
232 detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
232 detail = JournalDetail.new(:property => 'attachment', :prop_key => '1',
233 :old_value => 'error281.txt', :value => nil)
233 :old_value => 'error281.txt', :value => nil)
234 assert_match 'error281.txt', show_detail(detail, true)
234 assert_match 'error281.txt', show_detail(detail, true)
235 end
235 end
236
236
237 def test_show_detail_relation_added
237 def test_show_detail_relation_added
238 detail = JournalDetail.new(:property => 'relation',
238 detail = JournalDetail.new(:property => 'relation',
239 :prop_key => 'precedes',
239 :prop_key => 'precedes',
240 :value => 1)
240 :value => 1)
241 assert_equal "Precedes Bug #1: Cannot print recipes added", show_detail(detail, true)
241 assert_equal "Precedes Bug #1: Cannot print recipes added", show_detail(detail, true)
242 str = link_to("Bug #1", "/issues/1", :class => Issue.find(1).css_classes)
242 str = link_to("Bug #1", "/issues/1", :class => Issue.find(1).css_classes)
243 assert_equal "<strong>Precedes</strong> <i>#{str}: Cannot print recipes</i> added",
243 assert_equal "<strong>Precedes</strong> <i>#{str}: Cannot print recipes</i> added",
244 show_detail(detail, false)
244 show_detail(detail, false)
245 end
245 end
246
246
247 def test_show_detail_relation_added_with_inexistant_issue
247 def test_show_detail_relation_added_with_inexistant_issue
248 inexistant_issue_number = 9999
248 inexistant_issue_number = 9999
249 assert_nil Issue.find_by_id(inexistant_issue_number)
249 assert_nil Issue.find_by_id(inexistant_issue_number)
250 detail = JournalDetail.new(:property => 'relation',
250 detail = JournalDetail.new(:property => 'relation',
251 :prop_key => 'precedes',
251 :prop_key => 'precedes',
252 :value => inexistant_issue_number)
252 :value => inexistant_issue_number)
253 assert_equal "Precedes Issue ##{inexistant_issue_number} added", show_detail(detail, true)
253 assert_equal "Precedes Issue ##{inexistant_issue_number} added", show_detail(detail, true)
254 assert_equal "<strong>Precedes</strong> <i>Issue ##{inexistant_issue_number}</i> added", show_detail(detail, false)
254 assert_equal "<strong>Precedes</strong> <i>Issue ##{inexistant_issue_number}</i> added", show_detail(detail, false)
255 end
255 end
256
256
257 def test_show_detail_relation_added_should_not_disclose_issue_that_is_not_visible
257 def test_show_detail_relation_added_should_not_disclose_issue_that_is_not_visible
258 issue = Issue.generate!(:is_private => true)
258 issue = Issue.generate!(:is_private => true)
259 detail = JournalDetail.new(:property => 'relation',
259 detail = JournalDetail.new(:property => 'relation',
260 :prop_key => 'precedes',
260 :prop_key => 'precedes',
261 :value => issue.id)
261 :value => issue.id)
262
262
263 assert_equal "Precedes Issue ##{issue.id} added", show_detail(detail, true)
263 assert_equal "Precedes Issue ##{issue.id} added", show_detail(detail, true)
264 assert_equal "<strong>Precedes</strong> <i>Issue ##{issue.id}</i> added", show_detail(detail, false)
264 assert_equal "<strong>Precedes</strong> <i>Issue ##{issue.id}</i> added", show_detail(detail, false)
265 end
265 end
266
266
267 def test_show_detail_relation_deleted
267 def test_show_detail_relation_deleted
268 detail = JournalDetail.new(:property => 'relation',
268 detail = JournalDetail.new(:property => 'relation',
269 :prop_key => 'precedes',
269 :prop_key => 'precedes',
270 :old_value => 1)
270 :old_value => 1)
271 assert_equal "Precedes deleted (Bug #1: Cannot print recipes)", show_detail(detail, true)
271 assert_equal "Precedes deleted (Bug #1: Cannot print recipes)", show_detail(detail, true)
272 str = link_to("Bug #1",
272 str = link_to("Bug #1",
273 "/issues/1",
273 "/issues/1",
274 :class => Issue.find(1).css_classes)
274 :class => Issue.find(1).css_classes)
275 assert_equal "<strong>Precedes</strong> deleted (<i>#{str}: Cannot print recipes</i>)",
275 assert_equal "<strong>Precedes</strong> deleted (<i>#{str}: Cannot print recipes</i>)",
276 show_detail(detail, false)
276 show_detail(detail, false)
277 end
277 end
278
278
279 def test_show_detail_relation_deleted_with_inexistant_issue
279 def test_show_detail_relation_deleted_with_inexistant_issue
280 inexistant_issue_number = 9999
280 inexistant_issue_number = 9999
281 assert_nil Issue.find_by_id(inexistant_issue_number)
281 assert_nil Issue.find_by_id(inexistant_issue_number)
282 detail = JournalDetail.new(:property => 'relation',
282 detail = JournalDetail.new(:property => 'relation',
283 :prop_key => 'precedes',
283 :prop_key => 'precedes',
284 :old_value => inexistant_issue_number)
284 :old_value => inexistant_issue_number)
285 assert_equal "Precedes deleted (Issue #9999)", show_detail(detail, true)
285 assert_equal "Precedes deleted (Issue #9999)", show_detail(detail, true)
286 assert_equal "<strong>Precedes</strong> deleted (<i>Issue #9999</i>)", show_detail(detail, false)
286 assert_equal "<strong>Precedes</strong> deleted (<i>Issue #9999</i>)", show_detail(detail, false)
287 end
287 end
288
288
289 def test_show_detail_relation_deleted_should_not_disclose_issue_that_is_not_visible
289 def test_show_detail_relation_deleted_should_not_disclose_issue_that_is_not_visible
290 issue = Issue.generate!(:is_private => true)
290 issue = Issue.generate!(:is_private => true)
291 detail = JournalDetail.new(:property => 'relation',
291 detail = JournalDetail.new(:property => 'relation',
292 :prop_key => 'precedes',
292 :prop_key => 'precedes',
293 :old_value => issue.id)
293 :old_value => issue.id)
294
294
295 assert_equal "Precedes deleted (Issue ##{issue.id})", show_detail(detail, true)
295 assert_equal "Precedes deleted (Issue ##{issue.id})", show_detail(detail, true)
296 assert_equal "<strong>Precedes</strong> deleted (<i>Issue ##{issue.id}</i>)", show_detail(detail, false)
296 assert_equal "<strong>Precedes</strong> deleted (<i>Issue ##{issue.id}</i>)", show_detail(detail, false)
297 end
297 end
298
298
299 def test_details_to_strings_with_multiple_values_removed_from_custom_field
299 def test_details_to_strings_with_multiple_values_removed_from_custom_field
300 field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
300 field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
301 details = []
301 details = []
302 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '1', :value => nil)
302 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '1', :value => nil)
303 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '3', :value => nil)
303 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '3', :value => nil)
304
304
305 assert_equal ["User deleted (Dave Lopper, Redmine Admin)"], details_to_strings(details, true)
305 assert_equal ["User deleted (Dave Lopper, Redmine Admin)"], details_to_strings(details, true)
306 assert_equal ["<strong>User</strong> deleted (<del><i>Dave Lopper, Redmine Admin</i></del>)"], details_to_strings(details, false)
306 assert_equal ["<strong>User</strong> deleted (<del><i>Dave Lopper, Redmine Admin</i></del>)"], details_to_strings(details, false)
307 end
307 end
308
308
309 def test_details_to_strings_with_multiple_values_added_to_custom_field
309 def test_details_to_strings_with_multiple_values_added_to_custom_field
310 field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
310 field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
311 details = []
311 details = []
312 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '1')
312 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '1')
313 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '3')
313 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '3')
314
314
315 assert_equal ["User Dave Lopper, Redmine Admin added"], details_to_strings(details, true)
315 assert_equal ["User Dave Lopper, Redmine Admin added"], details_to_strings(details, true)
316 assert_equal ["<strong>User</strong> <i>Dave Lopper, Redmine Admin</i> added"], details_to_strings(details, false)
316 assert_equal ["<strong>User</strong> <i>Dave Lopper, Redmine Admin</i> added"], details_to_strings(details, false)
317 end
317 end
318
318
319 def test_details_to_strings_with_multiple_values_added_and_removed_from_custom_field
319 def test_details_to_strings_with_multiple_values_added_and_removed_from_custom_field
320 field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
320 field = IssueCustomField.generate!(:name => 'User', :field_format => 'user', :multiple => true)
321 details = []
321 details = []
322 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '1')
322 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => nil, :value => '1')
323 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '2', :value => nil)
323 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '2', :value => nil)
324 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '3', :value => nil)
324 details << JournalDetail.new(:property => 'cf', :prop_key => field.id.to_s, :old_value => '3', :value => nil)
325
325
326 assert_equal [
326 assert_equal [
327 "User Redmine Admin added",
327 "User Redmine Admin added",
328 "User deleted (Dave Lopper, John Smith)"
328 "User deleted (Dave Lopper, John Smith)"
329 ], details_to_strings(details, true)
329 ], details_to_strings(details, true)
330 assert_equal [
330 assert_equal [
331 "<strong>User</strong> <i>Redmine Admin</i> added",
331 "<strong>User</strong> <i>Redmine Admin</i> added",
332 "<strong>User</strong> deleted (<del><i>Dave Lopper, John Smith</i></del>)"
332 "<strong>User</strong> deleted (<del><i>Dave Lopper, John Smith</i></del>)"
333 ], details_to_strings(details, false)
333 ], details_to_strings(details, false)
334 end
334 end
335
335
336 def test_find_name_by_reflection_should_return_nil_for_missing_record
336 def test_find_name_by_reflection_should_return_nil_for_missing_record
337 assert_nil find_name_by_reflection('status', 99)
337 assert_nil find_name_by_reflection('status', 99)
338 end
338 end
339 end
339 end
@@ -1,43 +1,44
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 MembersHelperTest < Redmine::HelperTest
20 class MembersHelperTest < Redmine::HelperTest
21 include Redmine::I18n
21 include Redmine::I18n
22 include ERB::Util
22 include ERB::Util
23 include MembersHelper
23 include MembersHelper
24 include Rails.application.routes.url_helpers
24
25
25 fixtures :projects, :users, :members, :member_roles,
26 fixtures :projects, :users, :members, :member_roles,
26 :trackers, :issue_statuses
27 :trackers, :issue_statuses
27
28
28 def test_render_principals_for_new_members
29 def test_render_principals_for_new_members
29 project = Project.generate!
30 project = Project.generate!
30
31
31 result = render_principals_for_new_members(project)
32 result = render_principals_for_new_members(project)
32 assert_select_in result, 'input[name=?][value="2"]', 'membership[user_ids][]'
33 assert_select_in result, 'input[name=?][value="2"]', 'membership[user_ids][]'
33 end
34 end
34
35
35 def test_render_principals_for_new_members_with_limited_results_should_paginate
36 def test_render_principals_for_new_members_with_limited_results_should_paginate
36 project = Project.generate!
37 project = Project.generate!
37
38
38 result = render_principals_for_new_members(project, 3)
39 result = render_principals_for_new_members(project, 3)
39 assert_select_in result, 'span.pagination'
40 assert_select_in result, 'span.pagination'
40 assert_select_in result, 'span.pagination li.current span', :text => '1'
41 assert_select_in result, 'span.pagination li.current span', :text => '1'
41 assert_select_in result, 'a[href=?]', "/projects/#{project.identifier}/memberships/autocomplete.js?page=2", :text => '2'
42 assert_select_in result, 'a[href=?]', "/projects/#{project.identifier}/memberships/autocomplete.js?page=2", :text => '2'
42 end
43 end
43 end
44 end
@@ -1,498 +1,498
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 Redmine::Helpers::GanttHelperTest < ActionView::TestCase
20 class Redmine::Helpers::GanttHelperTest < Redmine::HelperTest
21 fixtures :projects, :trackers, :issue_statuses,
21 fixtures :projects, :trackers, :issue_statuses,
22 :enumerations, :users, :issue_categories
22 :enumerations, :users, :issue_categories
23
23
24 include ProjectsHelper
24 include ProjectsHelper
25 include IssuesHelper
25 include IssuesHelper
26 include ERB::Util
26 include ERB::Util
27 include Rails.application.routes.url_helpers
27 include Rails.application.routes.url_helpers
28
28
29 def setup
29 def setup
30 setup_with_controller
30 setup_with_controller
31 User.current = User.find(1)
31 User.current = User.find(1)
32 end
32 end
33
33
34 def today
34 def today
35 @today ||= Date.today
35 @today ||= Date.today
36 end
36 end
37 private :today
37 private :today
38
38
39 def gantt_start
39 def gantt_start
40 @gantt.date_from
40 @gantt.date_from
41 end
41 end
42
42
43 # Creates a Gantt chart for a 4 week span
43 # Creates a Gantt chart for a 4 week span
44 def create_gantt(project=Project.generate!, options={})
44 def create_gantt(project=Project.generate!, options={})
45 @project = project
45 @project = project
46 @gantt = Redmine::Helpers::Gantt.new(options)
46 @gantt = Redmine::Helpers::Gantt.new(options)
47 @gantt.project = @project
47 @gantt.project = @project
48 @gantt.query = IssueQuery.new(:project => @project, :name => 'Gantt')
48 @gantt.query = IssueQuery.new(:project => @project, :name => 'Gantt')
49 @gantt.view = self
49 @gantt.view = self
50 @gantt.instance_variable_set('@date_from', options[:date_from] || (today - 14))
50 @gantt.instance_variable_set('@date_from', options[:date_from] || (today - 14))
51 @gantt.instance_variable_set('@date_to', options[:date_to] || (today + 14))
51 @gantt.instance_variable_set('@date_to', options[:date_to] || (today + 14))
52 end
52 end
53 private :create_gantt
53 private :create_gantt
54
54
55 test "#number_of_rows with one project should return the number of rows just for that project" do
55 test "#number_of_rows with one project should return the number of rows just for that project" do
56 p1, p2 = Project.generate!, Project.generate!
56 p1, p2 = Project.generate!, Project.generate!
57 i1, i2 = Issue.generate!(:project => p1), Issue.generate!(:project => p2)
57 i1, i2 = Issue.generate!(:project => p1), Issue.generate!(:project => p2)
58 create_gantt(p1)
58 create_gantt(p1)
59 assert_equal 2, @gantt.number_of_rows
59 assert_equal 2, @gantt.number_of_rows
60 end
60 end
61
61
62 test "#number_of_rows with no project should return the total number of rows for all the projects, resursively" do
62 test "#number_of_rows with no project should return the total number of rows for all the projects, resursively" do
63 p1, p2 = Project.generate!, Project.generate!
63 p1, p2 = Project.generate!, Project.generate!
64 create_gantt(nil)
64 create_gantt(nil)
65 # fix the return value of #number_of_rows_on_project() to an arbitrary value
65 # fix the return value of #number_of_rows_on_project() to an arbitrary value
66 # so that we really only test #number_of_rows
66 # so that we really only test #number_of_rows
67 @gantt.stubs(:number_of_rows_on_project).returns(7)
67 @gantt.stubs(:number_of_rows_on_project).returns(7)
68 # also fix #projects because we want to test #number_of_rows in isolation
68 # also fix #projects because we want to test #number_of_rows in isolation
69 @gantt.stubs(:projects).returns(Project.all)
69 @gantt.stubs(:projects).returns(Project.all)
70 # actual test
70 # actual test
71 assert_equal Project.count*7, @gantt.number_of_rows
71 assert_equal Project.count*7, @gantt.number_of_rows
72 end
72 end
73
73
74 test "#number_of_rows should not exceed max_rows option" do
74 test "#number_of_rows should not exceed max_rows option" do
75 p = Project.generate!
75 p = Project.generate!
76 5.times do
76 5.times do
77 Issue.generate!(:project => p)
77 Issue.generate!(:project => p)
78 end
78 end
79 create_gantt(p)
79 create_gantt(p)
80 @gantt.render
80 @gantt.render
81 assert_equal 6, @gantt.number_of_rows
81 assert_equal 6, @gantt.number_of_rows
82 assert !@gantt.truncated
82 assert !@gantt.truncated
83 create_gantt(p, :max_rows => 3)
83 create_gantt(p, :max_rows => 3)
84 @gantt.render
84 @gantt.render
85 assert_equal 3, @gantt.number_of_rows
85 assert_equal 3, @gantt.number_of_rows
86 assert @gantt.truncated
86 assert @gantt.truncated
87 end
87 end
88
88
89 test "#number_of_rows_on_project should count 0 for an empty the project" do
89 test "#number_of_rows_on_project should count 0 for an empty the project" do
90 create_gantt
90 create_gantt
91 assert_equal 0, @gantt.number_of_rows_on_project(@project)
91 assert_equal 0, @gantt.number_of_rows_on_project(@project)
92 end
92 end
93
93
94 test "#number_of_rows_on_project should count the number of issues without a version" do
94 test "#number_of_rows_on_project should count the number of issues without a version" do
95 create_gantt
95 create_gantt
96 @project.issues << Issue.generate!(:project => @project, :fixed_version => nil)
96 @project.issues << Issue.generate!(:project => @project, :fixed_version => nil)
97 assert_equal 2, @gantt.number_of_rows_on_project(@project)
97 assert_equal 2, @gantt.number_of_rows_on_project(@project)
98 end
98 end
99
99
100 test "#number_of_rows_on_project should count the number of issues on versions, including cross-project" do
100 test "#number_of_rows_on_project should count the number of issues on versions, including cross-project" do
101 create_gantt
101 create_gantt
102 version = Version.generate!
102 version = Version.generate!
103 @project.versions << version
103 @project.versions << version
104 @project.issues << Issue.generate!(:project => @project, :fixed_version => version)
104 @project.issues << Issue.generate!(:project => @project, :fixed_version => version)
105 assert_equal 3, @gantt.number_of_rows_on_project(@project)
105 assert_equal 3, @gantt.number_of_rows_on_project(@project)
106 end
106 end
107
107
108 def setup_subjects
108 def setup_subjects
109 create_gantt
109 create_gantt
110 @project.enabled_module_names = [:issue_tracking]
110 @project.enabled_module_names = [:issue_tracking]
111 @tracker = Tracker.generate!
111 @tracker = Tracker.generate!
112 @project.trackers << @tracker
112 @project.trackers << @tracker
113 @version = Version.generate!(:effective_date => (today + 7), :sharing => 'none')
113 @version = Version.generate!(:effective_date => (today + 7), :sharing => 'none')
114 @project.versions << @version
114 @project.versions << @version
115 @issue = Issue.generate!(:fixed_version => @version,
115 @issue = Issue.generate!(:fixed_version => @version,
116 :subject => "gantt#line_for_project",
116 :subject => "gantt#line_for_project",
117 :tracker => @tracker,
117 :tracker => @tracker,
118 :project => @project,
118 :project => @project,
119 :done_ratio => 30,
119 :done_ratio => 30,
120 :start_date => (today - 1),
120 :start_date => (today - 1),
121 :due_date => (today + 7))
121 :due_date => (today + 7))
122 @project.issues << @issue
122 @project.issues << @issue
123 end
123 end
124 private :setup_subjects
124 private :setup_subjects
125
125
126 # TODO: more of an integration test
126 # TODO: more of an integration test
127 test "#subjects project should be rendered" do
127 test "#subjects project should be rendered" do
128 setup_subjects
128 setup_subjects
129 @output_buffer = @gantt.subjects
129 @output_buffer = @gantt.subjects
130 assert_select "div.project-name a", /#{@project.name}/
130 assert_select "div.project-name a", /#{@project.name}/
131 assert_select 'div.project-name[style*="left:4px"]'
131 assert_select 'div.project-name[style*="left:4px"]'
132 end
132 end
133
133
134 test "#subjects version should be rendered" do
134 test "#subjects version should be rendered" do
135 setup_subjects
135 setup_subjects
136 @output_buffer = @gantt.subjects
136 @output_buffer = @gantt.subjects
137 assert_select "div.version-name a", /#{@version.name}/
137 assert_select "div.version-name a", /#{@version.name}/
138 assert_select 'div.version-name[style*="left:24px"]'
138 assert_select 'div.version-name[style*="left:24px"]'
139 end
139 end
140
140
141 test "#subjects version without assigned issues should not be rendered" do
141 test "#subjects version without assigned issues should not be rendered" do
142 setup_subjects
142 setup_subjects
143 @version = Version.generate!(:effective_date => (today + 14),
143 @version = Version.generate!(:effective_date => (today + 14),
144 :sharing => 'none',
144 :sharing => 'none',
145 :name => 'empty_version')
145 :name => 'empty_version')
146 @project.versions << @version
146 @project.versions << @version
147 @output_buffer = @gantt.subjects
147 @output_buffer = @gantt.subjects
148 assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
148 assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
149 end
149 end
150
150
151 test "#subjects issue should be rendered" do
151 test "#subjects issue should be rendered" do
152 setup_subjects
152 setup_subjects
153 @output_buffer = @gantt.subjects
153 @output_buffer = @gantt.subjects
154 assert_select "div.issue-subject", /#{@issue.subject}/
154 assert_select "div.issue-subject", /#{@issue.subject}/
155 assert_select 'div.issue-subject[style*="left:44px"]'
155 assert_select 'div.issue-subject[style*="left:44px"]'
156 end
156 end
157
157
158 test "#subjects issue assigned to a shared version of another project should be rendered" do
158 test "#subjects issue assigned to a shared version of another project should be rendered" do
159 setup_subjects
159 setup_subjects
160 p = Project.generate!
160 p = Project.generate!
161 p.enabled_module_names = [:issue_tracking]
161 p.enabled_module_names = [:issue_tracking]
162 @shared_version = Version.generate!(:sharing => 'system')
162 @shared_version = Version.generate!(:sharing => 'system')
163 p.versions << @shared_version
163 p.versions << @shared_version
164 # Reassign the issue to a shared version of another project
164 # Reassign the issue to a shared version of another project
165 @issue = Issue.generate!(:fixed_version => @shared_version,
165 @issue = Issue.generate!(:fixed_version => @shared_version,
166 :subject => "gantt#assigned_to_shared_version",
166 :subject => "gantt#assigned_to_shared_version",
167 :tracker => @tracker,
167 :tracker => @tracker,
168 :project => @project,
168 :project => @project,
169 :done_ratio => 30,
169 :done_ratio => 30,
170 :start_date => (today - 1),
170 :start_date => (today - 1),
171 :due_date => (today + 7))
171 :due_date => (today + 7))
172 @project.issues << @issue
172 @project.issues << @issue
173 @output_buffer = @gantt.subjects
173 @output_buffer = @gantt.subjects
174 assert_select "div.issue-subject", /#{@issue.subject}/
174 assert_select "div.issue-subject", /#{@issue.subject}/
175 end
175 end
176
176
177 test "#subjects issue with subtasks should indent subtasks" do
177 test "#subjects issue with subtasks should indent subtasks" do
178 setup_subjects
178 setup_subjects
179 attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
179 attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
180 @child1 = Issue.generate!(
180 @child1 = Issue.generate!(
181 attrs.merge(:subject => 'child1',
181 attrs.merge(:subject => 'child1',
182 :parent_issue_id => @issue.id,
182 :parent_issue_id => @issue.id,
183 :start_date => (today - 1),
183 :start_date => (today - 1),
184 :due_date => (today + 2))
184 :due_date => (today + 2))
185 )
185 )
186 @child2 = Issue.generate!(
186 @child2 = Issue.generate!(
187 attrs.merge(:subject => 'child2',
187 attrs.merge(:subject => 'child2',
188 :parent_issue_id => @issue.id,
188 :parent_issue_id => @issue.id,
189 :start_date => today,
189 :start_date => today,
190 :due_date => (today + 7))
190 :due_date => (today + 7))
191 )
191 )
192 @grandchild = Issue.generate!(
192 @grandchild = Issue.generate!(
193 attrs.merge(:subject => 'grandchild',
193 attrs.merge(:subject => 'grandchild',
194 :parent_issue_id => @child1.id,
194 :parent_issue_id => @child1.id,
195 :start_date => (today - 1),
195 :start_date => (today - 1),
196 :due_date => (today + 2))
196 :due_date => (today + 2))
197 )
197 )
198 @output_buffer = @gantt.subjects
198 @output_buffer = @gantt.subjects
199 # parent task 44px
199 # parent task 44px
200 assert_select 'div.issue-subject[style*="left:44px"]', /#{@issue.subject}/
200 assert_select 'div.issue-subject[style*="left:44px"]', /#{@issue.subject}/
201 # children 64px
201 # children 64px
202 assert_select 'div.issue-subject[style*="left:64px"]', /child1/
202 assert_select 'div.issue-subject[style*="left:64px"]', /child1/
203 assert_select 'div.issue-subject[style*="left:64px"]', /child2/
203 assert_select 'div.issue-subject[style*="left:64px"]', /child2/
204 # grandchild 84px
204 # grandchild 84px
205 assert_select 'div.issue-subject[style*="left:84px"]', /grandchild/, @output_buffer
205 assert_select 'div.issue-subject[style*="left:84px"]', /grandchild/, @output_buffer
206 end
206 end
207
207
208 test "#lines" do
208 test "#lines" do
209 create_gantt
209 create_gantt
210 @project.enabled_module_names = [:issue_tracking]
210 @project.enabled_module_names = [:issue_tracking]
211 @tracker = Tracker.generate!
211 @tracker = Tracker.generate!
212 @project.trackers << @tracker
212 @project.trackers << @tracker
213 @version = Version.generate!(:effective_date => (today + 7))
213 @version = Version.generate!(:effective_date => (today + 7))
214 @project.versions << @version
214 @project.versions << @version
215 @issue = Issue.generate!(:fixed_version => @version,
215 @issue = Issue.generate!(:fixed_version => @version,
216 :subject => "gantt#line_for_project",
216 :subject => "gantt#line_for_project",
217 :tracker => @tracker,
217 :tracker => @tracker,
218 :project => @project,
218 :project => @project,
219 :done_ratio => 30,
219 :done_ratio => 30,
220 :start_date => (today - 1),
220 :start_date => (today - 1),
221 :due_date => (today + 7))
221 :due_date => (today + 7))
222 @project.issues << @issue
222 @project.issues << @issue
223 @output_buffer = @gantt.lines
223 @output_buffer = @gantt.lines
224
224
225 assert_select "div.project.task_todo"
225 assert_select "div.project.task_todo"
226 assert_select "div.project.starting"
226 assert_select "div.project.starting"
227 assert_select "div.project.ending"
227 assert_select "div.project.ending"
228 assert_select "div.label.project", /#{@project.name}/
228 assert_select "div.label.project", /#{@project.name}/
229
229
230 assert_select "div.version.task_todo"
230 assert_select "div.version.task_todo"
231 assert_select "div.version.starting"
231 assert_select "div.version.starting"
232 assert_select "div.version.ending"
232 assert_select "div.version.ending"
233 assert_select "div.label.version", /#{@version.name}/
233 assert_select "div.label.version", /#{@version.name}/
234
234
235 assert_select "div.task_todo"
235 assert_select "div.task_todo"
236 assert_select "div.task.label", /#{@issue.done_ratio}/
236 assert_select "div.task.label", /#{@issue.done_ratio}/
237 assert_select "div.tooltip", /#{@issue.subject}/
237 assert_select "div.tooltip", /#{@issue.subject}/
238 end
238 end
239
239
240 test "#subject_for_project" do
240 test "#subject_for_project" do
241 create_gantt
241 create_gantt
242 @output_buffer = @gantt.subject_for_project(@project, :format => :html)
242 @output_buffer = @gantt.subject_for_project(@project, :format => :html)
243 assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
243 assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
244 end
244 end
245
245
246 test "#subject_for_project should style overdue projects" do
246 test "#subject_for_project should style overdue projects" do
247 create_gantt
247 create_gantt
248 @project.stubs(:overdue?).returns(true)
248 @project.stubs(:overdue?).returns(true)
249 @output_buffer = @gantt.subject_for_project(@project, :format => :html)
249 @output_buffer = @gantt.subject_for_project(@project, :format => :html)
250 assert_select 'div span.project-overdue'
250 assert_select 'div span.project-overdue'
251 end
251 end
252
252
253 test "#subject_for_version" do
253 test "#subject_for_version" do
254 create_gantt
254 create_gantt
255 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
255 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
256 @output_buffer = @gantt.subject_for_version(version, :format => :html)
256 @output_buffer = @gantt.subject_for_version(version, :format => :html)
257 assert_select 'a[href=?]', "/versions/#{version.to_param}", :text => /Foo/
257 assert_select 'a[href=?]', "/versions/#{version.to_param}", :text => /Foo/
258 end
258 end
259
259
260 test "#subject_for_version should style overdue versions" do
260 test "#subject_for_version should style overdue versions" do
261 create_gantt
261 create_gantt
262 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
262 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
263 version.stubs(:overdue?).returns(true)
263 version.stubs(:overdue?).returns(true)
264 @output_buffer = @gantt.subject_for_version(version, :format => :html)
264 @output_buffer = @gantt.subject_for_version(version, :format => :html)
265 assert_select 'div span.version-overdue'
265 assert_select 'div span.version-overdue'
266 end
266 end
267
267
268 test "#subject_for_version should style behind schedule versions" do
268 test "#subject_for_version should style behind schedule versions" do
269 create_gantt
269 create_gantt
270 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
270 version = Version.generate!(:name => 'Foo', :effective_date => today, :project => @project)
271 version.stubs(:behind_schedule?).returns(true)
271 version.stubs(:behind_schedule?).returns(true)
272 @output_buffer = @gantt.subject_for_version(version, :format => :html)
272 @output_buffer = @gantt.subject_for_version(version, :format => :html)
273 assert_select 'div span.version-behind-schedule'
273 assert_select 'div span.version-behind-schedule'
274 end
274 end
275
275
276 test "#subject_for_issue" do
276 test "#subject_for_issue" do
277 create_gantt
277 create_gantt
278 issue = Issue.generate!(:project => @project)
278 issue = Issue.generate!(:project => @project)
279 @output_buffer = @gantt.subject_for_issue(issue, :format => :html)
279 @output_buffer = @gantt.subject_for_issue(issue, :format => :html)
280 assert_select 'div', :text => /#{issue.subject}/
280 assert_select 'div', :text => /#{issue.subject}/
281 assert_select 'a[href=?]', "/issues/#{issue.to_param}", :text => /#{issue.tracker.name} ##{issue.id}/
281 assert_select 'a[href=?]', "/issues/#{issue.to_param}", :text => /#{issue.tracker.name} ##{issue.id}/
282 end
282 end
283
283
284 test "#subject_for_issue should style overdue issues" do
284 test "#subject_for_issue should style overdue issues" do
285 create_gantt
285 create_gantt
286 issue = Issue.generate!(:project => @project)
286 issue = Issue.generate!(:project => @project)
287 issue.stubs(:overdue?).returns(true)
287 issue.stubs(:overdue?).returns(true)
288 @output_buffer = @gantt.subject_for_issue(issue, :format => :html)
288 @output_buffer = @gantt.subject_for_issue(issue, :format => :html)
289 assert_select 'div span.issue-overdue'
289 assert_select 'div span.issue-overdue'
290 end
290 end
291
291
292 test "#subject should add an absolute positioned div" do
292 test "#subject should add an absolute positioned div" do
293 create_gantt
293 create_gantt
294 @output_buffer = @gantt.subject('subject', :format => :html)
294 @output_buffer = @gantt.subject('subject', :format => :html)
295 assert_select "div[style*=absolute]", :text => 'subject'
295 assert_select "div[style*=absolute]", :text => 'subject'
296 end
296 end
297
297
298 test "#subject should use the indent option to move the div to the right" do
298 test "#subject should use the indent option to move the div to the right" do
299 create_gantt
299 create_gantt
300 @output_buffer = @gantt.subject('subject', :format => :html, :indent => 40)
300 @output_buffer = @gantt.subject('subject', :format => :html, :indent => 40)
301 assert_select 'div[style*="left:40"]'
301 assert_select 'div[style*="left:40"]'
302 end
302 end
303
303
304 test "#line_for_project" do
304 test "#line_for_project" do
305 create_gantt
305 create_gantt
306 @project.stubs(:start_date).returns(today - 7)
306 @project.stubs(:start_date).returns(today - 7)
307 @project.stubs(:due_date).returns(today + 7)
307 @project.stubs(:due_date).returns(today + 7)
308 @output_buffer = @gantt.line_for_project(@project, :format => :html)
308 @output_buffer = @gantt.line_for_project(@project, :format => :html)
309 assert_select "div.project.label", :text => @project.name
309 assert_select "div.project.label", :text => @project.name
310 end
310 end
311
311
312 test "#line_for_version" do
312 test "#line_for_version" do
313 create_gantt
313 create_gantt
314 version = Version.generate!(:name => 'Foo', :project => @project)
314 version = Version.generate!(:name => 'Foo', :project => @project)
315 version.stubs(:start_date).returns(today - 7)
315 version.stubs(:start_date).returns(today - 7)
316 version.stubs(:due_date).returns(today + 7)
316 version.stubs(:due_date).returns(today + 7)
317 version.stubs(:completed_percent).returns(30)
317 version.stubs(:completed_percent).returns(30)
318 @output_buffer = @gantt.line_for_version(version, :format => :html)
318 @output_buffer = @gantt.line_for_version(version, :format => :html)
319 assert_select "div.version.label", :text => /Foo/
319 assert_select "div.version.label", :text => /Foo/
320 assert_select "div.version.label", :text => /30%/
320 assert_select "div.version.label", :text => /30%/
321 end
321 end
322
322
323 test "#line_for_issue" do
323 test "#line_for_issue" do
324 create_gantt
324 create_gantt
325 issue = Issue.generate!(:project => @project, :start_date => today - 7, :due_date => today + 7, :done_ratio => 30)
325 issue = Issue.generate!(:project => @project, :start_date => today - 7, :due_date => today + 7, :done_ratio => 30)
326 @output_buffer = @gantt.line_for_issue(issue, :format => :html)
326 @output_buffer = @gantt.line_for_issue(issue, :format => :html)
327 assert_select "div.task.label", :text => /#{issue.status.name}/
327 assert_select "div.task.label", :text => /#{issue.status.name}/
328 assert_select "div.task.label", :text => /30%/
328 assert_select "div.task.label", :text => /30%/
329 assert_select "div.tooltip", /#{issue.subject}/
329 assert_select "div.tooltip", /#{issue.subject}/
330 end
330 end
331
331
332 test "#line todo line should start from the starting point on the left" do
332 test "#line todo line should start from the starting point on the left" do
333 create_gantt
333 create_gantt
334 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
334 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
335 assert_select 'div.task_todo[style*="left:28px"]', 1
335 assert_select 'div.task_todo[style*="left:28px"]', 1
336 end
336 end
337
337
338 test "#line todo line should be the total width" do
338 test "#line todo line should be the total width" do
339 create_gantt
339 create_gantt
340 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
340 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
341 assert_select 'div.task_todo[style*="width:58px"]', 1
341 assert_select 'div.task_todo[style*="width:58px"]', 1
342 end
342 end
343
343
344 test "#line late line should start from the starting point on the left" do
344 test "#line late line should start from the starting point on the left" do
345 create_gantt
345 create_gantt
346 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
346 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
347 assert_select 'div.task_late[style*="left:28px"]', 1
347 assert_select 'div.task_late[style*="left:28px"]', 1
348 end
348 end
349
349
350 test "#line late line should be the total delayed width" do
350 test "#line late line should be the total delayed width" do
351 create_gantt
351 create_gantt
352 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
352 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
353 assert_select 'div.task_late[style*="width:30px"]', 1
353 assert_select 'div.task_late[style*="width:30px"]', 1
354 end
354 end
355
355
356 test "#line done line should start from the starting point on the left" do
356 test "#line done line should start from the starting point on the left" do
357 create_gantt
357 create_gantt
358 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
358 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
359 assert_select 'div.task_done[style*="left:28px"]', 1
359 assert_select 'div.task_done[style*="left:28px"]', 1
360 end
360 end
361
361
362 test "#line done line should be the width for the done ratio" do
362 test "#line done line should be the width for the done ratio" do
363 create_gantt
363 create_gantt
364 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
364 @output_buffer = @gantt.line(today - 7, today + 7, 30, false, 'line', :format => :html, :zoom => 4)
365 # 15 days * 4 px * 30% - 2 px for borders = 16 px
365 # 15 days * 4 px * 30% - 2 px for borders = 16 px
366 assert_select 'div.task_done[style*="width:16px"]', 1
366 assert_select 'div.task_done[style*="width:16px"]', 1
367 end
367 end
368
368
369 test "#line done line should be the total width for 100% done ratio" do
369 test "#line done line should be the total width for 100% done ratio" do
370 create_gantt
370 create_gantt
371 @output_buffer = @gantt.line(today - 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
371 @output_buffer = @gantt.line(today - 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
372 # 15 days * 4 px - 2 px for borders = 58 px
372 # 15 days * 4 px - 2 px for borders = 58 px
373 assert_select 'div.task_done[style*="width:58px"]', 1
373 assert_select 'div.task_done[style*="width:58px"]', 1
374 end
374 end
375
375
376 test "#line done line should be the total width for 100% done ratio with same start and end dates" do
376 test "#line done line should be the total width for 100% done ratio with same start and end dates" do
377 create_gantt
377 create_gantt
378 @output_buffer = @gantt.line(today + 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
378 @output_buffer = @gantt.line(today + 7, today + 7, 100, false, 'line', :format => :html, :zoom => 4)
379 assert_select 'div.task_done[style*="width:2px"]', 1
379 assert_select 'div.task_done[style*="width:2px"]', 1
380 end
380 end
381
381
382 test "#line done line should not be the total done width if the gantt starts after start date" do
382 test "#line done line should not be the total done width if the gantt starts after start date" do
383 create_gantt
383 create_gantt
384 @output_buffer = @gantt.line(today - 16, today - 2, 30, false, 'line', :format => :html, :zoom => 4)
384 @output_buffer = @gantt.line(today - 16, today - 2, 30, false, 'line', :format => :html, :zoom => 4)
385 assert_select 'div.task_done[style*="left:0px"]', 1
385 assert_select 'div.task_done[style*="left:0px"]', 1
386 assert_select 'div.task_done[style*="width:8px"]', 1
386 assert_select 'div.task_done[style*="width:8px"]', 1
387 end
387 end
388
388
389 test "#line starting marker should appear at the start date" do
389 test "#line starting marker should appear at the start date" do
390 create_gantt
390 create_gantt
391 @output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
391 @output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
392 assert_select "div.starting", 1
392 assert_select "div.starting", 1
393 assert_select 'div.starting[style*="left:28px"]', 1
393 assert_select 'div.starting[style*="left:28px"]', 1
394 end
394 end
395
395
396 test "#line starting marker should not appear if the start date is before gantt start date" do
396 test "#line starting marker should not appear if the start date is before gantt start date" do
397 create_gantt
397 create_gantt
398 @output_buffer = @gantt.line(gantt_start - 2, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
398 @output_buffer = @gantt.line(gantt_start - 2, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
399 assert_select "div.starting", 0
399 assert_select "div.starting", 0
400 end
400 end
401
401
402 test "#line ending marker should appear at the end date" do
402 test "#line ending marker should appear at the end date" do
403 create_gantt
403 create_gantt
404 @output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
404 @output_buffer = @gantt.line(today - 7, today + 7, 30, true, 'line', :format => :html, :zoom => 4)
405 assert_select "div.ending", 1
405 assert_select "div.ending", 1
406 assert_select 'div.ending[style*="left:88px"]', 1
406 assert_select 'div.ending[style*="left:88px"]', 1
407 end
407 end
408
408
409 test "#line ending marker should not appear if the end date is before gantt start date" do
409 test "#line ending marker should not appear if the end date is before gantt start date" do
410 create_gantt
410 create_gantt
411 @output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
411 @output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
412 assert_select "div.ending", 0
412 assert_select "div.ending", 0
413 end
413 end
414
414
415 test "#line label should appear at the far left, even if it's before gantt start date" do
415 test "#line label should appear at the far left, even if it's before gantt start date" do
416 create_gantt
416 create_gantt
417 @output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
417 @output_buffer = @gantt.line(gantt_start - 30, gantt_start - 21, 30, true, 'line', :format => :html)
418 assert_select "div.label", :text => 'line'
418 assert_select "div.label", :text => 'line'
419 end
419 end
420
420
421 def test_sort_issues_no_date
421 def test_sort_issues_no_date
422 project = Project.generate!
422 project = Project.generate!
423 issue1 = Issue.generate!(:subject => "test", :project => project)
423 issue1 = Issue.generate!(:subject => "test", :project => project)
424 issue2 = Issue.generate!(:subject => "test", :project => project)
424 issue2 = Issue.generate!(:subject => "test", :project => project)
425 assert issue1.root_id < issue2.root_id
425 assert issue1.root_id < issue2.root_id
426 child1 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
426 child1 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
427 :project => project)
427 :project => project)
428 child2 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
428 child2 = Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
429 :project => project)
429 :project => project)
430 child3 = Issue.generate!(:parent_issue_id => child1.id, :subject => 'child',
430 child3 = Issue.generate!(:parent_issue_id => child1.id, :subject => 'child',
431 :project => project)
431 :project => project)
432 assert_equal child1.root_id, child2.root_id
432 assert_equal child1.root_id, child2.root_id
433 assert child1.lft < child2.lft
433 assert child1.lft < child2.lft
434 assert child3.lft < child2.lft
434 assert child3.lft < child2.lft
435 issues = [child3, child2, child1, issue2, issue1]
435 issues = [child3, child2, child1, issue2, issue1]
436 Redmine::Helpers::Gantt.sort_issues!(issues)
436 Redmine::Helpers::Gantt.sort_issues!(issues)
437 assert_equal [issue1.id, child1.id, child3.id, child2.id, issue2.id],
437 assert_equal [issue1.id, child1.id, child3.id, child2.id, issue2.id],
438 issues.map{|v| v.id}
438 issues.map{|v| v.id}
439 end
439 end
440
440
441 def test_sort_issues_root_only
441 def test_sort_issues_root_only
442 project = Project.generate!
442 project = Project.generate!
443 issue1 = Issue.generate!(:subject => "test", :project => project)
443 issue1 = Issue.generate!(:subject => "test", :project => project)
444 issue2 = Issue.generate!(:subject => "test", :project => project)
444 issue2 = Issue.generate!(:subject => "test", :project => project)
445 issue3 = Issue.generate!(:subject => "test", :project => project,
445 issue3 = Issue.generate!(:subject => "test", :project => project,
446 :start_date => (today - 1))
446 :start_date => (today - 1))
447 issue4 = Issue.generate!(:subject => "test", :project => project,
447 issue4 = Issue.generate!(:subject => "test", :project => project,
448 :start_date => (today - 2))
448 :start_date => (today - 2))
449 issues = [issue4, issue3, issue2, issue1]
449 issues = [issue4, issue3, issue2, issue1]
450 Redmine::Helpers::Gantt.sort_issues!(issues)
450 Redmine::Helpers::Gantt.sort_issues!(issues)
451 assert_equal [issue1.id, issue2.id, issue4.id, issue3.id],
451 assert_equal [issue1.id, issue2.id, issue4.id, issue3.id],
452 issues.map{|v| v.id}
452 issues.map{|v| v.id}
453 end
453 end
454
454
455 def test_sort_issues_tree
455 def test_sort_issues_tree
456 project = Project.generate!
456 project = Project.generate!
457 issue1 = Issue.generate!(:subject => "test", :project => project)
457 issue1 = Issue.generate!(:subject => "test", :project => project)
458 issue2 = Issue.generate!(:subject => "test", :project => project,
458 issue2 = Issue.generate!(:subject => "test", :project => project,
459 :start_date => (today - 2))
459 :start_date => (today - 2))
460 issue1_child1 =
460 issue1_child1 =
461 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
461 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
462 :project => project)
462 :project => project)
463 issue1_child2 =
463 issue1_child2 =
464 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
464 Issue.generate!(:parent_issue_id => issue1.id, :subject => 'child',
465 :project => project, :start_date => (today - 10))
465 :project => project, :start_date => (today - 10))
466 issue1_child1_child1 =
466 issue1_child1_child1 =
467 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
467 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
468 :project => project, :start_date => (today - 8))
468 :project => project, :start_date => (today - 8))
469 issue1_child1_child2 =
469 issue1_child1_child2 =
470 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
470 Issue.generate!(:parent_issue_id => issue1_child1.id, :subject => 'child',
471 :project => project, :start_date => (today - 9))
471 :project => project, :start_date => (today - 9))
472 issue1_child1_child1_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child1)
472 issue1_child1_child1_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child1)
473 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
473 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
474 [today - 8, issue1_child1_child1.id]],
474 [today - 8, issue1_child1_child1.id]],
475 issue1_child1_child1_logic
475 issue1_child1_child1_logic
476 issue1_child1_child2_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child2)
476 issue1_child1_child2_logic = Redmine::Helpers::Gantt.sort_issue_logic(issue1_child1_child2)
477 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
477 assert_equal [[today - 10, issue1.id], [today - 9, issue1_child1.id],
478 [today - 9, issue1_child1_child2.id]],
478 [today - 9, issue1_child1_child2.id]],
479 issue1_child1_child2_logic
479 issue1_child1_child2_logic
480 issues = [issue1_child1_child2, issue1_child1_child1, issue1_child2,
480 issues = [issue1_child1_child2, issue1_child1_child1, issue1_child2,
481 issue1_child1, issue2, issue1]
481 issue1_child1, issue2, issue1]
482 Redmine::Helpers::Gantt.sort_issues!(issues)
482 Redmine::Helpers::Gantt.sort_issues!(issues)
483 assert_equal [issue1.id, issue1_child1.id, issue1_child2.id,
483 assert_equal [issue1.id, issue1_child1.id, issue1_child2.id,
484 issue1_child1_child2.id, issue1_child1_child1.id, issue2.id],
484 issue1_child1_child2.id, issue1_child1_child1.id, issue2.id],
485 issues.map{|v| v.id}
485 issues.map{|v| v.id}
486 end
486 end
487
487
488 def test_sort_versions
488 def test_sort_versions
489 project = Project.generate!
489 project = Project.generate!
490 versions = []
490 versions = []
491 versions << Version.create!(:project => project, :name => 'test1')
491 versions << Version.create!(:project => project, :name => 'test1')
492 versions << Version.create!(:project => project, :name => 'test2', :effective_date => '2013-10-25')
492 versions << Version.create!(:project => project, :name => 'test2', :effective_date => '2013-10-25')
493 versions << Version.create!(:project => project, :name => 'test3')
493 versions << Version.create!(:project => project, :name => 'test3')
494 versions << Version.create!(:project => project, :name => 'test4', :effective_date => '2013-10-02')
494 versions << Version.create!(:project => project, :name => 'test4', :effective_date => '2013-10-02')
495
495
496 assert_equal versions.sort, Redmine::Helpers::Gantt.sort_versions!(versions.dup)
496 assert_equal versions.sort, Redmine::Helpers::Gantt.sort_versions!(versions.dup)
497 end
497 end
498 end
498 end
@@ -1,341 +1,342
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 Redmine::MenuManager::MenuHelperTest < ActionView::TestCase
20 class Redmine::MenuManager::MenuHelperTest < Redmine::HelperTest
21
22 include Redmine::MenuManager::MenuHelper
21 include Redmine::MenuManager::MenuHelper
23 include ERB::Util
22 include ERB::Util
23 include Rails.application.routes.url_helpers
24
24 fixtures :users, :members, :projects, :enabled_modules, :roles, :member_roles
25 fixtures :users, :members, :projects, :enabled_modules, :roles, :member_roles
25
26
26 def setup
27 def setup
27 setup_with_controller
28 setup_with_controller
28 # Stub the current menu item in the controller
29 # Stub the current menu item in the controller
29 def current_menu_item
30 def current_menu_item
30 :index
31 :index
31 end
32 end
32 end
33 end
33
34
34 def test_render_single_menu_node
35 def test_render_single_menu_node
35 node = Redmine::MenuManager::MenuItem.new(:testing, '/test', { })
36 node = Redmine::MenuManager::MenuItem.new(:testing, '/test', { })
36 @output_buffer = render_single_menu_node(node, 'This is a test', node.url, false)
37 @output_buffer = render_single_menu_node(node, 'This is a test', node.url, false)
37
38
38 assert_select("a.testing", "This is a test")
39 assert_select("a.testing", "This is a test")
39 end
40 end
40
41
41 def test_render_menu_node
42 def test_render_menu_node
42 single_node = Redmine::MenuManager::MenuItem.new(:single_node, '/test', { })
43 single_node = Redmine::MenuManager::MenuItem.new(:single_node, '/test', { })
43 @output_buffer = render_menu_node(single_node, nil)
44 @output_buffer = render_menu_node(single_node, nil)
44
45
45 assert_select("li") do
46 assert_select("li") do
46 assert_select("a.single-node", "Single node")
47 assert_select("a.single-node", "Single node")
47 end
48 end
48 end
49 end
49
50
50 def test_render_menu_node_with_symbol_as_url
51 def test_render_menu_node_with_symbol_as_url
51 node = Redmine::MenuManager::MenuItem.new(:testing, :issues_path)
52 node = Redmine::MenuManager::MenuItem.new(:testing, :issues_path)
52 @output_buffer = render_menu_node(node, nil)
53 @output_buffer = render_menu_node(node, nil)
53
54
54 assert_select 'a[href="/issues"]', "Testing"
55 assert_select 'a[href="/issues"]', "Testing"
55 end
56 end
56
57
57 def test_render_menu_node_with_symbol_as_url_and_project
58 def test_render_menu_node_with_symbol_as_url_and_project
58 node = Redmine::MenuManager::MenuItem.new(:testing, :project_issues_path)
59 node = Redmine::MenuManager::MenuItem.new(:testing, :project_issues_path)
59 @output_buffer = render_menu_node(node, Project.find(1))
60 @output_buffer = render_menu_node(node, Project.find(1))
60
61
61 assert_select 'a[href="/projects/ecookbook/issues"]', "Testing"
62 assert_select 'a[href="/projects/ecookbook/issues"]', "Testing"
62 end
63 end
63
64
64 def test_render_menu_node_with_nested_items
65 def test_render_menu_node_with_nested_items
65 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node, '/test', { })
66 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node, '/test', { })
66 parent_node << Redmine::MenuManager::MenuItem.new(:child_one_node, '/test', { })
67 parent_node << Redmine::MenuManager::MenuItem.new(:child_one_node, '/test', { })
67 parent_node << Redmine::MenuManager::MenuItem.new(:child_two_node, '/test', { })
68 parent_node << Redmine::MenuManager::MenuItem.new(:child_two_node, '/test', { })
68 parent_node <<
69 parent_node <<
69 Redmine::MenuManager::MenuItem.new(:child_three_node, '/test', { }) <<
70 Redmine::MenuManager::MenuItem.new(:child_three_node, '/test', { }) <<
70 Redmine::MenuManager::MenuItem.new(:child_three_inner_node, '/test', { })
71 Redmine::MenuManager::MenuItem.new(:child_three_inner_node, '/test', { })
71
72
72 @output_buffer = render_menu_node(parent_node, nil)
73 @output_buffer = render_menu_node(parent_node, nil)
73
74
74 assert_select("li") do
75 assert_select("li") do
75 assert_select("a.parent-node", "Parent node")
76 assert_select("a.parent-node", "Parent node")
76 assert_select("ul") do
77 assert_select("ul") do
77 assert_select("li a.child-one-node", "Child one node")
78 assert_select("li a.child-one-node", "Child one node")
78 assert_select("li a.child-two-node", "Child two node")
79 assert_select("li a.child-two-node", "Child two node")
79 assert_select("li") do
80 assert_select("li") do
80 assert_select("a.child-three-node", "Child three node")
81 assert_select("a.child-three-node", "Child three node")
81 assert_select("ul") do
82 assert_select("ul") do
82 assert_select("li a.child-three-inner-node", "Child three inner node")
83 assert_select("li a.child-three-inner-node", "Child three inner node")
83 end
84 end
84 end
85 end
85 end
86 end
86 end
87 end
87
88
88 end
89 end
89
90
90 def test_render_menu_node_with_children
91 def test_render_menu_node_with_children
91 User.current = User.find(2)
92 User.current = User.find(2)
92
93
93 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
94 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
94 '/test',
95 '/test',
95 {
96 {
96 :children => Proc.new {|p|
97 :children => Proc.new {|p|
97 children = []
98 children = []
98 3.times do |time|
99 3.times do |time|
99 children << Redmine::MenuManager::MenuItem.new("test_child_#{time}",
100 children << Redmine::MenuManager::MenuItem.new("test_child_#{time}",
100 {:controller => 'issues', :action => 'index'},
101 {:controller => 'issues', :action => 'index'},
101 {})
102 {})
102 end
103 end
103 children
104 children
104 }
105 }
105 })
106 })
106 @output_buffer = render_menu_node(parent_node, Project.find(1))
107 @output_buffer = render_menu_node(parent_node, Project.find(1))
107
108
108 assert_select("li") do
109 assert_select("li") do
109 assert_select("a.parent-node", "Parent node")
110 assert_select("a.parent-node", "Parent node")
110 assert_select("ul") do
111 assert_select("ul") do
111 assert_select("li a.test-child-0", "Test child 0")
112 assert_select("li a.test-child-0", "Test child 0")
112 assert_select("li a.test-child-1", "Test child 1")
113 assert_select("li a.test-child-1", "Test child 1")
113 assert_select("li a.test-child-2", "Test child 2")
114 assert_select("li a.test-child-2", "Test child 2")
114 end
115 end
115 end
116 end
116 end
117 end
117
118
118 def test_render_menu_node_with_nested_items_and_children
119 def test_render_menu_node_with_nested_items_and_children
119 User.current = User.find(2)
120 User.current = User.find(2)
120
121
121 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
122 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
122 {:controller => 'issues', :action => 'index'},
123 {:controller => 'issues', :action => 'index'},
123 {
124 {
124 :children => Proc.new {|p|
125 :children => Proc.new {|p|
125 children = []
126 children = []
126 3.times do |time|
127 3.times do |time|
127 children << Redmine::MenuManager::MenuItem.new("test_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
128 children << Redmine::MenuManager::MenuItem.new("test_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
128 end
129 end
129 children
130 children
130 }
131 }
131 })
132 })
132
133
133 parent_node << Redmine::MenuManager::MenuItem.new(:child_node,
134 parent_node << Redmine::MenuManager::MenuItem.new(:child_node,
134 {:controller => 'issues', :action => 'index'},
135 {:controller => 'issues', :action => 'index'},
135 {
136 {
136 :children => Proc.new {|p|
137 :children => Proc.new {|p|
137 children = []
138 children = []
138 6.times do |time|
139 6.times do |time|
139 children << Redmine::MenuManager::MenuItem.new("test_dynamic_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
140 children << Redmine::MenuManager::MenuItem.new("test_dynamic_child_#{time}", {:controller => 'issues', :action => 'index'}, {})
140 end
141 end
141 children
142 children
142 }
143 }
143 })
144 })
144
145
145 @output_buffer = render_menu_node(parent_node, Project.find(1))
146 @output_buffer = render_menu_node(parent_node, Project.find(1))
146
147
147 assert_select("li") do
148 assert_select("li") do
148 assert_select("a.parent-node", "Parent node")
149 assert_select("a.parent-node", "Parent node")
149 assert_select("ul") do
150 assert_select("ul") do
150 assert_select("li a.child-node", "Child node")
151 assert_select("li a.child-node", "Child node")
151 assert_select("ul") do
152 assert_select("ul") do
152 assert_select("li a.test-dynamic-child-0", "Test dynamic child 0")
153 assert_select("li a.test-dynamic-child-0", "Test dynamic child 0")
153 assert_select("li a.test-dynamic-child-1", "Test dynamic child 1")
154 assert_select("li a.test-dynamic-child-1", "Test dynamic child 1")
154 assert_select("li a.test-dynamic-child-2", "Test dynamic child 2")
155 assert_select("li a.test-dynamic-child-2", "Test dynamic child 2")
155 assert_select("li a.test-dynamic-child-3", "Test dynamic child 3")
156 assert_select("li a.test-dynamic-child-3", "Test dynamic child 3")
156 assert_select("li a.test-dynamic-child-4", "Test dynamic child 4")
157 assert_select("li a.test-dynamic-child-4", "Test dynamic child 4")
157 assert_select("li a.test-dynamic-child-5", "Test dynamic child 5")
158 assert_select("li a.test-dynamic-child-5", "Test dynamic child 5")
158 end
159 end
159 assert_select("li a.test-child-0", "Test child 0")
160 assert_select("li a.test-child-0", "Test child 0")
160 assert_select("li a.test-child-1", "Test child 1")
161 assert_select("li a.test-child-1", "Test child 1")
161 assert_select("li a.test-child-2", "Test child 2")
162 assert_select("li a.test-child-2", "Test child 2")
162 end
163 end
163 end
164 end
164 end
165 end
165
166
166 def test_render_menu_node_with_allowed_and_unallowed_unattached_children
167 def test_render_menu_node_with_allowed_and_unallowed_unattached_children
167 User.current = User.find(2)
168 User.current = User.find(2)
168
169
169 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
170 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
170 {:controller => 'issues', :action => 'index'},
171 {:controller => 'issues', :action => 'index'},
171 {
172 {
172 :children => Proc.new {|p|
173 :children => Proc.new {|p|
173 [
174 [
174 Redmine::MenuManager::MenuItem.new("test_child_allowed", {:controller => 'issues', :action => 'index'}, {}),
175 Redmine::MenuManager::MenuItem.new("test_child_allowed", {:controller => 'issues', :action => 'index'}, {}),
175 Redmine::MenuManager::MenuItem.new("test_child_unallowed", {:controller => 'issues', :action => 'unallowed'}, {}),
176 Redmine::MenuManager::MenuItem.new("test_child_unallowed", {:controller => 'issues', :action => 'unallowed'}, {}),
176 ]
177 ]
177 }
178 }
178 })
179 })
179
180
180 @output_buffer = render_menu_node(parent_node, Project.find(1))
181 @output_buffer = render_menu_node(parent_node, Project.find(1))
181
182
182 assert_select("li") do
183 assert_select("li") do
183 assert_select("a.parent-node", "Parent node")
184 assert_select("a.parent-node", "Parent node")
184 assert_select("ul.menu-children.unattached") do
185 assert_select("ul.menu-children.unattached") do
185 assert_select("li a.test-child-allowed", "Test child allowed")
186 assert_select("li a.test-child-allowed", "Test child allowed")
186 assert_select("li a.test-child-unallowed", false)
187 assert_select("li a.test-child-unallowed", false)
187 end
188 end
188 end
189 end
189 end
190 end
190
191
191 def test_render_menu_node_with_allowed_and_unallowed_standard_children
192 def test_render_menu_node_with_allowed_and_unallowed_standard_children
192 User.current = User.find(6)
193 User.current = User.find(6)
193
194
194 Redmine::MenuManager.map :some_menu do |menu|
195 Redmine::MenuManager.map :some_menu do |menu|
195 menu.push(:parent_node, {:controller => 'issues', :action => 'index'}, { })
196 menu.push(:parent_node, {:controller => 'issues', :action => 'index'}, { })
196 menu.push(:test_child_allowed, {:controller => 'issues', :action => 'index'}, {:parent => :parent_node})
197 menu.push(:test_child_allowed, {:controller => 'issues', :action => 'index'}, {:parent => :parent_node})
197 menu.push(:test_child_unallowed, {:controller => 'issues', :action => 'new'}, {:parent => :parent_node})
198 menu.push(:test_child_unallowed, {:controller => 'issues', :action => 'new'}, {:parent => :parent_node})
198 end
199 end
199
200
200 @output_buffer = render_menu(:some_menu, Project.find(1))
201 @output_buffer = render_menu(:some_menu, Project.find(1))
201
202
202 assert_select("li") do
203 assert_select("li") do
203 assert_select("a.parent-node", "Parent node")
204 assert_select("a.parent-node", "Parent node")
204 assert_select("ul.menu-children.unattached", false)
205 assert_select("ul.menu-children.unattached", false)
205 assert_select("ul.menu-children") do
206 assert_select("ul.menu-children") do
206 assert_select("li a.test-child-allowed", "Test child allowed")
207 assert_select("li a.test-child-allowed", "Test child allowed")
207 assert_select("li a.test-child-unallowed", false)
208 assert_select("li a.test-child-unallowed", false)
208 end
209 end
209 end
210 end
210 end
211 end
211
212
212 def test_render_empty_virtual_menu_node_with_children
213 def test_render_empty_virtual_menu_node_with_children
213
214
214 # only empty item with no click target
215 # only empty item with no click target
215 Redmine::MenuManager.map :menu1 do |menu|
216 Redmine::MenuManager.map :menu1 do |menu|
216 menu.push(:parent_node, nil, { })
217 menu.push(:parent_node, nil, { })
217 end
218 end
218
219
219 # parent with unallowed unattached child
220 # parent with unallowed unattached child
220 Redmine::MenuManager.map :menu2 do |menu|
221 Redmine::MenuManager.map :menu2 do |menu|
221 menu.push(:parent_node, nil, {:children => Proc.new {|p|
222 menu.push(:parent_node, nil, {:children => Proc.new {|p|
222 [Redmine::MenuManager::MenuItem.new("test_child_unallowed", {:controller => 'issues', :action => 'new'}, {})]
223 [Redmine::MenuManager::MenuItem.new("test_child_unallowed", {:controller => 'issues', :action => 'new'}, {})]
223 } })
224 } })
224 end
225 end
225
226
226 # parent with unallowed standard child
227 # parent with unallowed standard child
227 Redmine::MenuManager.map :menu3 do |menu|
228 Redmine::MenuManager.map :menu3 do |menu|
228 menu.push(:parent_node, nil, {})
229 menu.push(:parent_node, nil, {})
229 menu.push(:test_child_unallowed, {:controller =>'issues', :action => 'new'}, {:parent => :parent_node})
230 menu.push(:test_child_unallowed, {:controller =>'issues', :action => 'new'}, {:parent => :parent_node})
230 end
231 end
231
232
232 # should not be displayed to anonymous
233 # should not be displayed to anonymous
233 User.current = User.find(6)
234 User.current = User.find(6)
234 assert_nil render_menu(:menu1, Project.find(1))
235 assert_nil render_menu(:menu1, Project.find(1))
235 assert_nil render_menu(:menu2, Project.find(1))
236 assert_nil render_menu(:menu2, Project.find(1))
236 assert_nil render_menu(:menu3, Project.find(1))
237 assert_nil render_menu(:menu3, Project.find(1))
237
238
238 # should be displayed to an admin
239 # should be displayed to an admin
239 User.current = User.find(1)
240 User.current = User.find(1)
240 @output_buffer = render_menu(:menu2, Project.find(1))
241 @output_buffer = render_menu(:menu2, Project.find(1))
241 assert_select("ul li a.parent-node", "Parent node")
242 assert_select("ul li a.parent-node", "Parent node")
242 @output_buffer = render_menu(:menu3, Project.find(1))
243 @output_buffer = render_menu(:menu3, Project.find(1))
243 assert_select("ul li a.parent-node", "Parent node")
244 assert_select("ul li a.parent-node", "Parent node")
244
245
245 end
246 end
246
247
247 def test_render_menu_node_with_children_without_an_array
248 def test_render_menu_node_with_children_without_an_array
248 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
249 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
249 '/test',
250 '/test',
250 {
251 {
251 :children => Proc.new {|p| Redmine::MenuManager::MenuItem.new("test_child", "/testing", {})}
252 :children => Proc.new {|p| Redmine::MenuManager::MenuItem.new("test_child", "/testing", {})}
252 })
253 })
253
254
254 assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
255 assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
255 @output_buffer = render_menu_node(parent_node, Project.find(1))
256 @output_buffer = render_menu_node(parent_node, Project.find(1))
256 end
257 end
257 end
258 end
258
259
259 def test_render_menu_node_with_incorrect_children
260 def test_render_menu_node_with_incorrect_children
260 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
261 parent_node = Redmine::MenuManager::MenuItem.new(:parent_node,
261 '/test',
262 '/test',
262 {
263 {
263 :children => Proc.new {|p| ["a string"] }
264 :children => Proc.new {|p| ["a string"] }
264 })
265 })
265
266
266 assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
267 assert_raises Redmine::MenuManager::MenuError, ":children must be an array of MenuItems" do
267 @output_buffer = render_menu_node(parent_node, Project.find(1))
268 @output_buffer = render_menu_node(parent_node, Project.find(1))
268 end
269 end
269
270
270 end
271 end
271
272
272 def test_menu_items_for_should_yield_all_items_if_passed_a_block
273 def test_menu_items_for_should_yield_all_items_if_passed_a_block
273 menu_name = :test_menu_items_for_should_yield_all_items_if_passed_a_block
274 menu_name = :test_menu_items_for_should_yield_all_items_if_passed_a_block
274 Redmine::MenuManager.map menu_name do |menu|
275 Redmine::MenuManager.map menu_name do |menu|
275 menu.push(:a_menu, '/', { })
276 menu.push(:a_menu, '/', { })
276 menu.push(:a_menu_2, '/', { })
277 menu.push(:a_menu_2, '/', { })
277 menu.push(:a_menu_3, '/', { })
278 menu.push(:a_menu_3, '/', { })
278 end
279 end
279
280
280 items_yielded = []
281 items_yielded = []
281 menu_items_for(menu_name) do |item|
282 menu_items_for(menu_name) do |item|
282 items_yielded << item
283 items_yielded << item
283 end
284 end
284
285
285 assert_equal 3, items_yielded.size
286 assert_equal 3, items_yielded.size
286 end
287 end
287
288
288 def test_menu_items_for_should_return_all_items
289 def test_menu_items_for_should_return_all_items
289 menu_name = :test_menu_items_for_should_return_all_items
290 menu_name = :test_menu_items_for_should_return_all_items
290 Redmine::MenuManager.map menu_name do |menu|
291 Redmine::MenuManager.map menu_name do |menu|
291 menu.push(:a_menu, '/', { })
292 menu.push(:a_menu, '/', { })
292 menu.push(:a_menu_2, '/', { })
293 menu.push(:a_menu_2, '/', { })
293 menu.push(:a_menu_3, '/', { })
294 menu.push(:a_menu_3, '/', { })
294 end
295 end
295
296
296 items = menu_items_for(menu_name)
297 items = menu_items_for(menu_name)
297 assert_equal 3, items.size
298 assert_equal 3, items.size
298 end
299 end
299
300
300 def test_menu_items_for_should_skip_unallowed_items_on_a_project
301 def test_menu_items_for_should_skip_unallowed_items_on_a_project
301 menu_name = :test_menu_items_for_should_skip_unallowed_items_on_a_project
302 menu_name = :test_menu_items_for_should_skip_unallowed_items_on_a_project
302 Redmine::MenuManager.map menu_name do |menu|
303 Redmine::MenuManager.map menu_name do |menu|
303 menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
304 menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
304 menu.push(:a_menu_2, {:controller => 'issues', :action => 'index' }, { })
305 menu.push(:a_menu_2, {:controller => 'issues', :action => 'index' }, { })
305 menu.push(:unallowed, {:controller => 'issues', :action => 'unallowed' }, { })
306 menu.push(:unallowed, {:controller => 'issues', :action => 'unallowed' }, { })
306 end
307 end
307
308
308 User.current = User.find(2)
309 User.current = User.find(2)
309
310
310 items = menu_items_for(menu_name, Project.find(1))
311 items = menu_items_for(menu_name, Project.find(1))
311 assert_equal 2, items.size
312 assert_equal 2, items.size
312 end
313 end
313
314
314 def test_menu_items_for_should_skip_items_that_fail_the_permission
315 def test_menu_items_for_should_skip_items_that_fail_the_permission
315 menu_name = :test_menu_items_for_should_skip_items_that_fail_the_permission
316 menu_name = :test_menu_items_for_should_skip_items_that_fail_the_permission
316 Redmine::MenuManager.map menu_name do |menu|
317 Redmine::MenuManager.map menu_name do |menu|
317 menu.push(:a_menu, :project_issues_path)
318 menu.push(:a_menu, :project_issues_path)
318 menu.push(:unallowed, :project_issues_path, :permission => :unallowed)
319 menu.push(:unallowed, :project_issues_path, :permission => :unallowed)
319 end
320 end
320
321
321 User.current = User.find(2)
322 User.current = User.find(2)
322
323
323 items = menu_items_for(menu_name, Project.find(1))
324 items = menu_items_for(menu_name, Project.find(1))
324 assert_equal 1, items.size
325 assert_equal 1, items.size
325 end
326 end
326
327
327 def test_menu_items_for_should_skip_items_that_fail_the_conditions
328 def test_menu_items_for_should_skip_items_that_fail_the_conditions
328 menu_name = :test_menu_items_for_should_skip_items_that_fail_the_conditions
329 menu_name = :test_menu_items_for_should_skip_items_that_fail_the_conditions
329 Redmine::MenuManager.map menu_name do |menu|
330 Redmine::MenuManager.map menu_name do |menu|
330 menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
331 menu.push(:a_menu, {:controller => 'issues', :action => 'index' }, { })
331 menu.push(:unallowed,
332 menu.push(:unallowed,
332 {:controller => 'issues', :action => 'index' },
333 {:controller => 'issues', :action => 'index' },
333 { :if => Proc.new { false }})
334 { :if => Proc.new { false }})
334 end
335 end
335
336
336 User.current = User.find(2)
337 User.current = User.find(2)
337
338
338 items = menu_items_for(menu_name, Project.find(1))
339 items = menu_items_for(menu_name, Project.find(1))
339 assert_equal 1, items.size
340 assert_equal 1, items.size
340 end
341 end
341 end
342 end
@@ -1,29 +1,30
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 Redmine::Views::LabelledFormBuilderTest < ActionView::TestCase
20 class Redmine::Views::LabelledFormBuilderTest < Redmine::HelperTest
21 include Rails.application.routes.url_helpers
21
22
22 def test_label_should_output_one_element
23 def test_label_should_output_one_element
23 set_language_if_valid 'en'
24 set_language_if_valid 'en'
24 labelled_form_for(Issue.new) do |f|
25 labelled_form_for(Issue.new) do |f|
25 output = f.label :subject
26 output = f.label :subject
26 assert_equal output, '<label for="issue_subject">Subject</label>'
27 assert_equal output, '<label for="issue_subject">Subject</label>'
27 end
28 end
28 end
29 end
29 end
30 end
@@ -1,401 +1,402
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 Redmine::WikiFormatting::MacrosTest < ActionView::TestCase
20 class Redmine::WikiFormatting::MacrosTest < Redmine::HelperTest
21 include ApplicationHelper
21 include ApplicationHelper
22 include ActionView::Helpers::TextHelper
22 include ActionView::Helpers::TextHelper
23 include ActionView::Helpers::SanitizeHelper
23 include ActionView::Helpers::SanitizeHelper
24 include ERB::Util
24 include ERB::Util
25 include Rails.application.routes.url_helpers
25 extend ActionView::Helpers::SanitizeHelper::ClassMethods
26 extend ActionView::Helpers::SanitizeHelper::ClassMethods
26
27
27 fixtures :projects, :roles, :enabled_modules, :users,
28 fixtures :projects, :roles, :enabled_modules, :users,
28 :repositories, :changesets,
29 :repositories, :changesets,
29 :trackers, :issue_statuses, :issues,
30 :trackers, :issue_statuses, :issues,
30 :versions, :documents,
31 :versions, :documents,
31 :wikis, :wiki_pages, :wiki_contents,
32 :wikis, :wiki_pages, :wiki_contents,
32 :boards, :messages,
33 :boards, :messages,
33 :attachments
34 :attachments
34
35
35 def setup
36 def setup
36 super
37 super
37 @project = nil
38 @project = nil
38 end
39 end
39
40
40 def teardown
41 def teardown
41 end
42 end
42
43
43 def test_macro_registration
44 def test_macro_registration
44 Redmine::WikiFormatting::Macros.register do
45 Redmine::WikiFormatting::Macros.register do
45 macro :foo do |obj, args|
46 macro :foo do |obj, args|
46 "Foo: #{args.size} (#{args.join(',')}) (#{args.class.name})"
47 "Foo: #{args.size} (#{args.join(',')}) (#{args.class.name})"
47 end
48 end
48 end
49 end
49
50
50 assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo}}")
51 assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo}}")
51 assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo()}}")
52 assert_equal '<p>Foo: 0 () (Array)</p>', textilizable("{{foo()}}")
52 assert_equal '<p>Foo: 1 (arg1) (Array)</p>', textilizable("{{foo(arg1)}}")
53 assert_equal '<p>Foo: 1 (arg1) (Array)</p>', textilizable("{{foo(arg1)}}")
53 assert_equal '<p>Foo: 2 (arg1,arg2) (Array)</p>', textilizable("{{foo(arg1, arg2)}}")
54 assert_equal '<p>Foo: 2 (arg1,arg2) (Array)</p>', textilizable("{{foo(arg1, arg2)}}")
54 end
55 end
55
56
56 def test_macro_registration_parse_args_set_to_false_should_disable_arguments_parsing
57 def test_macro_registration_parse_args_set_to_false_should_disable_arguments_parsing
57 Redmine::WikiFormatting::Macros.register do
58 Redmine::WikiFormatting::Macros.register do
58 macro :bar, :parse_args => false do |obj, args|
59 macro :bar, :parse_args => false do |obj, args|
59 "Bar: (#{args}) (#{args.class.name})"
60 "Bar: (#{args}) (#{args.class.name})"
60 end
61 end
61 end
62 end
62
63
63 assert_equal '<p>Bar: (args, more args) (String)</p>', textilizable("{{bar(args, more args)}}")
64 assert_equal '<p>Bar: (args, more args) (String)</p>', textilizable("{{bar(args, more args)}}")
64 assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar}}")
65 assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar}}")
65 assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar()}}")
66 assert_equal '<p>Bar: () (String)</p>', textilizable("{{bar()}}")
66 end
67 end
67
68
68 def test_macro_registration_with_3_args_should_receive_text_argument
69 def test_macro_registration_with_3_args_should_receive_text_argument
69 Redmine::WikiFormatting::Macros.register do
70 Redmine::WikiFormatting::Macros.register do
70 macro :baz do |obj, args, text|
71 macro :baz do |obj, args, text|
71 "Baz: (#{args.join(',')}) (#{text.class.name}) (#{text})"
72 "Baz: (#{args.join(',')}) (#{text.class.name}) (#{text})"
72 end
73 end
73 end
74 end
74
75
75 assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz}}")
76 assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz}}")
76 assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz()}}")
77 assert_equal "<p>Baz: () (NilClass) ()</p>", textilizable("{{baz()}}")
77 assert_equal "<p>Baz: () (String) (line1\nline2)</p>", textilizable("{{baz()\nline1\nline2\n}}")
78 assert_equal "<p>Baz: () (String) (line1\nline2)</p>", textilizable("{{baz()\nline1\nline2\n}}")
78 assert_equal "<p>Baz: (arg1,arg2) (String) (line1\nline2)</p>", textilizable("{{baz(arg1, arg2)\nline1\nline2\n}}")
79 assert_equal "<p>Baz: (arg1,arg2) (String) (line1\nline2)</p>", textilizable("{{baz(arg1, arg2)\nline1\nline2\n}}")
79 end
80 end
80
81
81 def test_macro_name_with_upper_case
82 def test_macro_name_with_upper_case
82 Redmine::WikiFormatting::Macros.macro(:UpperCase) {|obj, args| "Upper"}
83 Redmine::WikiFormatting::Macros.macro(:UpperCase) {|obj, args| "Upper"}
83
84
84 assert_equal "<p>Upper</p>", textilizable("{{UpperCase}}")
85 assert_equal "<p>Upper</p>", textilizable("{{UpperCase}}")
85 end
86 end
86
87
87 def test_multiple_macros_on_the_same_line
88 def test_multiple_macros_on_the_same_line
88 Redmine::WikiFormatting::Macros.macro :foo do |obj, args|
89 Redmine::WikiFormatting::Macros.macro :foo do |obj, args|
89 args.any? ? "args: #{args.join(',')}" : "no args"
90 args.any? ? "args: #{args.join(',')}" : "no args"
90 end
91 end
91
92
92 assert_equal '<p>no args no args</p>', textilizable("{{foo}} {{foo}}")
93 assert_equal '<p>no args no args</p>', textilizable("{{foo}} {{foo}}")
93 assert_equal '<p>args: a,b no args</p>', textilizable("{{foo(a,b)}} {{foo}}")
94 assert_equal '<p>args: a,b no args</p>', textilizable("{{foo(a,b)}} {{foo}}")
94 assert_equal '<p>args: a,b args: c,d</p>', textilizable("{{foo(a,b)}} {{foo(c,d)}}")
95 assert_equal '<p>args: a,b args: c,d</p>', textilizable("{{foo(a,b)}} {{foo(c,d)}}")
95 assert_equal '<p>no args args: c,d</p>', textilizable("{{foo}} {{foo(c,d)}}")
96 assert_equal '<p>no args args: c,d</p>', textilizable("{{foo}} {{foo(c,d)}}")
96 end
97 end
97
98
98 def test_macro_should_receive_the_object_as_argument_when_with_object_and_attribute
99 def test_macro_should_receive_the_object_as_argument_when_with_object_and_attribute
99 issue = Issue.find(1)
100 issue = Issue.find(1)
100 issue.description = "{{hello_world}}"
101 issue.description = "{{hello_world}}"
101 assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(issue, :description)
102 assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(issue, :description)
102 end
103 end
103
104
104 def test_macro_should_receive_the_object_as_argument_when_called_with_object_option
105 def test_macro_should_receive_the_object_as_argument_when_called_with_object_option
105 text = "{{hello_world}}"
106 text = "{{hello_world}}"
106 assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(text, :object => Issue.find(1))
107 assert_equal '<p>Hello world! Object: Issue, Called with no argument and no block of text.</p>', textilizable(text, :object => Issue.find(1))
107 end
108 end
108
109
109 def test_extract_macro_options_should_with_args
110 def test_extract_macro_options_should_with_args
110 options = extract_macro_options(["arg1", "arg2"], :foo, :size)
111 options = extract_macro_options(["arg1", "arg2"], :foo, :size)
111 assert_equal([["arg1", "arg2"], {}], options)
112 assert_equal([["arg1", "arg2"], {}], options)
112 end
113 end
113
114
114 def test_extract_macro_options_should_with_options
115 def test_extract_macro_options_should_with_options
115 options = extract_macro_options(["foo=bar", "size=2"], :foo, :size)
116 options = extract_macro_options(["foo=bar", "size=2"], :foo, :size)
116 assert_equal([[], {:foo => "bar", :size => "2"}], options)
117 assert_equal([[], {:foo => "bar", :size => "2"}], options)
117 end
118 end
118
119
119 def test_extract_macro_options_should_with_args_and_options
120 def test_extract_macro_options_should_with_args_and_options
120 options = extract_macro_options(["arg1", "arg2", "foo=bar", "size=2"], :foo, :size)
121 options = extract_macro_options(["arg1", "arg2", "foo=bar", "size=2"], :foo, :size)
121 assert_equal([["arg1", "arg2"], {:foo => "bar", :size => "2"}], options)
122 assert_equal([["arg1", "arg2"], {:foo => "bar", :size => "2"}], options)
122 end
123 end
123
124
124 def test_extract_macro_options_should_parse_options_lazily
125 def test_extract_macro_options_should_parse_options_lazily
125 options = extract_macro_options(["params=x=1&y=2"], :params)
126 options = extract_macro_options(["params=x=1&y=2"], :params)
126 assert_equal([[], {:params => "x=1&y=2"}], options)
127 assert_equal([[], {:params => "x=1&y=2"}], options)
127 end
128 end
128
129
129 def test_macro_exception_should_be_displayed
130 def test_macro_exception_should_be_displayed
130 Redmine::WikiFormatting::Macros.macro :exception do |obj, args|
131 Redmine::WikiFormatting::Macros.macro :exception do |obj, args|
131 raise "My message"
132 raise "My message"
132 end
133 end
133
134
134 text = "{{exception}}"
135 text = "{{exception}}"
135 assert_include '<div class="flash error">Error executing the <strong>exception</strong> macro (My message)</div>', textilizable(text)
136 assert_include '<div class="flash error">Error executing the <strong>exception</strong> macro (My message)</div>', textilizable(text)
136 end
137 end
137
138
138 def test_macro_arguments_should_not_be_parsed_by_formatters
139 def test_macro_arguments_should_not_be_parsed_by_formatters
139 text = '{{hello_world(http://www.redmine.org, #1)}}'
140 text = '{{hello_world(http://www.redmine.org, #1)}}'
140 assert_include 'Arguments: http://www.redmine.org, #1', textilizable(text)
141 assert_include 'Arguments: http://www.redmine.org, #1', textilizable(text)
141 end
142 end
142
143
143 def test_exclamation_mark_should_not_run_macros
144 def test_exclamation_mark_should_not_run_macros
144 text = "!{{hello_world}}"
145 text = "!{{hello_world}}"
145 assert_equal '<p>{{hello_world}}</p>', textilizable(text)
146 assert_equal '<p>{{hello_world}}</p>', textilizable(text)
146 end
147 end
147
148
148 def test_exclamation_mark_should_escape_macros
149 def test_exclamation_mark_should_escape_macros
149 text = "!{{hello_world(<tag>)}}"
150 text = "!{{hello_world(<tag>)}}"
150 assert_equal '<p>{{hello_world(&lt;tag&gt;)}}</p>', textilizable(text)
151 assert_equal '<p>{{hello_world(&lt;tag&gt;)}}</p>', textilizable(text)
151 end
152 end
152
153
153 def test_unknown_macros_should_not_be_replaced
154 def test_unknown_macros_should_not_be_replaced
154 text = "{{unknown}}"
155 text = "{{unknown}}"
155 assert_equal '<p>{{unknown}}</p>', textilizable(text)
156 assert_equal '<p>{{unknown}}</p>', textilizable(text)
156 end
157 end
157
158
158 def test_unknown_macros_should_parsed_as_text
159 def test_unknown_macros_should_parsed_as_text
159 text = "{{unknown(*test*)}}"
160 text = "{{unknown(*test*)}}"
160 assert_equal '<p>{{unknown(<strong>test</strong>)}}</p>', textilizable(text)
161 assert_equal '<p>{{unknown(<strong>test</strong>)}}</p>', textilizable(text)
161 end
162 end
162
163
163 def test_unknown_macros_should_be_escaped
164 def test_unknown_macros_should_be_escaped
164 text = "{{unknown(<tag>)}}"
165 text = "{{unknown(<tag>)}}"
165 assert_equal '<p>{{unknown(&lt;tag&gt;)}}</p>', textilizable(text)
166 assert_equal '<p>{{unknown(&lt;tag&gt;)}}</p>', textilizable(text)
166 end
167 end
167
168
168 def test_html_safe_macro_output_should_not_be_escaped
169 def test_html_safe_macro_output_should_not_be_escaped
169 Redmine::WikiFormatting::Macros.macro :safe_macro do |obj, args|
170 Redmine::WikiFormatting::Macros.macro :safe_macro do |obj, args|
170 "<tag>".html_safe
171 "<tag>".html_safe
171 end
172 end
172 assert_equal '<p><tag></p>', textilizable("{{safe_macro}}")
173 assert_equal '<p><tag></p>', textilizable("{{safe_macro}}")
173 end
174 end
174
175
175 def test_macro_hello_world
176 def test_macro_hello_world
176 text = "{{hello_world}}"
177 text = "{{hello_world}}"
177 assert textilizable(text).match(/Hello world!/)
178 assert textilizable(text).match(/Hello world!/)
178 end
179 end
179
180
180 def test_macro_hello_world_should_escape_arguments
181 def test_macro_hello_world_should_escape_arguments
181 text = "{{hello_world(<tag>)}}"
182 text = "{{hello_world(<tag>)}}"
182 assert_include 'Arguments: &lt;tag&gt;', textilizable(text)
183 assert_include 'Arguments: &lt;tag&gt;', textilizable(text)
183 end
184 end
184
185
185 def test_macro_macro_list
186 def test_macro_macro_list
186 text = "{{macro_list}}"
187 text = "{{macro_list}}"
187 assert_match %r{<code>hello_world</code>}, textilizable(text)
188 assert_match %r{<code>hello_world</code>}, textilizable(text)
188 end
189 end
189
190
190 def test_macro_include
191 def test_macro_include
191 @project = Project.find(1)
192 @project = Project.find(1)
192 # include a page of the current project wiki
193 # include a page of the current project wiki
193 text = "{{include(Another page)}}"
194 text = "{{include(Another page)}}"
194 assert_include 'This is a link to a ticket', textilizable(text)
195 assert_include 'This is a link to a ticket', textilizable(text)
195
196
196 @project = nil
197 @project = nil
197 # include a page of a specific project wiki
198 # include a page of a specific project wiki
198 text = "{{include(ecookbook:Another page)}}"
199 text = "{{include(ecookbook:Another page)}}"
199 assert_include 'This is a link to a ticket', textilizable(text)
200 assert_include 'This is a link to a ticket', textilizable(text)
200
201
201 text = "{{include(ecookbook:)}}"
202 text = "{{include(ecookbook:)}}"
202 assert_include 'CookBook documentation', textilizable(text)
203 assert_include 'CookBook documentation', textilizable(text)
203
204
204 text = "{{include(unknowidentifier:somepage)}}"
205 text = "{{include(unknowidentifier:somepage)}}"
205 assert_include 'Page not found', textilizable(text)
206 assert_include 'Page not found', textilizable(text)
206 end
207 end
207
208
208 def test_macro_collapse
209 def test_macro_collapse
209 text = "{{collapse\n*Collapsed* block of text\n}}"
210 text = "{{collapse\n*Collapsed* block of text\n}}"
210 with_locale 'en' do
211 with_locale 'en' do
211 result = textilizable(text)
212 result = textilizable(text)
212
213
213 assert_select_in result, 'div.collapsed-text'
214 assert_select_in result, 'div.collapsed-text'
214 assert_select_in result, 'strong', :text => 'Collapsed'
215 assert_select_in result, 'strong', :text => 'Collapsed'
215 assert_select_in result, 'a.collapsible.collapsed', :text => 'Show'
216 assert_select_in result, 'a.collapsible.collapsed', :text => 'Show'
216 assert_select_in result, 'a.collapsible', :text => 'Hide'
217 assert_select_in result, 'a.collapsible', :text => 'Hide'
217 end
218 end
218 end
219 end
219
220
220 def test_macro_collapse_with_one_arg
221 def test_macro_collapse_with_one_arg
221 text = "{{collapse(Example)\n*Collapsed* block of text\n}}"
222 text = "{{collapse(Example)\n*Collapsed* block of text\n}}"
222 result = textilizable(text)
223 result = textilizable(text)
223
224
224 assert_select_in result, 'div.collapsed-text'
225 assert_select_in result, 'div.collapsed-text'
225 assert_select_in result, 'strong', :text => 'Collapsed'
226 assert_select_in result, 'strong', :text => 'Collapsed'
226 assert_select_in result, 'a.collapsible.collapsed', :text => 'Example'
227 assert_select_in result, 'a.collapsible.collapsed', :text => 'Example'
227 assert_select_in result, 'a.collapsible', :text => 'Example'
228 assert_select_in result, 'a.collapsible', :text => 'Example'
228 end
229 end
229
230
230 def test_macro_collapse_with_two_args
231 def test_macro_collapse_with_two_args
231 text = "{{collapse(Show example, Hide example)\n*Collapsed* block of text\n}}"
232 text = "{{collapse(Show example, Hide example)\n*Collapsed* block of text\n}}"
232 result = textilizable(text)
233 result = textilizable(text)
233
234
234 assert_select_in result, 'div.collapsed-text'
235 assert_select_in result, 'div.collapsed-text'
235 assert_select_in result, 'strong', :text => 'Collapsed'
236 assert_select_in result, 'strong', :text => 'Collapsed'
236 assert_select_in result, 'a.collapsible.collapsed', :text => 'Show example'
237 assert_select_in result, 'a.collapsible.collapsed', :text => 'Show example'
237 assert_select_in result, 'a.collapsible', :text => 'Hide example'
238 assert_select_in result, 'a.collapsible', :text => 'Hide example'
238 end
239 end
239
240
240 def test_macro_collapse_should_not_break_toc
241 def test_macro_collapse_should_not_break_toc
241 text = <<-RAW
242 text = <<-RAW
242 {{toc}}
243 {{toc}}
243
244
244 h1. Title
245 h1. Title
245
246
246 {{collapse(Show example, Hide example)
247 {{collapse(Show example, Hide example)
247 h2. Heading
248 h2. Heading
248 }}"
249 }}"
249 RAW
250 RAW
250
251
251 expected_toc = '<ul class="toc"><li><a href="#Title">Title</a><ul><li><a href="#Heading">Heading</a></li></ul></li></ul>'
252 expected_toc = '<ul class="toc"><li><a href="#Title">Title</a><ul><li><a href="#Heading">Heading</a></li></ul></li></ul>'
252
253
253 assert_include expected_toc, textilizable(text).gsub(/[\r\n]/, '')
254 assert_include expected_toc, textilizable(text).gsub(/[\r\n]/, '')
254 end
255 end
255
256
256 def test_macro_child_pages
257 def test_macro_child_pages
257 expected = "<p><ul class=\"pages-hierarchy\">\n" +
258 expected = "<p><ul class=\"pages-hierarchy\">\n" +
258 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
259 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
259 "<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
260 "<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
260 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
261 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
261 "</ul>\n</p>"
262 "</ul>\n</p>"
262
263
263 @project = Project.find(1)
264 @project = Project.find(1)
264 # child pages of the current wiki page
265 # child pages of the current wiki page
265 assert_equal expected, textilizable("{{child_pages}}", :object => WikiPage.find(2).content)
266 assert_equal expected, textilizable("{{child_pages}}", :object => WikiPage.find(2).content)
266 # child pages of another page
267 # child pages of another page
267 assert_equal expected, textilizable("{{child_pages(Another_page)}}", :object => WikiPage.find(1).content)
268 assert_equal expected, textilizable("{{child_pages(Another_page)}}", :object => WikiPage.find(1).content)
268
269
269 @project = Project.find(2)
270 @project = Project.find(2)
270 assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page)}}", :object => WikiPage.find(1).content)
271 assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page)}}", :object => WikiPage.find(1).content)
271 end
272 end
272
273
273 def test_macro_child_pages_with_parent_option
274 def test_macro_child_pages_with_parent_option
274 expected = "<p><ul class=\"pages-hierarchy\">\n" +
275 expected = "<p><ul class=\"pages-hierarchy\">\n" +
275 "<li><a href=\"/projects/ecookbook/wiki/Another_page\">Another page</a>\n" +
276 "<li><a href=\"/projects/ecookbook/wiki/Another_page\">Another page</a>\n" +
276 "<ul class=\"pages-hierarchy\">\n" +
277 "<ul class=\"pages-hierarchy\">\n" +
277 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
278 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a>\n" +
278 "<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
279 "<ul class=\"pages-hierarchy\">\n<li><a href=\"/projects/ecookbook/wiki/Child_1_1\">Child 1 1</a></li>\n</ul>\n</li>\n" +
279 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
280 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
280 "</ul>\n</li>\n</ul>\n</p>"
281 "</ul>\n</li>\n</ul>\n</p>"
281
282
282 @project = Project.find(1)
283 @project = Project.find(1)
283 # child pages of the current wiki page
284 # child pages of the current wiki page
284 assert_equal expected, textilizable("{{child_pages(parent=1)}}", :object => WikiPage.find(2).content)
285 assert_equal expected, textilizable("{{child_pages(parent=1)}}", :object => WikiPage.find(2).content)
285 # child pages of another page
286 # child pages of another page
286 assert_equal expected, textilizable("{{child_pages(Another_page, parent=1)}}", :object => WikiPage.find(1).content)
287 assert_equal expected, textilizable("{{child_pages(Another_page, parent=1)}}", :object => WikiPage.find(1).content)
287
288
288 @project = Project.find(2)
289 @project = Project.find(2)
289 assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page, parent=1)}}", :object => WikiPage.find(1).content)
290 assert_equal expected, textilizable("{{child_pages(ecookbook:Another_page, parent=1)}}", :object => WikiPage.find(1).content)
290 end
291 end
291
292
292 def test_macro_child_pages_with_depth_option
293 def test_macro_child_pages_with_depth_option
293 expected = "<p><ul class=\"pages-hierarchy\">\n" +
294 expected = "<p><ul class=\"pages-hierarchy\">\n" +
294 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a></li>\n" +
295 "<li><a href=\"/projects/ecookbook/wiki/Child_1\">Child 1</a></li>\n" +
295 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
296 "<li><a href=\"/projects/ecookbook/wiki/Child_2\">Child 2</a></li>\n" +
296 "</ul>\n</p>"
297 "</ul>\n</p>"
297
298
298 @project = Project.find(1)
299 @project = Project.find(1)
299 assert_equal expected, textilizable("{{child_pages(depth=1)}}", :object => WikiPage.find(2).content)
300 assert_equal expected, textilizable("{{child_pages(depth=1)}}", :object => WikiPage.find(2).content)
300 end
301 end
301
302
302 def test_macro_child_pages_without_wiki_page_should_fail
303 def test_macro_child_pages_without_wiki_page_should_fail
303 assert_match /can be called from wiki pages only/, textilizable("{{child_pages}}")
304 assert_match /can be called from wiki pages only/, textilizable("{{child_pages}}")
304 end
305 end
305
306
306 def test_macro_thumbnail
307 def test_macro_thumbnail
307 link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17" />'.html_safe,
308 link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17" />'.html_safe,
308 "/attachments/17",
309 "/attachments/17",
309 :class => "thumbnail",
310 :class => "thumbnail",
310 :title => "testfile.PNG")
311 :title => "testfile.PNG")
311 assert_equal "<p>#{link}</p>",
312 assert_equal "<p>#{link}</p>",
312 textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14))
313 textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14))
313 end
314 end
314
315
315 def test_macro_thumbnail_with_full_path
316 def test_macro_thumbnail_with_full_path
316 link = link_to('<img alt="testfile.PNG" src="http://test.host/attachments/thumbnail/17" />'.html_safe,
317 link = link_to('<img alt="testfile.PNG" src="http://test.host/attachments/thumbnail/17" />'.html_safe,
317 "http://test.host/attachments/17",
318 "http://test.host/attachments/17",
318 :class => "thumbnail",
319 :class => "thumbnail",
319 :title => "testfile.PNG")
320 :title => "testfile.PNG")
320 assert_equal "<p>#{link}</p>",
321 assert_equal "<p>#{link}</p>",
321 textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14), :only_path => false)
322 textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14), :only_path => false)
322 end
323 end
323
324
324 def test_macro_thumbnail_with_size
325 def test_macro_thumbnail_with_size
325 link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17/200" />'.html_safe,
326 link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17/200" />'.html_safe,
326 "/attachments/17",
327 "/attachments/17",
327 :class => "thumbnail",
328 :class => "thumbnail",
328 :title => "testfile.PNG")
329 :title => "testfile.PNG")
329 assert_equal "<p>#{link}</p>",
330 assert_equal "<p>#{link}</p>",
330 textilizable("{{thumbnail(testfile.png, size=200)}}", :object => Issue.find(14))
331 textilizable("{{thumbnail(testfile.png, size=200)}}", :object => Issue.find(14))
331 end
332 end
332
333
333 def test_macro_thumbnail_with_title
334 def test_macro_thumbnail_with_title
334 link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17" />'.html_safe,
335 link = link_to('<img alt="testfile.PNG" src="/attachments/thumbnail/17" />'.html_safe,
335 "/attachments/17",
336 "/attachments/17",
336 :class => "thumbnail",
337 :class => "thumbnail",
337 :title => "Cool image")
338 :title => "Cool image")
338 assert_equal "<p>#{link}</p>",
339 assert_equal "<p>#{link}</p>",
339 textilizable("{{thumbnail(testfile.png, title=Cool image)}}", :object => Issue.find(14))
340 textilizable("{{thumbnail(testfile.png, title=Cool image)}}", :object => Issue.find(14))
340 end
341 end
341
342
342 def test_macro_thumbnail_with_invalid_filename_should_fail
343 def test_macro_thumbnail_with_invalid_filename_should_fail
343 assert_include 'test.png not found',
344 assert_include 'test.png not found',
344 textilizable("{{thumbnail(test.png)}}", :object => Issue.find(14))
345 textilizable("{{thumbnail(test.png)}}", :object => Issue.find(14))
345 end
346 end
346
347
347 def test_macros_should_not_be_executed_in_pre_tags
348 def test_macros_should_not_be_executed_in_pre_tags
348 text = <<-RAW
349 text = <<-RAW
349 {{hello_world(foo)}}
350 {{hello_world(foo)}}
350
351
351 <pre>
352 <pre>
352 {{hello_world(pre)}}
353 {{hello_world(pre)}}
353 !{{hello_world(pre)}}
354 !{{hello_world(pre)}}
354 </pre>
355 </pre>
355
356
356 {{hello_world(bar)}}
357 {{hello_world(bar)}}
357 RAW
358 RAW
358
359
359 expected = <<-EXPECTED
360 expected = <<-EXPECTED
360 <p>Hello world! Object: NilClass, Arguments: foo and no block of text.</p>
361 <p>Hello world! Object: NilClass, Arguments: foo and no block of text.</p>
361
362
362 <pre>
363 <pre>
363 {{hello_world(pre)}}
364 {{hello_world(pre)}}
364 !{{hello_world(pre)}}
365 !{{hello_world(pre)}}
365 </pre>
366 </pre>
366
367
367 <p>Hello world! Object: NilClass, Arguments: bar and no block of text.</p>
368 <p>Hello world! Object: NilClass, Arguments: bar and no block of text.</p>
368 EXPECTED
369 EXPECTED
369
370
370 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
371 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
371 end
372 end
372
373
373 def test_macros_should_be_escaped_in_pre_tags
374 def test_macros_should_be_escaped_in_pre_tags
374 text = "<pre>{{hello_world(<tag>)}}</pre>"
375 text = "<pre>{{hello_world(<tag>)}}</pre>"
375 assert_equal "<pre>{{hello_world(&lt;tag&gt;)}}</pre>", textilizable(text)
376 assert_equal "<pre>{{hello_world(&lt;tag&gt;)}}</pre>", textilizable(text)
376 end
377 end
377
378
378 def test_macros_should_not_mangle_next_macros_outputs
379 def test_macros_should_not_mangle_next_macros_outputs
379 text = '{{macro(2)}} !{{macro(2)}} {{hello_world(foo)}}'
380 text = '{{macro(2)}} !{{macro(2)}} {{hello_world(foo)}}'
380 assert_equal '<p>{{macro(2)}} {{macro(2)}} Hello world! Object: NilClass, Arguments: foo and no block of text.</p>', textilizable(text)
381 assert_equal '<p>{{macro(2)}} {{macro(2)}} Hello world! Object: NilClass, Arguments: foo and no block of text.</p>', textilizable(text)
381 end
382 end
382
383
383 def test_macros_with_text_should_not_mangle_following_macros
384 def test_macros_with_text_should_not_mangle_following_macros
384 text = <<-RAW
385 text = <<-RAW
385 {{hello_world
386 {{hello_world
386 Line of text
387 Line of text
387 }}
388 }}
388
389
389 {{hello_world
390 {{hello_world
390 Another line of text
391 Another line of text
391 }}
392 }}
392 RAW
393 RAW
393
394
394 expected = <<-EXPECTED
395 expected = <<-EXPECTED
395 <p>Hello world! Object: NilClass, Called with no argument and a 12 bytes long block of text.</p>
396 <p>Hello world! Object: NilClass, Called with no argument and a 12 bytes long block of text.</p>
396 <p>Hello world! Object: NilClass, Called with no argument and a 20 bytes long block of text.</p>
397 <p>Hello world! Object: NilClass, Called with no argument and a 20 bytes long block of text.</p>
397 EXPECTED
398 EXPECTED
398
399
399 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
400 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(text).gsub(%r{[\r\n\t]}, '')
400 end
401 end
401 end
402 end
General Comments 0
You need to be logged in to leave comments. Login now