# # Copyright 2023 © AE UTBM # ae@utbm.fr / ae.info@utbm.fr # # This file is part of the website of the UTBM Student Association (AE UTBM), # https://ae.utbm.fr. # # You can find the source code of the website at https://github.com/ae-utbm/sith # # LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3) # SEE : https://raw.githubusercontent.com/ae-utbm/sith/master/LICENSE # OR WITHIN THE LOCAL FILE "LICENSE" # # from datetime import timedelta from django.conf import settings from django.core.cache import cache from django.test import TestCase from django.urls import reverse from django.utils import timezone from django.utils.timezone import localdate, localtime, now from django.utils.translation import gettext as _ from club.forms import MailingForm from club.models import Club, Mailing, Membership from core.baker_recipes import subscriber_user from core.models import AnonymousUser, User from sith.settings import SITH_BAR_MANAGER, SITH_MAIN_CLUB_ID class TestClub(TestCase): """Set up data for test cases related to clubs and membership. The generated dataset is the one created by the populate command, plus the following modifications : - `self.club` is a dummy club recreated for each test - `self.club` has two board members : skia (role 3) and comptable (role 10) - `self.club` has one regular member : richard - `self.club` has one former member : sli (who had role 2) - None of the `self.club` members are in the AE club. """ @classmethod def setUpTestData(cls): # subscribed users - initial members cls.skia = User.objects.get(username="skia") # by default, Skia is in the AE, which creates side effect cls.skia.memberships.all().delete() cls.richard = User.objects.get(username="rbatsbak") cls.comptable = User.objects.get(username="comptable") cls.sli = User.objects.get(username="sli") cls.root = User.objects.get(username="root") # subscribed users - not initial members cls.krophil = User.objects.get(username="krophil") cls.subscriber = User.objects.get(username="subscriber") # old subscriber cls.old_subscriber = User.objects.get(username="old_subscriber") # not subscribed cls.public = User.objects.get(username="public") cls.ae = Club.objects.filter(pk=SITH_MAIN_CLUB_ID)[0] cls.club = Club.objects.create( name="Fake Club", unix_name="fake-club", address="5 rue de la République, 90000 Belfort", ) cls.members_url = reverse("club:club_members", kwargs={"club_id": cls.club.id}) a_month_ago = now() - timedelta(days=30) yesterday = now() - timedelta(days=1) Membership.objects.create( club=cls.club, user=cls.skia, start_date=a_month_ago, role=3 ) Membership.objects.create(club=cls.club, user=cls.richard, role=1) Membership.objects.create( club=cls.club, user=cls.comptable, start_date=a_month_ago, role=10 ) # sli was a member but isn't anymore Membership.objects.create( club=cls.club, user=cls.sli, start_date=a_month_ago, end_date=yesterday, role=2, ) def setUp(self): cache.clear() class TestMembershipQuerySet(TestClub): def test_ongoing(self): """Test that the ongoing queryset method returns the memberships that are not ended. """ current_members = list(self.club.members.ongoing().order_by("id")) expected = [ self.skia.memberships.get(club=self.club), self.comptable.memberships.get(club=self.club), self.richard.memberships.get(club=self.club), ] expected.sort(key=lambda i: i.id) assert current_members == expected def test_ongoing_with_membership_ending_today(self): """Test that a membership ending the present day is considered as ended.""" today = localdate() self.richard.memberships.filter(club=self.club).update(end_date=today) current_members = list(self.club.members.ongoing().order_by("id")) expected = [ self.skia.memberships.get(club=self.club), self.comptable.memberships.get(club=self.club), ] expected.sort(key=lambda i: i.id) assert current_members == expected def test_board(self): """Test that the board queryset method returns the memberships of user in the club board. """ board_members = list(self.club.members.board().order_by("id")) expected = [ self.skia.memberships.get(club=self.club), self.comptable.memberships.get(club=self.club), # sli is no more member, but he was in the board self.sli.memberships.get(club=self.club), ] expected.sort(key=lambda i: i.id) assert board_members == expected def test_ongoing_board(self): """Test that combining ongoing and board returns users who are currently board members of the club. """ members = list(self.club.members.ongoing().board().order_by("id")) expected = [ self.skia.memberships.get(club=self.club), self.comptable.memberships.get(club=self.club), ] expected.sort(key=lambda i: i.id) assert members == expected def test_update_invalidate_cache(self): """Test that the `update` queryset method properly invalidate cache.""" mem_skia = self.skia.memberships.get(club=self.club) cache.set(f"membership_{mem_skia.club_id}_{mem_skia.user_id}", mem_skia) self.skia.memberships.update(end_date=localtime(now()).date()) assert ( cache.get(f"membership_{mem_skia.club_id}_{mem_skia.user_id}") == "not_member" ) mem_richard = self.richard.memberships.get(club=self.club) cache.set( f"membership_{mem_richard.club_id}_{mem_richard.user_id}", mem_richard ) self.richard.memberships.update(role=5) new_mem = self.richard.memberships.get(club=self.club) assert new_mem != "not_member" assert new_mem.role == 5 def test_delete_invalidate_cache(self): """Test that the `delete` queryset properly invalidate cache.""" mem_skia = self.skia.memberships.get(club=self.club) mem_comptable = self.comptable.memberships.get(club=self.club) cache.set(f"membership_{mem_skia.club_id}_{mem_skia.user_id}", mem_skia) cache.set( f"membership_{mem_comptable.club_id}_{mem_comptable.user_id}", mem_comptable ) # should delete the subscriptions of skia and comptable self.club.members.ongoing().board().delete() for membership in (mem_skia, mem_comptable): cached_mem = cache.get( f"membership_{membership.club_id}_{membership.user_id}" ) assert cached_mem == "not_member" class TestClubModel(TestClub): def assert_membership_started_today(self, user: User, role: int): """Assert that the given membership is active and started today.""" membership = user.memberships.ongoing().filter(club=self.club).first() assert membership is not None assert localtime(now()).date() == membership.start_date assert membership.end_date is None assert membership.role == role assert membership.club.get_membership_for(user) == membership member_group = self.club.unix_name + settings.SITH_MEMBER_SUFFIX board_group = self.club.unix_name + settings.SITH_BOARD_SUFFIX assert user.is_in_group(name=member_group) assert user.is_in_group(name=board_group) def assert_membership_ended_today(self, user: User): """Assert that the given user have a membership which ended today.""" today = localtime(now()).date() assert user.memberships.filter(club=self.club, end_date=today).exists() assert self.club.get_membership_for(user) is None def test_access_unauthorized(self): """Test that users who never subscribed and anonymous users cannot see the page. """ response = self.client.post(self.members_url) assert response.status_code == 403 self.client.force_login(self.public) response = self.client.post(self.members_url) assert response.status_code == 403 def test_display(self): """Test that a GET request return a page where the requested information are displayed. """ self.client.force_login(self.skia) response = self.client.get(self.members_url) assert response.status_code == 200 expected_html = ( "" "" "" "" ) memberships = self.club.members.ongoing().order_by("-role") input_id = 0 for membership in memberships.select_related("user"): user = membership.user expected_html += ( f"" f"" f"" f"" expected_html += "
UtilisateurRôleDescriptionDepuisMarquer comme ancien
" f"{user.get_display_name()}{settings.SITH_CLUB_ROLES[membership.role]}{membership.description}{membership.start_date}" ) if membership.role <= 3: # 3 is the role of skia expected_html += ( '' ) input_id += 1 expected_html += "
" self.assertInHTML(expected_html, response.content.decode()) def test_root_add_one_club_member(self): """Test that root users can add members to clubs, one at a time.""" self.client.force_login(self.root) response = self.client.post( self.members_url, {"users": [self.subscriber.id], "role": 3}, ) self.assertRedirects(response, self.members_url) self.subscriber.refresh_from_db() self.assert_membership_started_today(self.subscriber, role=3) def test_root_add_multiple_club_member(self): """Test that root users can add multiple members at once to clubs.""" self.client.force_login(self.root) response = self.client.post( self.members_url, { "users": (self.subscriber.id, self.krophil.id), "role": 3, }, ) self.assertRedirects(response, self.members_url) self.subscriber.refresh_from_db() self.assert_membership_started_today(self.subscriber, role=3) self.assert_membership_started_today(self.krophil, role=3) def test_add_unauthorized_members(self): """Test that users who are not currently subscribed cannot be members of clubs. """ self.client.force_login(self.root) response = self.client.post( self.members_url, {"users": self.public.id, "role": 1}, ) assert not self.public.memberships.filter(club=self.club).exists() assert '