0001-forms-don-t-let-conditional-pages-alter-evaluation-o.patch
tests/test_form_pages.py | ||
---|---|---|
5298 | 5298 |
assert '<span class="label">Bar</span>' in resp.body |
5299 | 5299 |
assert '<span class="label">Foo</span>' in resp.body |
5300 | 5300 | |
5301 |
def test_field_condition_on_required_field(pub): |
|
5302 |
# from https://dev.entrouvert.org/issues/27247 |
|
5303 |
FormDef.wipe() |
|
5304 |
formdef = FormDef() |
|
5305 |
formdef.name = 'Foo' |
|
5306 |
formdef.fields = [ |
|
5307 |
fields.PageField(id='0', label='1st page', type='page'), |
|
5308 |
fields.ItemField(type='item', id='1', label='Bar', |
|
5309 |
items=['oui', 'non'], |
|
5310 |
show_as_radio=True, |
|
5311 |
required=True, varname='bar'), |
|
5312 |
fields.ItemField(type='item', id='2', label='Foo', size='40', |
|
5313 |
required=True, |
|
5314 |
hint='---', |
|
5315 |
items=['plop'], |
|
5316 |
condition={'type': 'django', 'value': 'form_var_bar == "oui"'}), |
|
5317 |
fields.PageField(id='3', label='1st page', type='page', |
|
5318 |
condition={'type': 'python', 'value': 'True'}), |
|
5319 |
fields.CommentField(type='comment', id='4', label='HELLO!'), |
|
5320 |
] |
|
5321 |
formdef.store() |
|
5322 | ||
5323 |
app = get_app(pub) |
|
5324 |
resp = app.get('/foo/') |
|
5325 |
assert 'f1' in resp.form.fields |
|
5326 |
assert 'f2' in resp.form.fields |
|
5327 |
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true' |
|
5328 |
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none' |
|
5329 |
resp.form['f1'] = 'non' |
|
5330 |
live_resp = app.post('/foo/live', params=resp.form.submit_fields()) |
|
5331 |
assert live_resp.json['result']['1']['visible'] |
|
5332 |
assert not live_resp.json['result']['2']['visible'] |
|
5333 |
resp = resp.form.submit('submit') |
|
5334 |
assert 'HELLO' in resp.body |
|
5335 |
resp = resp.form.submit('previous') |
|
5336 |
resp.form['f1'] = 'oui' |
|
5337 |
live_resp = app.post('/foo/live', params=resp.form.submit_fields()) |
|
5338 |
assert live_resp.json['result']['1']['visible'] |
|
5339 |
assert live_resp.json['result']['2']['visible'] |
|
5340 |
print 'HELLO!!!!' |
|
5341 |
resp = resp.form.submit('submit') |
|
5342 |
assert '<div class="error">required field</div>' in resp.body |
|
5343 |
assert 'HELLO' not in resp.body |
|
5344 | ||
5301 | 5345 |
def test_field_live_condition_multipages(pub): |
5302 | 5346 |
FormDef.wipe() |
5303 | 5347 |
formdef = FormDef() |
wcs/forms/root.py | ||
---|---|---|
524 | 524 |
current_data = self.get_transient_formdata().data |
525 | 525 |
pages = [] |
526 | 526 |
field_page = None |
527 |
for field in self.formdef.fields: |
|
528 |
if field.type == 'page': |
|
529 |
field_page = field |
|
530 |
if field.is_visible(current_data, self.formdef): |
|
531 |
pages.append(field) |
|
527 |
with get_publisher().substitutions.freeze(): |
|
528 |
# don't let evaluation of pages alter substitution variables (this |
|
529 |
# avoids a ConditionVars being added with current form data and |
|
530 |
# influencing later code evaluating field visibility based on |
|
531 |
# submitted data) (#27247). |
|
532 |
for field in self.formdef.fields: |
|
533 |
if field.type == 'page': |
|
534 |
field_page = field |
|
535 |
if field.is_visible(current_data, self.formdef): |
|
536 |
pages.append(field) |
|
532 | 537 |
if not field_page: # form without page fields |
533 | 538 |
pages = [None] |
534 | 539 |
self._pages = pages |
wcs/qommon/substitution.py | ||
---|---|---|
69 | 69 |
self.sources.append(source) |
70 | 70 |
self.invalidate_cache() |
71 | 71 | |
72 |
@contextmanager |
|
73 |
def freeze(self): |
|
74 |
orig_sources, self.sources = self.sources, self.sources[:] |
|
75 |
self.invalidate_cache() |
|
76 |
yield |
|
77 |
self.sources = orig_sources |
|
78 |
self.invalidate_cache() |
|
79 | ||
72 | 80 |
@contextmanager |
73 | 81 |
def temporary_feed(self, source, force_mode=None): |
74 | 82 |
if source is None or source in self.sources: |
75 |
- |