Projet

Général

Profil

0001-add-test-tools-in-formdata-inspect-view-23685.patch

Thomas Noël, 06 février 2019 16:54

Télécharger (13,7 ko)

Voir les différences:

Subject: [PATCH] add test tools in formdata inspect view (#23685)

 tests/test_backoffice_pages.py      |  78 +++++++++++++++++++
 wcs/backoffice/management.py        | 116 +++++++++++++++++++++++++++-
 wcs/conditions.py                   |   7 +-
 wcs/qommon/static/css/dc2/admin.css |  23 ++++++
 4 files changed, 220 insertions(+), 4 deletions(-)
tests/test_backoffice_pages.py
3727 3727
    resp = login(get_app(pub)).get('%sinspect' % formdata.get_url(backoffice=True), status=200)
3728 3728
    assert re.findall('New Function.*(deleted)', resp.body)
3729 3729

  
3730
    # test tools
3731
    resp = login(get_app(pub)).get('%sinspect' % formdata.get_url(backoffice=True), status=200)
3732
    assert "Test tool" in resp.body
3733

  
3734
    resp.form['test_mode'] = 'condition'
3735

  
3736
    resp.form['condition$type'] = 'python'
3737
    resp.form['condition$value_python'] = 'len(form_name) == 10'  # "form title"
3738
    resp = resp.form.submit()
3739
    assert 'Condition result' in resp.body
3740
    assert 'result-true' in resp.body
3741
    assert '<code>True</code>' in resp.body
3742
    resp.form['condition$value_python'] = 'len(form_name) == 5'
3743
    resp = resp.form.submit()
3744
    assert 'Condition result' in resp.body
3745
    assert 'result-false' in resp.body
3746
    assert '<code>False</code>' in resp.body
3747
    resp.form['condition$value_python'] = 'form_do_not_exist == 3'
3748
    resp = resp.form.submit()
3749
    assert 'Condition result' not in resp.body
3750
    assert 'Failed to evaluate condition' in resp.body
3751
    assert 'NameError' in resp.body
3752

  
3753
    resp.form['condition$type'] = 'django'
3754
    resp.form['condition$value_django'] = 'form_name|length == 10'
3755
    resp = resp.form.submit()
3756
    assert 'Condition result' in resp.body
3757
    assert 'result-true' in resp.body
3758
    resp.form['condition$type'] = 'django'
3759
    resp.form['condition$value_django'] = 'form_name|length == 5'
3760
    resp = resp.form.submit()
3761
    assert 'Condition result' in resp.body
3762
    assert 'result-false' in resp.body
3763
    resp.form['condition$type'] = 'django'
3764
    resp.form['condition$value_django'] = 'foo bar'
3765
    resp = resp.form.submit()
3766
    assert 'Condition result' not in resp.body
3767
    assert 'syntax error' in resp.body
3768
    resp.form['condition$value_python'] = None
3769
    resp.form['condition$value_django'] = None
3770

  
3771
    resp.form['test_mode'] = 'template'
3772
    resp.form['template'] = '{{ form_name }}'
3773
    resp = resp.form.submit()
3774
    assert 'Template rendering' in resp.body
3775
    assert '<div class="testtool-result">form title</div>' in resp.body
3776
    assert 'HTML Source' not in resp.body
3777
    resp.form['template'] = '<p>{{ form_name }}</p>'
3778
    resp = resp.form.submit()
3779
    assert 'Template rendering' in resp.body
3780
    assert '<p>form title</p>' in resp.body
3781
    assert 'HTML Source' in resp.body
3782
    resp.form['template'] = '{% for x in 1 %}ok{% endfor %}'
3783
    resp = resp.form.submit()
3784
    assert 'Failed to evaluate template' in resp.body
3785
    assert 'TypeError' in resp.body
3786
    resp.form['template'] = '{% for x in 1 %}ok{% end %}'
3787
    resp = resp.form.submit()
3788
    assert 'syntax error' in resp.body
3789
    assert 'Invalid block tag' in resp.body
3790
    resp.form['template'] = ''
3791

  
3792
    resp.form['test_mode'] = 'html_template'
3793
    resp.form['html_template'] = '<p>{{ form_name }}</p>'
3794
    resp = resp.form.submit()
3795
    resp = resp.form.submit()
3796
    assert 'Template rendering' in resp.body
3797
    assert '<p>form title</p>' in resp.body
3798
    assert 'HTML Source' in resp.body
3799
    resp.form['html_template'] = '{% for x in 1 %}ok{% endfor %}'
3800
    resp = resp.form.submit()
3801
    assert 'Failed to evaluate HTML template' in resp.body
3802
    assert 'TypeError' in resp.body
3803
    resp.form['html_template'] = '{% for x in 1 %}ok{% end %}'
3804
    resp = resp.form.submit()
3805
    assert 'syntax error' in resp.body
3806
    assert 'Invalid block tag' in resp.body
3807

  
3730 3808
def test_workflow_jump_previous(pub):
3731 3809
    user = create_user(pub)
3732 3810
    create_environment(pub)
wcs/backoffice/management.py
32 32
from quixote.directory import Directory
33 33
from quixote.html import TemplateIO, htmltext, htmlescape
34 34

  
35
from qommon import _, ngettext
35
from qommon import _, ngettext, ezt
36 36
from qommon.admin.emails import EmailsDirectory
37 37
from qommon.admin.menu import command_icon
38 38
from qommon.backoffice.menu import html_top
......
50 50
        Intersects, ILike, FtsMatch, Contains, Null)
