269 lines
11 KiB
Python
269 lines
11 KiB
Python
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)
|
|
|
|
|
|
class HomeIndexViewTests(TestCase):
|
|
def test_home_index_inspector_link(self):
|
|
from django.urls import reverse
|
|
from django.contrib.auth import get_user_model
|
|
from common.models import Role, UserConfig
|
|
User = get_user_model()
|
|
user = User.objects.create_user('inspector_user', password='pass')
|
|
user_config = UserConfig.objects.create(user=user)
|
|
inspector_role, _ = Role.objects.get_or_create(name='inspector')
|
|
user_config.roles.add(inspector_role)
|
|
self.client.force_login(user)
|
|
|
|
response = self.client.get(reverse('home:index'))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, reverse('inspections:quick_inspection_map'))
|
|
self.assertNotContains(response, 'data-bs-target="#newInspectionModal"')
|
|
|