33from ddt import data , ddt , unpack
44from django .contrib .auth .models import User
55from django .test import TestCase
6- from lms .djangoapps .lti_provider .models import LtiUser
76from rest_framework import status
87from rest_framework .test import APIClient
98
@@ -36,25 +35,25 @@ def setUp(self):
3635 def test_successful_lti_user_fix (self , mock_user_model , mock_lti_user_model ):
3736 """Test successful LTI user fix."""
3837 # Mock LTI user with bad username
38+ mock_lti_user = Mock ()
39+ mock_lti_user .lti_user_id = "TEST_LTI_USER_ID"
40+
3941 mock_edx_user = Mock ()
40- mock_edx_user .username = self . lti_username
42+ mock_edx_user .username = "TEST_LTI_USER_ID"
4143 mock_edx_user .email = self .valid_email
42-
43- mock_lti_user = Mock ()
4444 mock_lti_user .edx_user = mock_edx_user
4545
4646 mock_qs = Mock ()
47- mock_qs .exists .return_value = True
4847 mock_qs .first .return_value = mock_lti_user
4948 mock_lti_user_model .objects .filter .return_value = mock_qs
5049
5150 # Mock User.objects.get
5251 mock_user = Mock ()
5352 mock_user_model .objects .get .return_value = mock_user
5453
55- data = {"email" : self .valid_email , "username" : self .valid_username }
54+ payload = {"email" : self .valid_email , "username" : self .valid_username }
5655
57- response = self .client .post (self .url , data )
56+ response = self .client .post (self .url , payload )
5857
5958 assert response .status_code == status .HTTP_200_OK
6059 mock_user_model .objects .get .assert_called_once_with (email = self .valid_email )
@@ -69,23 +68,19 @@ def test_successful_lti_user_fix(self, mock_user_model, mock_lti_user_model):
6968 def test_missing_required_fields (self , test_data , expected_message ):
7069 """Test request with missing required fields."""
7170 response = self .client .post (self .url , test_data )
72-
73- assert response .status_code == status .HTTP_400_BAD_REQUEST
74- assert expected_message in response .data ["detail" ]
7571 assert response .status_code == status .HTTP_400_BAD_REQUEST
76- assert expected_message in response .data [ "detail" ]
72+ assert expected_message in response .content . decode ()
7773
7874 @patch ("ol_openedx_lti_utilities.views.LtiUser" )
7975 def test_no_lti_user_found (self , mock_lti_user_model ):
8076 """Test when no LTI user exists for given email."""
8177 mock_qs = Mock ()
82- mock_qs .exists .return_value = False
78+ mock_qs .first .return_value = None
8379 mock_lti_user_model .objects .filter .return_value = mock_qs
84- mock_lti_user_model .DoesNotExist = LtiUser .DoesNotExist
8580
86- data = {"email" : self .valid_email , "username" : self .valid_username }
81+ payload = {"email" : self .valid_email , "username" : self .valid_username }
8782
88- response = self .client .post (self .url , data )
83+ response = self .client .post (self .url , payload )
8984
9085 assert response .status_code == status .HTTP_404_NOT_FOUND
9186
@@ -105,97 +100,43 @@ def test_user_does_not_need_fixing(self, mock_lti_user_model):
105100 mock_qs .first .return_value = mock_lti_user
106101 mock_lti_user_model .objects .filter .return_value = mock_qs
107102
108- data = {"email" : self .valid_email , "username" : self .valid_username }
103+ payload = {"email" : self .valid_email , "username" : self .valid_username }
109104
110- response = self .client .post (self .url , data )
105+ response = self .client .post (self .url , payload )
111106
112107 assert response .status_code == status .HTTP_400_BAD_REQUEST
113- assert "User does not need fixing" in response .data ["detail" ]
114-
115- @patch ("ol_openedx_lti_utilities.views.LtiUser" )
116- def test_lti_username_regex_matching (self , mock_lti_user_model ):
117- """Test various username formats against LTI username regex."""
118- test_cases = [
119- (
120- "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0" , # pragma: allowlist secret
121- True ,
122- ), # 40 chars, alphanumeric
123- (
124- "abcdefghijklmnopqrstuvwxyz1234567890ABCD" , # pragma: allowlist secret
125- True ,
126- ), # pragma: allowlist secret
127- (
128- "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9" , # pragma: allowlist secret
129- False ,
130- ), # pragma: allowlist secret
131- (
132- "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0X" , # pragma: allowlist secret
133- False ,
134- ), # pragma: allowlist secret
135- ("normalusername" , False ), # Normal username
136- (
137- "A1B2-C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0" , # pragma: allowlist secret
138- False ,
139- ), # pragma: allowlist secret
140- ("" , False ), # Empty string
141- ]
142-
143- for username , should_match in test_cases :
144- with self .subTest (username = username ):
145- mock_edx_user = Mock ()
146- mock_edx_user .username = username
147- mock_edx_user .email = self .valid_email
148-
149- mock_lti_user = Mock ()
150- mock_lti_user .edx_user = mock_edx_user
151-
152- mock_qs = Mock ()
153- mock_qs .exists .return_value = True
154- mock_qs .first .return_value = mock_lti_user
155- mock_lti_user_model .objects .filter .return_value = mock_qs
156-
157- data = {"email" : self .valid_email , "username" : self .valid_username }
158-
159- with patch ("ol_openedx_lti_utilities.views.User" ) as mock_user_model :
160- mock_user = Mock ()
161- mock_user_model .objects .get .return_value = mock_user
162-
163- response = self .client .post (self .url , data )
164-
165- if should_match :
166- assert response .status_code == status .HTTP_200_OK
167- mock_user .save .assert_called_once ()
168- else :
169- assert response .status_code == status .HTTP_400_BAD_REQUEST
170- assert "User does not need fixing" in response .data ["detail" ]
108+ assert (
109+ "User with the given email does not appear to be an LTI-created user."
110+ in response .content .decode ()
111+ )
171112
172113 def test_only_post_method_allowed (self ):
173114 """Test that only POST method is allowed."""
174- data = {"email" : self .valid_email , "username" : self .valid_username }
115+ payload = {"email" : self .valid_email , "username" : self .valid_username }
175116
176117 # Test GET
177118 response = self .client .get (self .url )
178119 assert response .status_code == status .HTTP_405_METHOD_NOT_ALLOWED
179120
180121 # Test PUT
181- response = self .client .put (self .url , data )
122+ response = self .client .put (self .url , payload )
182123 assert response .status_code == status .HTTP_405_METHOD_NOT_ALLOWED
183124
184125 # Test DELETE
185126 response = self .client .delete (self .url )
186127 assert response .status_code == status .HTTP_405_METHOD_NOT_ALLOWED
187128
188129 # Test PATCH
189- response = self .client .patch (self .url , data )
130+ response = self .client .patch (self .url , payload )
190131 assert response .status_code == status .HTTP_405_METHOD_NOT_ALLOWED
191132
192133 @patch ("ol_openedx_lti_utilities.views.log" )
193134 @patch ("ol_openedx_lti_utilities.views.LtiUser" )
194135 def test_logging_on_missing_fields (self , mock_lti_user_model , mock_log ): # noqa: ARG002
195136 """Test that error is logged when required fields are missing."""
196- data = {}
137+ payload = {}
197138
198- response = self .client .post (self .url , data )
139+ response = self .client .post (self .url , payload )
199140
200141 assert response .status_code == status .HTTP_400_BAD_REQUEST
201142 mock_log .error .assert_called_once_with ("email and username are required" )
@@ -205,13 +146,12 @@ def test_logging_on_missing_fields(self, mock_lti_user_model, mock_log): # noqa
205146 def test_logging_on_no_user_found (self , mock_lti_user_model , mock_log ):
206147 """Test that error is logged when no LTI user is found."""
207148 mock_qs = Mock ()
208- mock_qs .exists .return_value = False
149+ mock_qs .first .return_value = None
209150 mock_lti_user_model .objects .filter .return_value = mock_qs
210- mock_lti_user_model .DoesNotExist = LtiUser .DoesNotExist
211151
212- data = {"email" : self .valid_email , "username" : self .valid_username }
152+ payload = {"email" : self .valid_email , "username" : self .valid_username }
213153
214- response = self .client .post (self .url , data )
154+ response = self .client .post (self .url , payload )
215155
216156 assert response .status_code == status .HTTP_404_NOT_FOUND
217157 mock_log .error .assert_called_once_with (
0 commit comments