length_validation_test.rb 12.8 KB
Newer Older
1 2 3 4
# encoding: utf-8
require 'cases/helper'

require 'models/topic'
5
require 'models/person'
6 7

class LengthValidationTest < ActiveModel::TestCase
8
  def teardown
9
    Topic.clear_validators!
10
  end
11 12

  def test_validates_length_of_with_allow_nil
13
    Topic.validates_length_of( :title, is: 5, allow_nil: true )
14

15 16 17 18
    assert Topic.new("title" => "ab").invalid?
    assert Topic.new("title" => "").invalid?
    assert Topic.new("title" => nil).valid?
    assert Topic.new("title" => "abcde").valid?
19 20 21
  end

  def test_validates_length_of_with_allow_blank
22
    Topic.validates_length_of( :title, is: 5, allow_blank: true )
23

24 25 26 27
    assert Topic.new("title" => "ab").invalid?
    assert Topic.new("title" => "").valid?
    assert Topic.new("title" => nil).valid?
    assert Topic.new("title" => "abcde").valid?
28 29 30
  end

  def test_validates_length_of_using_minimum
31
    Topic.validates_length_of :title, minimum: 5
32

33
    t = Topic.new("title" => "valid", "content" => "whatever")
34 35 36
    assert t.valid?

    t.title = "not"
37
    assert t.invalid?
38 39
    assert t.errors[:title].any?
    assert_equal ["is too short (minimum is 5 characters)"], t.errors[:title]
40 41

    t.title = ""
42
    assert t.invalid?
43 44
    assert t.errors[:title].any?
    assert_equal ["is too short (minimum is 5 characters)"], t.errors[:title]
45 46

    t.title = nil
47
    assert t.invalid?
48
    assert t.errors[:title].any?
49 50 51
    assert_equal ["is too short (minimum is 5 characters)"], t.errors["title"]
  end

52
  def test_validates_length_of_using_maximum_should_allow_nil
53
    Topic.validates_length_of :title, maximum: 10
54
    t = Topic.new
55 56 57
    assert t.valid?
  end

58
  def test_optionally_validates_length_of_using_minimum
59
    Topic.validates_length_of :title, minimum: 5, allow_nil: true
60

61
    t = Topic.new("title" => "valid", "content" => "whatever")
62 63 64 65 66 67 68
    assert t.valid?

    t.title = nil
    assert t.valid?
  end

  def test_validates_length_of_using_maximum
69
    Topic.validates_length_of :title, maximum: 5
70

71
    t = Topic.new("title" => "valid", "content" => "whatever")
72 73 74
    assert t.valid?

    t.title = "notvalid"
75
    assert t.invalid?
76 77
    assert t.errors[:title].any?
    assert_equal ["is too long (maximum is 5 characters)"], t.errors[:title]
78 79 80 81 82 83

    t.title = ""
    assert t.valid?
  end

  def test_optionally_validates_length_of_using_maximum
84
    Topic.validates_length_of :title, maximum: 5, allow_nil: true
85

86
    t = Topic.new("title" => "valid", "content" => "whatever")
87 88 89 90 91 92 93
    assert t.valid?

    t.title = nil
    assert t.valid?
  end

  def test_validates_length_of_using_within
94
    Topic.validates_length_of(:title, :content, within: 3..5)
95 96

    t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
97
    assert t.invalid?
98 99
    assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title]
    assert_equal ["is too long (maximum is 5 characters)"], t.errors[:content]
100 101 102

    t.title = nil
    t.content = nil
103
    assert t.invalid?
104 105
    assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title]
    assert_equal ["is too short (minimum is 3 characters)"], t.errors[:content]
106 107 108 109 110 111

    t.title = "abe"
    t.content  = "mad"
    assert t.valid?
  end

112
  def test_validates_length_of_using_within_with_exclusive_range
113
    Topic.validates_length_of(:title, within: 4...10)
114 115 116 117 118

    t = Topic.new("title" => "9 chars!!")
    assert t.valid?

    t.title = "Now I'm 10"
119
    assert t.invalid?
