1683 lines
58 KiB
Python
1683 lines
58 KiB
Python
import json
|
|
import os
|
|
import time
|
|
import urllib
|
|
|
|
import pytest
|
|
import responses
|
|
from webtest import Upload
|
|
|
|
from wcs import fields
|
|
from wcs.admin.settings import UserFieldsFormDef
|
|
from wcs.blocks import BlockDef
|
|
from wcs.carddef import CardDef
|
|
from wcs.categories import Category
|
|
from wcs.data_sources import NamedDataSource
|
|
from wcs.wf.create_formdata import Mapping
|
|
from wcs.workflows import Workflow
|
|
|
|
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
|
|
from .test_all import assert_current_page, create_formdef, create_user, get_displayed_tracking_code
|
|
|
|
|
|
def pytest_generate_tests(metafunc):
|
|
if 'pub' in metafunc.fixturenames:
|
|
metafunc.parametrize('pub', ['sql', 'sql-lazy'], indirect=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def pub(request):
|
|
pub = create_temporary_pub(lazy_mode=bool('lazy' in request.param))
|
|
pub.cfg['identification'] = {'methods': ['password']}
|
|
pub.cfg['language'] = {'language': 'en'}
|
|
pub.cfg['users'] = {
|
|
'field_phone': '_phone',
|
|
}
|
|
pub.write_cfg()
|
|
|
|
formdef = UserFieldsFormDef(pub)
|
|
formdef.fields = [
|
|
fields.StringField(id='_phone', label='phone', varname='phone', validation={'type': 'phone'})
|
|
]
|
|
formdef.store()
|
|
|
|
Category.wipe()
|
|
cat = Category(name='foobar')
|
|
cat.store()
|
|
|
|
return pub
|
|
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
|
|
def test_form_phone_prefill(pub, nocache):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': 'phone'})]
|
|
formdef.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.pyquery('input#form_f0').val() == '01 23 45 67 89'
|
|
resp.forms[0]['f0'] = '+33987654321'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.pyquery('button.form-submit').val() == 'Submit'
|
|
|
|
|
|
def test_form_phone_prefill_phone_fr_validation(pub, nocache):
|
|
create_user(pub)
|
|
pub.load_site_options()
|
|
if not pub.site_options.has_section('options'):
|
|
pub.site_options.add_section('options')
|
|
pub.site_options.set('options', 'local-region-code', 'FR')
|
|
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
|
pub.site_options.write(fd)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
field = fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': 'phone'})
|
|
field.validation = {'type': 'phone-fr'}
|
|
formdef.fields = [field]
|
|
formdef.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.pyquery('input#form_f0').val() == '01 23 45 67 89'
|
|
resp.forms[0]['f0'] = '0987654321'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.pyquery('button.form-submit').val() == 'Submit'
|
|
|
|
|
|
def test_form_phone_prefill_phone_validation(pub, nocache):
|
|
user = create_user(pub)
|
|
pub.load_site_options()
|
|
if not pub.site_options.has_section('options'):
|
|
pub.site_options.add_section('options')
|
|
pub.site_options.set('options', 'local-region-code', 'BE')
|
|
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
|
pub.site_options.write(fd)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
field = fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': 'phone'})
|
|
field.validation = {'type': 'phone'}
|
|
formdef.fields = [field]
|
|
formdef.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.pyquery('input#form_f0').val() == '01 23 45 67 89'
|
|
resp.forms[0]['f0'] = '0987654321'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.pyquery('button.form-submit').val() == 'Submit'
|
|
|
|
user.form_data['_phone'] = '+3281000000'
|
|
user.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.pyquery('input#form_f0').val() == '081 00 00 00'
|
|
resp.forms[0]['f0'] = '0987654321'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.pyquery('button.form-submit').val() == 'Submit'
|
|
|
|
user.form_data['_phone'] = '+99981000000'
|
|
user.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.pyquery('input#form_f0').val() == '+99981000000'
|
|
resp.forms[0]['f0'] = '0987654321'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.pyquery('button.form-submit').val() == 'Submit'
|
|
|
|
|
|
def test_form_tracking_code_prefill(pub, nocache):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': 'email'})]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
|
|
# first time
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert '<h3>Tracking code</h3>' in resp.text
|
|
assert 'You already started to fill this form.' not in resp.text
|
|
resp.forms[0]['f0'] = 'foobar'
|
|
resp = resp.forms[0].submit('submit')
|
|
|
|
# second time, invitation to load an existing draft
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert '<h3>Tracking code</h3>' in resp.text
|
|
assert 'You already started to fill this form.' in resp.text
|
|
|
|
|
|
@pytest.mark.parametrize('field_type', ['string', 'item'])
|
|
@pytest.mark.parametrize('logged_in', ['anonymous', 'logged-in'])
|
|
def test_form_draft_from_prefill(pub, field_type, logged_in):
|
|
create_user(pub)
|
|
|
|
formdef = create_formdef()
|
|
if field_type == 'string':
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
else:
|
|
formdef.fields = [fields.ItemField(id='0', label='item', items=['foo', 'bar', 'hello'])]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
if logged_in == 'logged-in':
|
|
login(app, username='foo', password='foo')
|
|
|
|
# no draft
|
|
app.get('/test/')
|
|
assert formdef.data_class().count() == 0
|
|
formdef.data_class().wipe()
|
|
|
|
# draft created if there's been some prefilled fields
|
|
formdef.fields[0].prefill = {'type': 'string', 'value': '{{request.GET.test|default:""}}'}
|
|
formdef.store()
|
|
app.get('/test/?test=hello')
|
|
assert formdef.data_class().count() == 1
|
|
formdef.data_class().wipe()
|
|
|
|
# unless the call was made from an application
|
|
app.get('/test/?test=hello', headers={'User-agent': 'python-requests/0'})
|
|
assert formdef.data_class().count() == 0
|
|
|
|
# or a bot
|
|
app.get('/test/?test=hello', headers={'User-agent': 'Googlebot'})
|
|
assert formdef.data_class().count() == 0
|
|
|
|
# check there's no leftover draft after submission
|
|
for with_tracking_code in (False, True):
|
|
formdef.enable_tracking_codes = with_tracking_code
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = app.get('/test/?test=hello')
|
|
resp = resp.form.submit('submit') # -> validation
|
|
resp = resp.form.submit('submit') # -> submit
|
|
assert formdef.data_class().count() == 1
|
|
|
|
|
|
def test_form_page_string_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', prefill={'type': 'string', 'value': 'HELLO WORLD'})
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'HELLO WORLD'
|
|
assert 'widget-prefilled' in resp.text
|
|
|
|
|
|
def test_form_page_profile_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': 'email'})]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'foo@localhost'
|
|
|
|
|
|
def test_form_page_profile_first_name_prefill(pub):
|
|
user = create_user(pub)
|
|
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields = [
|
|
fields.StringField(id='_first_name', label='first name', extra_css_class='autocomplete-given-name'),
|
|
fields.StringField(id='_city', label='city', extra_css_class='autocomplete-address-level2'),
|
|
fields.StringField(id='_plop', label='plop', extra_css_class='xxx'),
|
|
]
|
|
user_formdef.store()
|
|
user.form_data = {'_first_name': 'plop', '_city': 'mytown'}
|
|
user.set_attributes_from_formdata(user.form_data)
|
|
user.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': '_first_name'}),
|
|
fields.StringField(id='1', label='string', prefill={'type': 'user', 'value': '_city'}),
|
|
fields.StringField(id='2', label='string', prefill={'type': 'user', 'value': '_plop'}),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
assert resp.forms[0]['f0'].attrs['autocomplete'] == 'given-name' # html5
|
|
assert resp.forms[0]['f1'].value == ''
|
|
assert resp.forms[0]['f1'].attrs['autocomplete'] == 'address-level2' # html5
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'plop'
|
|
assert resp.forms[0]['f1'].value == 'mytown'
|
|
|
|
|
|
def test_form_page_formula_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', prefill={'type': 'formula', 'value': repr('HELLO WORLD')})
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'HELLO WORLD'
|
|
assert 'widget-prefilled' in resp.text
|
|
|
|
|
|
def test_form_page_template_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id='0', label='string', prefill={'type': 'string', 'value': '{{session_user_display_name}}'}
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub), username='foo', password='foo')
|
|
resp = app.get('/test/')
|
|
assert resp.form['f0'].value == 'User Name'
|
|
assert 'widget-prefilled' in resp.text
|
|
|
|
# erroneous prefill
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id='0',
|
|
label='string',
|
|
prefill={'type': 'string', 'value': '{{session_user_display_name|unknown}}'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
resp = app.get('/test/')
|
|
assert resp.form['f0'].value == ''
|
|
# still marked with a css class, in case of live changes.
|
|
assert 'widget-prefilled' in resp.text
|
|
|
|
|
|
def test_form_page_session_var_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', prefill={'type': 'formula', 'value': 'session_var_foo'})
|
|
]
|
|
formdef.store()
|
|
|
|
# check it's empty if it doesn't exist
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
# check it's not set if it's not whitelisted
|
|
resp = get_app(pub).get('/?session_var_foo=hello')
|
|
assert urllib.parse.urlparse(resp.location).path == '/'
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
# check it works
|
|
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
|
fd.write(
|
|
'''[options]
|
|
query_string_allowed_vars = foo,bar
|
|
'''
|
|
)
|
|
|
|
resp = get_app(pub).get('/?session_var_foo=hello')
|
|
assert urllib.parse.urlparse(resp.location).path == '/'
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == 'hello'
|
|
|
|
# check it survives a login
|
|
resp = get_app(pub).get('/?session_var_foo=hello2')
|
|
assert urllib.parse.urlparse(resp.location).path == '/'
|
|
resp = resp.follow()
|
|
resp = resp.click('Login')
|
|
resp = resp.follow()
|
|
resp.forms[0]['username'] = 'foo'
|
|
resp.forms[0]['password'] = 'foo'
|
|
resp = resp.forms[0].submit()
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == 'hello2'
|
|
|
|
# check repeated options are ignored
|
|
resp = get_app(pub).get('/?session_var_foo=hello&session_var_foo=hello2')
|
|
assert urllib.parse.urlparse(resp.location).path == '/'
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
# check extra query string parameters are not lost
|
|
resp = get_app(pub).get('/?session_var_foo=hello&foo=bar')
|
|
assert urllib.parse.urlparse(resp.location).path == '/'
|
|
assert urllib.parse.urlparse(resp.location).query == 'foo=bar'
|
|
|
|
os.unlink(os.path.join(pub.app_dir, 'site-options.cfg'))
|
|
|
|
|
|
def test_form_page_template_list_prefill(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='1',
|
|
label='item',
|
|
varname='item',
|
|
required=True,
|
|
items=['Foo', 'Bar'],
|
|
prefill={'type': 'string', 'value': 'Foo'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].value == 'Foo'
|
|
|
|
formdef.fields[0].prefill['value'] = 'Bar'
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].value == 'Bar'
|
|
|
|
formdef.fields[0].prefill['value'] = 'Baz'
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
assert 'invalid value selected' in resp.text
|
|
|
|
formdef.fields[0].prefill['value'] = '{{plop|default:""}}'
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
assert 'invalid value selected' not in resp.text
|
|
|
|
|
|
def test_form_page_template_list_prefill_by_text(pub):
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'jsonvalue',
|
|
'value': '[{"id": 1, "text": "foo"}, {"id": 2, "text": "bar"}]',
|
|
}
|
|
data_source.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='1',
|
|
label='item',
|
|
varname='item',
|
|
required=True,
|
|
data_source={'type': data_source.slug},
|
|
prefill={'type': 'string', 'value': 'bar'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].value == '2'
|
|
assert 'invalid value selected' not in resp.text
|
|
|
|
# check with card data source
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'Test'
|
|
carddef.fields = [
|
|
fields.StringField(id='0', label='blah', varname='blah'),
|
|
]
|
|
carddef.digest_templates = {'default': '{{ form_var_blah }}'}
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
|
|
carddata1 = carddef.data_class()()
|
|
carddata1.data = {'0': 'foo'}
|
|
carddata1.just_created()
|
|
carddata1.store()
|
|
|
|
carddata2 = carddef.data_class()()
|
|
carddata2.data = {'0': 'bar'}
|
|
carddata2.just_created()
|
|
carddata2.store()
|
|
|
|
formdef.data_source = {'type': 'carddef:test'}
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].value == str(carddata2.id)
|
|
assert 'invalid value selected' not in resp.text
|
|
|
|
formdef.fields[0].prefill = {'type': 'string', 'value': '{{ %s }}' % carddata2.id}
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
assert resp.form['f1'].value == str(carddata2.id)
|
|
assert 'invalid value selected' not in resp.text
|
|
assert app.post('/test/autosave', params=resp.form.submit_fields()).json == {'result': 'success'}
|
|
|
|
|
|
@pytest.mark.parametrize('id_type', [int, str])
|
|
def test_form_page_template_list_prefill_by_number(pub, id_type):
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'jsonvalue',
|
|
'value': json.dumps([{'id': id_type(1), 'text': 'foo'}, {'id': id_type(2), 'text': 'bar'}]),
|
|
}
|
|
data_source.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.enable_tracking_codes = True
|
|
formdef.fields = [
|
|
fields.PageField(id='1', label='1st page'),
|
|
fields.ItemField(
|
|
id='2',
|
|
label='item',
|
|
varname='item',
|
|
required=True,
|
|
data_source={'type': data_source.slug},
|
|
prefill={'type': 'string', 'value': '{{ 2 }}'},
|
|
),
|
|
fields.PageField(id='3', label='2nd page'),
|
|
fields.ItemField(
|
|
id='4',
|
|
label='item',
|
|
varname='item',
|
|
required=True,
|
|
data_source={'type': data_source.slug},
|
|
prefill={'type': 'string', 'value': '{{ 3 }}'}, # invalid value
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
assert resp.form['f2'].value == '2'
|
|
assert 'invalid value selected' not in resp.text
|
|
assert app.post('/test/autosave', params=resp.form.submit_fields()).json == {'result': 'success'}
|
|
resp = resp.form.submit('submit')
|
|
assert 'invalid value selected' in resp.text
|
|
|
|
|
|
def test_form_page_query_string_list_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='1',
|
|
label='item',
|
|
varname='item',
|
|
required=False,
|
|
data_source={'type': 'foobar'},
|
|
prefill={'type': 'string', 'value': '{{request.GET.preselect}}'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'jsonvalue',
|
|
'value': json.dumps(
|
|
[
|
|
{'id': '1', 'text': 'un'},
|
|
{'id': '2', 'text': 'deux'},
|
|
{'id': '3', 'text': 'trois'},
|
|
{'id': '4', 'text': 'quatre'},
|
|
]
|
|
),
|
|
}
|
|
data_source.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].value == '1'
|
|
|
|
resp = get_app(pub).get('/test/?preselect=2')
|
|
assert resp.form['f1'].value == '2'
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.form.submit('submit').follow()
|
|
assert 'deux' in resp.text
|
|
|
|
|
|
def test_form_page_profile_prefill_list(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='0',
|
|
label='item',
|
|
items=['', 'bar@localhost', 'foo@localhost'],
|
|
required=False,
|
|
prefill={'type': 'user', 'value': 'email'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'foo@localhost'
|
|
|
|
# invalid value
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='0',
|
|
label='item',
|
|
items=['', 'bar@localhost'],
|
|
required=False,
|
|
prefill={'type': 'user', 'value': 'email'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert 'invalid value selected' in resp.text
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
|
|
def test_form_page_item_with_variable_data_source_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id='1', label='string', varname='string', prefill={'type': 'string', 'value': 'foobar'}
|
|
),
|
|
fields.ItemField(
|
|
id='2',
|
|
label='item',
|
|
varname='item',
|
|
required=False,
|
|
data_source={'type': 'foobar'},
|
|
prefill={'type': 'string', 'value': '4'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'json',
|
|
'value': 'http://example.net/{{form_var_string}}',
|
|
}
|
|
data_source.store()
|
|
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.get('http://example.net/None', json={'data': [{'id': '1', 'text': 'hello'}]})
|
|
rsps.get(
|
|
'http://example.net/foobar',
|
|
json={'data': [{'id': '1', 'text': 'hello'}, {'id': '4', 'text': 'world'}]},
|
|
)
|
|
resp = get_app(pub).get('/test/')
|
|
assert len(rsps.calls) == 2
|
|
assert rsps.calls[0].request.url == 'http://example.net/None'
|
|
assert rsps.calls[1].request.url == 'http://example.net/foobar'
|
|
assert [x.attrib['value'] for x in resp.pyquery('#form_f2 option')] == ['1', '4']
|
|
assert resp.form['f2'].value == '4'
|
|
assert not resp.pyquery('#form_error_f2').text()
|
|
|
|
|
|
def test_form_page_item_with_card_with_custom_id_prefill(pub):
|
|
create_user(pub)
|
|
CardDef.wipe()
|
|
|
|
carddef = CardDef()
|
|
carddef.name = 'Test'
|
|
carddef.fields = [
|
|
fields.StringField(id='0', label='blah', varname='blah'),
|
|
]
|
|
carddef.digest_templates = {'default': '{{ form_var_blah|upper }}'}
|
|
carddef.id_template = '{{ form_var_blah }}'
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
|
|
carddata1 = carddef.data_class()()
|
|
carddata1.data = {'0': 'bar'}
|
|
carddata1.just_created()
|
|
carddata1.store()
|
|
|
|
carddata2 = carddef.data_class()()
|
|
carddata2.data = {'0': 'foo'}
|
|
carddata2.just_created()
|
|
carddata2.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='2',
|
|
label='item',
|
|
varname='item',
|
|
required=False,
|
|
data_source={'type': 'carddef:test'},
|
|
prefill={'type': 'string', 'value': 'foo'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert [x.attrib['value'] for x in resp.pyquery('#form_f2 option')] == ['bar', 'foo']
|
|
assert resp.form['f2'].value == 'foo'
|
|
assert not resp.pyquery('#form_error_f2').text()
|
|
|
|
|
|
def test_form_page_block_with_item_with_card_with_custom_id_prefill(pub):
|
|
create_user(pub)
|
|
CardDef.wipe()
|
|
|
|
carddef = CardDef()
|
|
carddef.name = 'Test'
|
|
carddef.fields = [
|
|
fields.StringField(id='0', label='blah', varname='blah'),
|
|
]
|
|
carddef.digest_templates = {'default': 'card {{ form_var_blah }}'}
|
|
carddef.id_template = '{{ form_var_blah }}'
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
|
|
carddata1 = carddef.data_class()()
|
|
carddata1.data = {'0': 'bar'}
|
|
carddata1.just_created()
|
|
carddata1.store()
|
|
|
|
carddata2 = carddef.data_class()()
|
|
carddata2.data = {'0': 'foo'}
|
|
carddata2.just_created()
|
|
carddata2.store()
|
|
|
|
BlockDef.wipe()
|
|
block = BlockDef()
|
|
block.name = 'foobar'
|
|
block.fields = [
|
|
fields.ItemField(
|
|
id='123',
|
|
label='item',
|
|
varname='item',
|
|
required=False,
|
|
data_source={'type': 'carddef:test'},
|
|
),
|
|
]
|
|
block.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.BlockField(
|
|
id='2',
|
|
label='test',
|
|
block_slug='foobar',
|
|
varname='foobar',
|
|
prefill={'type': 'string', 'value': '{% block_value item="foo" %}'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert [x.attrib['value'] for x in resp.pyquery('#form_f2__element0__f123 option')] == ['bar', 'foo']
|
|
assert resp.form['f2$element0$f123'].value == 'foo'
|
|
assert not resp.pyquery('.widget-with-error')
|
|
|
|
|
|
def test_form_page_item_with_computed_field_variable_data_source_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='string',
|
|
varname='string',
|
|
value_template='foobar',
|
|
),
|
|
fields.ItemField(
|
|
id='2',
|
|
label='item',
|
|
varname='item',
|
|
required=False,
|
|
data_source={'type': 'foobar'},
|
|
prefill={'type': 'string', 'value': '4'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'json',
|
|
'value': 'http://example.net/{{form_var_string}}',
|
|
}
|
|
data_source.store()
|
|
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.get(
|
|
'http://example.net/foobar',
|
|
json={'data': [{'id': '1', 'text': 'hello'}, {'id': '4', 'text': 'world'}]},
|
|
)
|
|
resp = get_app(pub).get('/test/')
|
|
assert [x.attrib['value'] for x in resp.pyquery('#form_f2 option')] == ['1', '4']
|
|
assert resp.form['f2'].value == '4'
|
|
assert not resp.pyquery('#form_error_f2').text()
|
|
|
|
|
|
def test_form_page_formula_prefill_items_field(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemsField(
|
|
id='0',
|
|
label='items',
|
|
items=['foo', 'bar', 'baz'],
|
|
prefill={'type': 'formula', 'value': '["foo", "baz"]'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0$element0'].checked
|
|
assert not resp.form['f0$element1'].checked
|
|
assert resp.form['f0$element2'].checked
|
|
assert 'widget-prefilled' in resp.text
|
|
|
|
resp.form['f0$element0'].checked = False
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.form.submit('submit').follow()
|
|
assert '>foo<' not in resp.text
|
|
assert '>bar<' not in resp.text
|
|
assert '>baz<' in resp.text
|
|
|
|
# check with remote json
|
|
ds = {'type': 'json', 'value': 'http://remote.example.net/json'}
|
|
formdef.fields = [
|
|
fields.ItemsField(
|
|
id='0',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill={'type': 'formula', 'value': '["2"]'},
|
|
)
|
|
]
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert not resp.form['f0$element1'].checked
|
|
assert resp.form['f0$element2'].checked
|
|
|
|
|
|
def test_form_page_checkbox_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.BoolField(id='0', label='check', prefill={'type': 'formula', 'value': 'True'})]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].checked
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert resp.forms[0]['f0'].value == 'True'
|
|
assert resp.forms[0]['f0disabled'].checked
|
|
assert resp.forms[0]['f0disabled'].attrs['disabled']
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f0'].checked = False
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert resp.forms[0]['f0'].value == 'False'
|
|
assert not resp.forms[0]['f0disabled'].checked
|
|
assert resp.forms[0]['f0disabled'].attrs['disabled']
|
|
|
|
# check with locked value
|
|
formdef.fields[0].prefill['locked'] = True
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].attrs['onclick']
|
|
assert resp.forms[0]['f0'].checked
|
|
resp.forms[0]['f0'].checked = False # alter value while it's not allowed
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert resp.forms[0]['f0'].value == 'True'
|
|
assert resp.forms[0]['f0disabled'].checked
|
|
assert resp.forms[0]['f0disabled'].attrs['disabled']
|
|
|
|
|
|
def test_form_page_date_prefill(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
# check simple date and with a template with extraneous space
|
|
for value in ('2023-07-07', '{{ " 2023-07-07" }}'):
|
|
formdef.fields = [fields.DateField(id='0', label='date', prefill={'type': 'string', 'value': value})]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == '2023-07-07'
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert resp.forms[0]['f0'].value == '2023-07-07'
|
|
|
|
|
|
@pytest.mark.parametrize('prefill_value', ['foo,baz', 'foo|baz'])
|
|
def test_form_page_template_prefill_items_field_checkboxes(pub, prefill_value):
|
|
# prefill value should be given as foo|baz but foo,baz has been used for a while
|
|
# and must be kept working (even if it worked by chance).
|
|
BlockDef.wipe()
|
|
create_user(pub)
|
|
|
|
block = BlockDef()
|
|
block.name = 'foobar'
|
|
block.fields = [
|
|
fields.StringField(id='123', required=True, label='Test', varname='test'),
|
|
]
|
|
block.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemsField(
|
|
id='0',
|
|
label='items',
|
|
items=['foo', 'bar', 'baz'],
|
|
prefill={'type': 'string', 'value': prefill_value},
|
|
),
|
|
fields.FileField(id='1', label='file', varname='file'),
|
|
fields.BlockField(id='2', label='test', block_slug='foobar', varname='foobar'),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0$element0'].checked
|
|
assert not resp.form['f0$element1'].checked
|
|
assert resp.form['f0$element2'].checked
|
|
# this selection will be reused in the complex data test
|
|
resp.form['f0$element1'].checked = True
|
|
resp.form['f0$element2'].checked = False
|
|
assert 'widget-prefilled' in resp.text
|
|
resp.form['f1$file'] = Upload('test.txt', b'foobar', 'text/plain')
|
|
resp.form['f2$element0$f123'] = 'plop'
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.form.submit('submit')
|
|
assert formdef.data_class().count() == 1
|
|
|
|
# check with remote json
|
|
ds = {'type': 'json', 'value': 'http://remote.example.net/json'}
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill={'type': 'string', 'value': prefill_value},
|
|
)
|
|
formdef.store()
|
|
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.get(
|
|
'http://remote.example.net/json',
|
|
json={
|
|
'data': [
|
|
{'id': 'foo', 'text': 'hello'},
|
|
{'id': 'bar', 'text': 'world'},
|
|
{'id': 'baz', 'text': '!'},
|
|
]
|
|
},
|
|
)
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0$elementfoo'].checked
|
|
assert not resp.form['f0$elementbar'].checked
|
|
assert resp.form['f0$elementbaz'].checked
|
|
|
|
# check with template returning a complex data
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
varname='items',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill={'type': 'string', 'value': '{{form_objects|first|get:"form_var_items_raw"}}'},
|
|
)
|
|
formdef.store()
|
|
|
|
# it will use foo,bar as selected in the first part of this test
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0$elementfoo'].checked
|
|
assert resp.form['f0$elementbar'].checked
|
|
assert not resp.form['f0$elementbaz'].checked
|
|
|
|
# check with complex data of wrong type
|
|
for invalid_prefill_value in [
|
|
{'type': 'string', 'value': '{{form_objects|first|get:"form_var_file_raw"}}'},
|
|
{'type': 'string', 'value': '{{form_objects|first|get:"form_var_foobar"}}'},
|
|
{'type': 'formula', 'value': '[{"a": "foo", "b": "baz"}]'},
|
|
]:
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
varname='items',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill=invalid_prefill_value,
|
|
)
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert not resp.form['f0$elementfoo'].checked
|
|
assert not resp.form['f0$elementbar'].checked
|
|
assert not resp.form['f0$elementbaz'].checked
|
|
|
|
assert pub.loggederror_class.count() == 1
|
|
logged_error = pub.loggederror_class.select()[0]
|
|
assert logged_error.summary == 'Invalid value for items prefill on field "items"'
|
|
pub.loggederror_class.wipe()
|
|
|
|
# check with a "none" explicit prefill, or a None value
|
|
for none_prefill_value in [
|
|
{},
|
|
{'type': 'none'},
|
|
{'type': 'string', 'value': '{{ None }}'},
|
|
{'type': 'formula', 'value': 'None'},
|
|
]:
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
varname='items',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill=none_prefill_value,
|
|
)
|
|
formdef.store()
|
|
|
|
# all checkboxes will be left unchecked
|
|
resp = get_app(pub).get('/test/')
|
|
assert not resp.form['f0$elementfoo'].checked
|
|
assert not resp.form['f0$elementbar'].checked
|
|
assert not resp.form['f0$elementbaz'].checked
|
|
assert pub.loggederror_class.count() == 0
|
|
|
|
|
|
def test_form_page_template_prefill_items_field_autocomplete(pub):
|
|
BlockDef.wipe()
|
|
create_user(pub)
|
|
|
|
block = BlockDef()
|
|
block.name = 'foobar'
|
|
block.fields = [
|
|
fields.StringField(id='123', required=True, label='Test', varname='test'),
|
|
]
|
|
block.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemsField(
|
|
id='0',
|
|
label='items',
|
|
items=['foo', 'bar', 'baz'],
|
|
prefill={'type': 'string', 'value': 'foo|baz'},
|
|
display_mode='autocomplete',
|
|
),
|
|
fields.FileField(id='1', label='file', varname='file'),
|
|
fields.BlockField(id='2', label='test', block_slug='foobar', varname='foobar'),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0[]'].value == ['foo', 'baz']
|
|
# this selection will be reused in the complex data test
|
|
resp.form['f0[]'].value = ['foo', 'bar']
|
|
assert 'widget-prefilled' in resp.text
|
|
resp.form['f1$file'] = Upload('test.txt', b'foobar', 'text/plain')
|
|
resp.form['f2$element0$f123'] = 'plop'
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.form.submit('submit')
|
|
assert formdef.data_class().count() == 1
|
|
|
|
# check with remote json
|
|
ds = {'type': 'json', 'value': 'http://remote.example.net/json'}
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill={'type': 'string', 'value': 'foo|baz'},
|
|
display_mode='autocomplete',
|
|
)
|
|
formdef.store()
|
|
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.get(
|
|
'http://remote.example.net/json',
|
|
json={
|
|
'data': [
|
|
{'id': 'foo', 'text': 'hello'},
|
|
{'id': 'bar', 'text': 'world'},
|
|
{'id': 'baz', 'text': '!'},
|
|
]
|
|
},
|
|
)
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0[]'].value == ['foo', 'baz']
|
|
|
|
# check with template returning a complex data
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
varname='items',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill={'type': 'string', 'value': '{{form_objects|first|get:"form_var_items_raw"}}'},
|
|
display_mode='autocomplete',
|
|
)
|
|
formdef.store()
|
|
|
|
# it will use foo,bar as selected in the first part of this test
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0[]'].value == ['foo', 'bar']
|
|
|
|
# check with complex data of wrong type
|
|
for invalid_prefill_value in [
|
|
{'type': 'string', 'value': '{{form_objects|first|get:"form_var_file_raw"}}'},
|
|
{'type': 'string', 'value': '{{form_objects|first|get:"form_var_foobar"}}'},
|
|
{'type': 'formula', 'value': '[{"a": "foo", "b": "baz"}]'},
|
|
]:
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
varname='items',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill=invalid_prefill_value,
|
|
display_mode='autocomplete',
|
|
)
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0[]'].value is None
|
|
|
|
assert pub.loggederror_class.count() == 1
|
|
logged_error = pub.loggederror_class.select()[0]
|
|
assert logged_error.summary == 'Invalid value for items prefill on field "items"'
|
|
pub.loggederror_class.wipe()
|
|
|
|
# check with a "none" explicit prefill, or a None value
|
|
for none_prefill_value in [
|
|
{},
|
|
{'type': 'none'},
|
|
{'type': 'string', 'value': '{{ None }}'},
|
|
{'type': 'formula', 'value': 'None'},
|
|
]:
|
|
formdef.fields[0] = fields.ItemsField(
|
|
id='0',
|
|
varname='items',
|
|
label='items',
|
|
data_source=ds,
|
|
display_disabled_items=True,
|
|
prefill=none_prefill_value,
|
|
display_mode='autocomplete',
|
|
)
|
|
formdef.store()
|
|
|
|
# all checkboxes will be left unchecked
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0[]'].value is None
|
|
assert pub.loggederror_class.count() == 0
|
|
|
|
|
|
def test_form_page_changing_prefill(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page'),
|
|
fields.StringField(id='1', label='string', varname='foo'),
|
|
fields.PageField(id='2', label='2nd page'),
|
|
fields.StringField(
|
|
id='3', label='string 2', prefill={'type': 'string', 'value': '{{ form_var_foo }} World'}
|
|
),
|
|
fields.PageField(id='4', label='3rd page'),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.form['f1'] = 'Hello'
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert resp.form['f3'].value == 'Hello World'
|
|
resp = resp.form.submit('submit') # -> 3rd page
|
|
resp = resp.form.submit('previous') # back to 2nd page
|
|
assert resp.form['f3'].value == 'Hello World'
|
|
resp = resp.form.submit('previous') # back to 1st page
|
|
assert resp.form['f1'].value == 'Hello'
|
|
resp.form['f1'] = 'Goodbye Cruel'
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert resp.form['f3'].value == 'Goodbye Cruel World'
|
|
resp = resp.form.submit('submit') # -> 3rd page
|
|
resp = resp.form.submit('previous') # back to 2nd page
|
|
resp.form['f3'].value = 'Changed value'
|
|
resp = resp.form.submit('previous') # back to 1st page
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert resp.form['f3'].value == 'Changed value'
|
|
resp = resp.form.submit('submit') # -> 3rd page
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert resp.form['f3'].value == 'Changed value'
|
|
|
|
|
|
def test_form_page_changing_prefill_draft(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page'),
|
|
fields.StringField(id='1', label='string', varname='foo'),
|
|
fields.PageField(id='2', label='2nd page'),
|
|
fields.StringField(
|
|
id='3', label='string 2', prefill={'type': 'string', 'value': '{{ form_var_foo }} World'}
|
|
),
|
|
fields.PageField(id='4', label='3rd page'),
|
|
]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.form['f1'] = 'Hello'
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert resp.form['f3'].value == 'Hello World'
|
|
resp = resp.form.submit('submit') # -> 3rd page
|
|
resp = resp.form.submit('previous') # back to 2nd page
|
|
assert resp.form['f3'].value == 'Hello World'
|
|
resp = resp.form.submit('submit') # -> 3rd page
|
|
tracking_code = get_displayed_tracking_code(resp)
|
|
|
|
# start with a new session and restore draft using the tracking code
|
|
resp = get_app(pub).get('/')
|
|
resp.form['code'] = tracking_code
|
|
resp = resp.form.submit().follow().follow().follow()
|
|
assert_current_page(resp, '3rd page')
|
|
resp = resp.forms[1].submit('previous') # back to 2nd page
|
|
assert resp.forms[1]['f3'].value == 'Hello World'
|
|
resp = resp.forms[1].submit('previous') # back to 1st page
|
|
assert resp.forms[1]['f1'].value == 'Hello'
|
|
resp.forms[1]['f1'] = 'Goodbye Cruel'
|
|
resp = resp.forms[1].submit('submit') # -> 2nd page
|
|
assert resp.forms[1]['f3'].value == 'Goodbye Cruel World'
|
|
|
|
|
|
def test_prefill_query_parameter(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page'),
|
|
fields.StringField(
|
|
id='1',
|
|
label='str',
|
|
varname='foo',
|
|
required=False,
|
|
prefill={'type': 'string', 'value': '{{request.GET.prefill}}'},
|
|
),
|
|
fields.PageField(id='2', label='2nd page'),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/?prefill=Hello')
|
|
assert resp.form['f1'].value == 'Hello'
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
resp = resp.form.submit('previous') # back to 1st page
|
|
# check it has not be reset to the empty string (as there's no request.GET
|
|
# anymore)
|
|
assert resp.form['f1'].value == 'Hello'
|
|
|
|
|
|
def test_form_table_rows_field_and_prefill(pub, emails):
|
|
formdef = create_formdef()
|
|
formdef.fields = [
|
|
fields.TableRowsField(id='0', label='table', columns=['a', 'b'], required=True),
|
|
fields.StringField(id='1', label='string', prefill={'type': 'string', 'value': 'HELLO WORLD'}),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
get_app(pub).get('/test/')
|
|
|
|
|
|
def test_form_map_field_prefill_address(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page'),
|
|
fields.StringField(id='1', label='address', required=True, varname='address'),
|
|
fields.PageField(id='2', label='2nd page'),
|
|
fields.MapField(id='3', label='map', prefill={'type': 'string', 'value': '{{ form_var_address }}'}),
|
|
]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.form['f1'] = '169 rue du chateau, paris'
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.get('https://nominatim.entrouvert.org/search', json=[{'lat': '48.8337085', 'lon': '2.3233693'}])
|
|
resp = resp.form.submit('submit')
|
|
assert resp.form['f3$latlng'].value == '48.8337085;2.3233693'
|
|
assert 'chateau' in rsps.calls[0].request.url
|
|
|
|
|
|
def test_form_map_field_prefill_coords(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page'),
|
|
fields.MapField(id='1', label='map', varname='map1'),
|
|
fields.PageField(id='2', label='2nd page'),
|
|
fields.MapField(id='3', label='map', prefill={'type': 'string', 'value': '{{ form_var_map1 }}'}),
|
|
]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.form['f1$latlng'] = '1.234;-1.234'
|
|
resp = resp.form.submit('submit')
|
|
assert resp.form['f3$latlng'].value == '1.234;-1.234'
|
|
|
|
|
|
def test_form_page_formula_prefill_user_name(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', prefill={'type': 'formula', 'value': 'form_user_email'})
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'foo@localhost'
|
|
|
|
|
|
def test_form_page_formula_prefill_session_user(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', prefill={'type': 'formula', 'value': 'session_user_email'})
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'foo@localhost'
|
|
|
|
app = login(get_app(pub), username='foo', password='foo')
|
|
for session in pub.session_manager.values():
|
|
session.extra_user_variables = {'foo': 'bar'}
|
|
session.store()
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id='0', label='string', prefill={'type': 'formula', 'value': 'session_var_user_foo'}
|
|
)
|
|
]
|
|
formdef.store()
|
|
resp = app.get('/test/')
|
|
assert resp.forms[0]['f0'].value == 'bar'
|
|
|
|
|
|
def test_form_page_profile_verified_prefill(pub):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string', prefill={'type': 'user', 'value': 'email'})]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0'].value == ''
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
assert 'readonly' not in resp.form['f0'].attrs
|
|
resp.form['f0'].value = 'Hello'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert resp.form['f0'].value == 'Hello'
|
|
|
|
user.verified_fields = ['email']
|
|
user.store()
|
|
|
|
for prefill_settings in (
|
|
{'type': 'user', 'value': 'email'}, # verified profile
|
|
{'type': 'string', 'value': 'foo@localhost', 'locked': True}, # locked value
|
|
):
|
|
formdef.confirmation = True
|
|
formdef.fields[0].prefill = prefill_settings
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
assert 'readonly' in resp.form['f0'].attrs
|
|
|
|
resp.form['f0'].value = 'Hello' # try changing the value
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert resp.form['f0'].value == 'foo@localhost' # it is reverted
|
|
|
|
resp.form['f0'].value = 'Hello' # try again changing the value
|
|
resp = resp.form.submit('submit')
|
|
|
|
formdatas = [x for x in formdef.data_class().select() if not x.is_draft()]
|
|
assert len(formdatas) == 1
|
|
assert formdatas[0].data['0'] == 'foo@localhost'
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
resp.form['f0'].value = 'Hello' # try changing
|
|
resp = resp.form.submit('previous')
|
|
assert 'readonly' in resp.form['f0'].attrs
|
|
assert 'Check values then click submit.' not in resp.text
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
|
|
# try it without validation page
|
|
formdef.confirmation = False
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
assert 'readonly' in resp.form['f0'].attrs
|
|
|
|
resp.form['f0'].value = 'Hello' # try changing the value
|
|
resp = resp.form.submit('submit')
|
|
|
|
formdatas = [x for x in formdef.data_class().select() if not x.is_draft()]
|
|
assert len(formdatas) == 1
|
|
assert formdatas[0].data['0'] == 'foo@localhost'
|
|
|
|
|
|
def test_form_page_verified_prefill_error_page(pub):
|
|
user = create_user(pub)
|
|
user.verified_fields = ['email']
|
|
user.store()
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='0', label='string', required=False),
|
|
fields.StringField(id='1', label='string2', required=True),
|
|
]
|
|
formdef.store()
|
|
|
|
for prefill_settings in (
|
|
{'type': 'user', 'value': 'email'}, # verified profile
|
|
{'type': 'string', 'value': 'foo@localhost', 'locked': True}, # locked value
|
|
):
|
|
formdef.fields[0].prefill = prefill_settings
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
assert 'readonly' in resp.form['f0'].attrs
|
|
|
|
resp = resp.form.submit('submit')
|
|
assert 'There were errors processing the form' in resp.text
|
|
assert 'readonly' in resp.form['f0'].attrs
|
|
|
|
|
|
def test_form_page_profile_verified_date_prefill(pub):
|
|
user = create_user(pub)
|
|
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields.append(fields.DateField(id='_date', label='date'))
|
|
user_formdef.store()
|
|
user.form_data = {'_date': time.strptime('2018-09-27', '%Y-%m-%d')}
|
|
user.set_attributes_from_formdata(user.form_data)
|
|
user.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.DateField(id='0', label='date', prefill={'type': 'user', 'value': '_date'})]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0'].value == ''
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == '2018-09-27'
|
|
assert 'readonly' not in resp.form['f0'].attrs
|
|
assert resp.form['f0'].attrs['type'] == 'date'
|
|
resp.form['f0'].value = '2018-09-27'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert resp.form['f0'].value == '2018-09-27'
|
|
|
|
user.verified_fields = ['_date']
|
|
user.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == '2018-09-27'
|
|
# for readonly values there is a <input type=hidden> with the real value
|
|
# then an unnamed <input type=text> with the formatted value.
|
|
assert resp.form['f0'].attrs['type'] == 'hidden'
|
|
assert resp.pyquery('input#form_f0[type=text][readonly=readonly]')
|
|
|
|
resp.form['f0'].value = '2018-09-24' # try changing the value
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert resp.form['f0'].value == '2018-09-27' # it is reverted
|
|
|
|
resp.form['f0'].value = '2018-09-24' # try again changing the value
|
|
resp = resp.form.submit('submit')
|
|
|
|
formdatas = [x for x in formdef.data_class().select() if not x.is_draft()]
|
|
assert len(formdatas) == 1
|
|
assert time.strftime('%Y-%m-%d', formdatas[0].data['0']) == '2018-09-27'
|
|
|
|
|
|
def test_form_page_profile_date_as_locked_string_prefill(pub):
|
|
user = create_user(pub)
|
|
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields.append(fields.DateField(id='_date', label='date'))
|
|
user_formdef.store()
|
|
user.form_data = {'_date': time.strptime('2018-09-27', '%Y-%m-%d')}
|
|
user.set_attributes_from_formdata(user.form_data)
|
|
user.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.PageField(id='1', label='1st page'),
|
|
fields.PageField(id='2', label='2nd page'),
|
|
fields.StringField(id='0', label='date', prefill={'type': 'user', 'value': '_date', 'locked': True}),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
resp = resp.form.submit('submit') # -> second page
|
|
assert resp.form['f0'].value == '2018-09-27'
|
|
assert 'readonly' in resp.form['f0'].attrs
|
|
resp.form['f0'].value = '2015-09-27'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert resp.form['f0'].value == '2018-09-27'
|
|
|
|
|
|
def test_form_page_profile_verified_radio_item_prefill(pub):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
id='0',
|
|
label='item',
|
|
items=['bar@localhost', 'foo@localhost', 'baz@localhost'],
|
|
display_mode='radio',
|
|
prefill={'type': 'user', 'value': 'email'},
|
|
)
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f0'].value is None
|
|
|
|
user.verified_fields = ['email']
|
|
user.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
assert resp.form['f0'].value == 'foo@localhost'
|
|
assert 'disabled' in resp.form['f0'].attrs
|
|
for radio in resp.html.findAll('input'):
|
|
if radio['name'] == 'f0':
|
|
if radio['value'] == 'foo@localhost':
|
|
assert radio.attrs.get('checked')
|
|
assert not radio.attrs.get('disabled')
|
|
else:
|
|
assert not radio.attrs.get('checked')
|
|
assert radio.attrs.get('disabled')
|
|
|
|
resp.form['f0'].value = 'baz@localhost' # try changing the value
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert resp.form['f0'].value == 'foo@localhost' # it is reverted
|
|
|
|
|
|
def test_file_prefill_on_edit(pub, http_requests):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.FileField(id='0', label='file', varname='foo_file')]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
workflow = Workflow(name='test')
|
|
st1 = workflow.add_status('New', 'st1')
|
|
st2 = workflow.add_status('CreateFormdata')
|
|
|
|
editable = st1.add_action('editable', id='_editable')
|
|
editable.by = ['_submitter', '_receiver']
|
|
|
|
jump = st1.add_action('choice', id='_resubmit')
|
|
jump.label = 'Resubmit'
|
|
jump.by = ['_submitter']
|
|
jump.status = st2.id
|
|
|
|
create_formdata = st2.add_action('create_formdata', id='_create_formdata')
|
|
create_formdata.formdef_slug = formdef.url_name
|
|
create_formdata.mappings = [
|
|
Mapping(field_id='0', expression='{{form_var_foo_file}}'),
|
|
]
|
|
|
|
workflow.store()
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
upload = Upload('test.txt', b'foobar', 'text/plain')
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f0$file'] = upload
|
|
resp = resp.form.submit('submit') # -> validation page
|
|
resp = resp.form.submit('submit') # -> submit
|
|
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.text
|
|
resp = resp.click('test.txt')
|
|
assert resp.location.endswith('/test.txt')
|
|
resp = resp.follow()
|
|
assert resp.content_type == 'text/plain'
|
|
assert resp.text == 'foobar'
|
|
|
|
formdata = formdef.data_class().select()[0]
|
|
formdata.user_id = user.id
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub), username='foo', password='foo')
|
|
resp = app.get('/test/%s/' % formdata.id)
|
|
assert 'button_editable-button' in resp.text
|
|
|
|
# go to edition page
|
|
resp = resp.form.submit('button_editable').follow()
|
|
# file is "prefilled"
|
|
assert 'test.txt' in resp.text
|
|
|
|
# go back to form page and trigger formdata creation
|
|
resp = app.get('/test/%s/' % formdata.id)
|
|
resp = resp.form.submit('button_resubmit')
|
|
assert resp.status == '303 See Other'
|
|
resp = resp.follow()
|
|
|
|
assert formdef.data_class().count() == 2
|
|
new_formdata = formdef.data_class().select(lambda x: str(x.id) != str(formdata.id))[0]
|
|
assert new_formdata.data['0'].orig_filename == 'test.txt'
|
|
assert new_formdata.data['0'].get_content() == b'foobar'
|
|
|
|
resp = app.get('/test/%s/' % new_formdata.id)
|
|
assert 'button_editable-button' in resp.text
|
|
# go to edition page
|
|
resp = resp.form.submit('button_editable').follow()
|
|
# file is "prefilled"
|
|
assert 'test.txt' in resp.text
|
|
# and persist after being saved again
|
|
resp = resp.form.submit('submit').follow()
|
|
assert '<span>test.txt</span>' in resp.text
|
|
|
|
|
|
def test_form_page_prefill_and_table_field(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='1', label='string', prefill={'type': 'string', 'value': 'HELLO WORLD'}),
|
|
fields.TableField(id='2', label='table', rows=['A', 'B'], columns=['a', 'b', 'c']),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f1'].value == 'HELLO WORLD'
|
|
assert not resp.pyquery('.widget-with-error')
|
|
|
|
# check it also works on second page
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='page1'),
|
|
fields.PageField(id='3', label='page2'),
|
|
fields.StringField(id='1', label='string', prefill={'type': 'string', 'value': 'HELLO WORLD'}),
|
|
fields.TableField(id='2', label='table', rows=['A', 'B'], columns=['a', 'b', 'c']),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp = resp.form.submit('submit')
|
|
assert resp.forms[0]['f1'].value == 'HELLO WORLD'
|
|
assert not resp.pyquery('.widget-with-error')
|
|
|
|
|
|
def test_form_page_prefill_and_tablerows_field(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [
|
|
fields.StringField(id='1', label='string', prefill={'type': 'string', 'value': 'HELLO WORLD'}),
|
|
fields.TableRowsField(id='2', label='table', columns=['a', 'b', 'c']),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f1'].value == 'HELLO WORLD'
|
|
assert not resp.pyquery('.widget-with-error')
|
|
|
|
# check it also works on second page
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='page1'),
|
|
fields.PageField(id='3', label='page2'),
|
|
fields.StringField(id='1', label='string', prefill={'type': 'string', 'value': 'HELLO WORLD'}),
|
|
fields.TableRowsField(id='2', label='table', columns=['a', 'b', 'c']),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp = resp.form.submit('submit')
|
|
assert resp.forms[0]['f1'].value == 'HELLO WORLD'
|
|
assert not resp.pyquery('.widget-with-error')
|