240 lines
12 KiB
Python
240 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from odoo.tests import common
|
|
from odoo.exceptions import ValidationError
|
|
import unittest.mock as mock
|
|
import json
|
|
import tempfile
|
|
import base64
|
|
import os
|
|
|
|
class TestUnifiSiteController(common.TransactionCase):
|
|
"""Tests pour le modèle unifi.site.controller
|
|
|
|
Cette classe de test vérifie le bon fonctionnement des méthodes API
|
|
du modèle unifi.site.controller, y compris la gestion des certificats auto-signés.
|
|
"""
|
|
|
|
def setUp(self):
|
|
"""Configuration initiale pour les tests
|
|
|
|
Crée un site de test avec une configuration de contrôleur.
|
|
"""
|
|
super(TestUnifiSiteController, self).setUp()
|
|
|
|
# Créer un site de test
|
|
self.test_site = self.env['unifi.site'].create({
|
|
'name': 'Site de Test',
|
|
'description': 'Site de test pour les tests unitaires',
|
|
'api_type': 'controller'
|
|
})
|
|
|
|
# Créer une configuration de contrôleur pour le site
|
|
self.test_controller = self.env['unifi.site.controller'].create({
|
|
'site_id': self.test_site.id,
|
|
'host': 'test.example.com',
|
|
'port': 443,
|
|
'username': 'testuser',
|
|
'password': 'testpassword',
|
|
'verify_ssl': True,
|
|
'controller_type': 'udm'
|
|
})
|
|
|
|
def test_check_required_fields(self):
|
|
"""Teste la validation des champs requis
|
|
|
|
Vérifie que la méthode _check_required_fields lève une exception
|
|
si les champs requis ne sont pas renseignés.
|
|
"""
|
|
# Créer un site sans les champs requis
|
|
site_without_fields = self.env['unifi.site'].create({
|
|
'name': 'Site sans champs',
|
|
'description': 'Site sans les champs requis',
|
|
'api_type': 'controller'
|
|
})
|
|
|
|
# Vérifier que la méthode lève une exception
|
|
with self.assertRaises(ValidationError):
|
|
self.env['unifi.site.controller']._check_required_fields(site_without_fields)
|
|
|
|
@mock.patch('odoo.addons.unifi_integration.models.unifi_site_controller.requests.Session')
|
|
def test_authenticate_success(self, mock_session):
|
|
"""Teste l'authentification réussie
|
|
|
|
Vérifie que la méthode _authenticate fonctionne correctement
|
|
lorsque l'authentification réussit.
|
|
"""
|
|
# Configurer le mock pour simuler une réponse réussie
|
|
mock_response = mock.MagicMock()
|
|
mock_response.status_code = 200
|
|
mock_response.headers = {'X-CSRF-Token': 'test-csrf-token'}
|
|
mock_response.text = json.dumps({'meta': {'rc': 'ok'}})
|
|
|
|
mock_session_instance = mock_session.return_value
|
|
mock_session_instance.post.return_value = mock_response
|
|
mock_session_instance.cookies.items.return_value = [('cookie1', 'value1')]
|
|
|
|
# Appeler la méthode _authenticate
|
|
result = self.test_controller._authenticate()
|
|
|
|
# Vérifier que l'authentification a réussi
|
|
self.assertTrue(result)
|
|
self.assertEqual(self.test_controller.csrf_token, 'test-csrf-token')
|
|
self.assertEqual(json.loads(self.test_controller.session_cookies), {'cookie1': 'value1'})
|
|
|
|
@mock.patch('odoo.addons.unifi_integration.models.unifi_site_controller.requests.Session')
|
|
def test_authenticate_failure(self, mock_session):
|
|
"""Teste l'échec d'authentification
|
|
|
|
Vérifie que la méthode _authenticate gère correctement
|
|
les échecs d'authentification.
|
|
"""
|
|
# Configurer le mock pour simuler une réponse d'échec
|
|
mock_response = mock.MagicMock()
|
|
mock_response.status_code = 401
|
|
mock_response.text = json.dumps({'meta': {'rc': 'error', 'msg': 'Invalid credentials'}})
|
|
|
|
mock_session_instance = mock_session.return_value
|
|
mock_session_instance.post.return_value = mock_response
|
|
|
|
# Appeler la méthode _authenticate
|
|
result = self.test_controller._authenticate()
|
|
|
|
# Vérifier que l'authentification a échoué
|
|
self.assertFalse(result)
|
|
|
|
@mock.patch('odoo.addons.unifi_integration.models.unifi_site_controller.requests.Session')
|
|
def test_make_request_success(self, mock_session):
|
|
"""Teste une requête API réussie
|
|
|
|
Vérifie que la méthode _make_request fonctionne correctement
|
|
lorsque la requête réussit.
|
|
"""
|
|
# Configurer le test_controller avec des cookies de session
|
|
self.test_controller.session_cookies = json.dumps({'cookie1': 'value1'})
|
|
self.test_controller.csrf_token = 'test-csrf-token'
|
|
|
|
# Configurer le mock pour simuler une réponse réussie
|
|
mock_response = mock.MagicMock()
|
|
mock_response.status_code = 200
|
|
mock_response.text = json.dumps({'data': [{'id': 1, 'name': 'test'}]})
|
|
mock_response.json.return_value = {'data': [{'id': 1, 'name': 'test'}]}
|
|
|
|
mock_session_instance = mock_session.return_value
|
|
mock_session_instance.get.return_value = mock_response
|
|
|
|
# Appeler la méthode _make_request
|
|
success, data, status_code = self.test_controller._make_request('GET', 'devices', 'default')
|
|
|
|
# Vérifier que la requête a réussi
|
|
self.assertTrue(success)
|
|
self.assertEqual(status_code, 200)
|
|
self.assertEqual(data, {'data': [{'id': 1, 'name': 'test'}]})
|
|
|
|
@mock.patch('odoo.addons.unifi_integration.models.unifi_site_controller.requests.Session')
|
|
def test_make_request_with_custom_cert(self, mock_session):
|
|
"""Teste une requête API avec un certificat personnalisé
|
|
|
|
Vérifie que la méthode _make_request utilise correctement
|
|
un certificat SSL personnalisé lorsqu'il est fourni.
|
|
"""
|
|
# Créer un certificat de test
|
|
cert_content = b"-----BEGIN CERTIFICATE-----\nMIIDazCCAlOgAwIBAgIUJlq+zz4DP9fxg3LB9BQl0haIFr4wDQYJKoZIhvcNAQEL\nBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAzMjMxODUwMzJaFw0yNDAz\nMjIxODUwMzJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw\nHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB\nAQUAA4IBDwAwggEKAoIBAQDK4+VKWLJ5Qhytr5GE7XNd4YQlpbgpyFjxfOiLYWdY\ntZNptYfs1VSQgDlzqJsgLDEAeRBDJSPO5xiwURKPezCCfCjMgr9MWOGgP/OLiW9j\nLJQVYdJnw+HhTMFmcOmzSi0OjCHkZhBjHuUwgXhCbV/1sCQV1BiDmGYo5rYRnxPW\nVxgp2Pc+ABwCzTz3jLxozfeY3C9c0qiPgbYG+qFzidkBUqTpFIDi+iYMR3WfvCJt\nV/gYYKzQUi+tmjVtRIpIm5UIxYGK3xMwDVYCPKKQYHDvN9SXt+hopVzQhHkIEL4a\nXMKiBaCTjBQnY3rAJbwVjh9nVdCCIL3JMzwGn+7rAgMBAAGjUzBRMB0GA1UdDgQW\nBBRXLpff0CDtLkoBFyVWyZGJ5HBsNjAfBgNVHSMEGDAWgBRXLpff0CDtLkoBFyVW\nyZGJ5HBsNjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQC6p0Ay\nTNfJXoKlZ8KQHj9/j8ZJnMZ5LXxU6TzZeHNGJFrCCKZYh+iUWLkV5x9JxQo6npzH\nHJ94JI6HoJb8IWVe1xwNfv8D6mYky0WFcBsAVV3Bq2JZpGsXHT5lUv3/1+8qdEFP\nNWR9QUL+UhpK4p9bHKX3h8qEQGIO1t5EJVTNiZEVWQrJY9zLG6MjBwL0TBQ3nFvv\n4C5Ctw+8jnrTp6qdGFHlKLbBV5KXQtgbQx9nPgLlHVEYjSKQoWsJLfD9MaHAIUKW\nGGRGY3iUzQs8yiHBRDX9xyf+Jg75KnCi9FVkrF/JOxzZKGGV8Qn3/Yja+uLMnwKE\nRs8XuQwXQFYkKLvL\n-----END CERTIFICATE-----"
|
|
cert_filename = "test_cert.pem"
|
|
|
|
# Configurer le test_controller avec un certificat personnalisé
|
|
self.test_controller.ssl_cert_file = base64.b64encode(cert_content)
|
|
self.test_controller.ssl_cert_filename = cert_filename
|
|
|
|
# Créer un fichier temporaire pour le certificat
|
|
fd, cert_path = tempfile.mkstemp(suffix='.pem')
|
|
try:
|
|
os.write(fd, cert_content)
|
|
os.close(fd)
|
|
|
|
# Définir le chemin du certificat
|
|
self.test_controller.ssl_cert_path = cert_path
|
|
|
|
# Configurer le test_controller avec des cookies de session
|
|
self.test_controller.session_cookies = json.dumps({'cookie1': 'value1'})
|
|
self.test_controller.csrf_token = 'test-csrf-token'
|
|
|
|
# Configurer le mock pour simuler une réponse réussie
|
|
mock_response = mock.MagicMock()
|
|
mock_response.status_code = 200
|
|
mock_response.text = json.dumps({'data': [{'id': 1, 'name': 'test'}]})
|
|
mock_response.json.return_value = {'data': [{'id': 1, 'name': 'test'}]}
|
|
|
|
mock_session_instance = mock_session.return_value
|
|
mock_session_instance.get.return_value = mock_response
|
|
|
|
# Appeler la méthode _make_request
|
|
success, data, status_code = self.test_controller._make_request('GET', 'devices', 'default')
|
|
|
|
# Vérifier que la requête a réussi
|
|
self.assertTrue(success)
|
|
self.assertEqual(status_code, 200)
|
|
|
|
# Vérifier que le certificat personnalisé a été utilisé
|
|
mock_session_instance.get.assert_called_with(
|
|
mock.ANY, # URL
|
|
params=mock.ANY, # Params
|
|
headers=mock.ANY, # Headers
|
|
verify=cert_path, # Verify avec le certificat personnalisé
|
|
timeout=10
|
|
)
|
|
finally:
|
|
# Nettoyer le fichier temporaire
|
|
if os.path.exists(cert_path):
|
|
os.unlink(cert_path)
|
|
|
|
@mock.patch('odoo.addons.unifi_integration.models.unifi_site_controller.requests.Session')
|
|
def test_make_request_session_expired(self, mock_session):
|
|
"""Teste le renouvellement de session
|
|
|
|
Vérifie que la méthode _make_request gère correctement
|
|
l'expiration de la session et tente une nouvelle authentification.
|
|
"""
|
|
# Configurer le test_controller avec des cookies de session
|
|
self.test_controller.session_cookies = json.dumps({'cookie1': 'value1'})
|
|
|
|
# Configurer le mock pour simuler une réponse d'expiration de session
|
|
mock_response_expired = mock.MagicMock()
|
|
mock_response_expired.status_code = 401
|
|
mock_response_expired.text = json.dumps({'meta': {'rc': 'error', 'msg': 'Session expired'}})
|
|
|
|
# Configurer le mock pour simuler une réponse réussie après réauthentification
|
|
mock_response_success = mock.MagicMock()
|
|
mock_response_success.status_code = 200
|
|
mock_response_success.text = json.dumps({'data': [{'id': 1, 'name': 'test'}]})
|
|
mock_response_success.json.return_value = {'data': [{'id': 1, 'name': 'test'}]}
|
|
|
|
mock_session_instance = mock_session.return_value
|
|
mock_session_instance.get.side_effect = [mock_response_expired, mock_response_success]
|
|
|
|
# Configurer le mock pour simuler une authentification réussie
|
|
mock_auth_response = mock.MagicMock()
|
|
mock_auth_response.status_code = 200
|
|
mock_auth_response.headers = {'X-CSRF-Token': 'new-csrf-token'}
|
|
mock_auth_response.text = json.dumps({'meta': {'rc': 'ok'}})
|
|
|
|
mock_session_instance.post.return_value = mock_auth_response
|
|
mock_session_instance.cookies.items.return_value = [('cookie2', 'value2')]
|
|
|
|
# Remplacer la méthode _authenticate par un mock
|
|
original_authenticate = self.test_controller._authenticate
|
|
self.test_controller._authenticate = mock.MagicMock(return_value=True)
|
|
|
|
try:
|
|
# Appeler la méthode _make_request
|
|
success, data, status_code = self.test_controller._make_request('GET', 'devices', 'default')
|
|
|
|
# Vérifier que la méthode _authenticate a été appelée
|
|
self.test_controller._authenticate.assert_called_once()
|
|
|
|
# Vérifier que la requête a réussi après réauthentification
|
|
self.assertTrue(success)
|
|
self.assertEqual(status_code, 200)
|
|
finally:
|
|
# Restaurer la méthode _authenticate
|
|
self.test_controller._authenticate = original_authenticate
|