278 lines
11 KiB
Python
278 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
|
|
|
|
|
|
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 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"')
|
|
|
|
def test_home_index_unread_notifications_banner(self):
|
|
from django.urls import reverse
|
|
from django.contrib.auth import get_user_model
|
|
from common.models import UserConfig
|
|
from notifications.models import Notification, NotificationRecipient
|
|
|
|
User = get_user_model()
|
|
user = User.objects.create_user('notif_user', password='pass')
|
|
UserConfig.objects.create(user=user)
|
|
self.client.force_login(user)
|
|
|
|
# 1. No unread notifications -> banner not shown
|
|
response = self.client.get(reverse('home:index'))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertNotContains(response, 'id="home-unread-notifications-alert"')
|
|
|
|
# 2. Add unread notification -> banner shown with count
|
|
notif = Notification.objects.create(title="Test notification")
|
|
NotificationRecipient.objects.create(notification=notif, user=user)
|
|
|
|
response = self.client.get(reverse('home:index'))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, 'id="home-unread-notifications-alert"')
|
|
self.assertContains(response, 'Vous avez <strong class="home-unread-notifications-count">1</strong> notification non lue.')
|
|
|
|
def test_home_index_intervention_on_pause_widget(self):
|
|
from django.urls import reverse
|
|
from django.contrib.auth import get_user_model
|
|
from common.models import UserConfig
|
|
from home.models import HomeWidget
|
|
|
|
User = get_user_model()
|
|
user = User.objects.create_user('pause_widget_user', password='pass')
|
|
UserConfig.objects.create(user=user)
|
|
self.client.force_login(user)
|
|
|
|
# Create the widget
|
|
HomeWidget.objects.create(widget_code='intervention_on_pause')
|
|
|
|
response = self.client.get(reverse('home:index'), HTTP_ACCEPT_LANGUAGE='fr')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, 'Interventions en pause')
|
|
self.assertContains(response, 'status=on_pause')
|
|
|
|
|
|
class HomeWidgetAdminTests(TestCase):
|
|
def setUp(self):
|
|
from django.contrib.admin.sites import AdminSite
|
|
from home.admin import HomeWidgetAdmin
|
|
self.site = AdminSite()
|
|
self.admin = HomeWidgetAdmin(HomeWidget, self.site)
|
|
self.widget = HomeWidget.objects.create(widget_code='intervention_stats')
|
|
|
|
def test_conditions_overview_no_groups(self):
|
|
html = self.admin.conditions_overview(self.widget)
|
|
self.assertIn('Aucun groupe — visible pour tous', html)
|
|
|
|
def test_conditions_overview_with_groups(self):
|
|
group = HomeWidgetConditionGroup.objects.create(
|
|
widget=self.widget,
|
|
label='Group 1',
|
|
order=1,
|
|
priority=1
|
|
)
|
|
html = self.admin.conditions_overview(self.widget)
|
|
self.assertIn('Group 1', html)
|
|
|
|
|
|
|
|
|