Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

test_alert.py 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. from unittest import mock
  2. from django.contrib.auth.models import AnonymousUser
  3. from django.core import mail
  4. from django.test import TestCase
  5. from django.urls import reverse
  6. from django_webtest import WebTest
  7. from oscar.apps.customer.forms import ProductAlertForm
  8. from oscar.apps.customer.models import ProductAlert
  9. from oscar.core.loading import get_class
  10. from oscar.test.factories import (
  11. ProductAlertFactory, UserFactory, create_product, create_stockrecord)
  12. CustomerDispatcher = get_class('customer.utils', 'CustomerDispatcher')
  13. AlertsDispatcher = get_class('customer.alerts.utils', 'AlertsDispatcher')
  14. class TestProductAlert(WebTest):
  15. def setUp(self):
  16. self.user = UserFactory()
  17. self.product = create_product(num_in_stock=0)
  18. def test_can_create_a_stock_alert(self):
  19. product_page = self.app.get(self.product.get_absolute_url(), user=self.user)
  20. form = product_page.forms['alert_form']
  21. form.submit()
  22. alerts = ProductAlert.objects.filter(user=self.user)
  23. assert len(alerts) == 1
  24. alert = alerts[0]
  25. assert ProductAlert.ACTIVE == alert.status
  26. assert alert.product == self.product
  27. def test_cannot_create_multiple_alerts_for_one_product(self):
  28. ProductAlertFactory(user=self.user, product=self.product,
  29. status=ProductAlert.ACTIVE)
  30. # Alert form should not allow creation of additional alerts.
  31. form = ProductAlertForm(user=self.user, product=self.product, data={})
  32. assert not form.is_valid()
  33. assert "You already have an active alert for this product" in form.errors['__all__'][0]
  34. class TestAUserWithAnActiveStockAlert(WebTest):
  35. def setUp(self):
  36. self.user = UserFactory()
  37. self.product = create_product()
  38. self.stockrecord = create_stockrecord(self.product, num_in_stock=0)
  39. product_page = self.app.get(self.product.get_absolute_url(),
  40. user=self.user)
  41. form = product_page.forms['alert_form']
  42. form.submit()
  43. def test_can_cancel_it(self):
  44. alerts = ProductAlert.objects.filter(user=self.user)
  45. assert len(alerts) == 1
  46. alert = alerts[0]
  47. assert not alert.is_cancelled
  48. self.app.get(
  49. reverse('customer:alerts-cancel-by-pk', kwargs={'pk': alert.pk}),
  50. user=self.user)
  51. alerts = ProductAlert.objects.filter(user=self.user)
  52. assert len(alerts) == 1
  53. alert = alerts[0]
  54. assert alert.is_cancelled
  55. def test_gets_notified_when_it_is_back_in_stock(self):
  56. self.stockrecord.num_in_stock = 10
  57. self.stockrecord.save()
  58. assert self.user.notifications.all().count() == 1
  59. def test_gets_emailed_when_it_is_back_in_stock(self):
  60. self.stockrecord.num_in_stock = 10
  61. self.stockrecord.save()
  62. assert len(mail.outbox) == 1
  63. def test_does_not_get_emailed_when_it_is_saved_but_still_zero_stock(self):
  64. self.stockrecord.num_in_stock = 0
  65. self.stockrecord.save()
  66. assert len(mail.outbox) == 0
  67. @mock.patch('oscar.apps.communication.utils.Dispatcher.notify_user')
  68. def test_site_notification_sent(self, mock_notify):
  69. self.stockrecord.num_in_stock = 10
  70. self.stockrecord.save()
  71. mock_notify.assert_called_once_with(
  72. self.user,
  73. '{} is back in stock'.format(self.product.title),
  74. body='<a href="{}">{}</a> is back in stock'.format(
  75. self.product.get_absolute_url(), self.product.title)
  76. )
  77. @mock.patch('oscar.apps.communication.utils.Dispatcher.notify_user')
  78. def test_product_title_truncated_in_alert_notification_subject(self, mock_notify):
  79. self.product.title = ('Aut nihil dignissimos perspiciatis. Beatae sed consequatur odit incidunt. '
  80. 'Quaerat labore perferendis quasi aut sunt maxime accusamus laborum. '
  81. 'Ut quam repudiandae occaecati eligendi. Nihil rem vel eos.')
  82. self.product.save()
  83. self.stockrecord.num_in_stock = 10
  84. self.stockrecord.save()
  85. mock_notify.assert_called_once_with(
  86. self.user,
  87. '{} is back in stock'.format(self.product.title[:200]),
  88. body='<a href="{}">{}</a> is back in stock'.format(
  89. self.product.get_absolute_url(), self.product.title)
  90. )
  91. class TestAnAnonymousUser(WebTest):
  92. def test_can_create_a_stock_alert(self):
  93. product = create_product(num_in_stock=0)
  94. product_page = self.app.get(product.get_absolute_url())
  95. form = product_page.forms['alert_form']
  96. form['email'] = 'john@smith.com'
  97. form.submit()
  98. alerts = ProductAlert.objects.filter(email='john@smith.com')
  99. assert len(alerts) == 1
  100. alert = alerts[0]
  101. assert ProductAlert.UNCONFIRMED == alert.status
  102. assert alert.product == product
  103. def test_can_cancel_unconfirmed_stock_alert(self):
  104. alert = ProductAlertFactory(
  105. user=None, email='john@smith.com', status=ProductAlert.UNCONFIRMED)
  106. self.app.get(
  107. reverse('customer:alerts-cancel-by-key', kwargs={'key': alert.key}))
  108. alert.refresh_from_db()
  109. assert alert.is_cancelled
  110. def test_cannot_create_multiple_alerts_for_one_product(self):
  111. product = create_product(num_in_stock=0)
  112. alert = ProductAlertFactory(user=None, product=product,
  113. email='john@smith.com')
  114. alert.status = ProductAlert.ACTIVE
  115. alert.save()
  116. # Alert form should not allow creation of additional alerts.
  117. form = ProductAlertForm(user=AnonymousUser(), product=product,
  118. data={'email': 'john@smith.com'})
  119. assert not form.is_valid()
  120. assert "There is already an active stock alert for john@smith.com" in form.errors['__all__'][0]
  121. def test_cannot_create_multiple_unconfirmed_alerts(self):
  122. # Create an unconfirmed alert
  123. ProductAlertFactory(
  124. user=None, email='john@smith.com', status=ProductAlert.UNCONFIRMED)
  125. # Alert form should not allow creation of additional alerts.
  126. form = ProductAlertForm(
  127. user=AnonymousUser(),
  128. product=create_product(num_in_stock=0),
  129. data={'email': 'john@smith.com'},
  130. )
  131. assert not form.is_valid()
  132. message = "john@smith.com has been sent a confirmation email for another product alert on this site."
  133. assert message in form.errors['__all__'][0]
  134. class TestHurryMode(TestCase):
  135. def setUp(self):
  136. self.user = UserFactory()
  137. self.product = create_product()
  138. self.dispatcher = AlertsDispatcher()
  139. def test_hurry_mode_not_set_when_stock_high(self):
  140. # One alert, 5 items in stock. No need to hurry.
  141. create_stockrecord(self.product, num_in_stock=5)
  142. ProductAlert.objects.create(user=self.user, product=self.product)
  143. self.dispatcher.send_product_alert_email_for_user(self.product)
  144. assert len(mail.outbox) == 1
  145. assert 'Beware that the amount of items in stock is limited' not in mail.outbox[0].body
  146. def test_hurry_mode_set_when_stock_low(self):
  147. # Two alerts, 1 item in stock. Hurry mode should be set.
  148. create_stockrecord(self.product, num_in_stock=1)
  149. ProductAlert.objects.create(user=self.user, product=self.product)
  150. ProductAlert.objects.create(user=UserFactory(), product=self.product)
  151. self.dispatcher.send_product_alert_email_for_user(self.product)
  152. assert len(mail.outbox) == 2
  153. assert 'Beware that the amount of items in stock is limited' in mail.outbox[0].body
  154. def test_hurry_mode_not_set_multiple_stockrecords(self):
  155. # Two stockrecords, 5 items in stock for one. No need to hurry.
  156. create_stockrecord(self.product, num_in_stock=1)
  157. create_stockrecord(self.product, num_in_stock=5)
  158. ProductAlert.objects.create(user=self.user, product=self.product)
  159. self.dispatcher.send_product_alert_email_for_user(self.product)
  160. assert 'Beware that the amount of items in stock is limited' not in mail.outbox[0].body
  161. def test_hurry_mode_set_multiple_stockrecords(self):
  162. # Two stockrecords, low stock on both. Hurry mode should be set.
  163. create_stockrecord(self.product, num_in_stock=1)
  164. create_stockrecord(self.product, num_in_stock=1)
  165. ProductAlert.objects.create(user=self.user, product=self.product)
  166. ProductAlert.objects.create(user=UserFactory(), product=self.product)
  167. self.dispatcher.send_product_alert_email_for_user(self.product)
  168. assert 'Beware that the amount of items in stock is limited' in mail.outbox[0].body
  169. class TestAlertMessageSending(TestCase):
  170. def setUp(self):
  171. self.user = UserFactory()
  172. self.product = create_product()
  173. create_stockrecord(self.product, num_in_stock=1)
  174. self.dispatcher = AlertsDispatcher()
  175. @mock.patch('oscar.apps.communication.utils.Dispatcher.dispatch_direct_messages')
  176. def test_alert_confirmation_uses_dispatcher(self, mock_dispatch):
  177. alert = ProductAlert.objects.create(
  178. email='test@example.com',
  179. key='dummykey',
  180. status=ProductAlert.UNCONFIRMED,
  181. product=self.product
  182. )
  183. AlertsDispatcher().send_product_alert_confirmation_email_for_user(alert)
  184. assert mock_dispatch.call_count == 1
  185. assert mock_dispatch.call_args[0][0] == 'test@example.com'
  186. @mock.patch('oscar.apps.communication.utils.Dispatcher.dispatch_user_messages')
  187. def test_alert_uses_dispatcher(self, mock_dispatch):
  188. ProductAlert.objects.create(user=self.user, product=self.product)
  189. self.dispatcher.send_product_alert_email_for_user(self.product)
  190. assert mock_dispatch.call_count == 1
  191. assert mock_dispatch.call_args[0][0] == self.user
  192. def test_alert_creates_email_obj(self):
  193. ProductAlert.objects.create(user=self.user, product=self.product)
  194. self.dispatcher.send_product_alert_email_for_user(self.product)
  195. assert self.user.emails.count() == 1