mirror of
https://github.com/netbox-community/netbox.git
synced 2026-04-13 04:30:12 +02:00
test(extras): Stabilize ScriptModule tests and reduce CI noise
Patch `ScriptModule.sync_classes()` in tests that create `ScriptModule` records without backing files to avoid setup-time import attempts for non-existent modules. For the upload API test, mock both serializer and module storage access so the uploaded script can be saved and imported during the test, and assert that the corresponding `Script` object is created. Fixes #21862
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import datetime
|
||||
import hashlib
|
||||
import io
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
@@ -1013,10 +1014,14 @@ class ScriptTest(APITestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
module = ScriptModule.objects.create(
|
||||
file_root=ManagedFileRootPathChoices.SCRIPTS,
|
||||
file_path='script.py',
|
||||
)
|
||||
# Avoid trying to import a non-existent on-disk module during setup.
|
||||
# This test creates the Script row explicitly and monkey-patches
|
||||
# Script.python_class below.
|
||||
with patch.object(ScriptModule, 'sync_classes'):
|
||||
module = ScriptModule.objects.create(
|
||||
file_root=ManagedFileRootPathChoices.SCRIPTS,
|
||||
file_path='script.py',
|
||||
)
|
||||
script = Script.objects.create(
|
||||
module=module,
|
||||
name='Test script',
|
||||
@@ -1419,9 +1424,20 @@ class ScriptModuleTest(APITestCase):
|
||||
upload_file = SimpleUploadedFile('test_upload.py', script_content, content_type='text/plain')
|
||||
mock_storage = MagicMock()
|
||||
mock_storage.save.return_value = 'test_upload.py'
|
||||
with patch('extras.api.serializers_.scripts.storages') as mock_storages:
|
||||
mock_storages.create_storage.return_value = mock_storage
|
||||
mock_storages.backends = {'scripts': {}}
|
||||
|
||||
# The upload serializer writes the file via storages.create_storage(...).save(),
|
||||
# but ScriptModule.sync_classes() later imports it via storages["scripts"].open().
|
||||
# Provide both behaviors so the uploaded module can actually be loaded during the test.
|
||||
mock_storage.open.side_effect = lambda *args, **kwargs: io.BytesIO(script_content)
|
||||
|
||||
with (
|
||||
patch('extras.api.serializers_.scripts.storages') as mock_serializer_storages,
|
||||
patch('extras.models.mixins.storages') as mock_module_storages,
|
||||
):
|
||||
mock_serializer_storages.create_storage.return_value = mock_storage
|
||||
mock_serializer_storages.backends = {'scripts': {}}
|
||||
mock_module_storages.__getitem__.return_value = mock_storage
|
||||
|
||||
response = self.client.post(
|
||||
self.url,
|
||||
{'file': upload_file},
|
||||
@@ -1432,6 +1448,7 @@ class ScriptModuleTest(APITestCase):
|
||||
self.assertEqual(response.data['file_path'], 'test_upload.py')
|
||||
mock_storage.save.assert_called_once()
|
||||
self.assertTrue(ScriptModule.objects.filter(file_path='test_upload.py').exists())
|
||||
self.assertTrue(Script.objects.filter(module__file_path='test_upload.py', name='TestScript').exists())
|
||||
|
||||
def test_upload_script_module_without_file_fails(self):
|
||||
self.add_permissions('extras.add_scriptmodule', 'core.add_managedfile')
|
||||
|
||||
@@ -924,7 +924,14 @@ class ScriptValidationErrorTest(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
module = ScriptModule.objects.create(file_root=ManagedFileRootPathChoices.SCRIPTS, file_path='test_script.py')
|
||||
# Avoid trying to import a non-existent on-disk module during setup.
|
||||
# This test creates the Script row explicitly and monkey-patches
|
||||
# Script.python_class below.
|
||||
with patch.object(ScriptModule, 'sync_classes'):
|
||||
module = ScriptModule.objects.create(
|
||||
file_root=ManagedFileRootPathChoices.SCRIPTS,
|
||||
file_path='test_script.py',
|
||||
)
|
||||
cls.script = Script.objects.create(module=module, name='Test script', is_executable=True)
|
||||
|
||||
def setUp(self):
|
||||
@@ -986,7 +993,14 @@ class ScriptDefaultValuesTest(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
module = ScriptModule.objects.create(file_root=ManagedFileRootPathChoices.SCRIPTS, file_path='test_script.py')
|
||||
# Avoid trying to import a non-existent on-disk module during setup.
|
||||
# This test creates the Script row explicitly and monkey-patches
|
||||
# Script.python_class below.
|
||||
with patch.object(ScriptModule, 'sync_classes'):
|
||||
module = ScriptModule.objects.create(
|
||||
file_root=ManagedFileRootPathChoices.SCRIPTS,
|
||||
file_path='test_script.py',
|
||||
)
|
||||
cls.script = Script.objects.create(module=module, name='Test script', is_executable=True)
|
||||
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user