51 51

  
52 52
from wcs.api_utils import get_user_from_api_query_string
53
from wcs.conditions import Condition
53 54
from wcs.forms.backoffice import FormDefUI
54 55
from wcs.forms.common import FormStatusPage
55 56
from wcs.admin.settings import UserFieldsFormDef
......
57 58
from wcs.formdata import FormData
58 59
from wcs.formdef import FormDef
59 60
from wcs.roles import logged_users_role, Role
60
from wcs.workflows import get_role_translation
61
from wcs.workflows import get_role_translation, template_on_formdata
61 62

  
62 63
from .submission import FormFillPage
63 64

  
......
2218 2219
            r += htmltext('</div>')
2219 2220
        return r.getvalue()
2220 2221

  
2222
    def testtool_form(self):
2223
        form = Form(use_tokens=False)
2224
        form.add(RadiobuttonsWidget, 'test_mode',
2225
                 options=[
2226
                     ('condition', _('Condition'), 'condition'),
2227
                     ('template', '%s / %s' % (_('Template'), _('Django Expression')), 'template'),
2228
                     ('html_template', _('HTML Template (wysiwyg)'), 'html_template'),
2229
                 ], attrs={'data-dynamic-display-parent': 'true'})
2230
        form.add(ConditionWidget, 'condition',
2231
                 attrs={
2232
                     'data-dynamic-display-child-of': 'test_mode',
2233
                     'data-dynamic-display-value': 'condition'
2234
                 })
2235
        form.add(WysiwygTextWidget, 'html_template',
2236
                 validation_function=ComputedExpressionWidget.validate_template,
2237
                 attrs={
2238
                     'data-dynamic-display-child-of': 'test_mode',
2239
                     'data-dynamic-display-value': 'html_template'
2240
                 })
2241
        form.add(TextWidget, 'template',
2242
                 validation_function=ComputedExpressionWidget.validate_template,
2243
                 attrs={
2244
                     'data-dynamic-display-child-of': 'test_mode',
2245
                     'data-dynamic-display-value': 'template'
2246
                 })
2247
        form.add_submit('submit', _('Process'),
2248
                        attrs={
2249
                            'data-dynamic-display-child-of': 'test_mode',
2250
                            'data-dynamic-display-value-in': 'condition|html_template|template'
2251
                        })
2252
        return form
2253

  
2254
    def testtool_result(self):
2255
        form = self.testtool_form()
2256
        r = TemplateIO(html=True)
2257
        if form.is_submitted() and not form.has_errors():
2258
            # show test result
2259
            test_mode = form.get_widget('test_mode').parse()
2260
            if test_mode == 'condition':
2261
                condition = Condition(form.get_widget('condition').parse())
2262
                condition.log_errors = False
2263
                condition.record_errors = False
2264
                try:
2265
                    result = condition.unsafe_evaluate()
2266
                except Exception as exception:
2267
                    r += htmltext('<div class="errornotice">')
2268
                    r += htmltext('<p>%s</p>') % _('Failed to evaluate condition')
2269
                    r += htmltext('<p>%s <code>%s: %s</code></p>') % (
2270
                        _('Error message:'), exception.__class__.__name__, str(exception))
2271
                    r += htmltext('</div>')
2272
                else:
2273
                    r += htmltext('<h3>%s</h3>') % _('Condition result')
2274
                    r += htmltext('<div class="testtool-result">')
2275
                    r += htmltext('<p><span class="result-%s">%s</span>') % (
2276
                            str(bool(result)).lower(), ('True') if result else _('False'))
2277
                    if condition.type == 'python':
2278
                        r += htmltext(' &mdash; %s <strong><code>%r</code></strong> '
2279
                                      '<span class="type">(%r)</span>') % (
2280
                                        _('Python actual result is'), result, type(result))
2281
                    r += htmltext('</p>')
2282
                    r += htmltext('</div>')
2283
            elif test_mode == 'template':
2284
                try:
2285
                    template = form.get_widget('template').parse() or ''
