form: fix dynamic item field value on reload (#48495)

This commit is contained in:
Lauréline Guérin 2020-11-26 14:37:00 +01:00
parent c5c52e4ab8
commit 62cf149fe7
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 89 additions and 3 deletions

View File

@ -1,4 +1,8 @@
# -*- coding: utf-8 -*-
import json
import mock
from django.utils.six import StringIO
import pytest
from webtest import Upload
@ -870,3 +874,81 @@ def test_block_post_condition_on_2nd_page(pub, blocks_feature):
assert 'You shall not pass.' not in resp.text
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
@mock.patch('wcs.qommon.misc.urlopen')
def test_block_with_dynamic_item_field(mock_urlopen, pub, blocks_feature):
def data_source(url):
url, query = url.split('?q=')
payload = []
if query == 'foo':
payload = [{'id': '1', 'text': 'foo'}]
elif query == 'bar':
payload = [{'id': '2', 'text': 'bar'}]
return StringIO(json.dumps({'data': payload}))
mock_urlopen.side_effect = lambda url: data_source(url)
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123', required=True, label='Test',
type='string', varname='foo'),
]
block.store()
formdef = FormDef()
formdef.name = 'foo'
formdef.fields = [
fields.StringField(
id='1', label='field 1',
type='string', varname='foo'),
fields.ItemField(
id='2', label='field 2',
varname='bar', data_source={'type': 'json', 'value': 'http://whatever/data-source?q={{form_var_foo|default:""}}'}),
fields.BlockField(id='3', label='block', type='block:foobar', max_items=3),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
# select first field
resp.form['f1'] = 'foo'
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
assert live_resp.json['result']['2']['items'] == [{'id': '1', 'text': 'foo'}]
resp.form['f2'].options = []
for item in live_resp.json['result']['2']['items']:
# simulate javascript filling the <select>
resp.form['f2'].options.append((item['id'], False, item['text']))
# select second field
resp.form['f2'] = '1'
# add block
resp = resp.form.submit('f3$add_element')
# second field value is kept
assert resp.form['f2'].value == '1'
resp = app.get(formdef.get_url())
# select first field
resp.form['f1'] = 'foo'
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
assert live_resp.json['result']['2']['items'] == [{'id': '1', 'text': 'foo'}]
resp.form['f2'].options = []
for item in live_resp.json['result']['2']['items']:
# simulate javascript filling the <select>
resp.form['f2'].options.append((item['id'], False, item['text']))
# select second field
resp.form['f2'] = '1'
# submit form with empty value in block
resp = resp.form.submit()
# second field value is kept
assert resp.form['f2'].value == '1'

View File

@ -396,7 +396,7 @@ class FormPage(Directory, FormTemplateMixin):
had_prefill = True
return had_prefill
def page(self, page, page_change=True, page_error_messages=None, submit_button=None):
def page(self, page, page_change=True, page_error_messages=None, submit_button=None, transient_formdata=None):
displayed_fields = []
session = get_session()
@ -405,7 +405,10 @@ class FormPage(Directory, FormTemplateMixin):
magictoken = get_request().form['magictoken']
self.feed_current_data(magictoken)
form = self.create_form(page, displayed_fields)
with get_publisher().substitutions.temporary_feed(
transient_formdata, force_mode='lazy'):
form = self.create_form(page, displayed_fields, transient_formdata=transient_formdata)
if submit_button is True:
# submit_button at True means a non-submitting button has been
# clicked; details in [ADD_ROW_BUTTON].
@ -952,7 +955,8 @@ class FormPage(Directory, FormTemplateMixin):
if form.has_errors() or form.get_submit() is True:
return self.page(page, page_change=False,
page_error_messages=page_error_messages,
submit_button=form.get_submit())
submit_button=form.get_submit(),
transient_formdata=transient_formdata)
form_data = session.get_by_magictoken(magictoken, {})
with get_publisher().substitutions.temporary_feed(