120 121 122 123 124 125
    assert_equal ["is too long (maximum is 9 characters)"], t.errors[:title]

    t.title = "Four"
    assert t.valid?
  end

126
  def test_optionally_validates_length_of_using_within
127
    Topic.validates_length_of :title, :content, within: 3..5, allow_nil: true
128

129
    t = Topic.new('title' => 'abc', 'content' => 'abcd')
130 131 132 133 134 135 136
    assert t.valid?

    t.title = nil
    assert t.valid?
  end

  def test_validates_length_of_using_is
137
    Topic.validates_length_of :title, is: 5
138

139
    t = Topic.new("title" => "valid", "content" => "whatever")
140 141 142
    assert t.valid?

    t.title = "notvalid"
143
    assert t.invalid?
144 145
    assert t.errors[:title].any?
    assert_equal ["is the wrong length (should be 5 characters)"], t.errors[:title]
146 147

    t.title = ""
148
    assert t.invalid?
149 150

    t.title = nil
151
    assert t.invalid?
152 153 154
  end

  def test_optionally_validates_length_of_using_is
155
    Topic.validates_length_of :title, is: 5, allow_nil: true
156

157
    t = Topic.new("title" => "valid", "content" => "whatever")
158 159 160 161 162 163 164 165 166 167 168
    assert t.valid?

    t.title = nil
    assert t.valid?
  end

  def test_validates_length_of_using_bignum
    bigmin = 2 ** 30
    bigmax = 2 ** 32
    bigrange = bigmin...bigmax
    assert_nothing_raised do
169 170 171 172 173
      Topic.validates_length_of :title, is: bigmin + 5
      Topic.validates_length_of :title, within: bigrange
      Topic.validates_length_of :title, in: bigrange
      Topic.validates_length_of :title, minimum: bigmin
      Topic.validates_length_of :title, maximum: bigmax
174 175 176 177
    end
  end

  def test_validates_length_of_nasty_params
178 179 180 181 182 183
    assert_raise(ArgumentError) { Topic.validates_length_of(:title, is: -6) }
    assert_raise(ArgumentError) { Topic.validates_length_of(:title, within: 6) }
    assert_raise(ArgumentError) { Topic.validates_length_of(:title, minimum: "a") }
    assert_raise(ArgumentError) { Topic.validates_length_of(:title, maximum: "a") }
    assert_raise(ArgumentError) { Topic.validates_length_of(:title, within: "a") }
    assert_raise(ArgumentError) { Topic.validates_length_of(:title, is: "a") }
184 185 186
  end

  def test_validates_length_of_custom_errors_for_minimum_with_message
187
    Topic.validates_length_of( :title, minimum: 5, message: "boo %{count}" )
188 189
    t = Topic.new("title" => "uhoh", "content" => "whatever")
    assert t.invalid?
190 191
    assert t.errors[:title].any?
    assert_equal ["boo 5"], t.errors[:title]
192 193 194
  end

  def test_validates_length_of_custom_errors_for_minimum_with_too_short
195
    Topic.validates_length_of( :title, minimum: 5, too_short: "hoo %{count}" )
196 197
    t = Topic.new("title" => "uhoh", "content" => "whatever")
    assert t.invalid?
198 199
    assert t.errors[:title].any?
    assert_equal ["hoo 5"], t.errors[:title]
200 201 202
  end

  def test_validates_length_of_custom_errors_for_maximum_with_message
203
    Topic.validates_length_of( :title, maximum: 5, message: "boo %{count}" )
204 205
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
    assert t.invalid?
206
    assert t.errors[:title].any?
207 208 209 210
    assert_equal ["boo 5"], t.errors[:title]
  end

  def test_validates_length_of_custom_errors_for_in
211
    Topic.validates_length_of(:title, in: 10..20, message: "hoo %{count}")
212 213
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
    assert t.invalid?
214 215 216
    assert t.errors[:title].any?
    assert_equal ["hoo 10"], t.errors["title"]

217 218
    t = Topic.new("title" => "uhohuhohuhohuhohuhohuhohuhohuhoh", "content" => "whatever")
    assert t.invalid?
