wcs/tests/backoffice_pages/test_submission.py

1843 lines
64 KiB
Python

import datetime
import os
import re
import time
import urllib.parse
import pytest
from wcs import fields
from wcs.api_utils import sign_url
from wcs.carddef import CardDef
from wcs.formdef import FormDef
from wcs.qommon.http_request import HTTPRequest
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
from .test_all import create_superuser, create_user
@pytest.fixture
def pub(emails):
pub = create_temporary_pub()
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
pub.set_app_dir(req)
pub.cfg['identification'] = {'methods': ['password']}
pub.cfg['language'] = {'language': 'en'}
pub.write_cfg()
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
fd.write(
'''
[api-secrets]
coucou = 1234
'''
)
return pub
@pytest.fixture
def autosave(pub):
if not pub.site_options.has_section('options'):
pub.site_options.add_section('options')
pub.site_options.set('options', 'backoffice-autosave', 'true')
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
pub.site_options.write(fd)
def teardown_module(module):
clean_temporary_pub()
def test_backoffice_submission(pub):
user = create_user(pub)
datasource = {'type': 'formula', 'value': repr([('A', 'aa'), ('B', 'bb'), ('C', 'cc')])}
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
fields.ItemField(
id='2',
label='2nd field',
type='item',
items=['foo', 'bar', 'baz'],
display_locations=['validation', 'summary', 'listings'],
),
fields.ItemField(id='3', label='3rd field', type='item', data_source=datasource, varname='foo'),
]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/management/forms')
assert not resp.pyquery('#sidepage-menu .icon-submission')
app.get('/backoffice/submission/', status=403)
formdef = FormDef.get_by_urlname('form-title')
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
resp = app.get('/backoffice/management/forms')
assert resp.pyquery('#sidepage-menu .icon-submission')
resp = app.get('/backoffice/submission/')
assert formdef.url_name in resp.text
resp = resp.click(formdef.name)
assert resp.pyquery('form[data-autosave=false]').length
resp.form['f1'] = 'test submission'
resp.form['f2'] = 'baz'
resp.form['f3'] = 'C'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
# going back to first page, to check
resp = resp.form.submit('previous')
assert resp.form['f1'].value == 'test submission'
resp = resp.form.submit('submit')
# final submit
resp = resp.form.submit('submit')
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).data['1'] == 'test submission'
assert data_class.get(formdata_no).data['2'] == 'baz'
assert data_class.get(formdata_no).status == 'wf-new'
assert data_class.get(formdata_no).user is None
assert data_class.get(formdata_no).backoffice_submission is True
resp = resp.follow() # get to the formdata page
formdata_count = data_class.count()
# test submission when agent is not receiver
formdef.workflow_roles = {}
formdef.store()
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp.form['f2'] = 'baz'
resp.form['f3'] = 'C'
resp = resp.form.submit('submit') # to validation screen
resp = resp.form.submit('submit') # final submit
assert resp.location == 'http://example.net/backoffice/submission/'
resp = resp.follow() # should go back to submission screen
assert data_class.count() == formdata_count + 1
# test redirection on cancel
resp = app.get('/backoffice/submission/')
assert formdef.url_name in resp.text
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('cancel')
assert resp.location == 'http://example.net/backoffice/submission/'
# test submission when agent is not receiver but there's a redirect action
# in the workflow.
formdef = FormDef.get_by_urlname('form-title')
wf = Workflow(name='dispatch')
st1 = wf.add_status('Status1')
item = st1.add_action('redirect_to_url', id='_redirect')
item.url = 'http://www.example.org/'
wf.store()
formdef.workflow_id = wf.id
formdef.store()
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp.form['f2'] = 'baz'
resp.form['f3'] = 'C'
resp = resp.form.submit('submit') # to validation screen
resp = resp.form.submit('submit') # final submit
assert resp.location == 'http://www.example.org/'
def test_backoffice_submission_with_tracking_code(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.workflow_roles = {'_receiver': 1}
formdef.backoffice_submission_roles = user.roles[:]
formdef.enable_tracking_codes = True
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
# final submit
validation_resp_body = resp.text
resp = resp.form.submit('submit')
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
formdata = data_class.get(formdata_no)
assert formdata.tracking_code in validation_resp_body
formdata_location = resp.location
resp = resp.follow() # get to the formdata page
# check tracking code is still displayed in formdata page
assert 'test submission' in resp.text
assert formdata.tracking_code in resp.text
# check access by different user
formdata.submission_agent_id = '10000'
formdata.store()
resp = app.get(formdata_location)
assert 'test submission' in resp.text
assert formdata.tracking_code not in resp.text
# restore user
formdata.submission_agent_id = str(user.id)
formdata.store()
resp = app.get(formdata_location)
assert formdata.tracking_code in resp.text
# check access at a later time
formdata.receipt_time = time.localtime(time.time() - 3600)
formdata.store()
resp = app.get(formdata_location)
assert formdata.tracking_code not in resp.text
def test_backoffice_submission_welco(pub, welco_url):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = []
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
# if it's empty, redirect to welco
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert resp.location == 'http://welco.example.net'
# if there are pending submissions, display them
formdata = formdef.data_class()()
formdata.data = {}
formdata.status = 'draft'
formdata.backoffice_submission = True
formdata.submission_agent_id = str(user.id)
formdata.store()
resp = app.get('/backoffice/submission/')
assert 'Submission to complete' in resp.text
# check agent name is displayed next to pending submission
assert '(%s)' % user.display_name in resp.text
def test_backoffice_submission_initiated_from_welco(pub, welco_url):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(
id='0',
label='1st PAGE',
type='page',
condition={
'type': 'python',
'value': 'form_submission_channel != "counter" and is_in_backoffice',
},
),
fields.StringField(id='1', label='Field on 1st page', type='string'),
fields.PageField(id='2', label='2nd PAGE', type='page'),
fields.StringField(id='3', label='Field on 2nd page', type='string'),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
app = login(get_app(pub))
def post_formdata():
signed_url = sign_url(
'http://example.net/api/formdefs/form-title/submit'
'?format=json&orig=coucou&email=%s' % urllib.parse.quote(user.email),
'1234',
)
url = signed_url[len('http://example.net') :]
resp = get_app(pub).post_json(
url,
{
'meta': {
'draft': True,
'backoffice-submission': True,
},
'data': {},
'context': {'channel': 'counter'},
},
)
return resp.json['data']['id']
resp = app.get('/backoffice/management/form-title/%s/' % post_formdata())
resp = resp.follow() # -> /backoffice/submission/form-title/XXX/
resp = resp.follow() # -> /backoffice/submission/form-title/?mt=XYZ
# second page should be shown
pq = resp.pyquery.remove_namespaces()
assert pq('#steps li.current .label').text() == '2nd PAGE'
assert 'Field on 2nd page' in resp.text # and in fields
# reverse condition
formdef.fields[0].condition['value'] = 'form_submission_channel == "counter" and is_in_backoffice'
formdef.store()
resp = app.get('/backoffice/management/form-title/%s/' % post_formdata())
resp = resp.follow() # -> /backoffice/submission/form-title/XXX/
resp = resp.follow() # -> /backoffice/submission/form-title/?mt=XYZ
pq = resp.pyquery.remove_namespaces()
assert pq('#steps li.current .label').text() == '1st PAGE'
assert 'Field on 1st page' in resp.text # and in fields
def test_backoffice_submission_with_return_url(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/?ReturnURL=https://example.org')
resp = resp.follow().follow()
resp = resp.form.submit('cancel')
assert resp.location == 'https://example.org'
resp = app.get('/backoffice/submission/form-title/?ReturnURL=https://example.org')
resp = resp.follow().follow()
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> to validation
resp = resp.form.submit('submit') # -> to submit
assert resp.location.startswith('http://example.net/backoffice/management/form-title/')
# test submission when agent is not receiver
formdef.workflow_roles = {}
formdef.store()
resp = app.get('/backoffice/submission/form-title/?ReturnURL=https://example.org')
resp = resp.follow().follow()
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> to validation
resp = resp.form.submit('submit') # -> to submit
assert resp.location == 'https://example.org'
# test removal of draft
resp = app.get('/backoffice/submission/form-title/?ReturnURL=https://example.org')
resp = resp.follow().follow()
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> to validation
resp = resp.click('Delete this form')
resp = resp.form.submit('delete')
assert resp.location == 'https://example.org'
def test_backoffice_submission_with_caller(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
formdef.data_class().wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/?caller=0601020304')
resp = resp.follow().follow()
assert '<h3>Phone: 0601020304</h3>' not in resp.text
assert formdef.data_class().get(1).submission_channel == ''
assert not formdef.data_class().get(1).submission_context
resp = app.get('/backoffice/submission/form-title/?channel=phone&caller=0601020304')
resp = resp.follow().follow()
assert '<h3>Phone: 0601020304</h3>' in resp.text
assert 'submit-user-selection' in resp
assert formdef.data_class().get(2).submission_channel == 'phone'
assert formdef.data_class().get(2).submission_context == {'caller': '0601020304'}
resp.form['f1'] = 'test'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp
resp = resp.form.submit('submit').follow()
assert formdef.data_class().get(2).submission_channel == 'phone'
assert formdef.data_class().get(2).submission_context == {'caller': '0601020304'}
def test_backoffice_parallel_submission(pub, autosave):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
formdata = formdef.data_class()()
formdata.data = {}
formdata.status = 'draft'
formdata.backoffice_submission = True
formdata.submission_agent_id = str(user.id)
formdata.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert 'Submission to complete' in resp.text
resp1 = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp1 = resp1.follow()
resp2 = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp2 = resp2.follow()
resp3 = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp3 = resp3.follow()
assert not resp.pyquery('form[data-autosave=false]').length
resp1.form['f1'] = 'foo'
resp1 = resp1.form.submit('submit') # to validation page
# also move the second form to the validation page
resp2.form['f1'] = 'bar'
resp2 = resp2.form.submit('submit') # to validation page
resp1 = resp1.form.submit('submit') # final validation
resp1 = resp1.follow()
resp2 = resp2.form.submit('submit') # final validation
assert resp2.status_code == 302
resp2 = resp2.follow()
assert 'This form has already been submitted.' in resp2.text
# do the third form from the start
resp3.form['f1'] = 'baz'
resp_autosave = app.post('/backoffice/submission/form-title/autosave', params=resp3.form.submit_fields())
assert resp_autosave.json['result'] == 'error'
assert resp_autosave.json['reason'] == 'form has already been submitted'
resp3 = resp3.form.submit('submit') # to validation page
assert resp3.status_code == 302
resp3 = resp3.follow()
assert 'This form has already been submitted.' in resp3.text
assert formdef.data_class().get(formdata.id).data['1'] == 'foo'
# try again, very late.
resp4 = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp4 = resp4.follow()
assert 'This form has already been submitted.' in resp4.text
def test_backoffice_submission_autosave_tracking_code(pub, autosave):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.enable_tracking_codes = True
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'] = 'foo'
resp_autosave = app.post('/backoffice/submission/form-title/autosave', params=resp.form.submit_fields())
assert resp_autosave.json['result'] == 'success'
resp = resp.form.submit('submit') # -> validation
resp = resp.form.submit('submit') # -> done
def test_backoffice_submission_dispatch(pub):
user = create_user(pub)
Workflow.wipe()
wf = Workflow(name='dispatch')
st1 = wf.add_status('Status1')
dispatch = st1.add_action('dispatch', id='_dispatch')
dispatch.role_key = '_receiver'
dispatch.role_id = '2'
wf.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_id = wf.id
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # to validation screen
resp = resp.form.submit('submit') # final submit
# should go to the formdata because the formdef is defined as is
assert resp.location.startswith('http://example.net/backoffice/management/form-title/')
# remove function from formdef
formdef.workflow_roles = {}
formdef.store()
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # to validation screen
resp = resp.form.submit('submit') # final submit
# should NOT go to the formdata
assert resp.location == 'http://example.net/backoffice/submission/'
# if there's no function but the dispatch sets the right function, should
# go to the formdata screen
dispatch.role_id = '1'
wf.store()
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # to validation screen
resp = resp.form.submit('submit') # final submit
# should go to the formdata because the formdata was dispatched to the
# right role
assert resp.location.startswith('http://example.net/backoffice/management/form-title/')
def test_backoffice_submission_tracking_code(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.enable_tracking_codes = True
formdef.store()
data_class = formdef.data_class()
data_class.wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert formdef.url_name in resp.text
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
# stop here, don't validate, let user finish it.
assert data_class.count() == 1
formdata_no = data_class.select()[0].id
assert data_class.get(formdata_no).data['1'] == 'test submission'
assert data_class.get(formdata_no).status == 'draft'
assert data_class.get(formdata_no).user is None
resp = get_app(pub).get('/code/%s/load' % data_class.select()[0].tracking_code)
resp = resp.follow()
assert resp.location.startswith('http://example.net/form-title/?mt=')
resp = resp.follow()
assert 'Check values then click submit.' in resp.text
assert 'test submission' in resp.text
def test_backoffice_submission_drafts(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.enable_tracking_codes = True
formdef.store()
data_class = formdef.data_class()
data_class.wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert formdef.url_name in resp.text
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
assert data_class.count() == 1
formdata = data_class.select()[0]
formdata_no = formdata.id
tracking_code = data_class.select()[0].tracking_code
# stop here, go back to index
resp = app.get('/backoffice/submission/')
assert '%s/%s' % (formdef.url_name, formdata_no) in resp.text
assert '>#%s' % formdata_no in resp.text
formdata.submission_channel = 'mail'
formdata.store()
resp = app.get('/backoffice/submission/')
assert '>Mail #%s' % formdata_no in resp.text
# check it can also be accessed using its final URL
resp2 = app.get('/backoffice/management/%s/%s/' % (formdef.url_name, formdata_no))
assert resp2.location == 'http://example.net/backoffice/submission/%s/%s/' % (
formdef.url_name,
formdata_no,
)
resp = resp.click('#%s' % formdata_no)
resp = resp.follow()
assert tracking_code in resp.text
resp = resp.form.submit('previous')
assert resp.form['f1'].value == 'test submission'
resp = resp.form.submit('submit')
assert "Check values then click submit." in resp.text
resp = resp.form.submit('submit')
# check it kept the same id
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata_no
def test_backoffice_submission_remove_drafts(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.enable_tracking_codes = True
formdef.store()
data_class = formdef.data_class()
data_class.wipe()
pub.tracking_code_class.wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert formdef.url_name in resp.text
resp = resp.click(formdef.name)
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
assert data_class.count() == 1
formdata = data_class.select()[0]
formdata_no = formdata.id
# stop here, go back to the index
resp = app.get('/backoffice/submission/')
resp = resp.click('#%s' % formdata_no)
resp = resp.follow()
# and try to delete the form (but cancel)
resp = resp.click('Delete this form')
resp = resp.form.submit('cancel')
assert resp.location == 'http://example.net/backoffice/submission/'
assert data_class.count() == 1
assert pub.tracking_code_class().count() == 1
# and this time for real
resp = app.get('/backoffice/submission/')
resp = resp.click('#%s' % formdata_no)
resp = resp.follow()
resp = resp.click('Delete this form')
resp = resp.form.submit('delete')
assert resp.location == 'http://example.net/backoffice/submission/'
assert data_class.count() == 0
assert pub.tracking_code_class().count() == 0
# check it's not possible to delete an actual formdata
formdata = data_class()
formdata.store()
resp = app.get('/backoffice/submission/form-title/remove/%s' % formdata.id, status=403)
def test_backoffice_submission_live_condition(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
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.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
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_url = resp.html.find('form').attrs['data-live-url']
assert '/backoffice/' in live_url
live_resp = app.post(live_url, 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(live_url, 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
def test_backoffice_submission_conditional_jump_based_on_bo_field(pub):
user = create_superuser(pub)
Workflow.wipe()
workflow = Workflow(name='form-title')
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
workflow.backoffice_fields_formdef.fields = [
fields.StringField(id='bo0', varname='foo_bovar', type='string', label='bo variable'),
]
st1 = workflow.add_status('Status1', 'st1')
workflow.add_status('Status2', 'st2')
setbo = st1.add_action('set-backoffice-fields')
setbo.fields = [{'field_id': 'bo0', 'value': 'go'}]
jump = st1.add_action('jump')
jump.condition = {'type': 'django', 'value': "form_var_foo_bovar == 'go'"}
jump.status = 'st2'
workflow.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form-title'
formdef.fields = [
fields.TextField(id='1', varname='foo', type='text', label='fo variable'),
fields.TextField(
id='2', varname='var3', type='text', label='n/a', condition={'type': 'django', 'value': 'True'}
),
]
formdef.workflow_id = workflow.id
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
formdef.data_class().wipe()
# check jump condition being True
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'] = 'foo'
resp.form['f2'] = 'bar'
resp = resp.form.submit('submit') # -> confirmation page
resp = resp.form.submit('submit').follow()
assert formdef.data_class().count() == 1
assert formdef.data_class().select()[0].status == 'wf-st2'
# check jump condition being False
setbo.fields = [{'field_id': 'bo0', 'value': 'nogo'}]
workflow.store()
formdef.data_class().wipe()
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'] = 'foo'
resp.form['f2'] = 'bar'
resp = resp.form.submit('submit') # -> confirmation page
resp = resp.form.submit('submit').follow()
assert formdef.data_class().count() == 1
assert formdef.data_class().select()[0].status == 'wf-st1'
def test_backoffice_submission_sections(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
data_class = formdef.data_class()
data_class.wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert 'Submission to complete' not in resp.text
assert 'Running submission' not in resp.text
formdata = data_class()
formdata.data = {}
formdata.status = 'draft'
formdata.backoffice_submission = True
formdata.receipt_time = datetime.datetime(2015, 1, 1).timetuple()
formdata.store()
resp = app.get('/backoffice/submission/')
assert 'Submission to complete' in resp.text
assert 'Running submission' not in resp.text
assert '>#%s' % formdata.id in resp.text
formdata.data = {'1': 'xxx'}
formdata.store()
resp = app.get('/backoffice/submission/')
assert 'Submission to complete' not in resp.text
assert 'Running submission' in resp.text
assert '>#%s' % formdata.id in resp.text
def test_backoffice_submission_prefill_user(pub):
user = create_user(pub)
other_user = pub.user_class(name='other user')
other_user.email = 'other@example.net'
other_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1',
label='1st field',
type='string',
display_locations=['validation', 'summary', 'listings'],
prefill={'type': 'user', 'value': 'email'},
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
formdata = formdef.data_class()()
formdata.backoffice_submission = True
formdata.status = 'draft'
formdata.data = {}
formdata.submission_channel = 'mail'
formdata.user_id = other_user.id
formdata.submission_context = {}
formdata.store()
formdata2 = formdef.data_class()()
formdata2.backoffice_submission = True
formdata2.status = 'draft'
formdata2.data = {}
formdata.submission_channel = 'mail'
formdata.user_id = None
formdata2.submission_context = {}
formdata2.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
assert resp.form['f1'].value == ''
# restore a draft
resp = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp = resp.follow()
# and check it got prefilled with the user from context
assert resp.form['f1'].value == 'other@example.net'
# restore another, without user id
resp = app.get('/backoffice/submission/form-title/%s/' % formdata2.id)
resp = resp.follow()
# and check it was not prefilled
assert resp.form['f1'].value == ''
def test_backoffice_submission_prefill_user_via_formula(pub):
user = create_user(pub)
other_user = pub.user_class(name='other user')
other_user.email = 'other@example.net'
other_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1',
label='1st field',
type='string',
display_locations=['validation', 'summary', 'listings'],
prefill={'type': 'formula', 'value': 'form_user_email'},
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
formdata = formdef.data_class()()
formdata.backoffice_submission = True
formdata.status = 'draft'
formdata.data = {}
formdata.submission_channel = 'mail'
formdata.user_id = other_user.id
formdata.submission_context = {}
formdata.store()
formdata2 = formdef.data_class()()
formdata2.backoffice_submission = True
formdata2.status = 'draft'
formdata2.data = {}
formdata.submission_channel = 'mail'
formdata.user_id = None
formdata2.submission_context = {}
formdata2.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
assert resp.form['f1'].value == ''
# restore a draft
resp = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp = resp.follow()
# and check it got prefilled with the user from context
assert resp.form['f1'].value == 'other@example.net'
# restore another, without user id
resp = app.get('/backoffice/submission/form-title/%s/' % formdata2.id)
resp = resp.follow()
# and check it was not prefilled
assert resp.form['f1'].value == ''
@pytest.mark.parametrize('enable_tracking_code', [True, False])
def test_backoffice_submission_prefill_user_multiple_pages(pub, autosave, enable_tracking_code):
user = create_user(pub)
other_user = pub.user_class(name='other user')
other_user.email = 'other@example.net'
other_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='1st field', type='string', required=False),
fields.PageField(id='4', label='2nd page', type='page'),
fields.StringField(id='5', label='field on 2nd page', prefill={'type': 'user', 'value': 'email'}),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.enable_tracking_codes = enable_tracking_code
formdef.store()
formdef.data_class().wipe()
formdata = formdef.data_class()()
formdata.backoffice_submission = True
formdata.status = 'draft'
formdata.data = {}
formdata.submission_channel = 'mail'
formdata.user_id = other_user.id
formdata.submission_context = {}
formdata.store()
formdata2 = formdef.data_class()()
formdata2.backoffice_submission = True
formdata2.status = 'draft'
formdata2.data = {}
formdata2.submission_channel = 'mail'
formdata2.user_id = None
formdata2.submission_context = {}
formdata2.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp = resp.form.submit('submit')
assert resp.form['f5'].value == ''
# restore a draft
resp = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp = resp.follow()
resp = resp.form.submit('submit')
# and check it got prefilled with the user from context
assert resp.form['f5'].value == 'other@example.net'
# restore another, without user id
resp = app.get('/backoffice/submission/form-title/%s/' % formdata2.id)
resp = resp.follow()
resp = resp.form.submit('submit')
# and check it was not prefilled
assert resp.form['f5'].value == ''
# continue with additional tests when drafts are enabled, using autosave
if not enable_tracking_code:
return
# restore a draft
formdata.page_no = 0
formdata.user_id = other_user.id
formdata.store()
resp = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp = resp.follow()
resp.form['f1'] = 'Hello'
app.post('/backoffice/submission/form-title/autosave', params=resp.form.submit_fields())
assert formdef.data_class().get(formdata.id).user_id == str(other_user.id)
assert formdef.data_class().get(formdata.id).data['1'] == 'Hello'
resp = resp.form.submit('submit')
# and check it got prefilled with the user from context
assert resp.form['f5'].value == 'other@example.net'
assert formdef.data_class().get(formdata.id).user_id == str(other_user.id)
assert formdef.data_class().get(formdata.id).data['1'] == 'Hello'
formdef.data_class().wipe()
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'] = 'Hello'
app.post('/backoffice/submission/form-title/autosave', params=resp.form.submit_fields())
assert formdef.data_class().count() == 1
assert formdef.data_class().select()[0].user_id is None
resp = resp.form.submit('submit')
assert formdef.data_class().count() == 1
assert formdef.data_class().select()[0].user_id is None
def test_backoffice_submission_multiple_page_restore_on_validation(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='1st field', type='string', required=False),
fields.PageField(
id='2', label='2nd page', type='page', condition={'type': 'python', 'value': 'False'}
),
fields.PageField(id='3', label='3rd page', type='page'),
fields.StringField(id='5', label='field on 3rd page'),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.enable_tracking_codes = True
formdef.store()
formdef.data_class().wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'] = 'foo'
resp = resp.form.submit('submit')
resp.form['f5'] = 'bar'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
assert formdef.data_class().count() == 1
formdata = formdef.data_class().select()[0]
# restore draft
resp = app.get('/backoffice/submission/')
resp = resp.click(href='form-title/%s' % formdata.id)
resp = resp.follow()
assert 'Check values then click submit.' in resp.text
def test_backoffice_submission_substitution_vars(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='1st field', type='string', required=False, varname='foobar'),
fields.ItemField(
id='10', label='2nd field', type='item', items=['foo', 'bar', 'baz'], varname='foobar2'
),
fields.PageField(id='4', label='2nd page', type='page'),
fields.CommentField(id='5', label='X[form_var_foobar]Y[form_var_foobar2_raw]Z', type='comment'),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'].value = 'PLOP'
resp.form['f10'].value = 'bar'
resp = resp.form.submit('submit')
assert 'XPLOPYbarZ' in resp.text
# django-templated comment
formdef.fields[4] = fields.CommentField(
id='5', label='dj-{{ form_var_foobar }}-an-{{ form_var_foobar2_raw}}-go', type='comment'
)
formdef.store()
formdef.data_class().wipe()
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'].value = 'foo'
resp.form['f10'].value = 'bar'
resp = resp.form.submit('submit')
assert 'dj-foo-an-bar-go' in resp.text
formdef.data_class().wipe()
# same but starting from a draft, as if it was initiated by welco
formdata = formdef.data_class()()
formdata.data = {}
formdata.status = 'draft'
formdata.backoffice_submission = True
formdata.store()
resp = app.get('/backoffice/submission/form-title/%s/' % formdata.id)
resp = resp.follow()
resp.form['f1'].value = 'PLOP'
resp.form['f10'].value = 'bar'
resp = resp.form.submit('submit')
assert 'dj-PLOP-an-bar-go' in resp.text
def test_backoffice_submission_manual_channel(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
assert formdef.url_name in resp.text
resp = resp.click(formdef.name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
resp.form['submission_channel'] = 'mail'
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
# final submit
resp = resp.form.submit('submit')
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).data['1'] == 'test submission'
assert data_class.get(formdata_no).status == 'wf-new'
assert data_class.get(formdata_no).user is None
assert data_class.get(formdata_no).backoffice_submission is True
assert data_class.get(formdata_no).submission_channel == 'mail'
def test_backoffice_submission_manual_channel_with_return_url(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': '23'} # role the user doesn't have
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/%s/?ReturnURL=http://example.net' % formdef.url_name)
resp = resp.follow().follow()
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
resp.form['submission_channel'] = 'mail'
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
# final submit
resp = resp.form.submit('submit')
# as the user doesn't have a role to view the submitted form there's a
# redirection to the preset URL.
assert resp.location == 'http://example.net'
def test_backoffice_submission_no_manual_channel_with_welco(pub, welco_url):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = []
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
assert 'submission_channel' not in resp.form.fields
def test_backoffice_submission_with_nameid_and_channel(pub, local_user):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1',
label='1st field',
type='string',
display_locations=['validation', 'summary', 'listings'],
prefill={'type': 'formula', 'value': 'form_user_email'},
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get(
'/backoffice/submission/form-title/?NameID=%s&channel=mail' % local_user.name_identifiers[0]
)
assert resp.location.startswith('http://example.net/backoffice/submission/form-title/')
formdata_no = resp.location.split('/')[-2]
formdata = formdef.data_class().get(formdata_no)
assert formdata.user_id == str(local_user.id)
assert formdata.submission_channel == 'mail'
assert formdata.status == 'draft'
resp = resp.follow() # redirect to created draft
resp = resp.follow() # redirect to ?mt=
# check user is mentioned in sidebar
assert '<h3>Associated User</h3>' in resp
assert '<p>%s</p>' % local_user.get_display_name() in resp
assert resp.form['f1'].value == local_user.email # prefill with form_user_email
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.text
# final submit
resp = resp.form.submit('submit')
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
formdata = data_class.get(formdata_no)
assert formdata.user_id == str(local_user.id)
assert formdata.submission_channel == 'mail'
assert formdata.status == 'wf-new'
# target user is unknown
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/?NameID=UNKNOWN_NAMEID')
assert resp.location.startswith('http://example.net/backoffice/submission/form-title/')
formdata_no = resp.location.split('/')[-2]
formdata = formdef.data_class().get(formdata_no)
assert not formdata.user_id
resp = resp.follow() # redirect to created draft
resp = resp.follow() # redirect to ?mt=
assert 'The target user was not found, this form is anonymous.' in resp.text
def test_backoffice_submission_only_one_check(pub, local_user):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.StringField(
id='1', label='1st field', type='string', display_locations=['validation', 'summary', 'listings']
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.only_allow_one = True
formdef.store()
formdef.data_class().wipe()
# create a formdata attached the agent
formdata = formdef.data_class()()
formdata.user_id = user.id
formdata.just_created()
formdata.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp.form['f1'] = 'test'
resp = resp.form.submit('submit') # -> validation
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().count() == 2
# initiate a submission associated to a user
resp = app.get('/backoffice/submission/form-title/?NameID=%s' % local_user.name_identifiers[0])
resp = resp.follow().follow()
assert 'This form is limited to one per user' not in resp
resp.form['f1'] = 'test'
resp = resp.form.submit('submit') # -> validation
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().count() == 3
# initiate a second one
resp = app.get('/backoffice/submission/form-title/?NameID=%s' % local_user.name_identifiers[0])
resp = resp.follow().follow()
assert 'This form is limited to one per user' in resp
def test_backoffice_submission_channel_selection(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='Field on 1st page', type='string'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.StringField(id='3', label='Field on 2nd page', type='string'),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
assert resp.pyquery('.submit-channel-selection')
resp.form['submission_channel'] = 'counter' # happens via javascript
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.pyquery('.submit-channel-selection option[selected=selected]')[0].attrib['value'] == 'counter'
assert resp.form['submission_channel'].value == 'counter'
resp.form['f3'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<h3>Channel: Counter</h3>' in resp
resp = resp.form.submit('submit') # final submit
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).submission_channel == 'counter'
# select channel on second page
resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.pyquery('.submit-channel-selection')
resp.form['submission_channel'] = 'counter' # happens via javascript
resp.form['f3'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<h3>Channel: Counter</h3>' in resp
resp = resp.form.submit('submit') # final submit
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).submission_channel == 'counter'
# with preset channel
resp = app.get('/backoffice/submission/%s/?channel=counter' % formdef.url_name)
resp = resp.follow().follow()
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert not resp.pyquery('.submit-channel-selection')
assert '<h3>Channel: Counter</h3>' in resp
resp.form['f3'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<h3>Channel: Counter</h3>' in resp
resp = resp.form.submit('submit') # final submit
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).submission_channel == 'counter'
# with submission_context but not submission channel
resp = app.get('/backoffice/submission/%s/?ReturnURL=https://example.org' % formdef.url_name)
resp = resp.follow().follow()
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.pyquery('.submit-channel-selection')
resp.form['submission_channel'] = 'counter' # happens via javascript
resp.form['f3'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<h3>Channel: Counter</h3>' in resp
resp = resp.form.submit('submit') # final submit
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).submission_channel == 'counter'
def test_backoffice_submission_user_selection(pub):
user = create_user(pub)
for i in range(10):
random_user = pub.user_class()
random_user.name = 'random user %s' % i
random_user.email = 'test%s@invalid' % i
random_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='Field on 1st page', type='string'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.StringField(id='3', label='Field on 2nd page', type='string'),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
assert resp.pyquery('.submit-user-selection')
resp.form['user_id'] = str(random_user.id) # happens via javascript
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert not resp.pyquery('.submit-user-selection')
assert '>%s</p>' % random_user.name in resp
resp.form['f3'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<p>%s</p>' % random_user.name in resp
# final submit
resp = resp.form.submit('submit')
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).user.name == random_user.name
# select user on second page
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.pyquery('.submit-user-selection')
resp.form['user_id'] = str(random_user.id) # happens via javascript
resp.form['f3'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<p>%s</p>' % random_user.name in resp
# final submit
resp = resp.form.submit('submit')
formdata_no = resp.location.split('/')[-2]
data_class = formdef.data_class()
assert data_class.get(formdata_no).user.name == random_user.name
# check prefill
formdef.fields[-1].prefill = {'type': 'user', 'value': 'email'}
formdef.store()
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
assert resp.pyquery('.submit-user-selection')
resp.form['user_id'] = str(random_user.id) # happens via javascript
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert not resp.pyquery('.submit-user-selection')
assert '>%s</p>' % random_user.name in resp
assert resp.form['f3'].value == random_user.email
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert '<p>%s</p>' % random_user.name in resp
def test_backoffice_submission_user_selection_then_live(pub):
user = create_user(pub)
for i in range(10):
random_user = pub.user_class()
random_user.name = 'random user %s' % i
random_user.email = 'test%s@invalid' % i
random_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='Field on 1st page', type='string'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.StringField(
id='3',
label='Field on 2nd page',
type='string',
varname='plop',
prefill={'type': 'user', 'value': 'email'},
),
fields.StringField(
id='4',
label='2nd field on 2nd page',
type='string',
prefill={'type': 'string', 'value': '{{form_user_email}}', 'locked': True},
),
fields.StringField(
id='5',
label='field with condition',
type='string',
condition={'type': 'django', 'value': 'form_var_plop == "bye"'},
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/')
resp = resp.click(formdef.name)
assert resp.form['submission_channel'].attrs['type'] == 'hidden'
assert resp.pyquery('.submit-user-selection')
resp.form['user_id'] = str(random_user.id) # happens via javascript
resp.form['f1'] = 'test submission'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3'].value == random_user.email
assert resp.form['f4'].value == random_user.email
resp.form['f4'] = 'altered value' # alter value
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp
assert 'altered value' not in resp
def test_backoffice_submission_user_selection_then_live_prefill(pub):
user = create_user(pub)
for i in range(10):
random_user = pub.user_class()
random_user.name = 'random user %s' % i
random_user.email = 'test%s@invalid' % i
random_user.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(
id='3',
label='Field on 2nd page',
type='string',
varname='plop',
prefill={'type': 'user', 'value': 'email'},
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.store()
app = login(get_app(pub))
url = '/backoffice/submission/%s/' % formdef.url_name
resp = app.get(url)
live_url = resp.html.find('form').attrs['data-live-url']
assert resp.pyquery('.submit-user-selection')
resp.form['user_id'] = str(random_user.id) # happens via javascript
live_resp = app.post(live_url + '?modified_field_id=user', params=resp.form.submit_fields())
assert live_resp.json == {'result': {'3': {'visible': True, 'content': 'test9@invalid'}}}
def test_backoffice_submission_user_selection_then_card_data_source(pub):
pub.session_manager.session_class.wipe()
user = create_user(pub)
for i in range(10):
random_user = pub.user_class()
random_user.name = 'random user %s' % i
random_user.email = 'test%s@invalid' % i
random_user.store()
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = []
carddef.digest_templates = {'default': 'card {{ form_number }}'}
carddef.backoffice_submission_roles = user.roles
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.user_support = 'optional'
carddef.store()
carddata = carddef.data_class()()
carddata.data = {}
carddata.user_id = user.id
carddata.just_created()
carddata.store()
for i in range(3):
carddata = carddef.data_class()()
carddata.data = {}
carddata.user_id = random_user.id
carddata.just_created()
carddata.store()
pub.custom_view_class.wipe()
custom_view = pub.custom_view_class()
custom_view.title = 'shared custom test view'
custom_view.formdef = carddef
custom_view.visibility = 'datasource'
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {
'filter-user': 'on',
'filter-user-value': '__current__',
}
custom_view.store()
Workflow.wipe()
workflow = Workflow(name='wfedit')
st1 = workflow.add_status('Status1')
wfedit = st1.add_action('editable', id='_wfedit')
wfedit.by = [user.roles[0]]
workflow.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='1', label='1st page', type='page'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.ItemField(
id='3',
label='Test',
type='item',
data_source={'type': 'carddef:foo:%s' % custom_view.slug, 'value': ''},
),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': 1}
formdef.workflow_id = workflow.id
formdef.store()
formdef.data_class().wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
resp = resp.form.submit('submit') # -> 2nd page
# check the field doesn't propose cards linked to agent
assert resp.form['f3'].options == [('', False, '---')]
formdef.data_class().wipe()
resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
resp.form['user_id'] = str(random_user.id) # happens via javascript
resp = resp.form.submit('submit') # -> 2nd page
# check three cards are proposed
assert len(resp.form['f3'].options) == 3
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().count() == 1
formdata = formdef.data_class().select()[0]
assert formdata.data['3_display'] == 'card 2'
# check it's also ok during edition
resp = app.get(formdata.get_backoffice_url())
resp = resp.form.submit('button_wfedit')
resp = resp.follow()
resp = resp.form.submit('submit') # page 2
assert len(resp.form['f3'].options) == 3
def test_backoffice_submission_sidebar_lateral_block(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = []
formdef.backoffice_submission_roles = user.roles[:]
formdef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
assert '/lateral-block' not in resp.text
formdef.submission_lateral_template = 'foo bar blah'
formdef.store()
resp = app.get('/backoffice/submission/form-title/')
assert '/lateral-block' in resp.text
lateral_block_url = re.findall('data-async-url="(.*/lateral-block)"', resp.text)[0]
partial_resp = app.get(lateral_block_url)
assert partial_resp.text == '<div class="lateral-block">foo bar blah</div>'
def test_backoffice_submission_computed_field(pub):
user = create_user(pub)
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.ComputedField(id='1', label='computed', varname='computed', value_template='{{ "xxx" }}'),
]
formdef.backoffice_submission_roles = user.roles[:]
formdef.workflow_roles = {'_receiver': user.roles[0]}
formdef.store()
formdef.data_class().wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/submission/form-title/')
resp = resp.forms[0].submit('submit') # -> validation
resp = resp.forms[0].submit('submit').follow() # -> submit
assert 'The form has been recorded' in resp.text
assert formdef.data_class().count() == 1
formdata = formdef.data_class().select()[0]
assert formdata.data == {'1': 'xxx'}
def test_backoffice_submission_parent_var(pub):
user = create_user(pub)
FormDef.wipe()
Workflow.wipe()
source_formdef = FormDef()
source_formdef.name = 'source form'
source_formdef.workflow_roles = {'_receiver': user.roles[0]}
source_formdef.fields = [
fields.StringField(id='0', label='string', varname='toto_string'),
]
source_formdef.store()
target_formdef = FormDef()
target_formdef.name = 'target form'
target_formdef.workflow_roles = {'_receiver': user.roles[0]}
target_formdef.backoffice_submission_roles = user.roles[:]
target_formdef.fields = [
fields.PageField(id='0', type='page', label='page 1'),
fields.ComputedField(
id='1',
type='computed',
label='computed',
varname='computed',
value_template='{{ form_parent_form_var_toto_string }}',
),
fields.CommentField(id='2', type='comment', label='parent:{{ form_parent_form_var_toto_string }}'),
fields.CommentField(id='3', type='comment', label='computed:{{ form_var_computed }}'),
]
target_formdef.store()
# workflow
wf = Workflow(name='create-formdata')
st1 = wf.add_status('New')
create_formdata = st1.add_action('create_formdata', id='_create_formdata')
create_formdata.varname = 'resubmitted'
create_formdata.draft = True
create_formdata.formdef_slug = target_formdef.url_name
create_formdata.user_association_mode = 'keep-user'
create_formdata.backoffice_submission = True
create_formdata.attach_to_history = True
create_formdata.map_fields_by_varname = True
wf.store()
source_formdef.workflow = wf
source_formdef.store()
# create source formdata
formdata = source_formdef.data_class()()
formdata.data = {'0': 'foobar'}
formdata.just_created()
formdata.store()
formdata.perform_workflow()
# login and go to backoffice management page
app = login(get_app(pub))
resp = app.get(formdata.get_backoffice_url())
# click on target form in history
resp = resp.click(href=r'/target-form/')
resp = resp.follow().follow()
assert 'parent:foobar' in resp.text # parent var is ok
assert 'computed:foobar' in resp.text # and getting it via a computed var is also ok