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 12KB

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