feat: add parser source dashboard and scheduling
All checks were successful
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 1m6s
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m18s
CI/CD Pipeline / Build Docker Images (pull_request) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (pull_request) Has been skipped

This commit is contained in:
2026-04-27 23:36:28 +02:00
parent 199d871923
commit 44355deeb3
96 changed files with 15015 additions and 309 deletions

View File

@@ -7,6 +7,8 @@ from django.urls import reverse
from faker import Faker
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken
from rest_framework_simplejwt.tokens import RefreshToken
from .factories import ProfileFactory, UserFactory
@@ -86,7 +88,7 @@ class LoginViewTest(APITestCase):
self.password = fake.password(length=12, special_chars=False)
self.user = UserFactory.create_user(password=self.password)
self.login_data = {"email": self.user.email, "password": self.password}
self.login_data = {"username": self.user.username, "password": self.password}
def test_login_success(self):
"""Test successful login"""
@@ -96,6 +98,30 @@ class LoginViewTest(APITestCase):
self.assertIn("refresh", response.data)
self.assertIn("access", response.data)
def test_login_success_with_email_for_legacy_clients(self):
"""Test legacy email login is still supported."""
response = self.client.post(
self.login_url,
{"email": self.user.email, "password": self.password},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn("refresh", response.data)
self.assertIn("access", response.data)
def test_login_success_with_login_alias(self):
"""Test login alias can authenticate by username."""
response = self.client.post(
self.login_url,
{"login": self.user.username, "password": self.password},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn("refresh", response.data)
self.assertIn("access", response.data)
def test_login_invalid_credentials(self):
"""Test login fails with invalid credentials"""
data = self.login_data.copy()
@@ -109,7 +135,7 @@ class LoginViewTest(APITestCase):
def test_login_nonexistent_user(self):
"""Test login fails for nonexistent user"""
data = {
"email": fake.unique.email(),
"username": fake.unique.user_name(),
"password": fake.password(length=12, special_chars=False),
}
@@ -118,6 +144,36 @@ class LoginViewTest(APITestCase):
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
class LogoutViewTest(APITestCase):
"""Tests for LogoutView"""
def setUp(self):
self.user = UserFactory.create_user()
self.logout_url = reverse("api_v1:user:logout")
self.tokens = UserService.get_tokens_for_user(self.user)
self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {self.tokens['access']}")
def test_logout_blacklists_refresh_token(self):
"""Test logout revokes refresh token when blacklist app is enabled."""
refresh = RefreshToken(self.tokens["refresh"])
response = self.client.post(
self.logout_url,
{"refresh": self.tokens["refresh"]},
format="json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(
BlacklistedToken.objects.filter(token__jti=refresh["jti"]).exists()
)
def test_logout_requires_refresh_token(self):
"""Test logout without refresh token fails explicitly."""
response = self.client.post(self.logout_url, {}, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
class CurrentUserViewTest(APITestCase):
"""Tests for CurrentUserView"""
@@ -293,8 +349,7 @@ class TokenRefreshViewTest(APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn("access", response.data)
self.assertIn("refresh", response.data)
# New refresh token should be different
# Refresh token may be the same or different depending on implementation
self.assertNotEqual(response.data["refresh"], self.tokens["refresh"])
def test_refresh_token_invalid(self):
"""Test token refresh fails with invalid refresh token"""