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.

checkout_tests.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. from decimal import Decimal as D
  2. import sys
  3. from django.core.urlresolvers import reverse
  4. from django.conf import settings
  5. from django.utils.importlib import import_module
  6. from oscar.test.helpers import create_product, create_voucher
  7. from oscar.test import ClientTestCase, patch_settings
  8. from oscar.apps.basket.models import Basket
  9. from oscar.apps.order.models import Order
  10. from oscar.apps.address.models import Country
  11. from oscar.apps.voucher.models import Voucher
  12. class CheckoutMixin(object):
  13. def add_product_to_basket(self):
  14. product = create_product(price=D('12.00'))
  15. self.client.post(reverse('basket:add'), {'product_id': product.id,
  16. 'quantity': 1})
  17. def add_voucher_to_basket(self, voucher=None):
  18. if voucher is None:
  19. voucher = create_voucher()
  20. self.client.post(reverse('basket:vouchers-add'),
  21. {'code': voucher.code})
  22. def complete_guest_email_form(self, email='test@example.com'):
  23. response = self.client.post(reverse('checkout:index'),
  24. {'username': email,
  25. 'options': 'new'})
  26. self.assertIsRedirect(response)
  27. def complete_shipping_address(self):
  28. Country.objects.get_or_create(
  29. iso_3166_1_a2='GB',
  30. is_shipping_country=True
  31. )
  32. response = self.client.post(reverse('checkout:shipping-address'),
  33. {'last_name': 'Doe',
  34. 'line1': '1 Egg Street',
  35. 'postcode': 'N1 9RT',
  36. 'country': 'GB',
  37. })
  38. self.assertRedirectUrlName(response, 'checkout:shipping-method')
  39. def complete_shipping_method(self):
  40. self.client.get(reverse('checkout:shipping-method'))
  41. def submit(self):
  42. return self.client.post(reverse('checkout:preview'), {'action': 'place_order'})
  43. class DisabledAnonymousCheckoutViewsTests(ClientTestCase):
  44. is_anonymous = True
  45. def test_index_does_require_login(self):
  46. url = reverse('checkout:index')
  47. response = self.client.get(url)
  48. self.assertIsRedirect(response)
  49. def test_user_address_views_require_a_login(self):
  50. urls = [reverse('checkout:user-address-create'),
  51. reverse('checkout:user-address-update', kwargs={'pk': 1}),
  52. reverse('checkout:user-address-delete', kwargs={'pk': 1}),]
  53. for url in urls:
  54. response = self.client.get(url)
  55. self.assertIsRedirect(response)
  56. def test_core_checkout_requires_login(self):
  57. urls = [reverse('checkout:shipping-address'),
  58. reverse('checkout:payment-method'),
  59. reverse('checkout:shipping-method'),
  60. reverse('checkout:payment-details')]
  61. for url in urls:
  62. response = self.client.get(url)
  63. self.assertIsRedirect(response)
  64. class EnabledAnonymousCheckoutViewsTests(ClientTestCase, CheckoutMixin):
  65. is_anonymous = True
  66. def reload_urlconf(self):
  67. if settings.ROOT_URLCONF in sys.modules:
  68. reload(sys.modules[settings.ROOT_URLCONF])
  69. return import_module(settings.ROOT_URLCONF)
  70. def add_product_to_basket(self):
  71. product = create_product(price=D('12.00'))
  72. self.client.post(reverse('basket:add'), {'product_id': product.id,
  73. 'quantity': 1})
  74. def test_shipping_address_does_require_session_email_address(self):
  75. with patch_settings(OSCAR_ALLOW_ANON_CHECKOUT=True):
  76. self.reload_urlconf()
  77. url = reverse('checkout:shipping-address')
  78. response = self.client.get(url)
  79. self.assertIsRedirect(response)
  80. def test_email_address_is_saved_with_order(self):
  81. with patch_settings(OSCAR_ALLOW_ANON_CHECKOUT=True):
  82. self.reload_urlconf()
  83. self.add_product_to_basket()
  84. self.complete_guest_email_form('barry@example.com')
  85. self.complete_shipping_address()
  86. self.complete_shipping_method()
  87. response = self.client.post(reverse('checkout:preview'), {'action': 'place_order'})
  88. response = self.client.get(reverse('checkout:thank-you'))
  89. order = response.context['order']
  90. self.assertEqual('barry@example.com', order.guest_email)
  91. class TestShippingAddressView(ClientTestCase, CheckoutMixin):
  92. fixtures = ['countries.json']
  93. def test_pages_returns_200(self):
  94. self.add_product_to_basket()
  95. response = self.client.get(reverse('checkout:shipping-address'))
  96. self.assertIsOk(response)
  97. def test_anon_checkout_disabled_by_default(self):
  98. self.assertFalse(settings.OSCAR_ALLOW_ANON_CHECKOUT)
  99. def test_create_shipping_address_adds_address_to_session(self):
  100. response = self.client.post(reverse('checkout:shipping-address'),
  101. {'last_name': 'Doe',
  102. 'line1': '1 Egg Street',
  103. 'postcode': 'N1 9RT',
  104. 'country': 'GB',
  105. })
  106. self.assertIsRedirect(response)
  107. session_address = self.client.session['checkout_data']['shipping']['new_address_fields']
  108. self.assertEqual('Doe', session_address['last_name'])
  109. self.assertEqual('1 Egg Street', session_address['line1'])
  110. self.assertEqual('N1 9RT', session_address['postcode'])
  111. def test_user_must_have_a_nonempty_basket(self):
  112. response = self.client.get(reverse('checkout:shipping-address'))
  113. self.assertRedirectUrlName(response, 'basket:summary')
  114. class TestShippingMethodView(ClientTestCase, CheckoutMixin):
  115. fixtures = ['countries.json']
  116. def test_shipping_method_view_redirects_if_no_shipping_address(self):
  117. self.add_product_to_basket()
  118. response = self.client.get(reverse('checkout:shipping-method'))
  119. self.assertIsRedirect(response)
  120. self.assertRedirectUrlName(response, 'checkout:shipping-address')
  121. def test_redirects_by_default(self):
  122. self.add_product_to_basket()
  123. self.complete_shipping_address()
  124. response = self.client.get(reverse('checkout:shipping-method'))
  125. self.assertRedirectUrlName(response, 'checkout:payment-method')
  126. def test_user_must_have_a_nonempty_basket(self):
  127. response = self.client.get(reverse('checkout:shipping-method'))
  128. self.assertRedirectUrlName(response, 'basket:summary')
  129. class TestPaymentMethodView(ClientTestCase, CheckoutMixin):
  130. def test_view_redirects_if_no_shipping_address(self):
  131. self.add_product_to_basket()
  132. response = self.client.get(reverse('checkout:payment-method'))
  133. self.assertIsRedirect(response)
  134. self.assertRedirectUrlName(response, 'checkout:shipping-address')
  135. def test_view_redirects_if_no_shipping_method(self):
  136. self.add_product_to_basket()
  137. self.complete_shipping_address()
  138. response = self.client.get(reverse('checkout:payment-method'))
  139. self.assertIsRedirect(response)
  140. self.assertRedirectUrlName(response, 'checkout:shipping-method')
  141. def test_user_must_have_a_nonempty_basket(self):
  142. response = self.client.get(reverse('checkout:payment-method'))
  143. self.assertRedirectUrlName(response, 'basket:summary')
  144. class TestPreviewView(ClientTestCase, CheckoutMixin):
  145. def test_user_must_have_a_nonempty_basket(self):
  146. response = self.client.get(reverse('checkout:preview'))
  147. self.assertRedirectUrlName(response, 'basket:summary')
  148. def test_view_redirects_if_no_shipping_address(self):
  149. self.add_product_to_basket()
  150. response = self.client.get(reverse('checkout:preview'))
  151. self.assertIsRedirect(response)
  152. self.assertRedirectUrlName(response, 'checkout:shipping-address')
  153. def test_view_redirects_if_no_shipping_method(self):
  154. self.add_product_to_basket()
  155. self.complete_shipping_address()
  156. response = self.client.get(reverse('checkout:preview'))
  157. self.assertIsRedirect(response)
  158. self.assertRedirectUrlName(response, 'checkout:shipping-method')
  159. def test_ok_response_if_previous_steps_complete(self):
  160. self.add_product_to_basket()
  161. self.complete_shipping_address()
  162. self.complete_shipping_method()
  163. response = self.client.get(reverse('checkout:preview'))
  164. self.assertIsOk(response)
  165. class TestPaymentDetailsView(ClientTestCase, CheckoutMixin):
  166. def test_user_must_have_a_nonempty_basket(self):
  167. response = self.client.get(reverse('checkout:payment-details'))
  168. self.assertRedirectUrlName(response, 'basket:summary')
  169. def test_view_redirects_if_no_shipping_address(self):
  170. self.add_product_to_basket()
  171. response = self.client.post(reverse('checkout:payment-details'))
  172. self.assertIsRedirect(response)
  173. self.assertRedirectUrlName(response, 'checkout:shipping-address')
  174. def test_view_redirects_if_no_shipping_method(self):
  175. self.add_product_to_basket()
  176. self.complete_shipping_address()
  177. response = self.client.post(reverse('checkout:payment-details'))
  178. self.assertIsRedirect(response)
  179. self.assertRedirectUrlName(response, 'checkout:shipping-method')
  180. def test_placing_order_with_empty_basket_redirects(self):
  181. response = self.client.post(reverse('checkout:preview'), {'action': 'place_order'})
  182. self.assertIsRedirect(response)
  183. self.assertRedirectUrlName(response, 'basket:summary')
  184. class TestOrderPlacement(ClientTestCase, CheckoutMixin):
  185. def setUp(self):
  186. Order.objects.all().delete()
  187. super(TestOrderPlacement, self).setUp()
  188. self.basket = Basket.objects.create(owner=self.user)
  189. self.basket.add_product(create_product(price=D('12.00')))
  190. self.complete_shipping_address()
  191. self.complete_shipping_method()
  192. self.response = self.client.post(reverse('checkout:preview'), {'action': 'place_order'})
  193. def test_placing_order_with_nonempty_basket_redirects(self):
  194. self.assertIsRedirect(self.response)
  195. self.assertRedirectUrlName(self.response, 'checkout:thank-you')
  196. def test_order_is_created(self):
  197. self.assertIsRedirect(self.response)
  198. orders = Order.objects.all()
  199. self.assertEqual(1, len(orders))
  200. class TestPlacingOrderUsingAVoucher(ClientTestCase, CheckoutMixin):
  201. def setUp(self):
  202. self.login()
  203. self.add_product_to_basket()
  204. voucher = create_voucher()
  205. self.add_voucher_to_basket(voucher)
  206. self.complete_shipping_address()
  207. self.complete_shipping_method()
  208. self.response = self.submit()
  209. # Reload voucher
  210. self.voucher = Voucher.objects.get(id=voucher.id)
  211. def test_is_successful(self):
  212. self.assertRedirectUrlName(self.response, 'checkout:thank-you')
  213. def test_records_use(self):
  214. self.assertEquals(1, self.voucher.num_orders)
  215. def test_records_discount(self):
  216. self.assertEquals(1, self.voucher.num_orders)