loko/streetup/interventions/tests/test_mobile_api.py
2026-07-22 14:48:40 +02:00

157 lines
6 KiB
Python

import json
from datetime import timedelta
from unittest import mock
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.contrib import messages
from django.contrib.messages import get_messages
from django.core.files.uploadedfile import SimpleUploadedFile
from common.models import UserConfig, Role, Thematic, UserThematics
from contracts.models import Company, CompanyTeam, CompanyMember, Contract, ContractPost, ContractOrder, ContractOrderQuote, ContractOrderQuoteItem
from assets.models import AssetCategory
from interventions.models import (
Intervention,
InterventionContractPost,
InterventionPlanificationTimeLine,
InterventionRealizationTimeLine,
Operation,
InterventionAsset,
OperationTemplate,
OperationTemplateItem,
OperationStatusSet,
OperationStatus,
STATUS_ORDERS,
InterventionDocument,
)
from django.contrib.contenttypes.models import ContentType
from interventions.views import _group_operations_by_asset_and_template, _create_equipment_operations_for_assets
from interventions.permissions import can_manage_occupations, can_delete_document
from django.urls import reverse
from django.utils import timezone
from decimal import Decimal
class MobileInterventionAssetsApiTests(TestCase):
def setUp(self):
self.User = get_user_model()
self.user = self.User.objects.create_user(username='mobile-admin', password='pwd')
self.role_admin = Role.objects.create(name='admin')
self.user_config = UserConfig.objects.create(user=self.user, is_intern=True)
self.user_config.roles.add(self.role_admin)
self.thematic = Thematic.objects.create(code='road', name_fr='Route', name_nl='Weg')
self.category = AssetCategory.objects.create(
code='CAT1',
name_fr='Catégorie 1',
name_nl='Categorie 1',
thematic=self.thematic,
)
self.intervention = Intervention.objects.create(
title='Mobile assets',
status='to_be_processed',
thematic=self.thematic,
)
self.filters_url = reverse('interventions:mobile_intervention_assets_filters', args=[self.intervention.id])
self.search_url = reverse('interventions:mobile_intervention_assets_search', args=[self.intervention.id])
self.sync_url = reverse('interventions:mobile_intervention_assets_sync', args=[self.intervention.id])
self.client.login(username='mobile-admin', password='pwd')
def test_filters_endpoint_returns_categories(self):
with mock.patch('interventions.views._get_asset_model_classes', return_value=[]):
response = self.client.get(self.filters_url)
self.assertEqual(response.status_code, 200)
payload = response.json()
self.assertTrue(payload.get('success'))
self.assertEqual(len(payload.get('categories', [])), 1)
self.assertEqual(payload['categories'][0]['id'], self.category.id)
def test_search_endpoint_wraps_helper(self):
fake_results = {
'assets': [],
'match_count': 0,
'has_more': False,
'requires_category': False,
'has_locations': False,
}
with mock.patch('interventions.views._search_mobile_assets', return_value=fake_results) as mocked:
response = self.client.get(self.search_url, {'q': 'lamp'})
self.assertEqual(response.status_code, 200)
self.assertTrue(response.json().get('success'))
self.assertEqual(response.json().get('results'), fake_results)
mocked.assert_called_once()
def test_sync_endpoint_returns_stats(self):
stats = {
'created': 1,
'deleted': 0,
'operations_created': 0,
'operations_deleted': 0,
'assets_with_values': 0,
'target_total': 1,
'requested_assets': 1,
}
with mock.patch('interventions.views._sync_intervention_assets_data', return_value=stats) as mocked:
response = self.client.post(
self.sync_url,
data=json.dumps({'assets': [{'model': 'signstreet', 'object_id': 42}]}),
content_type='application/json',
)
self.assertEqual(response.status_code, 200)
payload = response.json()
self.assertTrue(payload.get('success'))
self.assertEqual(payload.get('stats'), stats)
mocked.assert_called_once()
class MobileInterventionPauseTests(TestCase):
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(username='mobileuser', password='pwd')
# Give admin role to bypass permissions
self.role_admin = Role.objects.create(name='admin')
self.user_config = UserConfig.objects.create(user=self.user, is_intern=True)
self.user_config.roles.add(self.role_admin)
# Create an intervention in progress
self.intervention = Intervention.objects.create(title='Mobile Pause', status='in_progress')
# Optional: link a company member to the user
self.company = Company.objects.create(name='MobileCo')
self.team = CompanyTeam.objects.create(name='Team M', company=self.company)
self.member = CompanyMember.objects.create(user=self.user, name='Mobile User')
self.member.teams.add(self.team)
def test_pause_reason_is_persisted_from_mobile_detail(self):
self.client.login(username='mobileuser', password='pwd')
url = reverse('mobile:intervention_detail_mobile', args=[self.intervention.id])
resp = self.client.post(url, {
'status_action': 'pause',
'pause_reason': 'other',
'pause_reason_other': 'Pluie abondante',
})
# Redirect back to detail
self.assertEqual(resp.status_code, 302)
# Verify persisted values
self.intervention.refresh_from_db()
self.assertEqual(self.intervention.status, 'on_pause')
self.assertEqual(self.intervention.pause_reason, 'other')
self.assertEqual(self.intervention.pause_reason_other, 'Pluie abondante')