2286
                    result = template_on_formdata(self.filled, template, raises=True)
2287
                except Exception as exception:
2288
                    r += htmltext('<div class="errornotice">')
2289
                    r += htmltext('<p>%s</p>') % _('Failed to evaluate template')
2290
                    r += htmltext('<p>%s <code>%s: %s</code></p>') % (
2291
                            _('Error message:'), exception.__class__.__name__, str(exception))
2292
                else:
2293
                    r += htmltext('<h3>%s</h3>') % _('Template rendering')
2294
                    if result and result[0] == '<':  # seems to be HTML
2295
                        r += htmltext('<div class="testtool-result">')
2296
                        r += htmltext(result)
2297
                        r += htmltext('</div>')
2298
                        r += htmltext('<h3>%s</h3>') % _('HTML Source')
2299
                        r += htmltext('<pre class="testtool-result">%s</pre>') % result
2300
                    else:
2301
                        r += htmltext('<div class="testtool-result">%s</div>') % result
2302
            elif test_mode == 'html_template':
2303
                try:
2304
                    html_template = form.get_widget('html_template').parse() or ''
2305
                    result = template_on_formdata(self.filled, html_template, raises=True,
2306
                                                  ezt_format=ezt.FORMAT_HTML)
2307
                except Exception as exception:
2308
                    r += htmltext('<div class="errornotice">')
2309
                    r += htmltext('<p>%s</p>') % _('Failed to evaluate HTML template')
2310
                    r += htmltext('<p>%s <code>%s: %s</code></p>') % (
2311
                            _('Error message:'), exception.__class__.__name__, str(exception))
2312
                    r += htmltext('</div>')
2313
                else:
2314
                    r += htmltext('<h3>%s</h3>') % _('Template rendering')
2315
                    r += htmltext('<div class="testtool-result">')
2316
                    r += htmltext(result)
2317
                    r += htmltext('</div>')
2318
                    r += htmltext('<h3>%s</h3>') % _('HTML Source')
2319
                    r += htmltext('<pre class="testtool-result">%s</pre>') % result
2320
        return r.getvalue()
2321

  
2221 2322
    def inspect(self):
2222 2323
        if not (get_publisher().get_backoffice_root().is_accessible('forms') or
2223 2324
                get_publisher().get_backoffice_root().is_accessible('workflows')):
......
2237 2338
                    self.formdef.workflow.id, _('Workflow Definition'))
2238 2339
        r += htmltext('</span>')
2239 2340
        r += htmltext('</div>')
2341

  
2342
        r += htmltext('<div id="testtool" class="section">')
2343
        r += htmltext('<h2>Test tool</h2>')
2344
        r += htmltext('<div>')
2345
        form = self.testtool_form()
2346
        r += form.render()
2347
        r += htmltext('</div>')
2348
        r += htmltext('<div id="testtool-result">')
2349
        r += self.testtool_result()
2350
        r += htmltext('</div></div>')
2351

  
2240 2352
        r += htmltext('<ul class="biglist form-inspector">')
2241 2353
        r += htmltext(' <li><h3>%s</h3></li>') % _('Substitution variables')
2242 2354
        substvars = self.filled.get_static_substitution_variables()
wcs/conditions.py
45 45
        return get_publisher().substitutions.get_context_variables(
46 46
                mode='%s-condition' % self.type)
47 47

  
48
    def evaluate(self):
48
    def unsafe_evaluate(self):
49 49
        if not self.type or not self.value:
50 50
            return True
51 51
        local_variables = self.get_data()
52
        return getattr(self, 'evaluate_' + self.type)(local_variables)
53

  
54
    def evaluate(self):
52 55
        try:
53
            return getattr(self, 'evaluate_' + self.type)(local_variables)
56
            return self.unsafe_evaluate()
54 57
        except Exception as e:
55 58
            if self.log_errors:
56 59
                get_logger().warn('failed to evaluate %r (%r)', self, e)
wcs/qommon/static/css/dc2/admin.css
1567 1567
	position: absolute;
1568 1568
}
1569 1569

  
1570
div.testtool-result, pre.testtool-result {
1571
	padding: 0.6em;
1572
	background: #ddd;
1573
	border: 1px solid #888;
1574
}
1575

  
1576
div.testtool-result span.type {
1577
	font-size: 80%;
1578
	color: #888;
1579
	padding-left: 1em;
1580
}
1581

  
1582
div.testtool-result span.result-true {
1583
	padding: 5px;
1584
	background: lightgreen;
1585
}
1586

  
1587
div.testtool-result span.result-false {
1588
	padding: 5px;
1589
	background: red;
1590
	color: white;
1591
}
1592

  
1570 1593
ul#evolutions li div.msg li {
1571 1594
	margin: 1em 0;
1572 1595
}
1573
-