Projet

Général

Profil

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

Thomas Noël, 06 février 2019 15:40

Télécharger (13,2 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        | 108 +++++++++++++++++++++++++++-
 wcs/conditions.py                   |   7 +-
 wcs/qommon/static/css/dc2/admin.css |  23 ++++++
 4 files changed, 212 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

  
......
2237 2238
                    self.formdef.workflow.id, _('Workflow Definition'))
2238 2239
        r += htmltext('</span>')
2239 2240
        r += htmltext('</div>')
2241

  
2242
        form = Form(use_tokens=False)
2243
        form.add(SingleSelectWidget, 'test_mode',
2244
                 options=[
2245
                     (None, ('Choose a testing tool'), None),
2246
                     ('condition', _('Condition'), 'condition'),
2247
                     ('template', '%s / %s' % (_('Template'), _('Django Expression')), 'template'),
2248
                     ('html_template', _('HTML Template (wysiwyg)'), 'html_template'),
2249
                     # TODO: ODT/RTF tester
2250
                 ], attrs={'data-dynamic-display-parent': 'true'})
2251
        form.add(ConditionWidget, 'condition',
2252
                 attrs={
2253
                     'data-dynamic-display-child-of': 'test_mode',
2254
                     'data-dynamic-display-value': 'condition'
2255
                 })
2256
        form.add(WysiwygTextWidget, 'html_template',
2257
                 validation_function=ComputedExpressionWidget.validate_template,
2258
                 attrs={
2259
                     'data-dynamic-display-child-of': 'test_mode',
2260
                     'data-dynamic-display-value': 'html_template'
2261
                 })
2262
        form.add(TextWidget, 'template',
2263
                 validation_function=ComputedExpressionWidget.validate_template,
2264
                 attrs={
2265
                     'data-dynamic-display-child-of': 'test_mode',
2266
                     'data-dynamic-display-value': 'template'
2267
                 })
2268
        form.add_submit('submit', _('Process'),
2269
                        attrs={
2270
                            'data-dynamic-display-child-of': 'test_mode',
2271
                            'data-dynamic-display-value-in': 'condition|html_template|template'
2272
                        })
2273
        r += htmltext('<div id="tester" class="section foldable %s">') % (
2274
            'folded' if not form.is_submitted() else '')
2275
        r += htmltext('<h2>Test tool</h2>')
2276
        r += htmltext('<div>')
2277
        r += form.render()
2278

  
2279
        if form.is_submitted() and not form.has_errors():
2280
            # show test result
2281
            test_mode = form.get_widget('test_mode').parse()
2282
            if test_mode == 'condition':
2283
                condition = Condition(form.get_widget('condition').parse())
2284
                condition.log_errors = False
2285
                condition.record_errors = False
2286
                try:
2287
                    result = condition.unsafe_evaluate()
2288
                except Exception as exception:
2289
                    r += htmltext('<div class="errornotice">')
2290
                    r += htmltext('<p>%s</p>') % _('Failed to evaluate condition')
2291
                    r += htmltext('<p>%s <code>%s: %s</code></p>') % (
2292
                        _('Error message:'), exception.__class__.__name__, str(exception))
2293
                    r += htmltext('</div>')
2294
                else:
2295
                    r += htmltext('<h3>%s</h3>') % _('Condition result')
2296
                    r += htmltext('<div class="testtool-result">')
2297
                    r += htmltext('<p><span class="result-%s">%s</span>') % (
2298
                            str(bool(result)).lower(), ('True') if result else _('False'))
2299
                    if condition.type == 'python':
2300
                        r += htmltext(' &mdash; %s <strong><code>%r</code></strong> '
2301
                                      '<span class="type">(%r)</span>') % (
2302
                                        _('Python actual result is'), result, type(result))
2303
                    r += htmltext('</p>')
2304
                    r += htmltext('</div>')
2305
            elif test_mode == 'template':
2306
                try:
2307
                    template = form.get_widget('template').parse() or ''
2308
                    result = template_on_formdata(self.filled, template, raises=True)
2309
                except Exception as exception:
2310
                    r += htmltext('<div class="errornotice">')
2311
                    r += htmltext('<p>%s</p>') % _('Failed to evaluate template')
2312
                    r += htmltext('<p>%s <code>%s: %s</code></p>') % (
2313
                            _('Error message:'), exception.__class__.__name__, str(exception))
2314
                else:
2315
                    r += htmltext('<h3>%s</h3>') % _('Template rendering')
2316
                    if result and result[0] == '<':  # seems to be HTML
2317
                        r += htmltext('<div class="testtool-result">')
2318
                        r += htmltext(result)
2319
                        r += htmltext('</div>')
2320
                        r += htmltext('<h3>%s</h3>') % _('HTML Source')
2321
                        r += htmltext('<pre class="testtool-result">%s</pre>') % result
2322
                    else:
2323
                        r += htmltext('<div class="testtool-result">%s</div>') % result
2324
            elif test_mode == 'html_template':
2325
                try:
2326
                    html_template = form.get_widget('html_template').parse() or ''
2327
                    result = template_on_formdata(self.filled, html_template, raises=True,
2328
                                                  ezt_format=ezt.FORMAT_HTML)
2329
                except Exception as exception:
2330
                    r += htmltext('<div class="errornotice">')
2331
                    r += htmltext('<p>%s</p>') % _('Failed to evaluate HTML template')
2332
                    r += htmltext('<p>%s <code>%s: %s</code></p>') % (
2333
                            _('Error message:'), exception.__class__.__name__, str(exception))
2334
                    r += htmltext('</div>')
2335
                else:
2336
                    r += htmltext('<h3>%s</h3>') % _('Template rendering')
2337
                    r += htmltext('<div class="testtool-result">')
2338
                    r += htmltext(result)
2339
                    r += htmltext('</div>')
2340
                    r += htmltext('<h3>%s</h3>') % _('HTML Source')
2341
                    r += htmltext('<pre class="testtool-result">%s</pre>') % result
2342
        r += htmltext('</div></div>')
2343

  
2240 2344
        r += htmltext('<ul class="biglist form-inspector">')
2241 2345
        r += htmltext(' <li><h3>%s</h3></li>') % _('Substitution variables')
2242 2346
        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
-