from django.contrib.auth import get_user_model from django.test import TestCase from datetime import date from common.models import Role, Thematic, UserConfig, UserThematics from contracts.models import Company, CompanyTeam, Contract from home.models import HomeWidget, HomeWidgetConditionGroup, HomeWidgetCondition, TeambuildingVote class HomeWidgetConditionTests(TestCase): def setUp(self): User = get_user_model() self.user = User.objects.create_user('testuser', password='pass') self.user_config = UserConfig.objects.create(user=self.user, is_intern=True) self.widget = HomeWidget.objects.create(widget_code='intervention_stats') self.group = HomeWidgetConditionGroup.objects.create( widget=self.widget, label='Test Group', order=1, priority=10 ) # Role self.role_admin, _ = Role.objects.get_or_create(name='admin') self.role_tech, _ = Role.objects.get_or_create(name='technician') # Team self.company = Company.objects.create(name='Test Company') self.team_a = CompanyTeam.objects.create(name='Team A', company=self.company) self.team_b = CompanyTeam.objects.create(name='Team B', company=self.company) # Contract self.contract_a = Contract.objects.create( company=self.company, contract_number='C-001', start_date=date(2026, 1, 1), end_date=date(2026, 12, 31) ) self.contract_b = Contract.objects.create( company=self.company, contract_number='C-002', start_date=date(2026, 1, 1), end_date=date(2026, 12, 31) ) # Thematic self.thematic_a = Thematic.objects.create(code='THEME-A', name_fr='Thema A', name_nl='Thema A') self.thematic_b = Thematic.objects.create(code='THEME-B', name_fr='Thema B', name_nl='Thema B') def test_role_condition_evaluation(self): # 1. Non-negated: User has role -> True self.user_config.roles.add(self.role_admin) cond = HomeWidgetCondition.objects.create( group=self.group, condition_type='role', role=self.role_admin, is_negated=False ) self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) # User does not have role -> False cond.role = self.role_tech cond.save() self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # 2. Negated: User has role -> False cond.role = self.role_admin cond.is_negated = True cond.save() self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # User does not have role -> True cond.role = self.role_tech self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) def test_team_condition_evaluation(self): # 1. Non-negated: User team matches -> True cond = HomeWidgetCondition.objects.create( group=self.group, condition_type='team', team=self.team_a, is_negated=False ) self.assertTrue(cond.evaluate(self.user_config, self.team_a, Contract.objects.none())) # User team does not match -> False self.assertFalse(cond.evaluate(self.user_config, self.team_b, Contract.objects.none())) self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # 2. Negated: User team matches -> False cond.is_negated = True cond.save() self.assertFalse(cond.evaluate(self.user_config, self.team_a, Contract.objects.none())) # User team does not match -> True self.assertTrue(cond.evaluate(self.user_config, self.team_b, Contract.objects.none())) self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) def test_contract_condition_evaluation(self): # 1. Non-negated: User has contract -> True cond = HomeWidgetCondition.objects.create( group=self.group, condition_type='contract', contract=self.contract_a, is_negated=False ) user_contracts = Contract.objects.filter(id=self.contract_a.id) self.assertTrue(cond.evaluate(self.user_config, None, user_contracts)) # User does not have contract -> False other_contracts = Contract.objects.filter(id=self.contract_b.id) self.assertFalse(cond.evaluate(self.user_config, None, other_contracts)) # 2. Negated: User has contract -> False cond.is_negated = True cond.save() self.assertFalse(cond.evaluate(self.user_config, None, user_contracts)) # User does not have contract -> True self.assertTrue(cond.evaluate(self.user_config, None, other_contracts)) def test_thematic_condition_evaluation(self): # 1. Non-negated: User has thematic -> True UserThematics.objects.create(user_config=self.user_config, thematic=self.thematic_a) cond = HomeWidgetCondition.objects.create( group=self.group, condition_type='thematic', thematic=self.thematic_a, is_negated=False ) self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) # User does not have thematic -> False cond.thematic = self.thematic_b cond.save() self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # 2. Negated: User has thematic -> False cond.thematic = self.thematic_a cond.is_negated = True cond.save() self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # User does not have thematic -> True cond.thematic = self.thematic_b self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) def test_is_intern_condition_evaluation(self): # 1. Non-negated: matches -> True cond = HomeWidgetCondition.objects.create( group=self.group, condition_type='is_intern', is_intern=True, is_negated=False ) self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) # Does not match -> False cond.is_intern = False cond.save() self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # 2. Negated: matches -> False cond.is_intern = True cond.is_negated = True cond.save() self.assertFalse(cond.evaluate(self.user_config, None, Contract.objects.none())) # Does not match -> True cond.is_intern = False self.assertTrue(cond.evaluate(self.user_config, None, Contract.objects.none())) def test_condition_summary_and_string_representation(self): cond = HomeWidgetCondition.objects.create( group=self.group, condition_type='role', role=self.role_admin, is_negated=False ) self.assertEqual(str(cond), "Role: admin") self.assertEqual(self.group.get_summary(), "role=admin") cond.is_negated = True cond.save() self.assertEqual(str(cond), "NOT Role: admin") self.assertEqual(self.group.get_summary(), "not(role=admin)") class TeambuildingVoteViewsTests(TestCase): def test_flexi_teambuilding_get(self): # Page should be publicly accessible without logging in response = self.client.get("/flexi-teambuilding/") self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "home/flexi_teambuilding.html") def test_flexi_teambuilding_post(self): # Submit a vote (publicly accessible) response = self.client.post("/flexi-teambuilding/", { "voter_name": "Jean-Luc", "vote_gael": "3", "vote_charly": "2", "vote_tequila": "1", "vote_vivien": "0" }) # Should redirect to results page with success query param self.assertRedirects(response, "/flexi-teambuilding/results/?success=1") # Verify the database entry self.assertEqual(TeambuildingVote.objects.count(), 1) vote = TeambuildingVote.objects.first() self.assertEqual(vote.voter_name, "Jean-Luc") self.assertEqual(vote.vote_gael, 3) self.assertEqual(vote.vote_charly, 2) self.assertEqual(vote.vote_tequila, 1) self.assertEqual(vote.vote_vivien, 0) def test_flexi_teambuilding_results_calculation(self): # Create dummy votes TeambuildingVote.objects.create( voter_name="Alice", vote_gael=3, vote_charly=2, vote_tequila=1, vote_vivien=0 ) TeambuildingVote.objects.create( voter_name="Bob", vote_gael=1, vote_charly=2, vote_tequila=3, vote_vivien=3 ) # Access results page (publicly accessible) response = self.client.get("/flexi-teambuilding/results/") self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "home/flexi_teambuilding_results.html") # Check context averages self.assertEqual(response.context["total_votes"], 2) self.assertEqual(response.context["avg_gael"], 2.0) self.assertEqual(response.context["avg_charly"], 2.0) self.assertEqual(response.context["avg_tequila"], 2.0) self.assertEqual(response.context["avg_vivien"], 1.5) self.assertEqual(response.context["pct_gael"], 66.7) self.assertEqual(response.context["pct_charly"], 66.7) self.assertEqual(response.context["pct_tequila"], 66.7) self.assertEqual(response.context["pct_vivien"], 50.0)