You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_widget.py 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import datetime
  2. from django import forms
  3. from django.test import TestCase
  4. from django.urls import reverse_lazy
  5. from oscar.apps.catalogue.models import Product
  6. from oscar.forms import widgets
  7. from oscar.test.factories import create_product
  8. class ImageInputTestCase(TestCase):
  9. def test_unbound_context(self):
  10. i = widgets.ImageInput()
  11. ctx = i.get_context("test_input", None, {"id": "test-image-id"})
  12. self.assertEqual(ctx["image_id"], "test-image-id-image")
  13. self.assertEqual(ctx["image_url"], "")
  14. self.assertEqual(
  15. ctx["widget"]["attrs"], {"accept": "image/*", "id": "test-image-id"}
  16. )
  17. def test_bound_context(self):
  18. i = widgets.ImageInput()
  19. ctx = i.get_context("test_input", "/dummy-image-value", {"id": "test-image-id"})
  20. self.assertEqual(ctx["image_url"], "/dummy-image-value")
  21. class TimePickerInputTestCase(TestCase):
  22. def test_div_attrs_context(self):
  23. i = widgets.TimePickerInput(format="%H:%M")
  24. ctx = i.get_context("test_input", None, {})
  25. self.assertEqual(
  26. ctx["div_attrs"],
  27. {
  28. "data-oscarWidget": "time",
  29. "data-timeFormat": "HH:mm",
  30. },
  31. )
  32. def test_icon_classes_context(self):
  33. i = widgets.TimePickerInput(format="%H:%M")
  34. ctx = i.get_context("test_input", None, {})
  35. self.assertEqual(ctx["icon_classes"], "far fa-clock")
  36. def test_input_format_unicode(self):
  37. # Check that the widget can handle unicode formats
  38. i = widgets.TimePickerInput(format="τ-%H:%M")
  39. time = datetime.time(10, 47)
  40. html = i.render("time", time)
  41. self.assertIn('value="τ-10:47"', html)
  42. class DatePickerInputTestCase(TestCase):
  43. def test_div_attrs_context(self):
  44. i = widgets.DatePickerInput(format="%d/%m/%Y")
  45. ctx = i.get_context("test_input", None, {})
  46. self.assertEqual(
  47. ctx["div_attrs"],
  48. {
  49. "data-oscarWidget": "date",
  50. "data-dateFormat": "DD/MM/YYYY",
  51. },
  52. )
  53. def test_icon_classes_context(self):
  54. i = widgets.DatePickerInput(format="%H:%M")
  55. ctx = i.get_context("test_input", None, {})
  56. self.assertEqual(ctx["icon_classes"], "far fa-calendar-alt")
  57. def test_datepickerinput_format_unicode(self):
  58. # Check that the widget can handle unicode formats
  59. i = widgets.DatePickerInput(format="δ-%d/%m/%Y")
  60. date = datetime.date(2017, 5, 1)
  61. html = i.render("date", date)
  62. self.assertIn('value="δ-01/05/2017"', html)
  63. class DateTimePickerInputTestCase(TestCase):
  64. def test_div_attrs_context(self):
  65. i = widgets.DateTimePickerInput(format="%d/%m/%Y %H:%M")
  66. ctx = i.get_context("test_input", None, {})
  67. self.assertEqual(
  68. ctx["div_attrs"],
  69. {
  70. "data-oscarWidget": "datetime",
  71. "data-datetimeFormat": "DD/MM/YYYY HH:mm",
  72. },
  73. )
  74. def test_icon_classes_context(self):
  75. i = widgets.DateTimePickerInput(format="%d/%m/%Y %H:%M")
  76. ctx = i.get_context("test_input", None, {})
  77. self.assertEqual(ctx["icon_classes"], "far fa-calendar-alt")
  78. def test_datetimepickerinput_format_unicode(self):
  79. # Check that the widget can handle unicode formats
  80. i = widgets.DateTimePickerInput(format="δ-%d/%m/%Y %H:%M")
  81. date = datetime.datetime(2017, 5, 1, 10, 57)
  82. html = i.render("datetime", date)
  83. self.assertIn('value="δ-01/05/2017 10:57"', html)
  84. class TestWidgetsDatetimeFormat(TestCase):
  85. def test_datetime_to_date_format_conversion(self):
  86. format_testcases = (
  87. ("%Y-%m-%d", "YYYY-MM-DD"),
  88. ("%Y-%m-%d %H:%M", "YYYY-MM-DD"),
  89. )
  90. for format_, expected in format_testcases:
  91. self.assertEqual(
  92. widgets.datetime_format_to_js_date_format(format_), expected
  93. )
  94. def test_datetime_to_time_format_conversion(self):
  95. format_testcases = (
  96. ("%Y-%m-%d %H:%M", "HH:mm"),
  97. ("%H:%M", "HH:mm"),
  98. )
  99. for format_, expected in format_testcases:
  100. self.assertEqual(
  101. widgets.datetime_format_to_js_time_format(format_), expected
  102. )
  103. class AdvancedSelectWidgetTestCase(TestCase):
  104. def test_widget_disabled_options(self):
  105. choices = (
  106. ("red", "Red"),
  107. ("blue", "Blue"),
  108. ("green", "Green"),
  109. )
  110. disabled_values = ("red", "green")
  111. i = widgets.AdvancedSelect(choices=choices, disabled_values=disabled_values)
  112. html = i.render("advselect", [])
  113. self.assertInHTML('<option value="blue">Blue</option>', html, count=1)
  114. self.assertInHTML('<option value="red" disabled>Red</option>', html, count=1)
  115. self.assertInHTML(
  116. '<option value="green" disabled>Green</option>', html, count=1
  117. )
  118. class RemoteSelectTestCase(TestCase):
  119. def setUp(self):
  120. self.url = reverse_lazy("dashboard:catalogue-product-lookup")
  121. def _get_form_field(self, **kwargs):
  122. return forms.ModelChoiceField(
  123. queryset=Product.objects.all(),
  124. widget=widgets.RemoteSelect(lookup_url=self.url),
  125. **kwargs
  126. )
  127. def _get_multiselect_form_field(self, **kwargs):
  128. return forms.ModelChoiceField(
  129. queryset=Product.objects.all(),
  130. widget=widgets.MultipleRemoteSelect(lookup_url=self.url),
  131. **kwargs
  132. )
  133. def test_remote_url_required(self):
  134. with self.assertRaises(ValueError):
  135. widgets.RemoteSelect()
  136. def test_select_widget_renders_only_selected_choices(self):
  137. create_product()
  138. p2 = create_product()
  139. field = self._get_form_field()
  140. form_choices = list(field.widget.options(name="name", value=[p2.pk]))
  141. # We should only have one choice, not two
  142. self.assertEqual(len(form_choices), 1)
  143. self.assertEqual(form_choices[0]["value"], p2.pk)
  144. def test_widget_attrs(self):
  145. field = self._get_form_field()
  146. attrs = field.widget.get_context(name="my_field", value=None, attrs={})[
  147. "widget"
  148. ]["attrs"]
  149. self.assertEqual(attrs["data-multiple"], "")
  150. self.assertEqual(attrs["data-required"], "required")
  151. self.assertEqual(attrs["data-ajax-url"], self.url)
  152. def test_not_required_widget_attrs(self):
  153. field = self._get_multiselect_form_field(required=False)
  154. attrs = field.widget.get_context(name="my_field", value=None, attrs={})[
  155. "widget"
  156. ]["attrs"]
  157. self.assertEqual(attrs["data-required"], "")
  158. def test_multiselect_widget_renders_only_selected_choices(self):
  159. create_product()
  160. p2 = create_product()
  161. p3 = create_product()
  162. field = self._get_multiselect_form_field()
  163. form_choices = list(field.widget.options(name="name", value=[p2.pk, p3.pk]))
  164. # We should only have two choices, not three
  165. self.assertEqual(len(form_choices), 2)
  166. def test_multiselect_widget_attrs(self):
  167. field = self._get_multiselect_form_field()
  168. attrs = field.widget.get_context(name="my_field", value=None, attrs={})[
  169. "widget"
  170. ]["attrs"]
  171. self.assertEqual(attrs["data-multiple"], "multiple")
  172. class NullBooleanSelectTestCase(TestCase):
  173. def test_unknown_choice_label(self):
  174. self.assertEqual(
  175. dict(widgets.NullBooleanSelect().choices)["unknown"], "---------"
  176. )