def test_request_password_change(self): # Create and activate an account self.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) self.assertEqual(len(mail.outbox), 1) user = User.objects.get(username=self.USERNAME) activation_key = self.get_activation_key(user) activate_account(activation_key) request = RequestFactory().post('/password') request.user = Mock() request.site = SiteFactory() with patch('crum.get_current_request', return_value=request): # Request a password change request_password_change(self.EMAIL, self.IS_SECURE) # Verify that a new email message has been sent self.assertEqual(len(mail.outbox), 2) # Verify that the body of the message contains something that looks # like an activation link email_body = mail.outbox[0].body result = re.search(r'(?P<url>https?://[^\s]+)', email_body) self.assertIsNot(result, None)
def test_decline(self): """ Verify the view reports an error if the transaction is only authorized pending review. """ basket = self._create_valid_basket() data = self._generate_data(basket.id) order_number = OrderNumberGenerator().order_number_from_basket_id( self.site.siteconfiguration.partner, basket.id, ) # This response has been pruned to only the needed data. self._prep_request_success( """{"links":{"_self":{"href":"/pts/v2/payments/6021683934456376603262","method":"GET"}},"id":"6021683934456376603262","status":"DECLINED","error_information":{"reason":"PROCESSOR_DECLINED","message":"Decline - General decline of the card. No other information provided by the issuing bank."},"client_reference_information":{"code":"%s"},"processor_information":{"transaction_id":"460282531937765","network_transaction_id":"460282531937765","response_code":"005","avs":{"code":"D","code_raw":"D"},"card_verification":{"result_code":"M","result_code_raw":"M"}},"payment_information":{"account_features":{"category":"F"}}}""" % order_number # pylint: disable=line-too-long ) response = self.client.post(self.path, data) assert response.status_code == 400 assert response['content-type'] == JSON request = RequestFactory(SERVER_NAME='testserver.fake').post( self.path, data) request.site = self.site assert json.loads( response.content )['redirectTo'] == get_payment_microfrontend_or_basket_url(request) # Ensure the basket is frozen basket = Basket.objects.get(pk=basket.pk) self.assertEqual(basket.status, Basket.MERGED) assert Basket.objects.count() == 2
def setUp(self): super(SiteMixin, self).setUp() # Set the domain used for all test requests domain = 'testserver.fake' self.client = self.client_class(SERVER_NAME=domain) Site.objects.get_current().delete() site_configuration = SiteConfigurationFactory( partner__name='edX', site__id=settings.SITE_ID, site__domain=domain, segment_key='fake_segment_key', oauth_settings={ 'SOCIAL_AUTH_EDX_OIDC_KEY': 'key', 'SOCIAL_AUTH_EDX_OIDC_SECRET': 'secret' } ) self.partner = site_configuration.partner self.site = site_configuration.site request = RequestFactory().get('') request.session = None request.site = self.site set_thread_variable('request', request)
def test_listboard_filter_view(self): class SubjectVisitModelWrapper(ModelWrapper): model = 'edc_dashboard.subjectvisit' next_url_name = 'thenexturl' class MyListboardViewFilters(ListboardViewFilters): all = ListboardFilter( name='all', label='All', lookup={}) scheduled = ListboardFilter( label='Scheduled', lookup={'reason': 'scheduled'}) not_scheduled = ListboardFilter( label='Not Scheduled', exclude_filter=True, lookup={'reason': 'scheduled'}) class MyView(ListboardFilterViewMixin, ListboardView): model = 'edc_dashboard.subjectvisit' listboard_url = 'listboard_url' listboard_template = 'listboard_template' listboard_filter_url = 'listboard_url' model_wrapper_cls = SubjectVisitModelWrapper listboard_view_filters = MyListboardViewFilters() start = datetime(2013, 5, 1, 12, 30) end = datetime(2013, 5, 10, 17, 15) for r in arrow.Arrow.range('day', start, end): SubjectVisit.objects.create( subject_identifier='1234', report_datetime=r.datetime, reason='missed') subject_visit = SubjectVisit.objects.create( subject_identifier='1234', report_datetime=get_utcnow(), reason='scheduled') request = RequestFactory().get('/?scheduled=scheduled') request.user = '******' request.site = Site.objects.get_current() request.url_name_data = {'listboard_url': 'listboard_url'} request.template_data = {'listboard_template': 'listboard.html'} template_response = MyView.as_view()(request=request) object_list = template_response.__dict__.get( 'context_data').get('object_list') self.assertEqual( [wrapper.object.reason for wrapper in object_list if wrapper.object.pk == subject_visit.pk], [subject_visit.reason])
def test_request_password_change_inactive_user(self): # Create an account, but do not activate it create_account(self.USERNAME, self.PASSWORD, self.EMAIL) request = RequestFactory().post('/password') request.user = Mock() request.site = SiteFactory() with patch('crum.get_current_request', return_value=request): request_password_change(self.EMAIL, self.IS_SECURE) # Verify that the activation email was still sent self.assertEqual(len(mail.outbox), 1)
def test_order_number_for_basket_without_site(self): """ Verify the order number is linked to the default site, if the basket has no associated site. """ site_configuration = SiteConfigurationFactory(site__domain='acme.fake', partner__name='ACME') site = site_configuration.site partner = site_configuration.partner basket = BasketFactory(site=None) request = RequestFactory().get('') request.session = None request.site = site with mock.patch('ecommerce.extensions.order.utils.get_current_request', mock.Mock(return_value=request)): self.assert_order_number_matches_basket(basket, partner)
def test_listboard_filter_view(self): class SubjectVisitModelWrapper(ModelWrapper): model = "edc_dashboard.subjectvisit" next_url_name = "dashboard_url" class MyListboardViewFilters(ListboardViewFilters): all = ListboardFilter(name="all", label="All", lookup={}) scheduled = ListboardFilter(label="Scheduled", lookup={"reason": "scheduled"}) not_scheduled = ListboardFilter( label="Not Scheduled", exclude_filter=True, lookup={"reason": "scheduled"}, ) class MyView(ListboardFilterViewMixin, ListboardView): listboard_model = "edc_dashboard.subjectvisit" listboard_url = "listboard_url" listboard_template = "listboard_template" listboard_filter_url = "listboard_url" listboard_view_permission_codename = "edc_dashboard.view_my_listboard" model_wrapper_cls = SubjectVisitModelWrapper listboard_view_filters = MyListboardViewFilters() start = datetime(2013, 5, 1, 12, 30) end = datetime(2013, 5, 10, 17, 15) for r in arrow.Arrow.range("day", start, end): SubjectVisit.objects.create(subject_identifier="1234", report_datetime=r.datetime, reason="missed") subject_visit = SubjectVisit.objects.create( subject_identifier="1234", report_datetime=get_utcnow(), reason="scheduled") request = RequestFactory().get("/?scheduled=scheduled") request.user = self.user request.site = Site.objects.get_current() # request.url_name_data = {"listboard_url": "listboard_url"} request.template_data = {"listboard_template": "listboard.html"} template_response = MyView.as_view()(request=request) object_list = template_response.__dict__.get("context_data").get( "object_list") self.assertEqual( [ wrapper.object.reason for wrapper in object_list if wrapper.object.pk == subject_visit.pk ], [subject_visit.reason], )
def test_request_password_change(self): # Create and activate an account self.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) assert len(mail.outbox) == 1 request = RequestFactory().post('/password') request.user = Mock() request.site = SiteFactory() with patch('crum.get_current_request', return_value=request): # Request a password change request_password_change(self.EMAIL, self.IS_SECURE) # Verify that a new email message has been sent assert len(mail.outbox) == 2 # Verify that the body of the message contains something that looks # like an activation link email_body = mail.outbox[0].body result = re.search(r'(?P<url>https?://[^\s]+)', email_body) assert result is not None
def test_request_password_change(self): # Create and activate an account activation_key = create_account(self.USERNAME, self.PASSWORD, self.EMAIL) activate_account(activation_key) request = RequestFactory().post('/password') request.user = Mock() request.site = SiteFactory() with patch('crum.get_current_request', return_value=request): # Request a password change request_password_change(self.EMAIL, self.IS_SECURE) # Verify that one email message has been sent self.assertEqual(len(mail.outbox), 1) # Verify that the body of the message contains something that looks # like an activation link email_body = mail.outbox[0].body result = re.search(r'(?P<url>https?://[^\s]+)', email_body) self.assertIsNot(result, None)
def test_authorized_pending_review_request_reversal_failed(self): """ Verify the view reports an error if the transaction is only authorized pending review. """ basket = self._create_valid_basket() data = self._generate_data(basket.id) order_number = OrderNumberGenerator().order_number_from_basket_id( self.site.siteconfiguration.partner, basket.id, ) # This response has been pruned to only the needed data. self._prep_request_success( """{"links":{"_self":{"href":"/pts/v2/payments/6038898237296087603031","method":"GET"}},"id":"6038898237296087603031","submit_time_utc":"2020-10-28T12:57:04Z","status":"AUTHORIZED_PENDING_REVIEW","error_information":{"reason":"AVS_FAILED","message":"Soft Decline - The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the Address Verification Service (AVS) check."},"client_reference_information":{"code":"%s"},"processor_information":{"approval_code":"028252","transaction_id":"580302466249046","network_transaction_id":"580302466249046","response_code":"000","avs":{"code":"N","code_raw":"N"},"card_verification":{"result_code":"M","result_code_raw":"M"}},"payment_information":{"account_features":{"category":"C"}},"order_information":{"amount_details":{"authorized_amount":"25.00","currency":"USD"}}}""" % order_number # pylint: disable=line-too-long ) self._prep_request_invalid( """{"submitTimeUtc":"2020-09-30T18:53:23Z","status":"INVALID_REQUEST","reason":"DUPLICATE_REQUEST","message":"Declined - The\u00a0merchantReferenceCode\u00a0sent with this authorization request matches the merchantReferenceCode of another authorization request that you sent in the last 15 minutes."}""", # pylint: disable=line-too-long '6038898237296087603031') response = self.client.post(self.path, data) assert response.status_code == 400 assert response['content-type'] == JSON request = RequestFactory(SERVER_NAME='testserver.fake').post( self.path, data) request.site = self.site assert json.loads( response.content )['redirectTo'] == get_payment_microfrontend_or_basket_url(request) # Ensure the basket is frozen basket = Basket.objects.get(pk=basket.pk) self.assertEqual(basket.status, Basket.MERGED) assert Basket.objects.count() == 2 # Ensure that 2 requests were sent to cybersource assert self.mock_cybersource_request.call_count == 2 # Ensure that 2 requests and 2 responses were recorded as PaymentProcessorResponses assert PaymentProcessorResponse.objects.all().count() == 4
def test_for_non_staff_user_return_error(self): password = '******' user = EdlyUserFactory(password=password) site = SiteFactory(name=self.site_name) site_config = SiteConfigurationFactory( values={'address': self.site_address}, site=site) EdlySubOrganizationFactory(lms_site=site) request = RequestFactory() request.user = user request.site = site self.client.login(username=user.username, password=password) self.client.cookies.load({ settings.EDLY_USER_INFO_COOKIE_NAME: cookies._get_edly_user_info_cookie_string(request) }) url = reverse('redhouse_panel:redhouse_panel_api.v0:site', kwargs={'pk': site.id}) response = self.client.get(url, SERVER_NAME=site.domain) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(response.data['detail'], 'You do not have permission to perform this action.')
def setUp(self): super(SiteMixin, self).setUp() # Set the domain used for all test requests domain = 'testserver.fake' self.client = self.client_class(SERVER_NAME=domain) Site.objects.all().delete() site_configuration = SiteConfigurationFactory( partner__name='edX', site__id=settings.SITE_ID, site__domain=domain, segment_key='fake_segment_key', oauth_settings={ 'SOCIAL_AUTH_EDX_OIDC_KEY': 'key', 'SOCIAL_AUTH_EDX_OIDC_SECRET': 'secret' }) self.partner = site_configuration.partner self.site = site_configuration.site request = RequestFactory().get('') request.session = None request.site = self.site set_thread_variable('request', request)
def dummy_request(self, user=None): request = RequestFactory().get('/') request.user = user or AnonymousUser() request.site = Site.objects.first() return request
def create_coupon( self, title='Test coupon', price=100, client=None, partner=None, catalog=None, code='', benefit_value=100, note=None, max_uses=None, quantity=5 ): """Helper method for creating a coupon. Arguments: title(str): Title of the coupon price(int): Price of the coupon partner(Partner): Partner used for creating a catalog catalog(Catalog): Catalog of courses for which the coupon applies code(str): Custom coupon code benefit_value(int): The voucher benefit value Returns: coupon (Coupon) """ if partner is None: partner = PartnerFactory(name='Tester') if client is None: client, __ = BusinessClient.objects.get_or_create(name='Test Client') if catalog is None: catalog = Catalog.objects.create(partner=partner) if code is not '': quantity = 1 data = { 'partner': partner, 'benefit_type': Benefit.PERCENTAGE, 'benefit_value': benefit_value, 'catalog': catalog, 'end_date': datetime.date(2020, 1, 1), 'code': code, 'quantity': quantity, 'start_date': datetime.date(2015, 1, 1), 'voucher_type': Voucher.SINGLE_USE, 'categories': [self.category], 'note': note, 'max_uses': max_uses, } coupon = CouponViewSet().create_coupon_product( title=title, price=price, data=data ) request = RequestFactory() request.site = self.site request.user = factories.UserFactory() request.COOKIES = {} self.basket = prepare_basket(request, coupon) self.response_data = CouponViewSet().create_order_for_invoice(self.basket, coupon_id=coupon.id, client=client) coupon.client = client return coupon
def handle(self, *args, **options): site_id = options.get('site_id') try: site = Site.objects.get(id=site_id) except Site.DoesNotExist: logger.exception('Site id %s does not exist', site_id) raise Exception try: site_configurations = SiteConfiguration.objects.get(site=site) configuration_helpers = site_configurations.edly_client_theme_branding_settings voucher_api_url = configuration_helpers.get( 'LUMSXPAY_VOUCHER_API_URL') if not voucher_api_url: logger.exception( 'Cron Job of Update Payment Statuses is canceled due to no ' 'LUMSXPAY_VOUCHER_API_URL in client theme branding') raise Exception except: logger.exception( 'Site Configurations with side id %s does not exist', site_id) raise Exception try: unpaid_challan_baskets = BasketChallanVoucher.objects.filter( is_paid=False) except: logger.exception( 'could not fetch the unpaid challan baskets from Database') raise Exception headers = { "Authorization": configuration_helpers.get('PAYMENT_AUTHORIZATION_KEY'), "Content-Type": "application/json" } paid_vouchers = [] unpaid_vouchers = unpaid_challan_baskets.values_list('voucher_number', flat=True) if unpaid_challan_baskets: for unpaid_vouchers_lst in list( self.equal_divided_chunks(list(unpaid_vouchers), self.VOUCHERS_PER_REQUEST)): unpaid_vouchers_str = ','.join(unpaid_vouchers_lst) url = '{}/{}'.format(voucher_api_url, unpaid_vouchers_str) response = requests.get(url, headers=headers) if response.status_code == 200: voucher_details = response.json() voucher_data = voucher_details['data'] if not isinstance(voucher_details['data'], list): voucher_data = [voucher_details['data']] for voucher in voucher_data: if voucher['paid_status'].lower() == 'paid': paid_vouchers.append(voucher['voucher_id']) else: logger.info('VOUCHER API doesnot return 200 OK') return else: logger.info('No unpaid voucher found for update payment status') return if not paid_vouchers: logger.info('No voucher paid so exiting the job') return unpaid_basket_ids = unpaid_challan_baskets.filter( voucher_number__in=paid_vouchers).values_list('basket_id', flat=True) paid_baskets = Basket.objects.filter(id__in=unpaid_basket_ids, status=Basket.OPEN) if not paid_baskets: logger.info( 'ERROR: Basket corresponding to voucher does not exist') raise Exception for basket in paid_baskets: shipping_method = NoShippingRequired() shipping_charge = shipping_method.calculate(basket) basket.strategy = DefaultStrategy() order_total = OrderTotalCalculator().calculate( basket, shipping_charge) user = basket.owner billing_address = None request = RequestFactory() request.site = site request.user = user request.site.siteconfiguration = site_configurations set_thread_variable('request', request) order = EdxOrderPlacementMixin().handle_order_placement( order_number=basket.order_number, user=user, basket=basket, shipping_address=None, shipping_method=shipping_method, shipping_charge=shipping_charge, billing_address=billing_address, order_total=order_total, request=request) EdxOrderPlacementMixin().handle_post_order(order) challan_voucher_basket = BasketChallanVoucher.objects.filter( basket_id=basket.id) if len(challan_voucher_basket) > 1: logger.info( 'more than one basket exist with same id in challan table.' ) elif challan_voucher_basket: challan_voucher_basket.update(is_paid=True) logger.info( 'Successfully finished the cron job for updating the order payment' ) return
def create_coupon(self, title='Test coupon', price=100, client=None, partner=None, catalog=None, code='', benefit_value=100, note=None, max_uses=None, quantity=5): """Helper method for creating a coupon. Arguments: title(str): Title of the coupon price(int): Price of the coupon partner(Partner): Partner used for creating a catalog catalog(Catalog): Catalog of courses for which the coupon applies code(str): Custom coupon code benefit_value(int): The voucher benefit value Returns: coupon (Coupon) """ if partner is None: partner = PartnerFactory(name='Tester') if client is None: client, __ = BusinessClient.objects.get_or_create( name='Test Client') if catalog is None: catalog = Catalog.objects.create(partner=partner) if code is not '': quantity = 1 data = { 'partner': partner, 'benefit_type': Benefit.PERCENTAGE, 'benefit_value': benefit_value, 'catalog': catalog, 'end_date': datetime.date(2020, 1, 1), 'code': code, 'quantity': quantity, 'start_date': datetime.date(2015, 1, 1), 'voucher_type': Voucher.SINGLE_USE, 'categories': [self.category], 'note': note, 'max_uses': max_uses, } coupon = CouponViewSet().create_coupon_product(title=title, price=price, data=data) request = RequestFactory() request.site = self.site request.user = factories.UserFactory() request.COOKIES = {} self.basket = prepare_basket(request, coupon) self.response_data = CouponViewSet().create_order_for_invoice( self.basket, coupon_id=coupon.id, client=client) coupon.client = client return coupon