##// END OF EJS Templates
Additional tests for IssuesHelper#show_detail....
Jean-Philippe Lang -
r9332:4598c64ebd6d
parent child
Show More
@@ -1,485 +1,454
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 ENV["RAILS_ENV"] = "test"
19 19 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
20 20 require 'test_help'
21 21 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
22 22
23 23 require File.expand_path(File.dirname(__FILE__) + '/object_daddy_helpers')
24 24 include ObjectDaddyHelpers
25 25
26 26 class ActiveSupport::TestCase
27 27 # Transactional fixtures accelerate your tests by wrapping each test method
28 28 # in a transaction that's rolled back on completion. This ensures that the
29 29 # test database remains unchanged so your fixtures don't have to be reloaded
30 30 # between every test method. Fewer database queries means faster tests.
31 31 #
32 32 # Read Mike Clark's excellent walkthrough at
33 33 # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
34 34 #
35 35 # Every Active Record database supports transactions except MyISAM tables
36 36 # in MySQL. Turn off transactional fixtures in this case; however, if you
37 37 # don't care one way or the other, switching from MyISAM to InnoDB tables
38 38 # is recommended.
39 39 self.use_transactional_fixtures = true
40 40
41 41 # Instantiated fixtures are slow, but give you @david where otherwise you
42 42 # would need people(:david). If you don't want to migrate your existing
43 43 # test cases which use the @david style and don't mind the speed hit (each
44 44 # instantiated fixtures translates to a database query per test method),
45 45 # then set this back to true.
46 46 self.use_instantiated_fixtures = false
47 47
48 48 # Add more helper methods to be used by all tests here...
49 49
50 50 def log_user(login, password)
51 51 User.anonymous
52 52 get "/login"
53 53 assert_equal nil, session[:user_id]
54 54 assert_response :success
55 55 assert_template "account/login"
56 56 post "/login", :username => login, :password => password
57 57 assert_equal login, User.find(session[:user_id]).login
58 58 end
59 59
60 60 def uploaded_test_file(name, mime)
61 61 ActionController::TestUploadedFile.new(
62 62 ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
63 63 end
64 64
65 65 def credentials(user, password=nil)
66 66 {:authorization => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
67 67 end
68 68
69 69 # Mock out a file
70 70 def self.mock_file
71 71 file = 'a_file.png'
72 72 file.stubs(:size).returns(32)
73 73 file.stubs(:original_filename).returns('a_file.png')
74 74 file.stubs(:content_type).returns('image/png')
75 75 file.stubs(:read).returns(false)
76 76 file
77 77 end
78 78
79 79 def mock_file
80 80 self.class.mock_file
81 81 end
82 82
83 83 def mock_file_with_options(options={})
84 84 file = ''
85 85 file.stubs(:size).returns(32)
86 86 original_filename = options[:original_filename] || nil
87 87 file.stubs(:original_filename).returns(original_filename)
88 88 content_type = options[:content_type] || nil
89 89 file.stubs(:content_type).returns(content_type)
90 90 file.stubs(:read).returns(false)
91 91 file
92 92 end
93 93
94 94 # Use a temporary directory for attachment related tests
95 95 def set_tmp_attachments_directory
96 96 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
97 97 unless File.directory?("#{Rails.root}/tmp/test/attachments")
98 98 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
99 99 end
100 100 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
101 101 end
102 102
103 103 def set_fixtures_attachments_directory
104 104 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
105 105 end
106 106
107 107 def with_settings(options, &block)
108 108 saved_settings = options.keys.inject({}) {|h, k| h[k] = Setting[k].is_a?(Symbol) ? Setting[k] : Setting[k].dup; h}
109 109 options.each {|k, v| Setting[k] = v}
110 110 yield
111 111 ensure
112 112 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
113 113 end
114 114
115 115 def change_user_password(login, new_password)
116 116 user = User.first(:conditions => {:login => login})
117 117 user.password, user.password_confirmation = new_password, new_password
118 118 user.save!
119 119 end
120 120
121 121 def self.ldap_configured?
122 122 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
123 123 return @test_ldap.bind
124 124 rescue Exception => e
125 125 # LDAP is not listening
126 126 return nil
127 127 end
128 128
129 129 # Returns the path to the test +vendor+ repository
130 130 def self.repository_path(vendor)
131 131 Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
132 132 end
133 133
134 134 # Returns the url of the subversion test repository
135 135 def self.subversion_repository_url
136 136 path = repository_path('subversion')
137 137 path = '/' + path unless path.starts_with?('/')
138 138 "file://#{path}"
139 139 end
140 140
141 141 # Returns true if the +vendor+ test repository is configured
142 142 def self.repository_configured?(vendor)
143 143 File.directory?(repository_path(vendor))
144 144 end
145 145
146 146 def repository_path_hash(arr)
147 147 hs = {}
148 148 hs[:path] = arr.join("/")
149 149 hs[:param] = arr
150 150 hs
151 151 end
152 152
153 153 def assert_error_tag(options={})
154 154 assert_tag({:attributes => { :id => 'errorExplanation' }}.merge(options))
155 155 end
156 156
157 157 def assert_include(expected, s)
158 158 assert s.include?(expected), "\"#{expected}\" not found in \"#{s}\""
159 159 end
160 160
161 161 def assert_not_include(expected, s)
162 162 assert !s.include?(expected), "\"#{expected}\" found in \"#{s}\""
163 163 end
164 164
165 165 def assert_mail_body_match(expected, mail)
166 166 if expected.is_a?(String)
167 167 assert_include expected, mail_body(mail)
168 168 else
169 169 assert_match expected, mail_body(mail)
170 170 end
171 171 end
172 172
173 173 def assert_mail_body_no_match(expected, mail)
174 174 if expected.is_a?(String)
175 175 assert_not_include expected, mail_body(mail)
176 176 else
177 177 assert_no_match expected, mail_body(mail)
178 178 end
179 179 end
180 180
181 181 def mail_body(mail)
182 182 mail.body
183 183 end
184 184
185 185 # Shoulda macros
186 186 def self.should_render_404
187 187 should_respond_with :not_found
188 188 should_render_template 'common/error'
189 189 end
190 190
191 191 def self.should_have_before_filter(expected_method, options = {})
192 192 should_have_filter('before', expected_method, options)
193 193 end
194 194
195 195 def self.should_have_after_filter(expected_method, options = {})
196 196 should_have_filter('after', expected_method, options)
197 197 end
198 198
199 199 def self.should_have_filter(filter_type, expected_method, options)
200 200 description = "have #{filter_type}_filter :#{expected_method}"
201 201 description << " with #{options.inspect}" unless options.empty?
202 202
203 203 should description do
204 204 klass = "action_controller/filters/#{filter_type}_filter".classify.constantize
205 205 expected = klass.new(:filter, expected_method.to_sym, options)
206 206 assert_equal 1, @controller.class.filter_chain.select { |filter|
207 207 filter.method == expected.method && filter.kind == expected.kind &&
208 208 filter.options == expected.options && filter.class == expected.class
209 209 }.size
210 210 end
211 211 end
212 212
213 def self.should_show_the_old_and_new_values_for(prop_key, model, &block)
214 context "" do
215 setup do
216 if block_given?
217 instance_eval &block
218 else
219 @old_value = model.generate!
220 @new_value = model.generate!
221 end
222 end
223
224 should "use the new value's name" do
225 @detail = JournalDetail.generate!(:property => 'attr',
226 :old_value => @old_value.id,
227 :value => @new_value.id,
228 :prop_key => prop_key)
229
230 assert_match @new_value.name, show_detail(@detail, true)
231 end
232
233 should "use the old value's name" do
234 @detail = JournalDetail.generate!(:property => 'attr',
235 :old_value => @old_value.id,
236 :value => @new_value.id,
237 :prop_key => prop_key)
238
239 assert_match @old_value.name, show_detail(@detail, true)
240 end
241 end
242 end
243
244 213 # Test that a request allows the three types of API authentication
245 214 #
246 215 # * HTTP Basic with username and password
247 216 # * HTTP Basic with an api key for the username
248 217 # * Key based with the key=X parameter
249 218 #
250 219 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
251 220 # @param [String] url the request url
252 221 # @param [optional, Hash] parameters additional request parameters
253 222 # @param [optional, Hash] options additional options
254 223 # @option options [Symbol] :success_code Successful response code (:success)
255 224 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
256 225 def self.should_allow_api_authentication(http_method, url, parameters={}, options={})
257 226 should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters, options)
258 227 should_allow_http_basic_auth_with_key(http_method, url, parameters, options)
259 228 should_allow_key_based_auth(http_method, url, parameters, options)
260 229 end
261 230
262 231 # Test that a request allows the username and password for HTTP BASIC
263 232 #
264 233 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
265 234 # @param [String] url the request url
266 235 # @param [optional, Hash] parameters additional request parameters
267 236 # @param [optional, Hash] options additional options
268 237 # @option options [Symbol] :success_code Successful response code (:success)
269 238 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
270 239 def self.should_allow_http_basic_auth_with_username_and_password(http_method, url, parameters={}, options={})
271 240 success_code = options[:success_code] || :success
272 241 failure_code = options[:failure_code] || :unauthorized
273 242
274 243 context "should allow http basic auth using a username and password for #{http_method} #{url}" do
275 244 context "with a valid HTTP authentication" do
276 245 setup do
277 246 @user = User.generate_with_protected!(:password => 'my_password', :password_confirmation => 'my_password', :admin => true) # Admin so they can access the project
278 247 send(http_method, url, parameters, credentials(@user.login, 'my_password'))
279 248 end
280 249
281 250 should_respond_with success_code
282 251 should_respond_with_content_type_based_on_url(url)
283 252 should "login as the user" do
284 253 assert_equal @user, User.current
285 254 end
286 255 end
287 256
288 257 context "with an invalid HTTP authentication" do
289 258 setup do
290 259 @user = User.generate_with_protected!
291 260 send(http_method, url, parameters, credentials(@user.login, 'wrong_password'))
292 261 end
293 262
294 263 should_respond_with failure_code
295 264 should_respond_with_content_type_based_on_url(url)
296 265 should "not login as the user" do
297 266 assert_equal User.anonymous, User.current
298 267 end
299 268 end
300 269
301 270 context "without credentials" do
302 271 setup do
303 272 send(http_method, url, parameters)
304 273 end
305 274
306 275 should_respond_with failure_code
307 276 should_respond_with_content_type_based_on_url(url)
308 277 should "include_www_authenticate_header" do
309 278 assert @controller.response.headers.has_key?('WWW-Authenticate')
310 279 end
311 280 end
312 281 end
313 282
314 283 end
315 284
316 285 # Test that a request allows the API key with HTTP BASIC
317 286 #
318 287 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
319 288 # @param [String] url the request url
320 289 # @param [optional, Hash] parameters additional request parameters
321 290 # @param [optional, Hash] options additional options
322 291 # @option options [Symbol] :success_code Successful response code (:success)
323 292 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
324 293 def self.should_allow_http_basic_auth_with_key(http_method, url, parameters={}, options={})
325 294 success_code = options[:success_code] || :success
326 295 failure_code = options[:failure_code] || :unauthorized
327 296
328 297 context "should allow http basic auth with a key for #{http_method} #{url}" do
329 298 context "with a valid HTTP authentication using the API token" do
330 299 setup do
331 300 @user = User.generate_with_protected!(:admin => true)
332 301 @token = Token.generate!(:user => @user, :action => 'api')
333 302 send(http_method, url, parameters, credentials(@token.value, 'X'))
334 303 end
335 304
336 305 should_respond_with success_code
337 306 should_respond_with_content_type_based_on_url(url)
338 307 should_be_a_valid_response_string_based_on_url(url)
339 308 should "login as the user" do
340 309 assert_equal @user, User.current
341 310 end
342 311 end
343 312
344 313 context "with an invalid HTTP authentication" do
345 314 setup do
346 315 @user = User.generate_with_protected!
347 316 @token = Token.generate!(:user => @user, :action => 'feeds')
348 317 send(http_method, url, parameters, credentials(@token.value, 'X'))
349 318 end
350 319
351 320 should_respond_with failure_code
352 321 should_respond_with_content_type_based_on_url(url)
353 322 should "not login as the user" do
354 323 assert_equal User.anonymous, User.current
355 324 end
356 325 end
357 326 end
358 327 end
359 328
360 329 # Test that a request allows full key authentication
361 330 #
362 331 # @param [Symbol] http_method the HTTP method for request (:get, :post, :put, :delete)
363 332 # @param [String] url the request url, without the key=ZXY parameter
364 333 # @param [optional, Hash] parameters additional request parameters
365 334 # @param [optional, Hash] options additional options
366 335 # @option options [Symbol] :success_code Successful response code (:success)
367 336 # @option options [Symbol] :failure_code Failure response code (:unauthorized)
368 337 def self.should_allow_key_based_auth(http_method, url, parameters={}, options={})
369 338 success_code = options[:success_code] || :success
370 339 failure_code = options[:failure_code] || :unauthorized
371 340
372 341 context "should allow key based auth using key=X for #{http_method} #{url}" do
373 342 context "with a valid api token" do
374 343 setup do
375 344 @user = User.generate_with_protected!(:admin => true)
376 345 @token = Token.generate!(:user => @user, :action => 'api')
377 346 # Simple url parse to add on ?key= or &key=
378 347 request_url = if url.match(/\?/)
379 348 url + "&key=#{@token.value}"
380 349 else
381 350 url + "?key=#{@token.value}"
382 351 end
383 352 send(http_method, request_url, parameters)
384 353 end
385 354
386 355 should_respond_with success_code
387 356 should_respond_with_content_type_based_on_url(url)
388 357 should_be_a_valid_response_string_based_on_url(url)
389 358 should "login as the user" do
390 359 assert_equal @user, User.current
391 360 end
392 361 end
393 362
394 363 context "with an invalid api token" do
395 364 setup do
396 365 @user = User.generate_with_protected!
397 366 @token = Token.generate!(:user => @user, :action => 'feeds')
398 367 # Simple url parse to add on ?key= or &key=
399 368 request_url = if url.match(/\?/)
400 369 url + "&key=#{@token.value}"
401 370 else
402 371 url + "?key=#{@token.value}"
403 372 end
404 373 send(http_method, request_url, parameters)
405 374 end
406 375
407 376 should_respond_with failure_code
408 377 should_respond_with_content_type_based_on_url(url)
409 378 should "not login as the user" do
410 379 assert_equal User.anonymous, User.current
411 380 end
412 381 end
413 382 end
414 383
415 384 context "should allow key based auth using X-Redmine-API-Key header for #{http_method} #{url}" do
416 385 setup do
417 386 @user = User.generate_with_protected!(:admin => true)
418 387 @token = Token.generate!(:user => @user, :action => 'api')
419 388 send(http_method, url, parameters, {'X-Redmine-API-Key' => @token.value.to_s})
420 389 end
421 390
422 391 should_respond_with success_code
423 392 should_respond_with_content_type_based_on_url(url)
424 393 should_be_a_valid_response_string_based_on_url(url)
425 394 should "login as the user" do
426 395 assert_equal @user, User.current
427 396 end
428 397 end
429 398 end
430 399
431 400 # Uses should_respond_with_content_type based on what's in the url:
432 401 #
433 402 # '/project/issues.xml' => should_respond_with_content_type :xml
434 403 # '/project/issues.json' => should_respond_with_content_type :json
435 404 #
436 405 # @param [String] url Request
437 406 def self.should_respond_with_content_type_based_on_url(url)
438 407 case
439 408 when url.match(/xml/i)
440 409 should_respond_with_content_type :xml
441 410 when url.match(/json/i)
442 411 should_respond_with_content_type :json
443 412 else
444 413 raise "Unknown content type for should_respond_with_content_type_based_on_url: #{url}"
445 414 end
446 415
447 416 end
448 417
449 418 # Uses the url to assert which format the response should be in
450 419 #
451 420 # '/project/issues.xml' => should_be_a_valid_xml_string
452 421 # '/project/issues.json' => should_be_a_valid_json_string
453 422 #
454 423 # @param [String] url Request
455 424 def self.should_be_a_valid_response_string_based_on_url(url)
456 425 case
457 426 when url.match(/xml/i)
458 427 should_be_a_valid_xml_string
459 428 when url.match(/json/i)
460 429 should_be_a_valid_json_string
461 430 else
462 431 raise "Unknown content type for should_be_a_valid_response_based_on_url: #{url}"
463 432 end
464 433
465 434 end
466 435
467 436 # Checks that the response is a valid JSON string
468 437 def self.should_be_a_valid_json_string
469 438 should "be a valid JSON string (or empty)" do
470 439 assert(response.body.blank? || ActiveSupport::JSON.decode(response.body))
471 440 end
472 441 end
473 442
474 443 # Checks that the response is a valid XML string
475 444 def self.should_be_a_valid_xml_string
476 445 should "be a valid XML string" do
477 446 assert REXML::Document.new(response.body)
478 447 end
479 448 end
480 449
481 450 end
482 451
483 452 # Simple module to "namespace" all of the API tests
484 453 module ApiTest
485 454 end
@@ -1,171 +1,198
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class IssuesHelperTest < ActionView::TestCase
21 21 include ApplicationHelper
22 22 include IssuesHelper
23 include CustomFieldsHelper
23 24 include ERB::Util
24 25
25 26 fixtures :projects, :trackers, :issue_statuses, :issues,
26 27 :enumerations, :users, :issue_categories,
27 28 :projects_trackers,
28 29 :roles,
29 30 :member_roles,
30 31 :members,
31 32 :enabled_modules,
32 :workflows
33 :workflows,
34 :custom_fields,
35 :attachments
33 36
34 37 def setup
35 38 super
36 39 set_language_if_valid('en')
37 40 User.current = nil
38 41 end
39 42
40 43 def test_issue_heading
41 44 assert_equal "Bug #1", issue_heading(Issue.find(1))
42 45 end
43 46
44 47 def test_issues_destroy_confirmation_message_with_one_root_issue
45 48 assert_equal l(:text_issues_destroy_confirmation), issues_destroy_confirmation_message(Issue.find(1))
46 49 end
47 50
48 51 def test_issues_destroy_confirmation_message_with_an_arrayt_of_root_issues
49 52 assert_equal l(:text_issues_destroy_confirmation), issues_destroy_confirmation_message(Issue.find([1, 2]))
50 53 end
51 54
52 55 def test_issues_destroy_confirmation_message_with_one_parent_issue
53 56 Issue.find(2).update_attribute :parent_issue_id, 1
54 57 assert_equal l(:text_issues_destroy_confirmation) + "\n" + l(:text_issues_destroy_descendants_confirmation, :count => 1),
55 58 issues_destroy_confirmation_message(Issue.find(1))
56 59 end
57 60
58 61 def test_issues_destroy_confirmation_message_with_one_parent_issue_and_its_child
59 62 Issue.find(2).update_attribute :parent_issue_id, 1
60 63 assert_equal l(:text_issues_destroy_confirmation), issues_destroy_confirmation_message(Issue.find([1, 2]))
61 64 end
62 65
63 66 context "IssuesHelper#show_detail" do
64 67 context "with no_html" do
65 68 should 'show a changing attribute' do
66 69 @detail = JournalDetail.new(:property => 'attr', :old_value => '40', :value => '100', :prop_key => 'done_ratio')
67 70 assert_equal "% Done changed from 40 to 100", show_detail(@detail, true)
68 71 end
69 72
70 73 should 'show a new attribute' do
71 74 @detail = JournalDetail.new(:property => 'attr', :old_value => nil, :value => '100', :prop_key => 'done_ratio')
72 75 assert_equal "% Done set to 100", show_detail(@detail, true)
73 76 end
74 77
75 78 should 'show a deleted attribute' do
76 79 @detail = JournalDetail.new(:property => 'attr', :old_value => '50', :value => nil, :prop_key => 'done_ratio')
77 80 assert_equal "% Done deleted (50)", show_detail(@detail, true)
78 81 end
79 82 end
80 83
81 84 context "with html" do
82 85 should 'show a changing attribute with HTML highlights' do
83 86 @detail = JournalDetail.new(:property => 'attr', :old_value => '40', :value => '100', :prop_key => 'done_ratio')
84 87 html = show_detail(@detail, false)
85 88
86 89 assert_include '<strong>% Done</strong>', html
87 90 assert_include '<i>40</i>', html
88 91 assert_include '<i>100</i>', html
89 92 end
90 93
91 94 should 'show a new attribute with HTML highlights' do
92 95 @detail = JournalDetail.new(:property => 'attr', :old_value => nil, :value => '100', :prop_key => 'done_ratio')
93 96 html = show_detail(@detail, false)
94 97
95 98 assert_include '<strong>% Done</strong>', html
96 99 assert_include '<i>100</i>', html
97 100 end
98 101
99 102 should 'show a deleted attribute with HTML highlights' do
100 103 @detail = JournalDetail.new(:property => 'attr', :old_value => '50', :value => nil, :prop_key => 'done_ratio')
101 104 html = show_detail(@detail, false)
102 105
103 106 assert_include '<strong>% Done</strong>', html
104 107 assert_include '<strike><i>50</i></strike>', html
105 108 end
106 109 end
107 110
108 111 context "with a start_date attribute" do
109 112 should "format the current date" do
110 113 @detail = JournalDetail.new(:property => 'attr', :old_value => '2010-01-01', :value => '2010-01-31', :prop_key => 'start_date')
111 114 assert_match "01/31/2010", show_detail(@detail, true)
112 115 end
113 116
114 117 should "format the old date" do
115 118 @detail = JournalDetail.new(:property => 'attr', :old_value => '2010-01-01', :value => '2010-01-31', :prop_key => 'start_date')
116 119 assert_match "01/01/2010", show_detail(@detail, true)
117 120 end
118 121 end
119 122
120 123 context "with a due_date attribute" do
121 124 should "format the current date" do
122 125 @detail = JournalDetail.new(:property => 'attr', :old_value => '2010-01-01', :value => '2010-01-31', :prop_key => 'due_date')
123 126 assert_match "01/31/2010", show_detail(@detail, true)
124 127 end
125 128
126 129 should "format the old date" do
127 130 @detail = JournalDetail.new(:property => 'attr', :old_value => '2010-01-01', :value => '2010-01-31', :prop_key => 'due_date')
128 131 assert_match "01/01/2010", show_detail(@detail, true)
129 132 end
130 133 end
131 134
132 context "with a project attribute" do
133 should_show_the_old_and_new_values_for('project_id', Project)
135 should "show old and new values with a project attribute" do
136 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'project_id', :old_value => 1, :value => 2)
137 assert_match 'eCookbook', show_detail(detail, true)
138 assert_match 'OnlineStore', show_detail(detail, true)
134 139 end
135 140
136 context "with a issue status attribute" do
137 should_show_the_old_and_new_values_for('status_id', IssueStatus)
141 should "show old and new values with a issue status attribute" do
142 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'status_id', :old_value => 1, :value => 2)
143 assert_match 'New', show_detail(detail, true)
144 assert_match 'Assigned', show_detail(detail, true)
138 145 end
139 146
140 context "with a tracker attribute" do
141 should_show_the_old_and_new_values_for('tracker_id', Tracker)
147 should "show old and new values with a tracker attribute" do
148 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'tracker_id', :old_value => 1, :value => 2)
149 assert_match 'Bug', show_detail(detail, true)
150 assert_match 'Feature request', show_detail(detail, true)
142 151 end
143 152
144 context "with a assigned to attribute" do
145 should_show_the_old_and_new_values_for('assigned_to_id', User)
153 should "show old and new values with a assigned to attribute" do
154 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'assigned_to_id', :old_value => 1, :value => 2)
155 assert_match 'redMine Admin', show_detail(detail, true)
156 assert_match 'John Smith', show_detail(detail, true)
146 157 end
147 158
148 context "with a priority attribute" do
149 should_show_the_old_and_new_values_for('priority_id', IssuePriority) do
150 @old_value = IssuePriority.generate!(:type => 'IssuePriority')
151 @new_value = IssuePriority.generate!(:type => 'IssuePriority')
152 end
159 should "show old and new values with a priority attribute" do
160 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'priority_id', :old_value => 4, :value => 5)
161 assert_match 'Low', show_detail(detail, true)
162 assert_match 'Normal', show_detail(detail, true)
163 end
164
165 should "show old and new values with a category attribute" do
166 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'category_id', :old_value => 1, :value => 2)
167 assert_match 'Printing', show_detail(detail, true)
168 assert_match 'Recipes', show_detail(detail, true)
153 169 end
154 170
155 context "with a category attribute" do
156 should_show_the_old_and_new_values_for('category_id', IssueCategory)
171 should "show old and new values with a fixed version attribute" do
172 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'fixed_version_id', :old_value => 1, :value => 2)
173 assert_match '0.1', show_detail(detail, true)
174 assert_match '1.0', show_detail(detail, true)
157 175 end
158 176
159 context "with a fixed version attribute" do
160 should_show_the_old_and_new_values_for('fixed_version_id', Version)
177 should "show old and new values with a estimated hours attribute" do
178 detail = JournalDetail.generate!(:property => 'attr', :prop_key => 'estimated_hours', :old_value => '5', :value => '6.3')
179 assert_match '5.00', show_detail(detail, true)
180 assert_match '6.30', show_detail(detail, true)
161 181 end
162 182
163 context "with a estimated hours attribute" do
164 should "format the time into two decimal places"
165 should "format the old time into two decimal places"
183 should "show old and new values with a custom field" do
184 detail = JournalDetail.generate!(:property => 'cf', :prop_key => '1', :old_value => 'MySQL', :value => 'PostgreSQL')
185 assert_equal 'Database changed from MySQL to PostgreSQL', show_detail(detail, true)
166 186 end
167 187
168 should "test custom fields"
169 should "test attachments"
188 should "show added file" do
189 detail = JournalDetail.generate!(:property => 'attachment', :prop_key => '1', :old_value => nil, :value => 'error281.txt')
190 assert_match 'error281.txt', show_detail(detail, true)
191 end
192
193 should "show removed file" do
194 detail = JournalDetail.generate!(:property => 'attachment', :prop_key => '1', :old_value => 'error281.txt', :value => nil)
195 assert_match 'error281.txt', show_detail(detail, true)
196 end
170 197 end
171 198 end
General Comments 0
You need to be logged in to leave comments. Login now