219 220 221 222 223
    assert t.errors[:title].any?
    assert_equal ["hoo 20"], t.errors["title"]
  end

  def test_validates_length_of_custom_errors_for_maximum_with_too_long
224
    Topic.validates_length_of( :title, maximum: 5, too_long: "hoo %{count}" )
225 226
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
    assert t.invalid?
227 228 229 230
    assert t.errors[:title].any?
    assert_equal ["hoo 5"], t.errors["title"]
  end

231
  def test_validates_length_of_custom_errors_for_both_too_short_and_too_long
232
    Topic.validates_length_of :title, minimum: 3, maximum: 5, too_short: 'too short', too_long: 'too long'
233

234
    t = Topic.new(title: 'a')
235 236 237 238
    assert t.invalid?
    assert t.errors[:title].any?
    assert_equal ['too short'], t.errors['title']

239
    t = Topic.new(title: 'aaaaaa')
240 241 242 243 244
    assert t.invalid?
    assert t.errors[:title].any?
    assert_equal ['too long'], t.errors['title']
  end

245
  def test_validates_length_of_custom_errors_for_is_with_message
246
    Topic.validates_length_of( :title, is: 5, message: "boo %{count}" )
247 248
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
    assert t.invalid?
249 250 251 252 253
    assert t.errors[:title].any?
    assert_equal ["boo 5"], t.errors["title"]
  end

  def test_validates_length_of_custom_errors_for_is_with_wrong_length
254
    Topic.validates_length_of( :title, is: 5, wrong_length: "hoo %{count}" )
255 256
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
    assert t.invalid?
257 258 259 260 261
    assert t.errors[:title].any?
    assert_equal ["hoo 5"], t.errors["title"]
  end

  def test_validates_length_of_using_minimum_utf8
262
    Topic.validates_length_of :title, minimum: 5
263

J
José Valim 已提交
264 265
    t = Topic.new("title" => "一二三四五", "content" => "whatever")
    assert t.valid?
266

J
José Valim 已提交
267 268 269 270
    t.title = "一二三四"
    assert t.invalid?
    assert t.errors[:title].any?
    assert_equal ["is too short (minimum is 5 characters)"], t.errors["title"]
271 272 273
  end

  def test_validates_length_of_using_maximum_utf8
274
    Topic.validates_length_of :title, maximum: 5
275

J
José Valim 已提交
276 277
    t = Topic.new("title" => "一二三四五", "content" => "whatever")
    assert t.valid?
278

J
José Valim 已提交
279 280 281 282
    t.title = "一二34五六"
    assert t.invalid?
    assert t.errors[:title].any?
    assert_equal ["is too long (maximum is 5 characters)"], t.errors["title"]
283 284 285
  end

  def test_validates_length_of_using_within_utf8
286
    Topic.validates_length_of(:title, :content, within: 3..5)
J
José Valim 已提交
287 288 289 290 291 292 293 294

    t = Topic.new("title" => "一二", "content" => "12三四五六七")
    assert t.invalid?
    assert_equal ["is too short (minimum is 3 characters)"], t.errors[:title]
    assert_equal ["is too long (maximum is 5 characters)"], t.errors[:content]
    t.title = "一二三"
    t.content  = "12三"
    assert t.valid?
295 296 297
  end

  def test_optionally_validates_length_of_using_within_utf8
298
    Topic.validates_length_of :title, within: 3..5, allow_nil: true
299

300
    t = Topic.new(title: "一二三四五")
J
José Valim 已提交
301
    assert t.valid?, t.errors.inspect
302

303
    t = Topic.new(title: "一二三")
J
José Valim 已提交
304
    assert t.valid?, t.errors.inspect
305

J
José Valim 已提交
306 307
    t.title = nil
    assert t.valid?, t.errors.inspect
308 309 310
  end

  def test_validates_length_of_using_is_utf8
311
    Topic.validates_length_of :title, is: 5
312

J
José Valim 已提交
313 314
    t = Topic.new("title" => "一二345", "content" => "whatever")
    assert t.valid?
315

J
José Valim 已提交
316 317 318 319
    t.title = "一二345六"
    assert t.invalid?
    assert t.errors[:title].any?
    assert_equal ["is the wrong length (should be 5 characters)"], t.errors["title"]
