test_integerfield.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. from django.core.exceptions import ValidationError
  2. from django.forms import IntegerField, Textarea
  3. from django.test import SimpleTestCase
  4. from . import FormFieldAssertionsMixin
  5. class IntegerFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
  6. def test_integerfield_1(self):
  7. f = IntegerField()
  8. self.assertWidgetRendersTo(
  9. f, '<input type="number" name="f" id="id_f" required>'
  10. )
  11. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  12. f.clean("")
  13. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  14. f.clean(None)
  15. self.assertEqual(1, f.clean("1"))
  16. self.assertIsInstance(f.clean("1"), int)
  17. self.assertEqual(23, f.clean("23"))
  18. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  19. f.clean("a")
  20. self.assertEqual(42, f.clean(42))
  21. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  22. f.clean(3.14)
  23. self.assertEqual(1, f.clean("1 "))
  24. self.assertEqual(1, f.clean(" 1"))
  25. self.assertEqual(1, f.clean(" 1 "))
  26. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  27. f.clean("1a")
  28. self.assertIsNone(f.max_value)
  29. self.assertIsNone(f.min_value)
  30. def test_integerfield_2(self):
  31. f = IntegerField(required=False)
  32. self.assertIsNone(f.clean(""))
  33. self.assertEqual("None", repr(f.clean("")))
  34. self.assertIsNone(f.clean(None))
  35. self.assertEqual("None", repr(f.clean(None)))
  36. self.assertEqual(1, f.clean("1"))
  37. self.assertIsInstance(f.clean("1"), int)
  38. self.assertEqual(23, f.clean("23"))
  39. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  40. f.clean("a")
  41. self.assertEqual(1, f.clean("1 "))
  42. self.assertEqual(1, f.clean(" 1"))
  43. self.assertEqual(1, f.clean(" 1 "))
  44. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  45. f.clean("1a")
  46. self.assertIsNone(f.max_value)
  47. self.assertIsNone(f.min_value)
  48. def test_integerfield_3(self):
  49. f = IntegerField(max_value=10)
  50. self.assertWidgetRendersTo(
  51. f, '<input max="10" type="number" name="f" id="id_f" required>'
  52. )
  53. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  54. f.clean(None)
  55. self.assertEqual(1, f.clean(1))
  56. self.assertEqual(10, f.clean(10))
  57. with self.assertRaisesMessage(
  58. ValidationError, "'Ensure this value is less than or equal to 10.'"
  59. ):
  60. f.clean(11)
  61. self.assertEqual(10, f.clean("10"))
  62. with self.assertRaisesMessage(
  63. ValidationError, "'Ensure this value is less than or equal to 10.'"
  64. ):
  65. f.clean("11")
  66. self.assertEqual(f.max_value, 10)
  67. self.assertIsNone(f.min_value)
  68. def test_integerfield_4(self):
  69. f = IntegerField(min_value=10)
  70. self.assertWidgetRendersTo(
  71. f, '<input id="id_f" type="number" name="f" min="10" required>'
  72. )
  73. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  74. f.clean(None)
  75. with self.assertRaisesMessage(
  76. ValidationError, "'Ensure this value is greater than or equal to 10.'"
  77. ):
  78. f.clean(1)
  79. self.assertEqual(10, f.clean(10))
  80. self.assertEqual(11, f.clean(11))
  81. self.assertEqual(10, f.clean("10"))
  82. self.assertEqual(11, f.clean("11"))
  83. self.assertIsNone(f.max_value)
  84. self.assertEqual(f.min_value, 10)
  85. def test_integerfield_5(self):
  86. f = IntegerField(min_value=10, max_value=20)
  87. self.assertWidgetRendersTo(
  88. f, '<input id="id_f" max="20" type="number" name="f" min="10" required>'
  89. )
  90. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  91. f.clean(None)
  92. with self.assertRaisesMessage(
  93. ValidationError, "'Ensure this value is greater than or equal to 10.'"
  94. ):
  95. f.clean(1)
  96. self.assertEqual(10, f.clean(10))
  97. self.assertEqual(11, f.clean(11))
  98. self.assertEqual(10, f.clean("10"))
  99. self.assertEqual(11, f.clean("11"))
  100. self.assertEqual(20, f.clean(20))
  101. with self.assertRaisesMessage(
  102. ValidationError, "'Ensure this value is less than or equal to 20.'"
  103. ):
  104. f.clean(21)
  105. self.assertEqual(f.max_value, 20)
  106. self.assertEqual(f.min_value, 10)
  107. def test_integerfield_6(self):
  108. f = IntegerField(step_size=3)
  109. self.assertWidgetRendersTo(
  110. f,
  111. '<input name="f" step="3" type="number" id="id_f" required>',
  112. )
  113. with self.assertRaisesMessage(
  114. ValidationError, "'Ensure this value is a multiple of step size 3.'"
  115. ):
  116. f.clean("10")
  117. self.assertEqual(12, f.clean(12))
  118. self.assertEqual(12, f.clean("12"))
  119. self.assertEqual(f.step_size, 3)
  120. def test_integerfield_step_size_min_value(self):
  121. f = IntegerField(step_size=3, min_value=-1)
  122. self.assertWidgetRendersTo(
  123. f,
  124. '<input name="f" min="-1" step="3" type="number" id="id_f" required>',
  125. )
  126. msg = (
  127. "Ensure this value is a multiple of step size 3, starting from -1, e.g. "
  128. "-1, 2, 5, and so on."
  129. )
  130. with self.assertRaisesMessage(ValidationError, msg):
  131. f.clean("9")
  132. self.assertEqual(f.clean("2"), 2)
  133. self.assertEqual(f.clean("-1"), -1)
  134. self.assertEqual(f.step_size, 3)
  135. def test_integerfield_localized(self):
  136. """
  137. A localized IntegerField's widget renders to a text input without any
  138. number input specific attributes.
  139. """
  140. f1 = IntegerField(localize=True)
  141. self.assertWidgetRendersTo(
  142. f1, '<input id="id_f" name="f" type="text" required>'
  143. )
  144. def test_integerfield_float(self):
  145. f = IntegerField()
  146. self.assertEqual(1, f.clean(1.0))
  147. self.assertEqual(1, f.clean("1.0"))
  148. self.assertEqual(1, f.clean(" 1.0 "))
  149. self.assertEqual(1, f.clean("1."))
  150. self.assertEqual(1, f.clean(" 1. "))
  151. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  152. f.clean("1.5")
  153. with self.assertRaisesMessage(ValidationError, "'Enter a whole number.'"):
  154. f.clean("…")
  155. def test_integerfield_big_num(self):
  156. f = IntegerField()
  157. self.assertEqual(9223372036854775808, f.clean(9223372036854775808))
  158. self.assertEqual(9223372036854775808, f.clean("9223372036854775808"))
  159. self.assertEqual(9223372036854775808, f.clean("9223372036854775808.0"))
  160. def test_integerfield_unicode_number(self):
  161. f = IntegerField()
  162. self.assertEqual(50, f.clean("50"))
  163. def test_integerfield_subclass(self):
  164. """
  165. Class-defined widget is not overwritten by __init__() (#22245).
  166. """
  167. class MyIntegerField(IntegerField):
  168. widget = Textarea
  169. f = MyIntegerField()
  170. self.assertEqual(f.widget.__class__, Textarea)
  171. f = MyIntegerField(localize=True)
  172. self.assertEqual(f.widget.__class__, Textarea)