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

test_alert.py 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import mock
  2. import os
  3. import warnings
  4. from django_webtest import WebTest
  5. from django.core.urlresolvers import reverse
  6. from django.core import mail
  7. from django.test import TestCase
  8. from oscar.utils.deprecation import RemovedInOscar20Warning
  9. from oscar.apps.customer.alerts.utils import (send_alert_confirmation,
  10. send_product_alerts)
  11. from oscar.apps.customer.models import ProductAlert
  12. from oscar.test.factories import create_product, create_stockrecord
  13. from oscar.test.factories import UserFactory
  14. class TestAUser(WebTest):
  15. def test_can_create_a_stock_alert(self):
  16. user = UserFactory()
  17. product = create_product(num_in_stock=0)
  18. product_page = self.app.get(product.get_absolute_url(), user=user)
  19. form = product_page.forms['alert_form']
  20. form.submit()
  21. alerts = ProductAlert.objects.filter(user=user)
  22. self.assertEqual(1, len(alerts))
  23. alert = alerts[0]
  24. self.assertEqual(ProductAlert.ACTIVE, alert.status)
  25. self.assertEqual(alert.product, product)
  26. class TestAUserWithAnActiveStockAlert(WebTest):
  27. def setUp(self):
  28. self.user = UserFactory()
  29. self.product = create_product()
  30. self.stockrecord = create_stockrecord(self.product, num_in_stock=0)
  31. product_page = self.app.get(self.product.get_absolute_url(),
  32. user=self.user)
  33. form = product_page.forms['alert_form']
  34. form.submit()
  35. def test_can_cancel_it(self):
  36. alerts = ProductAlert.objects.filter(user=self.user)
  37. self.assertEqual(1, len(alerts))
  38. alert = alerts[0]
  39. self.assertFalse(alert.is_cancelled)
  40. self.app.get(
  41. reverse('customer:alerts-cancel-by-pk', kwargs={'pk': alert.pk}),
  42. user=self.user)
  43. alerts = ProductAlert.objects.filter(user=self.user)
  44. self.assertEqual(1, len(alerts))
  45. alert = alerts[0]
  46. self.assertTrue(alert.is_cancelled)
  47. def test_gets_notified_when_it_is_back_in_stock(self):
  48. self.stockrecord.num_in_stock = 10
  49. self.stockrecord.save()
  50. self.assertEqual(1, self.user.notifications.all().count())
  51. def test_gets_emailed_when_it_is_back_in_stock(self):
  52. self.stockrecord.num_in_stock = 10
  53. self.stockrecord.save()
  54. self.assertEqual(1, len(mail.outbox))
  55. def test_does_not_get_emailed_when_it_is_saved_but_still_zero_stock(self):
  56. self.stockrecord.num_in_stock = 0
  57. self.stockrecord.save()
  58. self.assertEqual(0, len(mail.outbox))
  59. class TestAnAnonymousUser(WebTest):
  60. def test_can_create_a_stock_alert(self):
  61. product = create_product(num_in_stock=0)
  62. product_page = self.app.get(product.get_absolute_url())
  63. form = product_page.forms['alert_form']
  64. form['email'] = 'john@smith.com'
  65. form.submit()
  66. alerts = ProductAlert.objects.filter(email='john@smith.com')
  67. self.assertEqual(1, len(alerts))
  68. alert = alerts[0]
  69. self.assertEqual(ProductAlert.UNCONFIRMED, alert.status)
  70. self.assertEqual(alert.product, product)
  71. class TestHurryMode(TestCase):
  72. def setUp(self):
  73. self.user = UserFactory()
  74. self.product = create_product()
  75. def test_hurry_mode_not_set_when_stock_high(self):
  76. # One alert, 5 items in stock. No need to hurry.
  77. create_stockrecord(self.product, num_in_stock=5)
  78. ProductAlert.objects.create(user=self.user, product=self.product)
  79. send_product_alerts(self.product)
  80. self.assertEqual(1, len(mail.outbox))
  81. self.assertNotIn('Beware that the amount of items in stock is limited',
  82. mail.outbox[0].body)
  83. def test_hurry_mode_set_when_stock_low(self):
  84. # Two alerts, 1 item in stock. Hurry mode should be set.
  85. create_stockrecord(self.product, num_in_stock=1)
  86. ProductAlert.objects.create(user=self.user, product=self.product)
  87. ProductAlert.objects.create(user=UserFactory(), product=self.product)
  88. send_product_alerts(self.product)
  89. self.assertEqual(2, len(mail.outbox))
  90. self.assertIn('Beware that the amount of items in stock is limited',
  91. mail.outbox[0].body)
  92. def test_hurry_mode_not_set_multiple_stockrecords(self):
  93. # Two stockrecords, 5 items in stock for one. No need to hurry.
  94. create_stockrecord(self.product, num_in_stock=1)
  95. create_stockrecord(self.product, num_in_stock=5)
  96. ProductAlert.objects.create(user=self.user, product=self.product)
  97. send_product_alerts(self.product)
  98. self.assertNotIn('Beware that the amount of items in stock is limited',
  99. mail.outbox[0].body)
  100. def test_hurry_mode_set_multiple_stockrecords(self):
  101. # Two stockrecords, low stock on both. Hurry mode should be set.
  102. create_stockrecord(self.product, num_in_stock=1)
  103. create_stockrecord(self.product, num_in_stock=1)
  104. ProductAlert.objects.create(user=self.user, product=self.product)
  105. ProductAlert.objects.create(user=UserFactory(), product=self.product)
  106. send_product_alerts(self.product)
  107. self.assertIn('Beware that the amount of items in stock is limited',
  108. mail.outbox[0].body)
  109. class TestAlertMessageSending(TestCase):
  110. def setUp(self):
  111. self.user = UserFactory()
  112. self.product = create_product()
  113. create_stockrecord(self.product, num_in_stock=1)
  114. @mock.patch('oscar.apps.customer.utils.Dispatcher.dispatch_direct_messages')
  115. def test_alert_confirmation_uses_dispatcher(self, mock_dispatch):
  116. alert = ProductAlert.objects.create(
  117. email='test@example.com',
  118. key='dummykey',
  119. status=ProductAlert.UNCONFIRMED,
  120. product=self.product
  121. )
  122. send_alert_confirmation(alert)
  123. self.assertEqual(mock_dispatch.call_count, 1)
  124. self.assertEqual(mock_dispatch.call_args[0][0], 'test@example.com')
  125. @mock.patch('oscar.apps.customer.utils.Dispatcher.dispatch_user_messages')
  126. def test_alert_uses_dispatcher(self, mock_dispatch):
  127. ProductAlert.objects.create(user=self.user, product=self.product)
  128. send_product_alerts(self.product)
  129. self.assertEqual(mock_dispatch.call_count, 1)
  130. self.assertEqual(mock_dispatch.call_args[0][0], self.user)
  131. def test_alert_creates_email_obj(self):
  132. ProductAlert.objects.create(user=self.user, product=self.product)
  133. send_product_alerts(self.product)
  134. self.assertEqual(self.user.emails.count(), 1)
  135. @staticmethod
  136. def _load_deprecated_template(path):
  137. from django.template.loader import select_template
  138. # Replace the old template paths with new ones, thereby mocking
  139. # the presence of the deprecated templates.
  140. if path.startswith('customer/alerts/emails/'):
  141. old_path = path.replace('customer/alerts/emails/', '')
  142. path_map = {
  143. 'confirmation_body.txt': 'confirmation_body.txt',
  144. 'confirmation_subject.txt': 'confirmation_subject.txt',
  145. 'alert_body.txt': 'body.txt',
  146. 'alert_subject.txt': 'subject.txt',
  147. }
  148. new_path = 'customer/emails/commtype_product_alert_{}'.format(
  149. path_map[old_path]
  150. )
  151. # We use 'select_template' because 'load_template' is mocked...
  152. return select_template([new_path])
  153. return select_template([path])
  154. @mock.patch('oscar.apps.customer.alerts.utils.loader.get_template')
  155. def test_deprecated_notification_templates_work(self, mock_loader):
  156. """
  157. This test can be removed when support for the deprecated templates is
  158. dropped.
  159. """
  160. mock_loader.side_effect = self._load_deprecated_template
  161. with warnings.catch_warnings(record=True) as warning_list:
  162. warnings.simplefilter("always")
  163. alert = ProductAlert.objects.create(
  164. email='test@example.com',
  165. key='dummykey',
  166. status=ProductAlert.UNCONFIRMED,
  167. product=self.product
  168. )
  169. send_alert_confirmation(alert)
  170. # Check that warnings were raised
  171. self.assertTrue(any(item.category == RemovedInOscar20Warning
  172. for item in warning_list))
  173. # Check that alerts were still sent
  174. self.assertEqual(len(mail.outbox), 1)
  175. @mock.patch('oscar.apps.customer.alerts.utils.loader.get_template')
  176. def test_deprecated_alert_templates_work(self, mock_loader):
  177. """
  178. This test can be removed when support for the deprecated templates is
  179. dropped.
  180. """
  181. mock_loader.side_effect = self._load_deprecated_template
  182. with warnings.catch_warnings(record=True) as warning_list:
  183. warnings.simplefilter("always")
  184. ProductAlert.objects.create(user=self.user, product=self.product)
  185. send_product_alerts(self.product)
  186. # Check that warnings were raised
  187. self.assertTrue(any(item.category == RemovedInOscar20Warning
  188. for item in warning_list))
  189. # Check that alerts were still sent
  190. self.assertEqual(len(mail.outbox), 1)