murano-dashboard/muranodashboard/tests/unit/dynamic_ui/test_forms.py

209 lines
7.9 KiB
Python

# Copyright (c) 2016 AT&T Corp
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import collections
import mock
import testtools
from yaql.language import contexts as yaql_contexts
from django import forms as django_forms
from muranodashboard.dynamic_ui import fields
from muranodashboard.dynamic_ui import forms
from muranodashboard.dynamic_ui import yaql_expression
class TestAnyFieldDict(testtools.TestCase):
def test_missing(self):
any_field_dict = forms.AnyFieldDict()
result = any_field_dict.__missing__(['foo', 'bar'])
self.assertEqual('DynamicSelect', result.__name__)
class TestDynamicUiForm(testtools.TestCase):
def test_collect_fields_process_widget(self):
test_spec = {
'type': 'text',
'name': 'foo_spec',
'widget_media': {
'js': 'foo.js',
'css': 'foo.css'
},
'widget_attrs': {'foo': 'bar'}
}
result = forms._collect_fields([test_spec], 'foo_form', None)
self.assertIsInstance(result, list)
self.assertEqual(1, len(result))
self.assertEqual('foo_spec', result[0][0])
self.assertIsInstance(result[0][1], fields.CharField)
field = result[0][1]
self.assertTrue(hasattr(field, 'widget'))
self.assertTrue(hasattr(field.widget, 'Media'))
self.assertEqual('foo.js', field.widget.Media.js)
self.assertEqual('foo.css', field.widget.Media.css)
self.assertIn('foo', field.widget.__dict__['attrs'])
self.assertEqual('bar', field.widget.__dict__['attrs']['foo'])
def test_collect_fields_parse_spec_with_yaql_expression(self):
mock_yaql = mock.Mock(spec=yaql_expression.YaqlExpression)
test_spec = {
'type': 'choice',
'name': 'foo_spec',
'validators': [{'expr': mock_yaql}]
}
result = forms._collect_fields([test_spec], 'foo_form', None)
self.assertIsInstance(result, list)
self.assertEqual(1, len(result))
self.assertEqual('foo_spec', result[0][0])
self.assertIsInstance(result[0][1], fields.ChoiceField)
field = result[0][1]
self.assertTrue(hasattr(field, 'validators'))
self.assertIn('expr', field.validators[0])
self.assertIsInstance(field.validators[0]['expr'], fields.RawProperty)
self.assertEqual(mock_yaql, field.validators[0]['expr'].spec)
class TestDynamicFormMetaclass(testtools.TestCase):
def test_new(self):
test_dict = {
'name': 'foo_form',
'field_specs': [{'type': 'text', 'name': 'foo_spec'}],
'service': 'foo_service',
}
form = forms.DynamicFormMetaclass('foo_form', (), test_dict)
self.assertEqual('foo_form', form.__name__)
self.assertEqual('foo_service', form.service)
self.assertIsInstance(form.declared_fields, collections.OrderedDict)
self.assertIn('foo_spec', form.declared_fields)
self.assertIsInstance(form.declared_fields['foo_spec'],
fields.CharField)
class TestUpdatableFieldsForm(testtools.TestCase):
def setUp(self):
super(TestUpdatableFieldsForm, self).setUp()
self.form = forms.UpdatableFieldsForm(None)
self.assertEqual('required', self.form.required_css_class)
def test_update_fields(self):
mock_password_field = mock.Mock(spec=fields.PasswordField)
mock_password_field.confirm_input = True
mock_password_field.has_clone = False
mock_password_field.original = True
mock_password_field.required = True
mock_password_field.update = mock.Mock()
mock_password_field.initial = 'foo_initial'
mock_password_field.get_clone_name.return_value = 'bar_password_field'
mock_clone_password_field = mock.Mock(
spec=fields.PasswordField, required=True)
mock_password_field.clone_field.return_value = \
mock_clone_password_field
self.form.fields = collections.OrderedDict({
'foo_password_field': mock_password_field})
self.form.update_fields()
self.assertEqual(2, len(self.form.fields))
self.assertIn('foo_password_field', self.form.fields)
self.assertIn('bar_password_field', self.form.fields)
self.assertEqual(mock_password_field,
self.form.fields['foo_password_field'])
self.assertEqual(mock_clone_password_field,
self.form.fields['bar_password_field'])
mock_password_field.get_clone_name.assert_called_once_with(
'foo_password_field')
self.assertTrue(mock_password_field.get_clone_name.called)
self.assertTrue(mock_password_field.update.called)
class TestServiceConfigurationForm(testtools.TestCase):
def setUp(self):
super(TestServiceConfigurationForm, self).setUp()
mock_service = mock.Mock()
mock_service.update_cleaned_data.return_value = \
{'foo': 'bar', 'baz': 'qux'}
self.form = forms.ServiceConfigurationForm(
initial={'app_id': 'foo_app'})
self.form._errors = []
self.form.validators = []
self.form.cleaned_data = {'foo': 'bar', 'baz': 'qux'}
self.form.service = mock_service
self.assertEqual('foo_app_%s', self.form.auto_id)
self.assertIsInstance(self.form.context, yaql_contexts.Context)
@mock.patch.object(forms, 'LOG', autospec=True)
def test_clean(self, mock_log):
password_field = mock.Mock(spec=fields.PasswordField)
password_field.enabled = True
password_field.confirm_input = True
foo_field = mock.Mock()
foo_field.enabled = False
foo_field.postclean.return_value = 'post_foo'
self.form.fields = {'foo': foo_field, 'password': password_field}
result = self.form.clean()
expected_cleaned_data = {'foo': 'post_foo', 'baz': 'qux'}
for key, val in expected_cleaned_data.items():
self.assertEqual(val, result[key])
# NOTE(felipemonteiro): mock.ANY is being used in the assertions
# below, rather than `{'foo': 'bar', 'baz': 'qux'}` because
# `cleaned_data[name] = value` in clean() appears to also change the
# dict that was passed in to mock objects in previous lines of code.
foo_field.postclean.assert_called_once_with(self.form, 'foo', mock.ANY)
password_field.compare.assert_called_once_with('password', mock.ANY)
mock_log.debug.assert_called_once_with(
"Update 'foo' data in postclean method")
self.form.service.update_cleaned_data.assert_called_with(
mock.ANY, form=self.form)
def test_clean_except_validation_error(self):
mock_expr = mock.Mock()
mock_expr.evaluate.return_value = False
test_validator = {'expr': mock_expr, 'message': 'Foo Error'}
self.form.validators = [test_validator]
with self.assertRaisesRegex(django_forms.ValidationError,
'Foo Error'):
self.form.clean()
self.form.service.update_cleaned_data.assert_called_once_with(
{'foo': 'bar', 'baz': 'qux'}, form=self.form)
mock_expr.evaluate.assert_called_once_with(
data={'foo': 'bar', 'baz': 'qux'}, context=self.form.context)
def test_clean_with_errors(self):
self.form._errors = ['foo_error']
self.assertEqual({'foo': 'bar', 'baz': 'qux'}, self.form.clean())