feat: add parser source dashboard and scheduling
Some checks failed
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 10m20s
CI/CD Pipeline / Run Tests (pull_request) Failing after 11m5s
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 7879d54958
95 changed files with 15004 additions and 259 deletions

View File

@@ -191,7 +191,7 @@ class LoginSerializerTest(TestCase):
def setUp(self):
self.login_data = {
"email": fake.email(),
"username": fake.user_name(),
"password": fake.password(length=12, special_chars=False),
}
@@ -200,16 +200,36 @@ class LoginSerializerTest(TestCase):
serializer = LoginSerializer(data=self.login_data)
self.assertTrue(serializer.is_valid())
def test_missing_email(self):
"""Test validation fails without email"""
def test_email_login_data_is_still_supported(self):
"""Test legacy email login payload is still valid."""
serializer = LoginSerializer(
data={
"email": fake.email(),
"password": fake.password(length=12, special_chars=False),
}
)
self.assertTrue(serializer.is_valid())
def test_login_alias_is_supported(self):
"""Test login alias can be used instead of username."""
serializer = LoginSerializer(
data={
"login": fake.user_name(),
"password": fake.password(length=12, special_chars=False),
}
)
self.assertTrue(serializer.is_valid())
def test_missing_identity(self):
"""Test validation fails without username, login or email."""
data = {"password": fake.password(length=12, special_chars=False)}
serializer = LoginSerializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertIn("email", serializer.errors)
self.assertIn("username", serializer.errors)
def test_missing_password(self):
"""Test validation fails without password"""
data = {"email": fake.email()}
data = {"username": fake.user_name()}
serializer = LoginSerializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertIn("password", serializer.errors)

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"""