test_urlfield.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. from django.forms import URLField, ValidationError
  2. from django.test import SimpleTestCase
  3. from . import FormFieldAssertionsMixin
  4. class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
  5. def test_urlfield_1(self):
  6. f = URLField()
  7. self.assertWidgetRendersTo(f, '<input type="url" name="f" id="id_f" required>')
  8. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  9. f.clean('')
  10. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  11. f.clean(None)
  12. self.assertEqual('http://localhost', f.clean('http://localhost'))
  13. self.assertEqual('http://example.com', f.clean('http://example.com'))
  14. self.assertEqual('http://example.com.', f.clean('http://example.com.'))
  15. self.assertEqual('http://www.example.com', f.clean('http://www.example.com'))
  16. self.assertEqual('http://www.example.com:8000/test', f.clean('http://www.example.com:8000/test'))
  17. self.assertEqual('http://valid-with-hyphens.com', f.clean('valid-with-hyphens.com'))
  18. self.assertEqual('http://subdomain.domain.com', f.clean('subdomain.domain.com'))
  19. self.assertEqual('http://200.8.9.10', f.clean('http://200.8.9.10'))
  20. self.assertEqual('http://200.8.9.10:8000/test', f.clean('http://200.8.9.10:8000/test'))
  21. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  22. f.clean('foo')
  23. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  24. f.clean('http://')
  25. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  26. f.clean('http://example')
  27. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  28. f.clean('http://example.')
  29. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  30. f.clean('com.')
  31. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  32. f.clean('.')
  33. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  34. f.clean('http://.com')
  35. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  36. f.clean('http://invalid-.com')
  37. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  38. f.clean('http://-invalid.com')
  39. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  40. f.clean('http://inv-.alid-.com')
  41. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  42. f.clean('http://inv-.-alid.com')
  43. self.assertEqual('http://valid-----hyphens.com', f.clean('http://valid-----hyphens.com'))
  44. self.assertEqual(
  45. 'http://some.idn.xyz\xe4\xf6\xfc\xdfabc.domain.com:123/blah',
  46. f.clean('http://some.idn.xyzäöüßabc.domain.com:123/blah')
  47. )
  48. self.assertEqual(
  49. 'http://www.example.com/s/http://code.djangoproject.com/ticket/13804',
  50. f.clean('www.example.com/s/http://code.djangoproject.com/ticket/13804')
  51. )
  52. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  53. f.clean('[a')
  54. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  55. f.clean('http://[a')
  56. def test_url_regex_ticket11198(self):
  57. f = URLField()
  58. # hangs "forever" if catastrophic backtracking in ticket:#11198 not fixed
  59. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  60. f.clean('http://%s' % ("X" * 200,))
  61. # a second test, to make sure the problem is really addressed, even on
  62. # domains that don't fail the domain label length check in the regex
  63. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  64. f.clean('http://%s' % ("X" * 60,))
  65. def test_urlfield_2(self):
  66. f = URLField(required=False)
  67. self.assertEqual('', f.clean(''))
  68. self.assertEqual('', f.clean(None))
  69. self.assertEqual('http://example.com', f.clean('http://example.com'))
  70. self.assertEqual('http://www.example.com', f.clean('http://www.example.com'))
  71. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  72. f.clean('foo')
  73. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  74. f.clean('http://')
  75. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  76. f.clean('http://example')
  77. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  78. f.clean('http://example.')
  79. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  80. f.clean('http://.com')
  81. def test_urlfield_5(self):
  82. f = URLField(min_length=15, max_length=20)
  83. self.assertWidgetRendersTo(f, '<input id="id_f" type="url" name="f" maxlength="20" minlength="15" required>')
  84. with self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 15 characters (it has 12).'"):
  85. f.clean('http://f.com')
  86. self.assertEqual('http://example.com', f.clean('http://example.com'))
  87. with self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 37).'"):
  88. f.clean('http://abcdefghijklmnopqrstuvwxyz.com')
  89. def test_urlfield_6(self):
  90. f = URLField(required=False)
  91. self.assertEqual('http://example.com', f.clean('example.com'))
  92. self.assertEqual('', f.clean(''))
  93. self.assertEqual('https://example.com', f.clean('https://example.com'))
  94. def test_urlfield_7(self):
  95. f = URLField()
  96. self.assertEqual('http://example.com', f.clean('http://example.com'))
  97. self.assertEqual('http://example.com/test', f.clean('http://example.com/test'))
  98. self.assertEqual(
  99. 'http://example.com?some_param=some_value',
  100. f.clean('http://example.com?some_param=some_value')
  101. )
  102. def test_urlfield_9(self):
  103. f = URLField()
  104. urls = (
  105. 'http://עברית.idn.icann.org/',
  106. 'http://sãopaulo.com/',
  107. 'http://sãopaulo.com.br/',
  108. 'http://пример.испытание/',
  109. 'http://مثال.إختبار/',
  110. 'http://例子.测试/',
  111. 'http://例子.測試/',
  112. 'http://उदाहरण.परीक्षा/',
  113. 'http://例え.テスト/',
  114. 'http://مثال.آزمایشی/',
  115. 'http://실례.테스트/',
  116. 'http://العربية.idn.icann.org/',
  117. )
  118. for url in urls:
  119. with self.subTest(url=url):
  120. # Valid IDN
  121. self.assertEqual(url, f.clean(url))
  122. def test_urlfield_10(self):
  123. """URLField correctly validates IPv6 (#18779)."""
  124. f = URLField()
  125. urls = (
  126. 'http://[12:34::3a53]/',
  127. 'http://[a34:9238::]:8080/',
  128. )
  129. for url in urls:
  130. with self.subTest(url=url):
  131. self.assertEqual(url, f.clean(url))
  132. def test_urlfield_not_string(self):
  133. f = URLField(required=False)
  134. with self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'"):
  135. f.clean(23)
  136. def test_urlfield_normalization(self):
  137. f = URLField()
  138. self.assertEqual(f.clean('http://example.com/ '), 'http://example.com/')
  139. def test_urlfield_strip_on_none_value(self):
  140. f = URLField(required=False, empty_value=None)
  141. self.assertIsNone(f.clean(None))
  142. def test_urlfield_unable_to_set_strip_kwarg(self):
  143. msg = "__init__() got multiple values for keyword argument 'strip'"
  144. with self.assertRaisesMessage(TypeError, msg):
  145. URLField(strip=False)