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

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