mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 09:12:11 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			329 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
 | 
						|
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
						|
 | 
						|
import os
 | 
						|
 | 
						|
from api.tests import TestAPI
 | 
						|
from django.contrib.auth.models import User
 | 
						|
from django.core.files.uploadedfile import SimpleUploadedFile
 | 
						|
from django.test import TestCase
 | 
						|
from rest_framework.test import APITestCase
 | 
						|
from django.urls import reverse
 | 
						|
from django.utils import timezone
 | 
						|
 | 
						|
from ..api.views import FamilyViewSet, FamilyMembershipViewSet, ChallengeViewSet, AchievementViewSet
 | 
						|
from ..models import Family, FamilyMembership, Challenge, Achievement
 | 
						|
 | 
						|
 | 
						|
class TestFamily(TestCase):
 | 
						|
    """
 | 
						|
    Test family
 | 
						|
    """
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        self.user = User.objects.create_superuser(
 | 
						|
            username='admintoto',
 | 
						|
            password='toto1234',
 | 
						|
            email='toto@example.com',
 | 
						|
        )
 | 
						|
        self.client.force_login(self.user)
 | 
						|
 | 
						|
        sess = self.client.session
 | 
						|
        sess['permission_mask'] = 42
 | 
						|
        sess.save()
 | 
						|
 | 
						|
        self.family = Family.objects.create(
 | 
						|
            name='Test family',
 | 
						|
            description='',
 | 
						|
        )
 | 
						|
 | 
						|
        self.challenge = Challenge.objects.create(
 | 
						|
            name='Test challenge',
 | 
						|
            description='',
 | 
						|
            points=100,
 | 
						|
        )
 | 
						|
 | 
						|
        self.achievement = Achievement.objects.create(
 | 
						|
            family=self.family,
 | 
						|
            challenge=self.challenge,
 | 
						|
            valid=False,
 | 
						|
        )
 | 
						|
 | 
						|
    def test_family_list(self):
 | 
						|
        """
 | 
						|
        Test display family list
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:family_list"))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
    def test_family_create(self):
 | 
						|
        """
 | 
						|
        Test create a family
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:family_create"))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        response = self.client.post(reverse("family:family_create"), data={
 | 
						|
            "name": "Family toto",
 | 
						|
            "description": "A test family",
 | 
						|
        })
 | 
						|
        self.assertTrue(Family.objects.filter(name="Family toto").exists())
 | 
						|
        self.assertRedirects(response, reverse("family:manage"), 302, 200)
 | 
						|
 | 
						|
    def test_family_detail(self):
 | 
						|
        """
 | 
						|
        Test display the detail of a family
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:family_detail", args=(self.family.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
    def test_family_update(self):
 | 
						|
        """
 | 
						|
        Test update a family
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:family_update", args=(self.family.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        response = self.client.post(reverse("family:family_update", args=(self.family.pk,)), data=dict(
 | 
						|
            name="Toto family updated",
 | 
						|
            description="A larger description for the test family"
 | 
						|
        ))
 | 
						|
        self.assertRedirects(response, self.family.get_absolute_url(), 302, 200)
 | 
						|
        self.assertTrue(Family.objects.filter(name="Toto family updated").exists())
 | 
						|
 | 
						|
    def test_family_update_picture(self):
 | 
						|
        """
 | 
						|
        Test update the picture of a family
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:update_pic", args=(self.family.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        old_pic = self.family.display_image
 | 
						|
 | 
						|
        with open("apps/family/static/family/img/default_picture.png", "rb") as f:
 | 
						|
            image = SimpleUploadedFile("image.png", f.read(), "image/png")
 | 
						|
            response = self.client.post(reverse("family:update_pic", args=(self.family.pk,)), dict(
 | 
						|
                image=image,
 | 
						|
                x=0,
 | 
						|
                y=0,
 | 
						|
                width=200,
 | 
						|
                height=200,
 | 
						|
            ))
 | 
						|
            self.assertRedirects(response, self.family.get_absolute_url(), 302, 200)
 | 
						|
 | 
						|
        self.family.refresh_from_db()
 | 
						|
        self.assertTrue(os.path.exists(self.family.display_image.path))
 | 
						|
        os.remove(self.family.display_image.path)
 | 
						|
 | 
						|
        self.family.display_image = old_pic
 | 
						|
        self.family.save()
 | 
						|
 | 
						|
    def test_family_add_member(self):
 | 
						|
        """
 | 
						|
        Test add memberships to a family
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:family_add_member", args=(self.family.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        user = User.objects.create(username="totototo")
 | 
						|
        user.profile.registration_valid = True
 | 
						|
        user.profile.email_confirmed = True
 | 
						|
        user.profile.save()
 | 
						|
        user.save()
 | 
						|
 | 
						|
        response = self.client.post(reverse("family:family_add_member", args=(self.family.pk,)), data=dict(
 | 
						|
            user=user.pk,
 | 
						|
        ))
 | 
						|
        self.assertRedirects(response, self.family.get_absolute_url(), 302, 200)
 | 
						|
 | 
						|
        self.assertTrue(FamilyMembership.objects.filter(user=user, family=self.family, year=timezone.now().year).exists())
 | 
						|
 | 
						|
    def test_challenge_list(self):
 | 
						|
        """
 | 
						|
        Test display challenge list
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse('family:challenge_list'))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
    def test_challenge_create(self):
 | 
						|
        """
 | 
						|
        Test create a challenge
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:challenge_create"))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        response = self.client.post(reverse("family:challenge_create"), data={
 | 
						|
            "name": "Challenge for toto",
 | 
						|
            "description": "A test challenge",
 | 
						|
            "points": 50,
 | 
						|
        })
 | 
						|
        self.assertTrue(Challenge.objects.filter(name="Challenge for toto").exists())
 | 
						|
        self.assertRedirects(response, reverse("family:manage"), 302, 200)
 | 
						|
 | 
						|
    def test_challenge_detail(self):
 | 
						|
        """
 | 
						|
        Test display the detail of a challenge
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:challenge_detail", args=(self.challenge.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
    def test_challenge_update(self):
 | 
						|
        """
 | 
						|
        Test update a challenge
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:challenge_update", args=(self.challenge.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        response = self.client.post(reverse("family:challenge_update", args=(self.challenge.pk,)), data=dict(
 | 
						|
            name="Challenge updated",
 | 
						|
            description="Another description",
 | 
						|
            points=10,
 | 
						|
        ))
 | 
						|
        self.assertRedirects(response, self.challenge.get_absolute_url(), 302, 200)
 | 
						|
        self.assertTrue(Challenge.objects.filter(name="Challenge updated").exists())
 | 
						|
 | 
						|
    def test_render_manage_page(self):
 | 
						|
        """
 | 
						|
        Test render manage page
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:manage"))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
    def test_validate_achievement(self):
 | 
						|
        """
 | 
						|
        Test validate an achievement
 | 
						|
        """
 | 
						|
        old_family_score = self.family.score
 | 
						|
 | 
						|
        response = self.client.get(reverse("family:achievement_validate", args=(self.achievement.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        response = self.client.post(reverse("family:achievement_validate", args=(self.achievement.pk,)))
 | 
						|
        self.assertRedirects(response, reverse("family:achievement_list"), 302, 200)
 | 
						|
 | 
						|
        self.achievement.refresh_from_db()
 | 
						|
        self.assertIs(self.achievement.valid, True)
 | 
						|
 | 
						|
        self.family.refresh_from_db()
 | 
						|
        self.assertEqual(self.family.score, old_family_score + self.achievement.challenge.points)
 | 
						|
 | 
						|
    def test_delete_achievement(self):
 | 
						|
        """
 | 
						|
        Test delete an achievement
 | 
						|
        """
 | 
						|
        response = self.client.get(reverse("family:achievement_delete", args=(self.achievement.pk,)))
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        response = self.client.delete(reverse("family:achievement_delete", args=(self.achievement.pk,)))
 | 
						|
        self.assertRedirects(response, reverse("family:achievement_list"), 302, 200)
 | 
						|
        self.assertFalse(Achievement.objects.filter(pk=self.achievement.pk).exists())
 | 
						|
 | 
						|
 | 
						|
class TestBatchAchievements(APITestCase):
 | 
						|
    def setUp(self):
 | 
						|
        self.user = User.objects.create_superuser(
 | 
						|
            username='admintoto',
 | 
						|
            password='toto1234',
 | 
						|
            email='toto@example.com',
 | 
						|
        )
 | 
						|
        self.client.force_login(self.user)
 | 
						|
 | 
						|
        sess = self.client.session
 | 
						|
        sess['permission_mask'] = 42
 | 
						|
        sess.save()
 | 
						|
 | 
						|
        self.families = [
 | 
						|
            Family.objects.create(name=f'Famille {i}', description='') for i in range(2)
 | 
						|
        ]
 | 
						|
        self.challenges = [
 | 
						|
            Challenge.objects.create(name=f'Challenge {i}', description='', points=50) for i in range(3)
 | 
						|
        ]
 | 
						|
 | 
						|
        self.achievement = Achievement.objects.create(
 | 
						|
            family=self.families[0],
 | 
						|
            challenge=self.challenges[0],
 | 
						|
            valid=False,
 | 
						|
        )
 | 
						|
 | 
						|
        self.url = reverse("family:api:batch_achievements")
 | 
						|
 | 
						|
    def test_batch_achievement_creation(self):
 | 
						|
        family_ids = [f.id for f in self.families]
 | 
						|
        challenge_ids = [c.id for c in self.challenges]
 | 
						|
        response = self.client.post(
 | 
						|
            self.url,
 | 
						|
            data={
 | 
						|
                'families': family_ids,
 | 
						|
                'challenges': challenge_ids
 | 
						|
            },
 | 
						|
            format='json'
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(response.status_code, 201)
 | 
						|
        for result in response.data['results']:
 | 
						|
            if result['family'] == self.families[0].name and result['challenge'] == self.challenges[0].name:
 | 
						|
                self.assertEqual(result['status'], 'existed')
 | 
						|
            else:
 | 
						|
                self.assertEqual(result['status'], 'created')
 | 
						|
 | 
						|
        expected_count = len(family_ids) * len(challenge_ids)
 | 
						|
        self.assertEqual(Achievement.objects.count(), expected_count)
 | 
						|
 | 
						|
        # Check that correct couples family/challenge exist
 | 
						|
        for f in self.families:
 | 
						|
            for c in self.challenges:
 | 
						|
                self.assertTrue(
 | 
						|
                    Achievement.objects.filter(family=f, challenge=c).exists()
 | 
						|
                )
 | 
						|
 | 
						|
 | 
						|
class TestFamilyAPI(TestAPI):
 | 
						|
    def setUp(self):
 | 
						|
        super().setUp()
 | 
						|
 | 
						|
        self.family = Family.objects.create(
 | 
						|
            name='Test family',
 | 
						|
            description='',
 | 
						|
        )
 | 
						|
 | 
						|
        self.familymembership = FamilyMembership.objects.create(
 | 
						|
            user=self.user,
 | 
						|
            family=self.family,
 | 
						|
        )
 | 
						|
 | 
						|
        self.challenge = Challenge.objects.create(
 | 
						|
            name='Test challenge',
 | 
						|
            description='',
 | 
						|
            points=100,
 | 
						|
        )
 | 
						|
 | 
						|
        self.achievement = Achievement.objects.create(
 | 
						|
            family=self.family,
 | 
						|
            challenge=self.challenge,
 | 
						|
            valid=False,
 | 
						|
        )
 | 
						|
 | 
						|
    def test_family_api(self):
 | 
						|
        """
 | 
						|
        Load Family API page and test all filters and permissions
 | 
						|
        """
 | 
						|
        self.check_viewset(FamilyViewSet, '/api/family/family/')
 | 
						|
 | 
						|
    def test_familymembership_api(self):
 | 
						|
        """
 | 
						|
        Load FamilyMembership API page and test all filters and permissions
 | 
						|
        """
 | 
						|
        self.check_viewset(FamilyMembershipViewSet, '/api/family/familymembership/')
 | 
						|
 | 
						|
    def test_challenge_api(self):
 | 
						|
        """
 | 
						|
        Load Challenge API page and test all filters and permissions
 | 
						|
        """
 | 
						|
        self.check_viewset(ChallengeViewSet, '/api/family/challenge/')
 | 
						|
 | 
						|
    def test_achievement_api(self):
 | 
						|
        """
 | 
						|
        Load Achievement API page and test all filters and permissions
 | 
						|
        """
 | 
						|
        self.check_viewset(AchievementViewSet, '/api/family/achievement/')
 |