feat(roadmap): implementar Sprints 1, 2 y 3 (MVC, Stateless JWT API y Spring Security)

This commit is contained in:
Carlos Tello
2026-09-05 01:46:57 -03:00
parent fa878cb0d5
commit 69b8b7ccef
34 changed files with 1750 additions and 21 deletions
+84
View File
@@ -0,0 +1,84 @@
import unittest
import json
from app import create_app, db
from app.models.user import User
from app.services.jwt_service import JWTService
class TestJWTAndAPI(unittest.TestCase):
def setUp(self):
self.app = create_app()
self.app.config['TESTING'] = True
self.client = self.app.test_client()
self.app_context = self.app.app_context()
self.app_context.push()
# Buscar usuario activo o crear de prueba
self.test_user = User.query.filter_by(is_active=True).first()
if not self.test_user:
self.test_user = User(
email="test_api_admin@unicaba.edu.ar",
name="Test API Admin",
role="ADMIN",
is_active=True
)
self.test_user.set_password("Test1234!")
db.session.add(self.test_user)
db.session.commit()
def tearDown(self):
db.session.rollback()
self.app_context.pop()
def test_jwt_generation_and_decoding(self):
tokens = JWTService.generate_tokens(self.test_user)
self.assertIn('access_token', tokens)
self.assertIn('refresh_token', tokens)
payload = JWTService.decode_token(tokens['access_token'], expected_type='access')
self.assertEqual(payload['sub'], str(self.test_user.id))
self.assertEqual(payload['email'], self.test_user.email)
def test_jwt_revocation(self):
tokens = JWTService.generate_tokens(self.test_user)
token = tokens['access_token']
# Antes de revocar: válido
payload = JWTService.decode_token(token, expected_type='access')
self.assertIsNotNone(payload)
# Revocar
revoked = JWTService.revoke_token(token)
self.assertTrue(revoked)
# Después de revocar: debe lanzar InvalidTokenError
with self.assertRaises(Exception):
JWTService.decode_token(token, expected_type='access')
def test_protected_endpoints_require_token(self):
# Sin token debe dar 401
res = self.client.get('/api/v1/auth/me')
self.assertEqual(res.status_code, 401)
res_classrooms = self.client.get('/api/v1/classrooms')
self.assertEqual(res_classrooms.status_code, 401)
def test_authorized_endpoint_access(self):
tokens = JWTService.generate_tokens(self.test_user)
headers = {'Authorization': f"Bearer {tokens['access_token']}"}
res = self.client.get('/api/v1/auth/me', headers=headers)
self.assertEqual(res.status_code, 200)
data = res.get_json()
self.assertEqual(data['email'], self.test_user.email)
res_classrooms = self.client.get('/api/v1/classrooms', headers=headers)
self.assertEqual(res_classrooms.status_code, 200)
def test_token_refresh_flow(self):
tokens = JWTService.generate_tokens(self.test_user)
res = self.client.post('/api/v1/auth/refresh', json={'refresh_token': tokens['refresh_token']})
self.assertEqual(res.status_code, 200)
data = res.get_json()
self.assertIn('access_token', data)
if __name__ == '__main__':
unittest.main()