1351 lines
50 KiB
Python
1351 lines
50 KiB
Python
import datetime
|
|
import io
|
|
import json
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
from webtest import Hidden
|
|
|
|
from wcs import fields
|
|
from wcs.blocks import BlockDef
|
|
from wcs.carddef import CardDef
|
|
from wcs.data_sources import NamedDataSource
|
|
from wcs.formdef import FormDef
|
|
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
|
|
from wcs.workflows import Workflow
|
|
|
|
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
|
|
from .test_all import create_user
|
|
|
|
|
|
def pytest_generate_tests(metafunc):
|
|
if 'pub' in metafunc.fixturenames:
|
|
metafunc.parametrize('pub', ['pickle', 'sql', 'pickle-templates', 'pickle-lazy'], indirect=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def pub(request):
|
|
pub = create_temporary_pub(
|
|
sql_mode=bool('sql' in request.param),
|
|
templates_mode=bool('templates' in request.param),
|
|
lazy_mode=bool('lazy' in request.param),
|
|
)
|
|
pub.cfg['identification'] = {'methods': ['password']}
|
|
pub.cfg['language'] = {'language': 'en'}
|
|
pub.write_cfg()
|
|
|
|
return pub
|
|
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
|
|
def test_field_live_condition(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='Foo',
|
|
size='40',
|
|
required=True,
|
|
varname='foo',
|
|
condition={'type': 'django', 'value': 'form_var_bar == "bye"'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert not live_resp.json['result']['2']['visible']
|
|
resp.form['f1'] = 'bye'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
resp.form['f1'] = 'hello'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert 'name="f1"' in resp.text
|
|
assert 'name="f2"' not in resp.text
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
assert '<span class="label">Bar</span>' in resp.text
|
|
assert '<span class="label">Foo</span>' not in resp.text
|
|
|
|
resp = get_app(pub).get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
resp.form['f1'] = 'bye'
|
|
resp = resp.form.submit('submit')
|
|
assert 'There were errors' in resp.text
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') is None
|
|
resp.form['f2'] = 'bye'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert 'name="f1"' in resp.text
|
|
assert 'name="f2"' in resp.text
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
assert '<span class="label">Bar</span>' in resp.text
|
|
assert '<span class="label">Foo</span>' in resp.text
|
|
|
|
|
|
def test_field_live_items_condition(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.ItemsField(type='items', id='1', label='Bar', items=['a', 'b'], varname='bar'),
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='Foo',
|
|
size='40',
|
|
required=True,
|
|
varname='foo',
|
|
condition={'type': 'django', 'value': '"b" in form_var_bar'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
|
|
create_user(pub)
|
|
app = login(get_app(pub), username='foo', password='foo')
|
|
resp = app.get('/foo/')
|
|
assert 'f1$element0' in resp.form.fields
|
|
assert 'f1$element1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
|
resp.form['f1$element0'].checked = True
|
|
app.post('/foo/autosave', params=resp.form.submit_fields())
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert not live_resp.json['result']['2']['visible']
|
|
resp.form['f1$element1'].checked = True
|
|
app.post('/foo/autosave', params=resp.form.submit_fields())
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
resp.form['f1$element0'].checked = False
|
|
resp.form['f1$element1'].checked = False
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert not live_resp.json['result']['2']['visible']
|
|
|
|
|
|
def test_live_field_condition_on_required_field(pub):
|
|
# from https://dev.entrouvert.org/issues/27247
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='1',
|
|
label='Bar',
|
|
items=['oui', 'non'],
|
|
display_mode='radio',
|
|
required=True,
|
|
varname='bar',
|
|
),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='2',
|
|
label='Foo',
|
|
size='40',
|
|
required=True,
|
|
hint='---',
|
|
items=['plop'],
|
|
condition={'type': 'django', 'value': 'form_var_bar == "oui"'},
|
|
),
|
|
fields.PageField(
|
|
id='3', label='1st page', type='page', condition={'type': 'python', 'value': 'True'}
|
|
),
|
|
fields.CommentField(type='comment', id='4', label='HELLO!'),
|
|
]
|
|
formdef.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
|
resp.form['f1'] = 'non'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert not live_resp.json['result']['2']['visible']
|
|
resp = resp.form.submit('submit')
|
|
assert 'HELLO' in resp.text
|
|
resp = resp.form.submit('previous')
|
|
resp.form['f1'] = 'oui'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
resp = resp.form.submit('submit')
|
|
assert resp.pyquery('div.error').text() == 'required field'
|
|
assert 'HELLO' not in resp.text
|
|
|
|
|
|
def test_field_live_condition_multipages(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='2nd page', type='page'),
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='Foo',
|
|
size='40',
|
|
required=True,
|
|
varname='foo',
|
|
condition={'type': 'django', 'value': 'form_var_bar == "bye"'},
|
|
),
|
|
fields.PageField(id='3', label='1st page', type='page'),
|
|
fields.StringField(type='string', id='4', label='Baz', size='40', required=True, varname='baz'),
|
|
]
|
|
formdef.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert not live_resp.json['result']['2']['visible']
|
|
resp.form['f1'] = 'bye'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
resp.form['f1'] = 'bye'
|
|
resp.form['f2'] = 'bye'
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.form.submit('previous')
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') is None
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
resp = resp.form.submit('submit')
|
|
resp.form['f4'] = 'plop'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert 'name="f1"' in resp.text
|
|
assert 'name="f2"' in resp.text
|
|
assert 'name="f4"' in resp.text
|
|
resp = resp.form.submit('submit')
|
|
|
|
|
|
def test_field_live_select_content(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(type='string', id='2', label='Bar2', size='40', required=True, varname='bar2'),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='3',
|
|
label='Foo',
|
|
data_source={
|
|
'type': 'json',
|
|
'value': '{% if form_var_bar2 %}http://remote.example.net/json-list?plop={{form_var_bar2}}{% endif %}',
|
|
},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
assert live_resp.json['result']['3']['visible']
|
|
assert 'items' not in live_resp.json['result']['3']
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
assert live_resp.json['result']['3']['visible']
|
|
assert 'items' in live_resp.json['result']['3']
|
|
resp.form['f3'].options = []
|
|
for item in live_resp.json['result']['3']['items']:
|
|
# simulate javascript filling the <select>
|
|
resp.form['f3'].options.append((item['id'], False, item['text']))
|
|
resp.form['f3'] = 'a'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert 'name="f1"' in resp.text
|
|
assert 'name="f2"' in resp.text
|
|
assert 'name="f3"' in resp.text
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data['1'] == 'hello'
|
|
assert formdata.data['2'] == 'plop'
|
|
assert formdata.data['3'] == 'a'
|
|
assert formdata.data['3_display'] == 'b'
|
|
|
|
# create and use geojson datasource
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='geofoobar')
|
|
data_source.data_source = {
|
|
'type': 'geojson',
|
|
'value': 'http://remote.example.net/geojson?plop={{form_var_bar2}}',
|
|
}
|
|
data_source.id_property = 'id'
|
|
data_source.label_template_property = '{{ text }}'
|
|
data_source.cache_duration = '5'
|
|
data_source.store()
|
|
formdef.fields[2].data_source = {'type': 'geofoobar'}
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
assert live_resp.json['result']['3']['visible']
|
|
assert 'items' not in live_resp.json['result']['3']
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['1']['visible']
|
|
assert live_resp.json['result']['2']['visible']
|
|
assert live_resp.json['result']['3']['visible']
|
|
assert 'items' in live_resp.json['result']['3']
|
|
resp.form['f3'].options = []
|
|
for item in live_resp.json['result']['3']['items']:
|
|
# simulate javascript filling the <select>
|
|
resp.form['f3'].options.append((item['id'], False, item['text']))
|
|
resp.form['f3'] = '1'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert 'name="f1"' in resp.text
|
|
assert 'name="f2"' in resp.text
|
|
assert 'name="f3"' in resp.text
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data['1'] == 'hello'
|
|
assert formdata.data['2'] == 'plop'
|
|
assert formdata.data['3'] == '1'
|
|
assert formdata.data['3_display'] == 'foo'
|
|
|
|
|
|
def test_field_live_select_content_on_workflow_form(pub, http_requests):
|
|
create_user(pub)
|
|
wf = Workflow(name='wf-title')
|
|
st1 = wf.add_status('Status1', 'st1')
|
|
|
|
# form displayed into the workflow
|
|
display_form = FormWorkflowStatusItem()
|
|
display_form.id = '_x'
|
|
display_form.by = ['_submitter']
|
|
display_form.varname = 'xxx'
|
|
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
|
display_form.formdef.fields = [
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(type='string', id='2', label='Bar2', size='40', required=True, varname='bar2'),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='3',
|
|
label='Foo',
|
|
required=False,
|
|
varname='foo',
|
|
data_source={
|
|
'type': 'json',
|
|
'value': '{% if xxx_var_bar2 %}http://remote.example.net/json-list?plop={{xxx_var_bar2}}{% endif %}',
|
|
},
|
|
),
|
|
]
|
|
st1.items.append(display_form)
|
|
display_form.parent = st1
|
|
wf.store()
|
|
|
|
# initial empty form
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = []
|
|
formdef.confirmation = False
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = login(app, username='foo', password='foo').get('/test/')
|
|
assert 'Forms - test' in resp.text
|
|
|
|
resp = resp.form.submit('submit').follow()
|
|
assert 'The form has been recorded' in resp.text
|
|
|
|
assert 'data-live-url' in resp.html.find('form').attrs
|
|
assert 'fxxx_1' in resp.form.fields
|
|
assert 'fxxx_2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': 'xxx_2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': 'xxx_3'}).find('select')
|
|
resp = resp.form.submit('submit') # submit with error, to check <form> attributes
|
|
assert 'data-live-url' in resp.html.find('form').attrs
|
|
assert 'fxxx_1' in resp.form.fields
|
|
assert 'fxxx_2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': 'xxx_2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': 'xxx_3'}).find('select')
|
|
resp.form['fxxx_1'] = 'hello'
|
|
live_resp = app.post('/test/1/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['xxx_1']['visible']
|
|
assert live_resp.json['result']['xxx_2']['visible']
|
|
assert live_resp.json['result']['xxx_3']['visible']
|
|
assert 'items' not in live_resp.json['result']['xxx_3']
|
|
resp.form['fxxx_2'] = 'plop'
|
|
live_resp = app.post('/test/1/live?modified_field_id=xxx_2', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['xxx_1']['visible']
|
|
assert live_resp.json['result']['xxx_2']['visible']
|
|
assert live_resp.json['result']['xxx_3']['visible']
|
|
assert 'items' in live_resp.json['result']['xxx_3']
|
|
assert len(live_resp.json['result']['xxx_3']['items']) > 0
|
|
|
|
resp.form['fxxx_3'].options = []
|
|
for item in live_resp.json['result']['xxx_3']['items']:
|
|
# simulate javascript filling the <select>
|
|
resp.form['fxxx_3'].options.append((item['id'], False, item['text']))
|
|
resp.form['fxxx_3'] = 'a'
|
|
|
|
resp = resp.form.submit('submit')
|
|
assert 'invalid value selected' not in resp
|
|
resp = resp.follow()
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.workflow_data['xxx_var_bar'] == 'hello'
|
|
assert formdata.workflow_data['xxx_var_bar2'] == 'plop'
|
|
assert formdata.workflow_data['xxx_var_foo_raw'] == 'a'
|
|
assert formdata.workflow_data['xxx_var_foo'] == 'b'
|
|
|
|
|
|
def test_field_live_select_content_based_on_prefill(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
type='string',
|
|
id='1',
|
|
label='Bar',
|
|
size='40',
|
|
required=True,
|
|
varname='bar',
|
|
prefill={'type': 'string', 'value': 'HELLO WORLD'},
|
|
),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='2',
|
|
label='Foo',
|
|
data_source={
|
|
'type': 'json',
|
|
'value': '{% if form_var_bar %}http://remote.example.net/json-list?plop={{form_var_bar}}{% endif %}',
|
|
},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '2'}).find('select')
|
|
assert resp.html.find('option', {'value': 'a'})
|
|
assert http_requests.get_last('url') == 'http://remote.example.net/json-list?plop=HELLO WORLD'
|
|
|
|
# check with autocomplete and a remote source with id
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'json',
|
|
'value': 'http://remote.example.net/json?plop={{form_var_bar}}',
|
|
}
|
|
data_source.query_parameter = 'q'
|
|
data_source.id_parameter = 'id'
|
|
data_source.store()
|
|
|
|
formdef.fields[1].display_mode = 'autocomplete'
|
|
formdef.fields[1].data_source['type'] = 'foobar'
|
|
formdef.store()
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
|
|
|
|
def test_field_live_select_content_on_other_default_select_option(pub, http_requests):
|
|
create_user(pub)
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
type='item',
|
|
id='2',
|
|
label='Foo',
|
|
varname='bar2',
|
|
data_source={'type': 'json', 'value': 'http://remote.example.net/json-list'},
|
|
),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='3',
|
|
label='Foo',
|
|
data_source={
|
|
'type': 'json',
|
|
'value': '{% if form_var_bar2 %}http://remote.example.net/json-list?plop={{form_var_bar2}}{% endif %}',
|
|
},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f2' in resp.form.fields
|
|
assert 'f3' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
# javascript will make an initial call with ?modified_dield_id=init,
|
|
# simulate.
|
|
live_resp = app.post('/foo/live?modified_field_id=init', params=resp.form.submit_fields())
|
|
assert 'items' in live_resp.json['result']['3']
|
|
resp.form['f3'].options = []
|
|
for item in live_resp.json['result']['3']['items']:
|
|
# simulate javascript filling the <select>
|
|
resp.form['f3'].options.append((item['id'], False, item['text']))
|
|
resp.form['f3'] = 'a'
|
|
resp = resp.form.submit('submit')
|
|
assert 'Check values then click submit.' in resp.text
|
|
assert 'name="f2"' in resp.text
|
|
assert 'name="f3"' in resp.text
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data['2'] == 'a'
|
|
assert formdata.data['3'] == 'a'
|
|
|
|
|
|
def test_field_live_select(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='2', label='Bar2', size='40', required=True, varname='bar2'),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='3',
|
|
label='Foo',
|
|
data_source={
|
|
'type': 'json',
|
|
'value': '{% if form_var_bar2 %}http://remote.example.net/json-list-extra-with-disabled?plop={{form_var_bar2}}{% endif %}',
|
|
},
|
|
display_disabled_items=True,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert len(live_resp.json['result']['3']['items']) == 2
|
|
assert live_resp.json['result']['3']['items'][1]['disabled'] is True
|
|
|
|
formdef.fields[1].display_disabled_items = False
|
|
formdef.store()
|
|
resp = app.get('/foo/')
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert len(live_resp.json['result']['3']['items']) == 1
|
|
|
|
|
|
def test_field_live_template_content(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='2', label='Bar2', size='40', required=True, varname='bar2'),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='3',
|
|
label='Foo',
|
|
extra_css_class='template-whatever',
|
|
data_source={
|
|
'type': 'json',
|
|
'value': '{% if form_var_bar2 %}http://remote.example.net/json-list-extra-with-disabled?plop={{form_var_bar2}}{% endif %}',
|
|
},
|
|
display_disabled_items=True,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['3']['items'][0]['foo'] == 'bar'
|
|
assert len(live_resp.json['result']['3']['items']) == 2
|
|
assert live_resp.json['result']['3']['items'][1]['disabled'] is True
|
|
|
|
formdef.fields[1].display_disabled_items = False
|
|
formdef.store()
|
|
resp = app.get('/foo/')
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert len(live_resp.json['result']['3']['items']) == 1
|
|
|
|
|
|
def test_field_live_timetable_select(pub, http_requests):
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {
|
|
'type': 'json',
|
|
'value': 'http://remote.example.net/api/datetimes{% if form_var_bar2 %}?{% endif %}',
|
|
}
|
|
data_source.store()
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='2', label='Bar2', size='40', required=True, varname='bar2'),
|
|
fields.ItemField(
|
|
id='3',
|
|
type='item',
|
|
label='datetime',
|
|
display_mode='timetable',
|
|
data_source={'type': 'foobar'},
|
|
display_disabled_items=True,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
|
|
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
|
|
data = {
|
|
"data": [
|
|
{"id": "1", "datetime": "2021-01-12 10:00:00", "text": "event 1", "api": {}},
|
|
{"id": "2", "datetime": "2021-01-13 10:20:00", "text": "event 2", "api": {}},
|
|
{
|
|
"id": "3",
|
|
"datetime": "2021-01-14 10:40:00",
|
|
"text": "event 3",
|
|
"api": {},
|
|
"disabled": True,
|
|
},
|
|
]
|
|
}
|
|
urlopen.side_effect = lambda *args: io.StringIO(json.dumps(data))
|
|
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert 'datetime' in live_resp.json['result']['3']['items'][0]
|
|
assert 'api' not in live_resp.json['result']['3']['items'][0]
|
|
assert len(live_resp.json['result']['3']['items']) == 3
|
|
assert live_resp.json['result']['3']['items'][2]['disabled'] is True
|
|
|
|
formdef.fields[1].display_disabled_items = False
|
|
formdef.store()
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
|
|
resp.form['f2'] = 'plop'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert 'datetime' in live_resp.json['result']['3']['items'][0]
|
|
assert 'api' not in live_resp.json['result']['3']['items'][0]
|
|
assert len(live_resp.json['result']['3']['items']) == 2
|
|
|
|
|
|
def test_field_live_comment_content(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(type='string', id='2', label='Baz', size='40'),
|
|
fields.CommentField(id='5', label='bla {{form_var_bar}} bla', type='comment'),
|
|
fields.StringField(type='string', id='6', label='Bar2', size='40', required=True, varname='bar2'),
|
|
fields.CommentField(id='7', label='bla {{form_var_bar2}} bla', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['5']['content'] == '<p>bla hello bla</p>'
|
|
resp.form['f1'] = 'toto'
|
|
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['5']['content'] == '<p>bla toto bla</p>'
|
|
live_resp = app.post('/foo/live?modified_field_id=2', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['5']['content'] == '<p>bla toto bla</p>'
|
|
|
|
# check evaluation of later fields
|
|
# <https://dev.entrouvert.org/issues/31922>
|
|
resp = app.get('/foo/')
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['5']['content'] == '<p>bla hello bla</p>'
|
|
resp.form['f6'] = 'hello'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['7']['content'] == '<p>bla hello bla</p>'
|
|
|
|
|
|
def test_field_live_comment_content_from_structured_item_data(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
type='item',
|
|
id='1',
|
|
label='Foo',
|
|
varname='bar',
|
|
data_source={'type': 'json', 'value': 'http://remote.example.net/json-list-extra'},
|
|
),
|
|
fields.CommentField(id='7', label='bla {{form_var_bar_structured_foo}} bla', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
resp.form['f1'] = 'a'
|
|
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['7']['content'] == '<p>bla bar bla</p>'
|
|
|
|
|
|
def test_field_live_string_prefill(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='Bar2',
|
|
size='40',
|
|
required=True,
|
|
varname='bar2',
|
|
prefill={'type': 'string', 'value': '{{form_var_bar|default:""}}'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.pyquery('#var_bar2.widget-prefilled') # second field is marked as prefilled
|
|
assert resp.form['f2'].value == ''
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True, 'content': 'hello'}
|
|
|
|
resp.form['f2'] = 'other' # manually changed -> widget-prefilled class will be removed
|
|
resp.form['f1'] = 'xxx'
|
|
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True}
|
|
|
|
# check it's not possible to declare user change from frontoffice
|
|
live_resp = app.post('/foo/live?modified_field_id=user', params=resp.form.submit_fields(), status=403)
|
|
|
|
|
|
def test_field_live_bool_prefill(pub, http_requests):
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
|
|
carddef.fields = [
|
|
fields.StringField(id='1', type='string', label='string', varname='foo'),
|
|
fields.BoolField(
|
|
type='bool',
|
|
id='2',
|
|
varname='bool',
|
|
),
|
|
]
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
carddata1 = carddef.data_class()()
|
|
carddata1.data = {
|
|
'1': 'bar',
|
|
'2': True,
|
|
}
|
|
carddata1.just_created()
|
|
carddata1.store()
|
|
carddata2 = carddef.data_class()()
|
|
carddata2.data = {
|
|
'1': 'baz',
|
|
'2': False,
|
|
}
|
|
carddata2.just_created()
|
|
carddata2.store()
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
type='item', id='1', label='foo', varname='foo', data_source={'type': 'carddef:foo'}
|
|
),
|
|
fields.BoolField(
|
|
type='bool',
|
|
id='2',
|
|
label='bool',
|
|
varname='bool',
|
|
prefill={'type': 'string', 'value': '{{ form_var_foo_live_var_bool }}'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.pyquery('#var_bool.widget-prefilled') # second field is marked as prefilled
|
|
assert resp.form['f2'].value is None
|
|
resp.form['f1'] = str(carddata1.id)
|
|
live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True, 'content': True}
|
|
|
|
resp.form['f2'] = False # manually changed -> widget-prefilled class will be removed
|
|
resp.form['f1'] = str(carddata2.id)
|
|
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True}
|
|
|
|
|
|
def test_field_live_date_prefill(pub, http_requests):
|
|
pub.cfg['language'] = {'language': 'fr'}
|
|
pub.write_cfg()
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
|
|
carddef.fields = [
|
|
fields.StringField(id='1', type='string', label='string', varname='foo'),
|
|
fields.DateField(
|
|
type='date',
|
|
id='2',
|
|
varname='date',
|
|
),
|
|
]
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
carddata1 = carddef.data_class()()
|
|
carddata1.data = {
|
|
'1': 'bar',
|
|
'2': datetime.date(2021, 10, 1).timetuple(),
|
|
}
|
|
carddata1.just_created()
|
|
carddata1.store()
|
|
carddata2 = carddef.data_class()()
|
|
carddata2.data = {
|
|
'1': 'baz',
|
|
'2': datetime.date(2021, 10, 30).timetuple(),
|
|
}
|
|
carddata2.just_created()
|
|
carddata2.store()
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
type='item', id='1', label='foo', varname='foo', data_source={'type': 'carddef:foo'}
|
|
),
|
|
fields.DateField(
|
|
type='date',
|
|
id='2',
|
|
label='date',
|
|
varname='date',
|
|
prefill={'type': 'string', 'value': '{{ form_var_foo_live_var_date }}'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.pyquery('#var_date.widget-prefilled') # second field is marked as prefilled
|
|
assert resp.form['f2'].value == ''
|
|
resp.form['f1'] = str(carddata1.id)
|
|
live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True, 'content': '2021-10-01'}
|
|
|
|
resp.form['f2'] = '2021-10-30' # manually changed -> widget-prefilled class will be removed
|
|
resp.form['f1'] = str(carddata2.id)
|
|
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True}
|
|
|
|
|
|
def test_field_live_item_datasource_carddef_prefill(pub, http_requests):
|
|
CardDef.wipe()
|
|
|
|
carddef_related = CardDef()
|
|
carddef_related.name = 'bar'
|
|
carddef_related.digest_templates = {'default': '{{ form_var_bar }}'}
|
|
carddef_related.fields = [
|
|
fields.StringField(id='1', type='string', label='string', varname='bar'),
|
|
]
|
|
carddef_related.store()
|
|
carddef_related.data_class().wipe()
|
|
for value in ['A', 'B', 'C']:
|
|
carddata = carddef_related.data_class()()
|
|
carddata.data = {
|
|
'1': value,
|
|
}
|
|
carddata.just_created()
|
|
carddata.store()
|
|
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
|
|
carddef.fields = [
|
|
fields.StringField(id='1', type='string', label='string', varname='foo'),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='2',
|
|
varname='item',
|
|
data_source={'type': 'carddef:bar'},
|
|
),
|
|
]
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
carddata1 = carddef.data_class()()
|
|
carddata1.data = {
|
|
'1': 'bar',
|
|
'2': '1',
|
|
'2_display': 'A',
|
|
}
|
|
carddata1.just_created()
|
|
carddata1.store()
|
|
carddata2 = carddef.data_class()()
|
|
carddata2.data = {
|
|
'1': 'baz',
|
|
'2': '2',
|
|
'2_display': 'B',
|
|
}
|
|
carddata2.just_created()
|
|
carddata2.store()
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
type='item', id='1', label='foo', varname='foo', data_source={'type': 'carddef:foo'}
|
|
),
|
|
fields.ItemField(
|
|
type='item',
|
|
id='2',
|
|
label='item',
|
|
varname='item',
|
|
prefill={'type': 'string', 'value': '{{ form_var_foo_live_var_item }}'},
|
|
data_source={'type': 'carddef:bar'},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.pyquery('#var_item.widget-prefilled') # second field is marked as prefilled
|
|
assert resp.form['f2'].value == '1'
|
|
resp.form['f1'] = str(carddata2.id)
|
|
live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True, 'content': '2'}
|
|
|
|
resp.form['f2'] = '3' # manually changed -> widget-prefilled class will be removed
|
|
resp.form['f1'] = str(carddata1.id)
|
|
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2'] == {'visible': True}
|
|
|
|
|
|
def test_field_live_block_string_prefill(pub, http_requests):
|
|
FormDef.wipe()
|
|
BlockDef.wipe()
|
|
|
|
block = BlockDef()
|
|
block.name = 'foobar'
|
|
block.fields = [
|
|
fields.StringField(
|
|
id='123',
|
|
required=True,
|
|
label='Test',
|
|
type='string',
|
|
prefill={'type': 'string', 'value': '{{form_var_foo|default:""}}'},
|
|
),
|
|
]
|
|
block.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'form title'
|
|
formdef.fields = [
|
|
fields.StringField(id='1', label='test', type='string', varname='foo'),
|
|
fields.BlockField(id='2', label='test', type='block:foobar'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get(formdef.get_url())
|
|
live_url = resp.html.find('form').attrs['data-live-url']
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.pyquery('[data-field-id="123"].widget-prefilled') # block/string
|
|
assert resp.form['f2$element0$f123'].value == ''
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post(live_url + '?modified_field_id=1&prefilled_123=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result'] == {
|
|
'1': {'visible': True},
|
|
'2': {'visible': True},
|
|
'2-123': {'block_id': '2', 'content': 'hello', 'field_id': '123', 'visible': True},
|
|
}
|
|
|
|
|
|
def test_field_live_condition_unknown_page_id(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='2nd page', type='page'),
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='Foo',
|
|
size='40',
|
|
required=True,
|
|
varname='foo',
|
|
condition={'type': 'django', 'value': 'form_var_bar == "bye"'},
|
|
),
|
|
fields.PageField(id='3', label='1st page', type='page'),
|
|
fields.StringField(type='string', id='4', label='Baz', size='40', required=True, varname='baz'),
|
|
]
|
|
formdef.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
|
resp.form['f1'] = 'hello'
|
|
params = resp.form.submit_fields()
|
|
params = [(key, value if key != 'page_id' else 'eiuiu') for key, value in params]
|
|
app.post('/foo/live', params=params)
|
|
|
|
|
|
def test_field_live_locked_prefilled_field(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(type='string', id='1', label='Bar', size='40', required=True, varname='bar'),
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='locked',
|
|
size='40',
|
|
required=True,
|
|
prefill={'type': 'string', 'value': 'bla {{form_var_bar}} bla', 'locked': True},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'f1' in resp.form.fields
|
|
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
|
resp.form['f1'] = 'hello'
|
|
live_resp = app.post('/foo/live?prefilled_2=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2']['content'] == 'bla hello bla'
|
|
resp.form['f1'] = 'toto'
|
|
live_resp = app.post('/foo/live?modified_field_id=1&prefilled_2=on', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2']['content'] == 'bla toto bla'
|
|
|
|
|
|
def test_field_live_locked_error_prefilled_field(pub, http_requests):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
type='string',
|
|
id='2',
|
|
label='locked',
|
|
size='40',
|
|
required=True,
|
|
prefill={'type': 'string', 'value': 'bla {% if foo %}{{ foo }}{% end %}', 'locked': True},
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/foo/')
|
|
assert 'readonly' in resp.form['f2'].attrs
|
|
assert not resp.form['f2'].attrs.get('value')
|
|
|
|
|
|
def test_dynamic_item_field_from_custom_view_on_cards(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
pub.role_class.wipe()
|
|
pub.custom_view_class.wipe()
|
|
|
|
user = create_user(pub)
|
|
role = pub.role_class(name='xxx')
|
|
role.store()
|
|
user.roles = [role.id]
|
|
user.is_admin = True
|
|
user.store()
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = []
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'items'
|
|
carddef.digest_templates = {'default': '{{form_var_attr}}'}
|
|
carddef.workflow_roles = {'_editor': user.roles[0]}
|
|
carddef.fields = [
|
|
fields.ItemField(id='0', type='item', label='item', varname='item', items=['foo', 'bar', 'baz']),
|
|
fields.StringField(id='1', type='string', label='string', varname='attr'),
|
|
]
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
baz_ids = set()
|
|
for i, value in enumerate(['foo', 'bar', 'baz'] * 10):
|
|
carddata = carddef.data_class()()
|
|
carddata.data = {
|
|
'0': value,
|
|
'0_display': value,
|
|
'1': 'attr%s' % i,
|
|
}
|
|
carddata.just_created()
|
|
carddata.store()
|
|
if value == 'baz':
|
|
baz_ids.add(str(carddata.id))
|
|
|
|
# create custom view
|
|
app = login(get_app(pub), username='foo', password='foo')
|
|
|
|
resp = app.get('/backoffice/data/items/')
|
|
if pub.is_using_postgresql():
|
|
assert resp.text.count('<tr') == 21 # thead + 20 items (max per page)
|
|
else:
|
|
assert resp.text.count('<tr') == 31 # thead + all items
|
|
resp.forms['listing-settings']['filter-0'].checked = True
|
|
resp.forms['listing-settings']['filter-status'].checked = True
|
|
resp = resp.forms['listing-settings'].submit()
|
|
|
|
resp.forms['listing-settings']['filter'].value = 'recorded'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
|
|
resp.forms['save-custom-view']['title'] = 'as data source'
|
|
resp.forms['save-custom-view']['visibility'] = 'datasource'
|
|
resp = resp.forms['save-custom-view'].submit().follow()
|
|
|
|
assert resp.forms['listing-settings']['filter-0-value'].attrs['data-allow-template']
|
|
assert 'custom value' in [x[2] for x in resp.forms['listing-settings']['filter-0-value'].options]
|
|
resp.forms['listing-settings']['filter-0-value'].force_value('{{ form_var_blah }}')
|
|
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.forms['listing-settings']['filter-0-value'].value == '{{ form_var_blah }}'
|
|
assert resp.text.count('<tr') == 1 # thead only
|
|
|
|
# save custom view with filter
|
|
resp = resp.forms['save-custom-view'].submit().follow()
|
|
|
|
custom_view = pub.custom_view_class.select()[0]
|
|
|
|
# use custom view as source
|
|
ds = {'type': 'carddef:%s:%s' % (carddef.url_name, custom_view.slug)}
|
|
formdef.fields = [
|
|
fields.ItemField(id='0', type='item', label='item', varname='blah', items=['foo', 'bar', 'baz']),
|
|
fields.ItemField(id='1', label='string', type='item', data_source=ds, display_disabled_items=True),
|
|
]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].options == [('', False, '---')]
|
|
resp.form['f0'] = 'baz'
|
|
live_resp = app.post('/test/live?modified_field_id=0', params=resp.form.submit_fields())
|
|
assert len(live_resp.json['result']['1']['items']) == 10
|
|
assert {str(x['id']) for x in live_resp.json['result']['1']['items']} == baz_ids
|
|
|
|
resp.form['f1'].options = []
|
|
for item in live_resp.json['result']['1']['items']:
|
|
# simulate javascript filling the <select>
|
|
resp.form['f1'].options.append((str(item['id']), False, item['text']))
|
|
|
|
resp.form['f1'] = resp.form['f1'].options[0][0]
|
|
resp = resp.form.submit('submit') # -> validation page
|
|
resp = resp.form.submit('submit') # -> submit
|
|
assert formdef.data_class().select()[0].data['1'] in baz_ids
|
|
assert formdef.data_class().select()[0].data['1_structured']['item'] == 'baz'
|
|
|
|
# same in autocomplete mode
|
|
formdef.fields[1].display_mode = 'autocomplete'
|
|
formdef.store()
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
# simulate select2 mode, with qommon.forms.js adding an extra hidden widget
|
|
resp.form.fields['f1_display'] = Hidden(form=resp.form, tag='input', name='f1_display', pos=10)
|
|
select2_url = resp.pyquery('select:last').attr['data-select2-url']
|
|
resp_json = app.get(select2_url + '?q=')
|
|
assert len(resp_json.json['data']) == 0
|
|
resp.form['f0'] = 'baz'
|
|
|
|
live_resp = app.post('/test/live?modified_field_id=0', params=resp.form.submit_fields())
|
|
new_select2_url = live_resp.json['result']['1']['source_url']
|
|
resp_json = app.get(new_select2_url + '?q=')
|
|
assert len(resp_json.json['data']) == 10
|
|
assert {str(x['id']) for x in resp_json.json['data']} == baz_ids
|
|
|
|
resp.form['f1'].force_value(str(resp_json.json['data'][0]['id']))
|
|
resp.form.fields['f1_display'].force_value(resp_json.json['data'][0]['text'])
|
|
|
|
resp = resp.form.submit('submit') # -> validation page
|
|
resp = resp.form.submit('submit') # -> submit
|
|
assert formdef.data_class().select()[0].data['1'] in baz_ids
|
|
assert formdef.data_class().select()[0].data['1_structured']['item'] == 'baz'
|
|
|
|
# delete custom view
|
|
if pub.is_using_postgresql():
|
|
pub.loggederror_class.wipe()
|
|
custom_view.remove_self()
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.form['f1'].options == []
|
|
if pub.is_using_postgresql():
|
|
assert pub.loggederror_class.count() == 1
|
|
logged_error = pub.loggederror_class.select()[0]
|
|
assert logged_error.formdef_id == formdef.id
|
|
assert logged_error.summary == '[DATASOURCE] Unknown custom view "as-data-source" for CardDef "items"'
|
|
|
|
|
|
def test_item_field_from_cards_check_lazy_live(pub):
|
|
create_user(pub)
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'items'
|
|
carddef.digest_templates = {'default': '{{form_var_name}}'}
|
|
carddef.fields = [
|
|
fields.StringField(id='0', label='string', varname='name'),
|
|
fields.StringField(id='1', label='string', varname='attr'),
|
|
]
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
for i, value in enumerate(['foo', 'bar', 'baz']):
|
|
carddata = carddef.data_class()()
|
|
carddata.data = {
|
|
'0': value,
|
|
'1': 'attr%s' % i,
|
|
}
|
|
carddata.just_created()
|
|
carddata.store()
|
|
|
|
ds = {'type': 'carddef:%s' % carddef.url_name}
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.ItemField(id='1', label='string', type='item', varname='item', data_source=ds),
|
|
fields.PageField(id='2', label='2nd page', type='page'),
|
|
fields.CommentField(id='3', label='live value: {{ form_var_item_live_var_attr }}', type='comment'),
|
|
fields.PageField(id='4', label='3rd page', type='page'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.form['f1'] = '2'
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert 'live value: attr1' in resp
|
|
|
|
# add a field with a condition on first page and third page
|
|
formdef.fields[1:1] = [
|
|
fields.StringField(
|
|
id='5',
|
|
label='field with condition',
|
|
type='string',
|
|
required=False,
|
|
condition={'type': 'django', 'value': '1'},
|
|
),
|
|
]
|
|
formdef.fields.append(
|
|
fields.StringField(
|
|
id='6',
|
|
label='second field with condition',
|
|
type='string',
|
|
required=False,
|
|
condition={'type': 'django', 'value': '1'},
|
|
)
|
|
)
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
resp.form['f1'] = '2'
|
|
resp = resp.form.submit('submit') # -> 2nd page
|
|
assert 'live value: attr1' in resp
|
|
resp = resp.form.submit('submit') # -> 3rd page
|
|
resp = resp.form.submit('previous') # -> 2nd page
|
|
assert 'live value: attr1' in resp
|