2026-04-10 01:31:18 +05:30
|
|
|
"""Unit tests for GoogleLoginView.
|
2025-12-01 04:52:49 +05:30
|
|
|
|
2026-04-10 01:31:18 +05:30
|
|
|
Run with:
|
|
|
|
|
python manage.py test mobile_api.tests
|
|
|
|
|
"""
|
|
|
|
|
import json
|
|
|
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
|
|
|
|
|
|
from django.test import TestCase, override_settings
|
|
|
|
|
from rest_framework.authtoken.models import Token
|
|
|
|
|
|
|
|
|
|
from accounts.models import User
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override_settings(GOOGLE_CLIENT_ID='test-client-id.apps.googleusercontent.com')
|
|
|
|
|
class GoogleLoginViewTests(TestCase):
|
|
|
|
|
url = '/api/user/google-login/'
|
|
|
|
|
|
|
|
|
|
def _valid_idinfo(self, email='new.user@example.com'):
|
|
|
|
|
return {
|
|
|
|
|
'email': email,
|
|
|
|
|
'given_name': 'New',
|
|
|
|
|
'family_name': 'User',
|
|
|
|
|
'aud': 'test-client-id.apps.googleusercontent.com',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@patch('google.oauth2.id_token.verify_oauth2_token')
|
|
|
|
|
def test_valid_token_creates_user(self, mock_verify):
|
|
|
|
|
mock_verify.return_value = self._valid_idinfo('fresh@example.com')
|
|
|
|
|
|
|
|
|
|
resp = self.client.post(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({'id_token': 'fake.google.jwt'}),
|
|
|
|
|
content_type='application/json',
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(resp.status_code, 200, resp.content)
|
|
|
|
|
body = resp.json()
|
|
|
|
|
self.assertEqual(body['email'], 'fresh@example.com')
|
|
|
|
|
self.assertEqual(body['role'], 'customer')
|
|
|
|
|
self.assertTrue(body['token'])
|
|
|
|
|
|
|
|
|
|
user = User.objects.get(email='fresh@example.com')
|
|
|
|
|
self.assertTrue(Token.objects.filter(user=user).exists())
|
|
|
|
|
# Confirm audience was passed to verify_oauth2_token
|
|
|
|
|
_, call_kwargs = mock_verify.call_args[0], mock_verify.call_args
|
|
|
|
|
self.assertEqual(mock_verify.call_args[0][2], 'test-client-id.apps.googleusercontent.com')
|
|
|
|
|
|
|
|
|
|
def test_missing_id_token_returns_400(self):
|
|
|
|
|
resp = self.client.post(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({}),
|
|
|
|
|
content_type='application/json',
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(resp.status_code, 400)
|
|
|
|
|
self.assertEqual(resp.json()['error'], 'id_token is required')
|
|
|
|
|
|
|
|
|
|
@patch('google.oauth2.id_token.verify_oauth2_token')
|
|
|
|
|
def test_invalid_token_returns_401(self, mock_verify):
|
|
|
|
|
mock_verify.side_effect = ValueError('Token audience mismatch')
|
|
|
|
|
|
|
|
|
|
resp = self.client.post(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({'id_token': 'tampered.or.wrong-aud.jwt'}),
|
|
|
|
|
content_type='application/json',
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(resp.status_code, 401)
|
|
|
|
|
self.assertEqual(resp.json()['error'], 'Invalid Google token')
|
|
|
|
|
|
|
|
|
|
@patch('google.oauth2.id_token.verify_oauth2_token')
|
|
|
|
|
def test_existing_user_reuses_token(self, mock_verify):
|
|
|
|
|
existing = User.objects.create_user(
|
|
|
|
|
username='returning@example.com',
|
|
|
|
|
email='returning@example.com',
|
|
|
|
|
password='irrelevant',
|
|
|
|
|
role='customer',
|
|
|
|
|
)
|
|
|
|
|
existing_auth_token = Token.objects.create(user=existing)
|
|
|
|
|
mock_verify.return_value = self._valid_idinfo('returning@example.com')
|
|
|
|
|
|
|
|
|
|
resp = self.client.post(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({'id_token': 'returning.user.jwt'}),
|
|
|
|
|
content_type='application/json',
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
|
self.assertEqual(resp.json()['token'], existing_auth_token.key)
|
|
|
|
|
# No duplicate user created
|
|
|
|
|
self.assertEqual(User.objects.filter(email='returning@example.com').count(), 1)
|