from django.test import TestCase from rest_framework.test import APIClient from .models import ContactMessage, Resource class PublicApiTests(TestCase): def setUp(self): self.client = APIClient() def test_resources_are_public_and_only_published(self): Resource.objects.create(title='Test caché', category='bph', url='https://example.com/doc', published=False) response = self.client.get('/api/education/resources/') self.assertEqual(response.status_code, 200) self.assertNotIn('Test caché', str(response.data)) def test_contact_requires_consent(self): payload = {'name': 'Alice', 'email': 'alice@example.com', 'message': 'Bonjour', 'accepted_privacy': False} response = self.client.post('/api/education/contact/', payload) self.assertEqual(response.status_code, 400) self.assertFalse(ContactMessage.objects.exists()) def test_contact_saves_message(self): payload = {'name': 'Alice', 'email': 'alice@example.com', 'message': 'Bonjour', 'accepted_privacy': True} response = self.client.post('/api/education/contact/', payload) self.assertEqual(response.status_code, 201) self.assertEqual(ContactMessage.objects.count(), 1) def test_honeypot_blocks_automated_messages(self): payload = {'name': 'Bot', 'email': 'bot@example.com', 'message': 'spam', 'accepted_privacy': True, 'website': 'https://spam.example'} self.assertEqual(self.client.post('/api/education/contact/', payload).status_code, 400) class SiteEditorTests(TestCase): def setUp(self): from django.contrib.auth import get_user_model from rest_framework.test import APIClient self.client = APIClient() User = get_user_model() self.admin_user = User.objects.create_superuser(username='editor', email='editor@example.com', password='a-safe-password!') self.normal_user = User.objects.create_user(username='visitor', password='a-safe-password!') def login_admin(self): response = self.client.post('/api/education/editor/login/', {'username': 'editor', 'password': 'a-safe-password!'}) self.assertEqual(response.status_code, 200) self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {response.data["access"]}') def test_only_staff_can_log_in(self): response = self.client.post('/api/education/editor/login/', {'username': 'visitor', 'password': 'a-safe-password!'}) self.assertEqual(response.status_code, 401) def test_public_can_read_but_not_edit_content(self): from .models import SiteContent SiteContent.objects.create(key='home.hero.title.first', value='Bonjour') response = self.client.get('/api/education/site-content/') self.assertEqual(response.status_code, 200) self.assertEqual(response.data['home.hero.title.first'], 'Bonjour') response = self.client.put('/api/education/site-content/home.hero.title.first/', {'value': 'Interdit'}, format='json') self.assertIn(response.status_code, (401, 403)) def test_admin_can_edit_and_restore_content(self): self.login_admin() key = 'home.hero.title.first' response = self.client.put(f'/api/education/site-content/{key}/', {'value': 'Nouveau titre'}, format='json') self.assertEqual(response.status_code, 200) self.assertEqual(self.client.get('/api/education/site-content/').data[key], 'Nouveau titre') response = self.client.delete(f'/api/education/site-content/{key}/') self.assertEqual(response.status_code, 204) self.assertNotIn(key, self.client.get('/api/education/site-content/').data) def test_link_validator_rejects_scripts(self): self.login_admin() response = self.client.put('/api/education/site-content/home.contact.href/', {'value': 'javascript:alert(1)'}, format='json') self.assertEqual(response.status_code, 400) def test_resources_admin_crud(self): self.login_admin() payload = {'title': 'Fiche biologie', 'description': 'Révision', 'category': 'bph', 'kind': 'pdf', 'url': 'https://example.com/fiche.pdf', 'published': True, 'position': 0} created = self.client.post('/api/education/editor/data/resources/', payload, format='json') self.assertEqual(created.status_code, 201) changed = self.client.patch(f'/api/education/editor/data/resources/{created.data["id"]}/', {'published': False}, format='json') self.assertEqual(changed.status_code, 200) self.assertFalse(changed.data['published'])