320 321 322
  end

  def test_validates_length_of_with_block
323 324 325
    Topic.validates_length_of :content, minimum: 5, too_short: "Your essay must be at least %{count} words.",
                                        tokenizer: lambda {|str| str.scan(/\w+/) }
    t = Topic.new(content: "this content should be long enough")
326 327 328
    assert t.valid?

    t.content = "not long enough"
329
    assert t.invalid?
330 331 332
    assert t.errors[:content].any?
    assert_equal ["Your essay must be at least 5 words."], t.errors[:content]
  end
S
Santiago Pastorino 已提交
333

A
Andriy Tyurnikov 已提交
334
  def test_validates_length_of_for_fixnum
335
    Topic.validates_length_of(:approved, is: 4)
S
Santiago Pastorino 已提交
336

337
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever", approved: 1)
A
Andriy Tyurnikov 已提交
338 339
    assert t.invalid?
    assert t.errors[:approved].any?
S
Santiago Pastorino 已提交
340

341
    t = Topic.new("title" => "uhohuhoh", "content" => "whatever", approved: 1234)
A
Andriy Tyurnikov 已提交
342 343
    assert t.valid?
  end
344

345
  def test_validates_length_of_for_ruby_class
346
    Person.validates_length_of :karma, minimum: 5
347

348 349 350
    p = Person.new
    p.karma = "Pix"
    assert p.invalid?
351

352
    assert_equal ["is too short (minimum is 5 characters)"], p.errors[:karma]
353

354 355 356
    p.karma = "The Smiths"
    assert p.valid?
  ensure
357
    Person.clear_validators!
358
  end
N
Niels Ganser 已提交
359 360

  def test_validates_length_of_for_infinite_maxima
361
    Topic.validates_length_of(:title, within: 5..Float::INFINITY)
N
Niels Ganser 已提交
362 363 364 365 366 367 368 369

    t = Topic.new("title" => "1234")
    assert t.invalid?
    assert t.errors[:title].any?

    t.title = "12345"
    assert t.valid?

370
    Topic.validates_length_of(:author_name, maximum: Float::INFINITY)
N
Niels Ganser 已提交
371 372 373 374 375 376

    assert t.valid?

    t.author_name = "A very long author name that should still be valid." * 100
    assert t.valid?
  end
377 378

  def test_validates_length_of_using_maximum_should_not_allow_nil_when_nil_not_allowed
379
    Topic.validates_length_of :title, maximum: 10, allow_nil: false
380 381 382 383 384
    t = Topic.new
    assert t.invalid?
  end

  def test_validates_length_of_using_maximum_should_not_allow_nil_and_empty_string_when_blank_not_allowed
385
    Topic.validates_length_of :title, maximum: 10, allow_blank: false
386 387 388 389 390 391 392 393
    t = Topic.new
    assert t.invalid?

    t.title = ""
    assert t.invalid?
  end

  def test_validates_length_of_using_both_minimum_and_maximum_should_not_allow_nil
394
    Topic.validates_length_of :title, minimum: 5, maximum: 10
395 396 397 398 399
    t = Topic.new
    assert t.invalid?
  end

  def test_validates_length_of_using_minimum_0_should_not_allow_nil
400
    Topic.validates_length_of :title, minimum: 0
401 402 403 404 405 406 407 408
    t = Topic.new
    assert t.invalid?

    t.title = ""
    assert t.valid?
  end

  def test_validates_length_of_using_is_0_should_not_allow_nil
409
    Topic.validates_length_of :title, is: 0
410 411 412 413 414 415
    t = Topic.new
    assert t.invalid?

    t.title = ""
    assert t.valid?
  end
D
David 已提交
416 417

  def test_validates_with_diff_in_option
418 419
    Topic.validates_length_of(:title, is: 5)
    Topic.validates_length_of(:title, is: 5, if: Proc.new { false } )
D
David 已提交
420 421 422 423

    assert Topic.new("title" => "david").valid?
    assert Topic.new("title" => "david2").invalid?
  end
424
end