|
7 | 7 | from unittest import mock |
8 | 8 |
|
9 | 9 | import ddt |
| 10 | +from django.conf import settings |
10 | 11 | from django.contrib.auth import get_user_model |
11 | 12 | from django.utils import timezone |
12 | 13 | from edx_rbac.constants import ALL_ACCESS_CONTEXT |
@@ -820,6 +821,80 @@ def test_new_subscription_plan_created( |
820 | 821 | ) |
821 | 822 | assert mock_license_client.create_subscription_plan.call_count == 2 |
822 | 823 |
|
| 824 | + @mock.patch('enterprise_access.apps.provisioning.api.LicenseManagerApiClient') |
| 825 | + @mock.patch('enterprise_access.apps.provisioning.api.LmsApiClient') |
| 826 | + @mock.patch('enterprise_access.apps.api.v1.views.provisioning.logger') |
| 827 | + def test_legacy_single_plan_request_transformation( |
| 828 | + self, mock_logger, mock_lms_api_client, mock_license_manager_client |
| 829 | + ): |
| 830 | + """ |
| 831 | + Test that legacy requests with single 'subscription_plan' key are transformed |
| 832 | + to the new two-plan format and successfully provision resources. |
| 833 | + """ |
| 834 | + # Setup mocks for successful provisioning. |
| 835 | + mock_lms_client = mock_lms_api_client.return_value |
| 836 | + mock_lms_client.get_enterprise_customer_data.return_value = None |
| 837 | + mock_lms_client.create_enterprise_customer.return_value = DEFAULT_CUSTOMER_RECORD |
| 838 | + mock_lms_client.get_enterprise_admin_users.return_value = [] |
| 839 | + mock_lms_client.get_enterprise_pending_admin_users.return_value = [] |
| 840 | + mock_lms_client.get_enterprise_catalogs.return_value = [DEFAULT_CATALOG_RECORD] |
| 841 | + |
| 842 | + mock_license_client = mock_license_manager_client.return_value |
| 843 | + mock_license_client.get_customer_agreement.return_value = None |
| 844 | + mock_license_client.create_customer_agreement.return_value = { |
| 845 | + **DEFAULT_AGREEMENT_RECORD, "subscriptions": [] |
| 846 | + } |
| 847 | + mock_license_client.create_subscription_plan.side_effect = [ |
| 848 | + DEFAULT_TRIAL_SUBSCRIPTION_PLAN_RECORD, |
| 849 | + DEFAULT_FIRST_PAID_SUBSCRIPTION_PLAN_RECORD, |
| 850 | + ] |
| 851 | + mock_license_client.create_subscription_plan_renewal.return_value = ( |
| 852 | + EXPECTED_SUBSCRIPTION_PLAN_RENEWAL_RESPONSE |
| 853 | + ) |
| 854 | + |
| 855 | + # Create a legacy request payload with 'subscription_plan' instead of the new format. |
| 856 | + legacy_request_payload = {**DEFAULT_REQUEST_PAYLOAD} |
| 857 | + legacy_request_payload.pop('first_paid_subscription_plan') |
| 858 | + legacy_request_payload['subscription_plan'] = legacy_request_payload.pop('trial_subscription_plan') |
| 859 | + |
| 860 | + # Make the provisioning request. |
| 861 | + response = self.client.post(PROVISIONING_CREATE_ENDPOINT, data=legacy_request_payload) |
| 862 | + |
| 863 | + # Should succeed despite using legacy format. |
| 864 | + self.assertEqual(response.status_code, status.HTTP_201_CREATED) |
| 865 | + |
| 866 | + # Verify warning was logged about deprecated format. |
| 867 | + mock_logger.warning.assert_called_once() |
| 868 | + warning_message = mock_logger.warning.call_args[0][0] |
| 869 | + self.assertIn('Deprecated request format detected', warning_message) |
| 870 | + self.assertIn('subscription_plan', warning_message) |
| 871 | + |
| 872 | + # Verify info log about transformation. |
| 873 | + mock_logger.info.assert_called() |
| 874 | + info_calls = [call[0][0] for call in mock_logger.info.call_args_list] |
| 875 | + self.assertTrue( |
| 876 | + any('Transformed legacy subscription_plan' in msg for msg in info_calls), |
| 877 | + "Expected transformation log message not found" |
| 878 | + ) |
| 879 | + |
| 880 | + # Verify response has both trial and paid subscription plans. |
| 881 | + response_data = response.json() |
| 882 | + self.assertIn('trial_subscription_plan', response_data) |
| 883 | + self.assertIn('first_paid_subscription_plan', response_data) |
| 884 | + |
| 885 | + # Verify the workflow input_data contains correct trial and paid plan data |
| 886 | + workflow = ProvisionNewCustomerWorkflow.objects.first() |
| 887 | + trial_plan_input = workflow.input_data.get('create_trial_subscription_plan_input') |
| 888 | + first_paid_plan_input = workflow.input_data.get('create_first_paid_subscription_plan_input') |
| 889 | + assert trial_plan_input['title'] == legacy_request_payload['subscription_plan']['title'] |
| 890 | + assert trial_plan_input['salesforce_opportunity_line_item'] == ( |
| 891 | + legacy_request_payload['subscription_plan']['salesforce_opportunity_line_item'] |
| 892 | + ) |
| 893 | + assert trial_plan_input['product_id'] == legacy_request_payload['subscription_plan']['product_id'] |
| 894 | + assert 'First Paid Plan' in first_paid_plan_input['title'] |
| 895 | + assert first_paid_plan_input['product_id'] == settings.PROVISIONING_PAID_SUBSCRIPTION_PRODUCT_ID |
| 896 | + assert first_paid_plan_input['salesforce_opportunity_line_item'] is None |
| 897 | + |
823 | 898 |
|
824 | 899 | @ddt.ddt |
825 | 900 | class TestCheckoutIntentSynchronization(APITest): |
|
0 commit comments