PageRenderTime 72ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/rails/activerecord/test/validations_test.rb

http://monkeycharger.googlecode.com/
Ruby | 1197 lines | 1108 code | 88 blank | 1 comment | 1 complexity | 72d703ae5efc4c0957244abaf3650112 MD5 | raw file
  1. require 'abstract_unit'
  2. require 'fixtures/topic'
  3. require 'fixtures/reply'
  4. require 'fixtures/person'
  5. require 'fixtures/developer'
  6. # The following methods in Topic are used in test_conditional_validation_*
  7. class Topic
  8. def condition_is_true
  9. return true
  10. end
  11. def condition_is_true_but_its_not
  12. return false
  13. end
  14. end
  15. class ProtectedPerson < ActiveRecord::Base
  16. set_table_name 'people'
  17. attr_accessor :addon
  18. attr_protected :first_name
  19. end
  20. class ValidationsTest < Test::Unit::TestCase
  21. fixtures :topics, :developers
  22. def setup
  23. Topic.write_inheritable_attribute(:validate, nil)
  24. Topic.write_inheritable_attribute(:validate_on_create, nil)
  25. Topic.write_inheritable_attribute(:validate_on_update, nil)
  26. end
  27. def test_single_field_validation
  28. r = Reply.new
  29. r.title = "There's no content!"
  30. assert !r.valid?, "A reply without content shouldn't be saveable"
  31. r.content = "Messa content!"
  32. assert r.valid?, "A reply with content should be saveable"
  33. end
  34. def test_single_attr_validation_and_error_msg
  35. r = Reply.new
  36. r.title = "There's no content!"
  37. assert !r.valid?
  38. assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
  39. assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
  40. assert_equal 1, r.errors.count
  41. end
  42. def test_double_attr_validation_and_error_msg
  43. r = Reply.new
  44. assert !r.valid?
  45. assert r.errors.invalid?("title"), "A reply without title should mark that attribute as invalid"
  46. assert_equal "Empty", r.errors.on("title"), "A reply without title should contain an error"
  47. assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
  48. assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
  49. assert_equal 2, r.errors.count
  50. end
  51. def test_error_on_create
  52. r = Reply.new
  53. r.title = "Wrong Create"
  54. assert !r.valid?
  55. assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
  56. assert_equal "is Wrong Create", r.errors.on("title"), "A reply with a bad content should contain an error"
  57. end
  58. def test_error_on_update
  59. r = Reply.new
  60. r.title = "Bad"
  61. r.content = "Good"
  62. assert r.save, "First save should be successful"
  63. r.title = "Wrong Update"
  64. assert !r.save, "Second save should fail"
  65. assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
  66. assert_equal "is Wrong Update", r.errors.on("title"), "A reply with a bad content should contain an error"
  67. end
  68. def test_invalid_record_exception
  69. assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
  70. assert_raises(ActiveRecord::RecordInvalid) { Reply.new.save! }
  71. begin
  72. r = Reply.new
  73. r.save!
  74. flunk
  75. rescue ActiveRecord::RecordInvalid => invalid
  76. assert_equal r, invalid.record
  77. end
  78. end
  79. def test_scoped_create_without_attributes
  80. Reply.with_scope(:create => {}) do
  81. assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
  82. end
  83. end
  84. def test_create_with_exceptions_using_scope_for_protected_attributes
  85. assert_nothing_raised do
  86. ProtectedPerson.with_scope( :create => { :first_name => "Mary" } ) do
  87. person = ProtectedPerson.create! :addon => "Addon"
  88. assert_equal person.first_name, "Mary", "scope should ignore attr_protected"
  89. end
  90. end
  91. end
  92. def test_create_with_exceptions_using_scope_and_empty_attributes
  93. assert_nothing_raised do
  94. ProtectedPerson.with_scope( :create => { :first_name => "Mary" } ) do
  95. person = ProtectedPerson.create!
  96. assert_equal person.first_name, "Mary", "should be ok when no attributes are passed to create!"
  97. end
  98. end
  99. end
  100. def test_single_error_per_attr_iteration
  101. r = Reply.new
  102. r.save
  103. errors = []
  104. r.errors.each { |attr, msg| errors << [attr, msg] }
  105. assert errors.include?(["title", "Empty"])
  106. assert errors.include?(["content", "Empty"])
  107. end
  108. def test_multiple_errors_per_attr_iteration_with_full_error_composition
  109. r = Reply.new
  110. r.title = "Wrong Create"
  111. r.content = "Mismatch"
  112. r.save
  113. errors = []
  114. r.errors.each_full { |error| errors << error }
  115. assert_equal "Title is Wrong Create", errors[0]
  116. assert_equal "Title is Content Mismatch", errors[1]
  117. assert_equal 2, r.errors.count
  118. end
  119. def test_errors_on_base
  120. r = Reply.new
  121. r.content = "Mismatch"
  122. r.save
  123. r.errors.add_to_base "Reply is not dignifying"
  124. errors = []
  125. r.errors.each_full { |error| errors << error }
  126. assert_equal "Reply is not dignifying", r.errors.on_base
  127. assert errors.include?("Title Empty")
  128. assert errors.include?("Reply is not dignifying")
  129. assert_equal 2, r.errors.count
  130. end
  131. def test_create_without_validation
  132. reply = Reply.new
  133. assert !reply.save
  134. assert reply.save(false)
  135. end
  136. def test_create_without_validation_bang
  137. count = Reply.count
  138. assert_nothing_raised { Reply.new.save_without_validation! }
  139. assert count+1, Reply.count
  140. end
  141. def test_validates_each
  142. perform = true
  143. hits = 0
  144. Topic.validates_each(:title, :content, [:title, :content]) do |record, attr|
  145. if perform
  146. record.errors.add attr, 'gotcha'
  147. hits += 1
  148. end
  149. end
  150. t = Topic.new("title" => "valid", "content" => "whatever")
  151. assert !t.save
  152. assert_equal 4, hits
  153. assert_equal %w(gotcha gotcha), t.errors.on(:title)
  154. assert_equal %w(gotcha gotcha), t.errors.on(:content)
  155. ensure
  156. perform = false
  157. end
  158. def test_no_title_confirmation
  159. Topic.validates_confirmation_of(:title)
  160. t = Topic.new(:author_name => "Plutarch")
  161. assert t.valid?
  162. t.title_confirmation = "Parallel Lives"
  163. assert !t.valid?
  164. t.title_confirmation = nil
  165. t.title = "Parallel Lives"
  166. assert t.valid?
  167. t.title_confirmation = "Parallel Lives"
  168. assert t.valid?
  169. end
  170. def test_title_confirmation
  171. Topic.validates_confirmation_of(:title)
  172. t = Topic.create("title" => "We should be confirmed","title_confirmation" => "")
  173. assert !t.save
  174. t.title_confirmation = "We should be confirmed"
  175. assert t.save
  176. end
  177. def test_terms_of_service_agreement_no_acceptance
  178. Topic.validates_acceptance_of(:terms_of_service, :on => :create)
  179. t = Topic.create("title" => "We should not be confirmed")
  180. assert t.save
  181. end
  182. def test_terms_of_service_agreement
  183. Topic.validates_acceptance_of(:terms_of_service, :on => :create)
  184. t = Topic.create("title" => "We should be confirmed","terms_of_service" => "")
  185. assert !t.save
  186. assert_equal "must be accepted", t.errors.on(:terms_of_service)
  187. t.terms_of_service = "1"
  188. assert t.save
  189. end
  190. def test_eula
  191. Topic.validates_acceptance_of(:eula, :message => "must be abided", :on => :create)
  192. t = Topic.create("title" => "We should be confirmed","eula" => "")
  193. assert !t.save
  194. assert_equal "must be abided", t.errors.on(:eula)
  195. t.eula = "1"
  196. assert t.save
  197. end
  198. def test_terms_of_service_agreement_with_accept_value
  199. Topic.validates_acceptance_of(:terms_of_service, :on => :create, :accept => "I agree.")
  200. t = Topic.create("title" => "We should be confirmed", "terms_of_service" => "")
  201. assert !t.save
  202. assert_equal "must be accepted", t.errors.on(:terms_of_service)
  203. t.terms_of_service = "I agree."
  204. assert t.save
  205. end
  206. def test_validate_presences
  207. Topic.validates_presence_of(:title, :content)
  208. t = Topic.create
  209. assert !t.save
  210. assert_equal "can't be blank", t.errors.on(:title)
  211. assert_equal "can't be blank", t.errors.on(:content)
  212. t.title = "something"
  213. t.content = " "
  214. assert !t.save
  215. assert_equal "can't be blank", t.errors.on(:content)
  216. t.content = "like stuff"
  217. assert t.save
  218. end
  219. def test_validate_uniqueness
  220. Topic.validates_uniqueness_of(:title)
  221. t = Topic.new("title" => "I'm unique!")
  222. assert t.save, "Should save t as unique"
  223. t.content = "Remaining unique"
  224. assert t.save, "Should still save t as unique"
  225. t2 = Topic.new("title" => "I'm unique!")
  226. assert !t2.valid?, "Shouldn't be valid"
  227. assert !t2.save, "Shouldn't save t2 as unique"
  228. assert_equal "has already been taken", t2.errors.on(:title)
  229. t2.title = "Now Im really also unique"
  230. assert t2.save, "Should now save t2 as unique"
  231. end
  232. def test_validate_uniqueness_with_scope
  233. Reply.validates_uniqueness_of(:content, :scope => "parent_id")
  234. t = Topic.create("title" => "I'm unique!")
  235. r1 = t.replies.create "title" => "r1", "content" => "hello world"
  236. assert r1.valid?, "Saving r1"
  237. r2 = t.replies.create "title" => "r2", "content" => "hello world"
  238. assert !r2.valid?, "Saving r2 first time"
  239. r2.content = "something else"
  240. assert r2.save, "Saving r2 second time"
  241. t2 = Topic.create("title" => "I'm unique too!")
  242. r3 = t2.replies.create "title" => "r3", "content" => "hello world"
  243. assert r3.valid?, "Saving r3"
  244. end
  245. def test_validate_uniqueness_with_scope_array
  246. Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
  247. t = Topic.create("title" => "The earth is actually flat!")
  248. r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
  249. assert r1.valid?, "Saving r1"
  250. r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
  251. assert !r2.valid?, "Saving r2. Double reply by same author."
  252. r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
  253. assert r2.save, "Saving r2 the second time."
  254. r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
  255. assert !r3.valid?, "Saving r3"
  256. r3.author_name = "jj"
  257. assert r3.save, "Saving r3 the second time."
  258. r3.author_name = "jeremy"
  259. assert !r3.save, "Saving r3 the third time."
  260. end
  261. def test_validate_case_insensitive_uniqueness
  262. Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
  263. t = Topic.new("title" => "I'm unique!", :parent_id => 2)
  264. assert t.save, "Should save t as unique"
  265. t.content = "Remaining unique"
  266. assert t.save, "Should still save t as unique"
  267. t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
  268. assert !t2.valid?, "Shouldn't be valid"
  269. assert !t2.save, "Shouldn't save t2 as unique"
  270. assert t2.errors.on(:title)
  271. assert t2.errors.on(:parent_id)
  272. assert_equal "has already been taken", t2.errors.on(:title)
  273. t2.title = "I'm truly UNIQUE!"
  274. assert !t2.valid?, "Shouldn't be valid"
  275. assert !t2.save, "Shouldn't save t2 as unique"
  276. assert_nil t2.errors.on(:title)
  277. assert t2.errors.on(:parent_id)
  278. t2.parent_id = 3
  279. assert t2.save, "Should now save t2 as unique"
  280. t2.parent_id = nil
  281. t2.title = nil
  282. assert t2.valid?, "should validate with nil"
  283. assert t2.save, "should save with nil"
  284. end
  285. def test_validate_format
  286. Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data")
  287. t = Topic.create("title" => "i'm incorrect", "content" => "Validation macros rule!")
  288. assert !t.valid?, "Shouldn't be valid"
  289. assert !t.save, "Shouldn't save because it's invalid"
  290. assert_equal "is bad data", t.errors.on(:title)
  291. assert_nil t.errors.on(:content)
  292. t.title = "Validation macros rule!"
  293. assert t.save
  294. assert_nil t.errors.on(:title)
  295. assert_raise(ArgumentError) { Topic.validates_format_of(:title, :content) }
  296. end
  297. # testing ticket #3142
  298. def test_validate_format_numeric
  299. Topic.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data")
  300. t = Topic.create("title" => "72x", "content" => "6789")
  301. assert !t.valid?, "Shouldn't be valid"
  302. assert !t.save, "Shouldn't save because it's invalid"
  303. assert_equal "is bad data", t.errors.on(:title)
  304. assert_nil t.errors.on(:content)
  305. t.title = "-11"
  306. assert !t.valid?, "Shouldn't be valid"
  307. t.title = "03"
  308. assert !t.valid?, "Shouldn't be valid"
  309. t.title = "z44"
  310. assert !t.valid?, "Shouldn't be valid"
  311. t.title = "5v7"
  312. assert !t.valid?, "Shouldn't be valid"
  313. t.title = "1"
  314. assert t.save
  315. assert_nil t.errors.on(:title)
  316. end
  317. def test_validates_inclusion_of
  318. Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) )
  319. assert !Topic.create("title" => "a!", "content" => "abc").valid?
  320. assert !Topic.create("title" => "a b", "content" => "abc").valid?
  321. assert !Topic.create("title" => nil, "content" => "def").valid?
  322. t = Topic.create("title" => "a", "content" => "I know you are but what am I?")
  323. assert t.valid?
  324. t.title = "uhoh"
  325. assert !t.valid?
  326. assert t.errors.on(:title)
  327. assert_equal "is not included in the list", t.errors["title"]
  328. assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => nil ) }
  329. assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => 0) }
  330. assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => "hi!" ) }
  331. assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => {} ) }
  332. assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => [] ) }
  333. end
  334. def test_validates_inclusion_of_with_allow_nil
  335. Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :allow_nil=>true )
  336. assert !Topic.create("title" => "a!", "content" => "abc").valid?
  337. assert !Topic.create("title" => "", "content" => "abc").valid?
  338. assert Topic.create("title" => nil, "content" => "abc").valid?
  339. end
  340. def test_numericality_with_getter_method
  341. Developer.validates_numericality_of( :salary )
  342. developer = Developer.new("name" => "michael", "salary" => nil)
  343. developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
  344. assert developer.valid?
  345. end
  346. def test_numericality_with_allow_nil_and_getter_method
  347. Developer.validates_numericality_of( :salary, :allow_nil => true)
  348. developer = Developer.new("name" => "michael", "salary" => nil)
  349. developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
  350. assert developer.valid?
  351. end
  352. def test_validates_exclusion_of
  353. Topic.validates_exclusion_of( :title, :in => %w( abe monkey ) )
  354. assert Topic.create("title" => "something", "content" => "abc").valid?
  355. assert !Topic.create("title" => "monkey", "content" => "abc").valid?
  356. end
  357. def test_validates_length_of_using_minimum
  358. Topic.validates_length_of :title, :minimum => 5
  359. t = Topic.create("title" => "valid", "content" => "whatever")
  360. assert t.valid?
  361. t.title = "not"
  362. assert !t.valid?
  363. assert t.errors.on(:title)
  364. assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
  365. t.title = ""
  366. assert !t.valid?
  367. assert t.errors.on(:title)
  368. assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
  369. t.title = nil
  370. assert !t.valid?
  371. assert t.errors.on(:title)
  372. assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
  373. end
  374. def test_optionally_validates_length_of_using_minimum
  375. Topic.validates_length_of :title, :minimum => 5, :allow_nil => true
  376. t = Topic.create("title" => "valid", "content" => "whatever")
  377. assert t.valid?
  378. t.title = nil
  379. assert t.valid?
  380. end
  381. def test_validates_length_of_using_maximum
  382. Topic.validates_length_of :title, :maximum => 5
  383. t = Topic.create("title" => "valid", "content" => "whatever")
  384. assert t.valid?
  385. t.title = "notvalid"
  386. assert !t.valid?
  387. assert t.errors.on(:title)
  388. assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
  389. t.title = ""
  390. assert t.valid?
  391. t.title = nil
  392. assert !t.valid?
  393. end
  394. def test_optionally_validates_length_of_using_maximum
  395. Topic.validates_length_of :title, :maximum => 5, :allow_nil => true
  396. t = Topic.create("title" => "valid", "content" => "whatever")
  397. assert t.valid?
  398. t.title = nil
  399. assert t.valid?
  400. end
  401. def test_validates_length_of_using_within
  402. Topic.validates_length_of(:title, :content, :within => 3..5)
  403. t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
  404. assert !t.valid?
  405. assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
  406. assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content)
  407. t.title = nil
  408. t.content = nil
  409. assert !t.valid?
  410. assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
  411. assert_equal "is too short (minimum is 3 characters)", t.errors.on(:content)
  412. t.title = "abe"
  413. t.content = "mad"
  414. assert t.valid?
  415. end
  416. def test_optionally_validates_length_of_using_within
  417. Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
  418. t = Topic.create('title' => 'abc', 'content' => 'abcd')
  419. assert t.valid?
  420. t.title = nil
  421. assert t.valid?
  422. end
  423. def test_optionally_validates_length_of_using_within_on_create
  424. Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "my string is too long: %d"
  425. t = Topic.create("title" => "thisisnotvalid", "content" => "whatever")
  426. assert !t.save
  427. assert t.errors.on(:title)
  428. assert_equal "my string is too long: 10", t.errors[:title]
  429. t.title = "butthisis"
  430. assert t.save
  431. t.title = "few"
  432. assert t.save
  433. t.content = "andthisislong"
  434. assert t.save
  435. t.content = t.title = "iamfine"
  436. assert t.save
  437. end
  438. def test_optionally_validates_length_of_using_within_on_update
  439. Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "my string is too short: %d"
  440. t = Topic.create("title" => "vali", "content" => "whatever")
  441. assert !t.save
  442. assert t.errors.on(:title)
  443. t.title = "not"
  444. assert !t.save
  445. assert t.errors.on(:title)
  446. assert_equal "my string is too short: 5", t.errors[:title]
  447. t.title = "valid"
  448. t.content = "andthisistoolong"
  449. assert !t.save
  450. assert t.errors.on(:content)
  451. t.content = "iamfine"
  452. assert t.save
  453. end
  454. def test_validates_length_of_using_is
  455. Topic.validates_length_of :title, :is => 5
  456. t = Topic.create("title" => "valid", "content" => "whatever")
  457. assert t.valid?
  458. t.title = "notvalid"
  459. assert !t.valid?
  460. assert t.errors.on(:title)
  461. assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
  462. t.title = ""
  463. assert !t.valid?
  464. t.title = nil
  465. assert !t.valid?
  466. end
  467. def test_optionally_validates_length_of_using_is
  468. Topic.validates_length_of :title, :is => 5, :allow_nil => true
  469. t = Topic.create("title" => "valid", "content" => "whatever")
  470. assert t.valid?
  471. t.title = nil
  472. assert t.valid?
  473. end
  474. def test_validates_length_of_using_bignum
  475. bigmin = 2 ** 30
  476. bigmax = 2 ** 32
  477. bigrange = bigmin...bigmax
  478. assert_nothing_raised do
  479. Topic.validates_length_of :title, :is => bigmin + 5
  480. Topic.validates_length_of :title, :within => bigrange
  481. Topic.validates_length_of :title, :in => bigrange
  482. Topic.validates_length_of :title, :minimum => bigmin
  483. Topic.validates_length_of :title, :maximum => bigmax
  484. end
  485. end
  486. def test_validates_length_with_globaly_modified_error_message
  487. ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre %d'
  488. Topic.validates_length_of :title, :minimum => 10
  489. t = Topic.create(:title => 'too short')
  490. assert !t.valid?
  491. assert_equal 'tu est trops petit hombre 10', t.errors['title']
  492. end
  493. def test_add_on_boundary_breaking_is_deprecated
  494. t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
  495. class << t
  496. def validate
  497. errors.add_on_boundary_breaking('title', 1..6)
  498. end
  499. end
  500. assert_deprecated 'add_on_boundary_breaking' do
  501. assert !t.valid?
  502. end
  503. end
  504. def test_validates_size_of_association
  505. assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
  506. t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
  507. assert !t.save
  508. assert t.errors.on(:replies)
  509. t.replies.create('title' => 'areply', 'content' => 'whateveragain')
  510. assert t.valid?
  511. end
  512. def test_validates_length_of_nasty_params
  513. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>6, :maximum=>9) }
  514. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :maximum=>9) }
  515. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :minimum=>9) }
  516. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :is=>9) }
  517. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>"a") }
  518. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum=>"a") }
  519. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>"a") }
  520. assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is=>"a") }
  521. end
  522. def test_validates_length_of_custom_errors_for_minimum_with_message
  523. Topic.validates_length_of( :title, :minimum=>5, :message=>"boo %d" )
  524. t = Topic.create("title" => "uhoh", "content" => "whatever")
  525. assert !t.valid?
  526. assert t.errors.on(:title)
  527. assert_equal "boo 5", t.errors["title"]
  528. end
  529. def test_validates_length_of_custom_errors_for_minimum_with_too_short
  530. Topic.validates_length_of( :title, :minimum=>5, :too_short=>"hoo %d" )
  531. t = Topic.create("title" => "uhoh", "content" => "whatever")
  532. assert !t.valid?
  533. assert t.errors.on(:title)
  534. assert_equal "hoo 5", t.errors["title"]
  535. end
  536. def test_validates_length_of_custom_errors_for_maximum_with_message
  537. Topic.validates_length_of( :title, :maximum=>5, :message=>"boo %d" )
  538. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  539. assert !t.valid?
  540. assert t.errors.on(:title)
  541. assert_equal "boo 5", t.errors["title"]
  542. end
  543. def test_validates_length_of_custom_errors_for_maximum_with_too_long
  544. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d" )
  545. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  546. assert !t.valid?
  547. assert t.errors.on(:title)
  548. assert_equal "hoo 5", t.errors["title"]
  549. end
  550. def test_validates_length_of_custom_errors_for_is_with_message
  551. Topic.validates_length_of( :title, :is=>5, :message=>"boo %d" )
  552. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  553. assert !t.valid?
  554. assert t.errors.on(:title)
  555. assert_equal "boo 5", t.errors["title"]
  556. end
  557. def test_validates_length_of_custom_errors_for_is_with_wrong_length
  558. Topic.validates_length_of( :title, :is=>5, :wrong_length=>"hoo %d" )
  559. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  560. assert !t.valid?
  561. assert t.errors.on(:title)
  562. assert_equal "hoo 5", t.errors["title"]
  563. end
  564. def kcode_scope(kcode)
  565. orig_kcode = $KCODE
  566. $KCODE = kcode
  567. begin
  568. yield
  569. ensure
  570. $KCODE = orig_kcode
  571. end
  572. end
  573. def test_validates_length_of_using_minimum_utf8
  574. kcode_scope('UTF8') do
  575. Topic.validates_length_of :title, :minimum => 5
  576. t = Topic.create("title" => "?????", "content" => "whatever")
  577. assert t.valid?
  578. t.title = "????"
  579. assert !t.valid?
  580. assert t.errors.on(:title)
  581. assert_equal "is too short (minimum is 5 characters)", t.errors["title"]
  582. end
  583. end
  584. def test_validates_length_of_using_maximum_utf8
  585. kcode_scope('UTF8') do
  586. Topic.validates_length_of :title, :maximum => 5
  587. t = Topic.create("title" => "?????", "content" => "whatever")
  588. assert t.valid?
  589. t.title = "??34??"
  590. assert !t.valid?
  591. assert t.errors.on(:title)
  592. assert_equal "is too long (maximum is 5 characters)", t.errors["title"]
  593. end
  594. end
  595. def test_validates_length_of_using_within_utf8
  596. kcode_scope('UTF8') do
  597. Topic.validates_length_of(:title, :content, :within => 3..5)
  598. t = Topic.new("title" => "??", "content" => "12?????")
  599. assert !t.valid?
  600. assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title)
  601. assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content)
  602. t.title = "???"
  603. t.content = "12?"
  604. assert t.valid?
  605. end
  606. end
  607. def test_optionally_validates_length_of_using_within_utf8
  608. kcode_scope('UTF8') do
  609. Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
  610. t = Topic.create('title' => '???', 'content' => '?????')
  611. assert t.valid?
  612. t.title = nil
  613. assert t.valid?
  614. end
  615. end
  616. def test_optionally_validates_length_of_using_within_on_create_utf8
  617. kcode_scope('UTF8') do
  618. Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "?????: %d"
  619. t = Topic.create("title" => "??????????A", "content" => "whatever")
  620. assert !t.save
  621. assert t.errors.on(:title)
  622. assert_equal "?????: 10", t.errors[:title]
  623. t.title = "?????????"
  624. assert t.save
  625. t.title = "??3"
  626. assert t.save
  627. t.content = "??????????"
  628. assert t.save
  629. t.content = t.title = "??????"
  630. assert t.save
  631. end
  632. end
  633. def test_optionally_validates_length_of_using_within_on_update_utf8
  634. kcode_scope('UTF8') do
  635. Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "?????: %d"
  636. t = Topic.create("title" => "???4", "content" => "whatever")
  637. assert !t.save
  638. assert t.errors.on(:title)
  639. t.title = "1??4"
  640. assert !t.save
  641. assert t.errors.on(:title)
  642. assert_equal "?????: 5", t.errors[:title]
  643. t.title = "valid"
  644. t.content = "??????????A"
  645. assert !t.save
  646. assert t.errors.on(:content)
  647. t.content = "??345"
  648. assert t.save
  649. end
  650. end
  651. def test_validates_length_of_using_is_utf8
  652. kcode_scope('UTF8') do
  653. Topic.validates_length_of :title, :is => 5
  654. t = Topic.create("title" => "??345", "content" => "whatever")
  655. assert t.valid?
  656. t.title = "??345?"
  657. assert !t.valid?
  658. assert t.errors.on(:title)
  659. assert_equal "is the wrong length (should be 5 characters)", t.errors["title"]
  660. end
  661. end
  662. def test_validates_size_of_association_utf8
  663. kcode_scope('UTF8') do
  664. assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
  665. t = Topic.new('title' => '?????', 'content' => '?????')
  666. assert !t.save
  667. assert t.errors.on(:replies)
  668. t.replies.create('title' => '?????', 'content' => '?????')
  669. assert t.valid?
  670. end
  671. end
  672. def test_validates_associated_many
  673. Topic.validates_associated( :replies )
  674. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  675. t.replies << [r = Reply.new("title" => "A reply"), r2 = Reply.new("title" => "Another reply", "content" => "non-empty"), r3 = Reply.new("title" => "Yet another reply"), r4 = Reply.new("title" => "The last reply", "content" => "non-empty")]
  676. assert !t.valid?
  677. assert t.errors.on(:replies)
  678. assert_equal 1, r.errors.count # make sure all associated objects have been validated
  679. assert_equal 0, r2.errors.count
  680. assert_equal 1, r3.errors.count
  681. assert_equal 0, r4.errors.count
  682. r.content = r3.content = "non-empty"
  683. assert t.valid?
  684. end
  685. def test_validates_associated_one
  686. Reply.validates_associated( :topic )
  687. Topic.validates_presence_of( :content )
  688. r = Reply.new("title" => "A reply", "content" => "with content!")
  689. r.topic = Topic.create("title" => "uhohuhoh")
  690. assert !r.valid?
  691. assert r.errors.on(:topic)
  692. r.topic.content = "non-empty"
  693. assert r.valid?
  694. end
  695. def test_validate_block
  696. Topic.validate { |topic| topic.errors.add("title", "will never be valid") }
  697. t = Topic.create("title" => "Title", "content" => "whatever")
  698. assert !t.valid?
  699. assert t.errors.on(:title)
  700. assert_equal "will never be valid", t.errors["title"]
  701. end
  702. def test_invalid_validator
  703. Topic.validate 3
  704. assert_raise(ActiveRecord::ActiveRecordError) { t = Topic.create }
  705. end
  706. def test_throw_away_typing
  707. d = Developer.new("name" => "David", "salary" => "100,000")
  708. assert !d.valid?
  709. assert_equal 100, d.salary
  710. assert_equal "100,000", d.salary_before_type_cast
  711. end
  712. def test_validates_acceptance_of_with_custom_error_using_quotes
  713. Developer.validates_acceptance_of :salary, :message=> "This string contains 'single' and \"double\" quotes"
  714. d = Developer.new
  715. d.salary = "0"
  716. assert !d.valid?
  717. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
  718. end
  719. def test_validates_confirmation_of_with_custom_error_using_quotes
  720. Developer.validates_confirmation_of :name, :message=> "confirm 'single' and \"double\" quotes"
  721. d = Developer.new
  722. d.name = "John"
  723. d.name_confirmation = "Johnny"
  724. assert !d.valid?
  725. assert_equal "confirm 'single' and \"double\" quotes", d.errors.on(:name)
  726. end
  727. def test_validates_format_of_with_custom_error_using_quotes
  728. Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
  729. d = Developer.new
  730. d.name = d.name_confirmation = "John 32"
  731. assert !d.valid?
  732. assert_equal "format 'single' and \"double\" quotes", d.errors.on(:name)
  733. end
  734. def test_validates_inclusion_of_with_custom_error_using_quotes
  735. Developer.validates_inclusion_of :salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes"
  736. d = Developer.new
  737. d.salary = "90,000"
  738. assert !d.valid?
  739. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
  740. end
  741. def test_validates_length_of_with_custom_too_long_using_quotes
  742. Developer.validates_length_of :name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes"
  743. d = Developer.new
  744. d.name = "Jeffrey"
  745. assert !d.valid?
  746. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
  747. end
  748. def test_validates_length_of_with_custom_too_short_using_quotes
  749. Developer.validates_length_of :name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes"
  750. d = Developer.new
  751. d.name = "Joe"
  752. assert !d.valid?
  753. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
  754. end
  755. def test_validates_length_of_with_custom_message_using_quotes
  756. Developer.validates_length_of :name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes"
  757. d = Developer.new
  758. d.name = "Joe"
  759. assert !d.valid?
  760. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
  761. end
  762. def test_validates_presence_of_with_custom_message_using_quotes
  763. Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
  764. d = Developer.new
  765. d.name = "Joe"
  766. assert !d.valid?
  767. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:non_existent)
  768. end
  769. def test_validates_uniqueness_of_with_custom_message_using_quotes
  770. Developer.validates_uniqueness_of :name, :message=> "This string contains 'single' and \"double\" quotes"
  771. d = Developer.new
  772. d.name = "David"
  773. assert !d.valid?
  774. assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
  775. end
  776. def test_validates_associated_with_custom_message_using_quotes
  777. Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
  778. Topic.validates_presence_of :content
  779. r = Reply.create("title" => "A reply", "content" => "with content!")
  780. r.topic = Topic.create("title" => "uhohuhoh")
  781. assert !r.valid?
  782. assert_equal "This string contains 'single' and \"double\" quotes", r.errors.on(:topic).last
  783. end
  784. def test_conditional_validation_using_method_true
  785. # When the method returns true
  786. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true )
  787. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  788. assert !t.valid?
  789. assert t.errors.on(:title)
  790. assert_equal "hoo 5", t.errors["title"]
  791. end
  792. def test_conditional_validation_using_method_false
  793. # When the method returns false
  794. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true_but_its_not )
  795. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  796. assert t.valid?
  797. assert !t.errors.on(:title)
  798. end
  799. def test_conditional_validation_using_string_true
  800. # When the evaluated string returns true
  801. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => "a = 1; a == 1" )
  802. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  803. assert !t.valid?
  804. assert t.errors.on(:title)
  805. assert_equal "hoo 5", t.errors["title"]
  806. end
  807. def test_conditional_validation_using_string_false
  808. # When the evaluated string returns false
  809. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => "false")
  810. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  811. assert t.valid?
  812. assert !t.errors.on(:title)
  813. end
  814. def test_conditional_validation_using_block_true
  815. # When the block returns true
  816. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d",
  817. :if => Proc.new { |r| r.content.size > 4 } )
  818. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  819. assert !t.valid?
  820. assert t.errors.on(:title)
  821. assert_equal "hoo 5", t.errors["title"]
  822. end
  823. def test_conditional_validation_using_block_false
  824. # When the block returns false
  825. Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d",
  826. :if => Proc.new { |r| r.title != "uhohuhoh"} )
  827. t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
  828. assert t.valid?
  829. assert !t.errors.on(:title)
  830. end
  831. def test_validates_associated_missing
  832. Reply.validates_presence_of(:topic)
  833. r = Reply.create("title" => "A reply", "content" => "with content!")
  834. assert !r.valid?
  835. assert r.errors.on(:topic)
  836. r.topic = Topic.find :first
  837. assert r.valid?
  838. end
  839. def test_errors_to_xml
  840. r = Reply.new :title => "Wrong Create"
  841. assert !r.valid?
  842. xml = r.errors.to_xml(:skip_instruct => true)
  843. assert_equal "<errors>", xml.first(8)
  844. assert xml.include?("<error>Title is Wrong Create</error>")
  845. assert xml.include?("<error>Content Empty</error>")
  846. end
  847. def test_validation_order
  848. Topic.validates_presence_of :title
  849. Topic.validates_length_of :title, :minimum => 2
  850. t = Topic.new("title" => "")
  851. assert !t.valid?
  852. assert_equal "can't be blank", t.errors.on("title").first
  853. end
  854. end
  855. class ValidatesNumericalityTest < Test::Unit::TestCase
  856. NIL = [nil]
  857. BLANK = ["", " ", " \t \r \n"]
  858. BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significent digits
  859. FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5)
  860. INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090)
  861. FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS
  862. INTEGERS = [0, 10, -10] + INTEGER_STRINGS
  863. BIGDECIMAL = BIGDECIMAL_STRINGS.collect! { |bd| BigDecimal.new(bd) }
  864. JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"]
  865. def setup
  866. Topic.write_inheritable_attribute(:validate, nil)
  867. Topic.write_inheritable_attribute(:validate_on_create, nil)
  868. Topic.write_inheritable_attribute(:validate_on_update, nil)
  869. end
  870. def test_default_validates_numericality_of
  871. Topic.validates_numericality_of :approved
  872. invalid!(NIL + BLANK + JUNK)
  873. valid!(FLOATS + INTEGERS + BIGDECIMAL)
  874. end
  875. def test_validates_numericality_of_with_nil_allowed
  876. Topic.validates_numericality_of :approved, :allow_nil => true
  877. invalid!(BLANK + JUNK)
  878. valid!(NIL + FLOATS + INTEGERS + BIGDECIMAL)
  879. end
  880. def test_validates_numericality_of_with_integer_only
  881. Topic.validates_numericality_of :approved, :only_integer => true
  882. invalid!(NIL + BLANK + JUNK + FLOATS + BIGDECIMAL)
  883. valid!(INTEGERS)
  884. end
  885. def test_validates_numericality_of_with_integer_only_and_nil_allowed
  886. Topic.validates_numericality_of :approved, :only_integer => true, :allow_nil => true
  887. invalid!(BLANK + JUNK + FLOATS + BIGDECIMAL)
  888. valid!(NIL + INTEGERS)
  889. end
  890. def test_validates_numericality_with_greater_than
  891. Topic.validates_numericality_of :approved, :greater_than => 10
  892. invalid!([-10, 10], 'must be greater than 10')
  893. valid!([11])
  894. end
  895. def test_validates_numericality_with_greater_than_or_equal
  896. Topic.validates_numericality_of :approved, :greater_than_or_equal_to => 10
  897. invalid!([-9, 9], 'must be greater than or equal to 10')
  898. valid!([10])
  899. end
  900. def test_validates_numericality_with_equal_to
  901. Topic.validates_numericality_of :approved, :equal_to => 10
  902. invalid!([-10, 11], 'must be equal to 10')
  903. valid!([10])
  904. end
  905. def test_validates_numericality_with_less_than
  906. Topic.validates_numericality_of :approved, :less_than => 10
  907. invalid!([10], 'must be less than 10')
  908. valid!([-9, 9])
  909. end
  910. def test_validates_numericality_with_less_than_or_equal_to
  911. Topic.validates_numericality_of :approved, :less_than_or_equal_to => 10
  912. invalid!([11], 'must be less than or equal to 10')
  913. valid!([-10, 10])
  914. end
  915. def test_validates_numericality_with_odd
  916. Topic.validates_numericality_of :approved, :odd => true
  917. invalid!([-2, 2], 'must be odd')
  918. valid!([-1, 1])
  919. end
  920. def test_validates_numericality_with_even
  921. Topic.validates_numericality_of :approved, :even => true
  922. invalid!([-1, 1], 'must be even')
  923. valid!([-2, 2])
  924. end
  925. def test_validates_numericality_with_greater_than_less_than_and_even
  926. Topic.validates_numericality_of :approved, :greater_than => 1, :less_than => 4, :even => true
  927. invalid!([1, 3, 4])
  928. valid!([2])
  929. end
  930. private
  931. def invalid!(values, error=nil)
  932. with_each_topic_approved_value(values) do |topic, value|
  933. assert !topic.valid?, "#{value.inspect} not rejected as a number"
  934. assert topic.errors.on(:approved)
  935. assert_equal error, topic.errors.on(:approved) if error
  936. end
  937. end
  938. def valid!(values)
  939. with_each_topic_approved_value(values) do |topic, value|
  940. assert topic.valid?, "#{value.inspect} not accepted as a number"
  941. end
  942. end
  943. def with_each_topic_approved_value(values)
  944. topic = Topic.new("title" => "numeric test", "content" => "whatever")
  945. values.each do |value|
  946. topic.approved = value
  947. yield topic, value
  948. end
  949. end
  950. end