add tests
This commit is contained in:
parent
8c697161b7
commit
7cff6a27d4
|
|
@ -1907,6 +1907,7 @@ class ScriptRunExecutionTestCase(APITestCase):
|
|||
site = ObjectVar(model=Site)
|
||||
sites = MultiObjectVar(model=Site, required=False)
|
||||
label = StringVar(default='hello')
|
||||
flag = BooleanVar(default=True)
|
||||
|
||||
def run(self, data, commit=True):
|
||||
return 'ok'
|
||||
|
|
@ -2046,6 +2047,55 @@ class ScriptRunExecutionTestCase(APITestCase):
|
|||
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
||||
mock_enqueue.assert_not_called()
|
||||
|
||||
@patch('extras.jobs.ScriptJob.enqueue')
|
||||
def test_run_ignores_undeclared_keys(self, mock_enqueue):
|
||||
# Binding 'data' to the script's form means keys which don't correspond to a declared
|
||||
# variable are dropped rather than forwarded to run(). This is the contract documented
|
||||
# under "Running Custom Scripts > Via the API"; pin it so it can't regress silently.
|
||||
payload = {
|
||||
'data': {'site': self.sites[0].pk, 'bogus': 'ignored', 'id': 99},
|
||||
'commit': True,
|
||||
}
|
||||
|
||||
response = self.client.post(self.url, payload, format='json', **self.header)
|
||||
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
data = mock_enqueue.call_args.kwargs['data']
|
||||
self.assertEqual(data['site'], self.sites[0])
|
||||
self.assertNotIn('bogus', data)
|
||||
self.assertNotIn('id', data)
|
||||
|
||||
@patch('extras.jobs.ScriptJob.enqueue')
|
||||
def test_run_rejects_omitted_required_var(self, mock_enqueue):
|
||||
# 'site' is required and declares no default, so unlike 'label' it cannot be
|
||||
# back-filled: omitting it must 400 rather than enqueue a job that fails at runtime.
|
||||
payload = {'data': {'label': 'hi'}, 'commit': True}
|
||||
|
||||
response = self.client.post(self.url, payload, format='json', **self.header)
|
||||
|
||||
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('site', response.data['data'])
|
||||
mock_enqueue.assert_not_called()
|
||||
|
||||
@patch('extras.jobs.ScriptJob.enqueue')
|
||||
def test_run_resolves_booleanvar_default_and_explicit_values(self, mock_enqueue):
|
||||
# BooleanVar renders as a checkbox, and CheckboxInput reads a missing key as False.
|
||||
# An omitted BooleanVar must therefore pick up its declared default, while an
|
||||
# explicitly supplied False must not be overwritten by that default.
|
||||
for case, supplied, expected in (
|
||||
('omitted', {}, True),
|
||||
('explicit False', {'flag': False}, False),
|
||||
('explicit True', {'flag': True}, True),
|
||||
):
|
||||
with self.subTest(case=case):
|
||||
mock_enqueue.reset_mock()
|
||||
payload = {'data': {'site': self.sites[0].pk, **supplied}, 'commit': True}
|
||||
|
||||
response = self.client.post(self.url, payload, format='json', **self.header)
|
||||
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
self.assertIs(mock_enqueue.call_args.kwargs['data']['flag'], expected)
|
||||
|
||||
|
||||
class CreatedUpdatedFilterTestCase(APITestCase):
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from core.models import Job, ObjectType
|
|||
from dcim.models import DeviceType, Manufacturer, Site
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
from extras.scripts import BooleanVar, IntegerVar
|
||||
from extras.scripts import BooleanVar, IntegerVar, StringVar
|
||||
from extras.scripts import Script as PythonClass
|
||||
from users.models import Group, ObjectPermission, User
|
||||
from utilities.testing import TestCase, ViewTestCases
|
||||
|
|
@ -1279,6 +1279,57 @@ class ScriptModuleCreateViewTestCase(TestCase):
|
|||
self.assertEqual(response.context['return_url'], reverse('extras:script_list'))
|
||||
|
||||
|
||||
class ScriptDefaultBackfillTestCase(TestCase):
|
||||
"""
|
||||
The UI and the REST API now share prepare_script_form(), so the UI's back-filling of
|
||||
declared defaults (previously inline in ScriptView.post()) must keep working after
|
||||
that logic moved into the helper.
|
||||
"""
|
||||
user_permissions = ['extras.view_script', 'extras.run_script']
|
||||
|
||||
class TestScriptClass(PythonClass):
|
||||
class Meta:
|
||||
name = 'Backfill test'
|
||||
commit_default = False
|
||||
|
||||
label = StringVar(default='hello')
|
||||
flag = BooleanVar(default=True)
|
||||
|
||||
def run(self, data, commit):
|
||||
return 'Complete'
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
with patch.object(ScriptModule, 'sync_classes'):
|
||||
module = ScriptModule.objects.create(
|
||||
file_root=ManagedFileRootPathChoices.SCRIPTS,
|
||||
file_path='backfill_script.py',
|
||||
)
|
||||
cls.script = Script.objects.create(module=module, name='Backfill test', is_executable=True)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
python_class_patch = patch.object(Script, 'python_class', new=self.TestScriptClass)
|
||||
python_class_patch.start()
|
||||
self.addCleanup(python_class_patch.stop)
|
||||
|
||||
@tag('regression')
|
||||
def test_ui_backfills_declared_defaults(self):
|
||||
url = reverse('extras:script', kwargs={'pk': self.script.pk})
|
||||
|
||||
with (
|
||||
patch('extras.views.any_workers_for_queue', return_value=True),
|
||||
patch('extras.jobs.ScriptJob.enqueue') as mock_enqueue,
|
||||
):
|
||||
mock_enqueue.return_value.pk = 1
|
||||
response = self.client.post(url, {'_commit': 'true'})
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
data = mock_enqueue.call_args.kwargs['data']
|
||||
self.assertEqual(data['label'], 'hello')
|
||||
self.assertIs(data['flag'], True)
|
||||
|
||||
|
||||
class ScriptValidationErrorTestCase(TestCase):
|
||||
user_permissions = ['extras.view_script', 'extras.run_script']
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue