test_urlfield.py 7.7 KB

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