5107 lines
187 KiB
Python
5107 lines
187 KiB
Python
# -*- coding: utf-8 -*-
|
|
import datetime
|
|
import json
|
|
import os
|
|
import re
|
|
import shutil
|
|
import time
|
|
import hashlib
|
|
import random
|
|
import xml.etree.ElementTree as ET
|
|
import zipfile
|
|
|
|
import mock
|
|
import pytest
|
|
|
|
try:
|
|
import xlwt
|
|
except ImportError:
|
|
xlwt = None
|
|
|
|
from django.utils import six
|
|
from django.utils.six import StringIO, BytesIO
|
|
from django.utils.six.moves.urllib import parse as urllib
|
|
from django.utils.six.moves.urllib import parse as urlparse
|
|
|
|
from quixote import cleanup, get_publisher
|
|
from wcs.qommon import ods
|
|
from wcs.api_utils import sign_url
|
|
from wcs.qommon import errors, sessions
|
|
from wcs.qommon.form import PicklableUpload
|
|
from wcs.qommon.ident.password_accounts import PasswordAccount
|
|
from wcs.qommon.http_request import HTTPRequest
|
|
from wcs.roles import Role
|
|
from wcs.workflows import (Workflow, CommentableWorkflowStatusItem,
|
|
ChoiceWorkflowStatusItem, EditableWorkflowStatusItem,
|
|
DisplayMessageWorkflowStatusItem,
|
|
JumpOnSubmitWorkflowStatusItem, WorkflowCriticalityLevel,
|
|
WorkflowBackofficeFieldsFormDef)
|
|
from wcs.wf.backoffice_fields import SetBackofficeFieldsWorkflowStatusItem
|
|
from wcs.wf.dispatch import DispatchWorkflowStatusItem
|
|
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
|
|
from wcs.wf.jump import JumpWorkflowStatusItem
|
|
from wcs.wf.wscall import WebserviceCallStatusItem
|
|
from wcs.wf.redirect_to_url import RedirectToUrlWorkflowStatusItem
|
|
from wcs.wf.register_comment import RegisterCommenterWorkflowStatusItem
|
|
from wcs.wf.resubmit import ResubmitWorkflowStatusItem
|
|
from wcs.carddef import CardDef
|
|
from wcs.categories import Category
|
|
from wcs.formdef import FormDef
|
|
from wcs.logged_errors import LoggedError
|
|
from wcs import fields
|
|
from wcs.wscalls import NamedWsCall
|
|
|
|
from utilities import (get_app, login, create_temporary_pub,
|
|
clean_temporary_pub)
|
|
|
|
|
|
def pytest_generate_tests(metafunc):
|
|
if 'pub' in metafunc.fixturenames:
|
|
metafunc.parametrize('pub', ['pickle', 'sql', 'pickle-templates'], indirect=True)
|
|
|
|
@pytest.fixture
|
|
def pub(request, emails):
|
|
pub = create_temporary_pub(
|
|
sql_mode=bool('sql' in request.param),
|
|
templates_mode=bool('templates' in request.param)
|
|
)
|
|
|
|
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()
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
fd.write('''
|
|
[api-secrets]
|
|
coucou = 1234
|
|
''')
|
|
fd.close()
|
|
|
|
return pub
|
|
|
|
def create_user(pub, is_admin=False):
|
|
if pub.user_class.select(lambda x: x.name == 'admin'):
|
|
user1 = pub.user_class.select(lambda x: x.name == 'admin')[0]
|
|
user1.is_admin = is_admin
|
|
user1.roles = [x.id for x in Role.select() if x.name == 'foobar']
|
|
user1.store()
|
|
return user1
|
|
user1 = pub.user_class(name='admin')
|
|
user1.email = 'admin@localhost'
|
|
user1.is_admin = is_admin
|
|
user1.store()
|
|
|
|
account1 = PasswordAccount(id='admin')
|
|
account1.set_password('admin')
|
|
account1.user_id = user1.id
|
|
account1.store()
|
|
|
|
Role.wipe()
|
|
role = Role(name='foobar')
|
|
role.store()
|
|
|
|
user1.roles = [role.id]
|
|
user1.store()
|
|
|
|
return user1
|
|
|
|
def create_superuser(pub): return create_user(pub, is_admin=True)
|
|
|
|
def create_environment(pub, set_receiver=True):
|
|
pub.session_manager.session_class.wipe()
|
|
Workflow.wipe()
|
|
Category.wipe()
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'form title'
|
|
if set_receiver:
|
|
formdef.workflow_roles = {'_receiver': 1}
|
|
|
|
datasource = {'type': 'formula',
|
|
'value': repr([('A', 'aa'), ('B', 'bb'), ('C', 'cc')])}
|
|
|
|
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.store()
|
|
formdef.data_class().wipe()
|
|
for i in range(50):
|
|
formdata = formdef.data_class()()
|
|
formdata.just_created()
|
|
formdata.receipt_time = datetime.datetime(2015, 1, 1).timetuple()
|
|
formdata.data = {'1': 'FOO BAR %d' % i}
|
|
if i%4 == 0:
|
|
formdata.data['2'] = 'foo'
|
|
formdata.data['2_display'] = 'foo'
|
|
formdata.data['3'] = 'A'
|
|
formdata.data['3_display'] = 'aa'
|
|
elif i%4 == 1:
|
|
formdata.data['2'] = 'bar'
|
|
formdata.data['2_display'] = 'bar'
|
|
formdata.data['3'] = 'B'
|
|
formdata.data['3_display'] = 'bb'
|
|
else:
|
|
formdata.data['2'] = 'baz'
|
|
formdata.data['2_display'] = 'baz'
|
|
formdata.data['3'] = 'C'
|
|
formdata.data['3_display'] = 'cc'
|
|
if i%3 == 0:
|
|
formdata.jump_status('new')
|
|
else:
|
|
formdata.jump_status('finished')
|
|
formdata.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {'1': 'XXX', '2': 'foo', '2_display': 'foo'}
|
|
formdata.status = 'draft'
|
|
formdata.store()
|
|
|
|
formdef = FormDef()
|
|
if set_receiver:
|
|
formdef.workflow_roles = {'_receiver': 1}
|
|
formdef.name = 'other form'
|
|
formdef.fields = []
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
for i in range(20):
|
|
formdata = formdef.data_class()()
|
|
formdata.just_created()
|
|
formdata.receipt_time = datetime.datetime(2014, 1, 1).timetuple()
|
|
formdata.jump_status('new')
|
|
formdata.store()
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
def test_backoffice_unlogged(pub):
|
|
create_superuser(pub)
|
|
resp = get_app(pub).get('/backoffice/', status=302)
|
|
assert resp.location == 'http://example.net/login/?next=http%3A%2F%2Fexample.net%2Fbackoffice%2F'
|
|
|
|
def test_backoffice_home(pub):
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
assert 'Management' in resp.text
|
|
assert 'Forms Workshop' in resp.text
|
|
assert 'Workflows Workshop' in resp.text
|
|
|
|
def test_backoffice_role_user(pub):
|
|
create_user(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
assert 'Management' in resp.text
|
|
assert not 'Forms Workshop' in resp.text
|
|
assert not 'Workflows Workshop' in resp.text
|
|
|
|
pub.cfg['admin-permissions'] = {'forms': [x.id for x in Role.select()]}
|
|
pub.write_cfg()
|
|
resp = app.get('/backoffice/')
|
|
assert 'Management' in resp.text
|
|
assert 'Forms Workshop' in resp.text
|
|
assert not 'Workflows Workshop' in resp.text
|
|
|
|
pub.cfg['admin-permissions'] = {'workflows': [x.id for x in Role.select()]}
|
|
pub.write_cfg()
|
|
resp = app.get('/backoffice/')
|
|
assert 'Management' in resp.text
|
|
assert not 'Forms Workshop' in resp.text
|
|
assert 'Workflows Workshop' in resp.text
|
|
|
|
# check role id int->str migration
|
|
pub.cfg['admin-permissions'] = {'workflows': [int(x.id) for x in Role.select()]}
|
|
pub.write_cfg()
|
|
resp = app.get('/backoffice/')
|
|
assert 'Management' in resp.text
|
|
assert not 'Forms Workshop' in resp.text
|
|
assert 'Workflows Workshop' in resp.text
|
|
|
|
def test_backoffice_forms(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub, set_receiver=False)
|
|
|
|
# 1st time with user not handling those forms
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
resp = resp.click('Management', index=0)
|
|
resp = resp.follow()
|
|
assert not 'Forms in your care' in resp.text
|
|
assert re.findall('Other Forms.*form-title', resp.text)
|
|
|
|
# 2nd time with user set as receiver of the forms
|
|
create_environment(pub, set_receiver=True)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
resp = resp.click('Management', index=0)
|
|
resp = resp.follow()
|
|
assert 'Forms in your care' in resp.text
|
|
assert '17 open on 50' in resp.text
|
|
|
|
# disable form, make sure it's still displayed
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.disabled = True
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/forms')
|
|
assert 'form-title' in resp.text
|
|
assert '17 open on 50' in resp.text
|
|
|
|
formdef.disabled = False
|
|
formdef.store()
|
|
|
|
# add an extra status to workflow and move a few formdatas to it, they
|
|
# should then be marked as open but not waiting for actions.
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
st1 = workflow.add_status('Status1')
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.timeout = 86400
|
|
jump.status = 'finished'
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
workflow.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow = workflow
|
|
formdef.store()
|
|
|
|
for i, formdata in enumerate(formdef.data_class().select(order_by='id')):
|
|
if formdata.status == 'wf-new' and i % 2:
|
|
formdata.status = 'wf-%s' % st1.id
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/')
|
|
resp = resp.click('Management', index=0)
|
|
resp = resp.follow()
|
|
assert 'Forms in your care' in resp.text
|
|
assert '9 open on 50' in resp.text
|
|
|
|
def test_backoffice_listing(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 17
|
|
|
|
# check status filter <select>
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp.forms[0]['filter'] = 'all'
|
|
resp = resp.forms[0].submit()
|
|
if pub.is_using_postgresql():
|
|
assert resp.text.count('data-link') == 20
|
|
else:
|
|
# not using sql -> no pagination
|
|
assert resp.text.count('data-link') == 50
|
|
|
|
# check status filter <select>
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp.forms[0]['filter'] = 'done'
|
|
resp = resp.forms[0].submit()
|
|
if pub.is_using_postgresql():
|
|
assert resp.text.count('data-link') == 20
|
|
resp = resp.click('Next Page')
|
|
assert resp.text.count('data-link') == 13
|
|
else:
|
|
assert resp.text.count('data-link') == 33
|
|
|
|
# add an extra status to workflow and move a few formdatas to it, they
|
|
# should then be marked as open but not waiting for actions.
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
st1 = workflow.add_status('Status1')
|
|
st1.id = 'plop'
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.timeout = 86400
|
|
jump.status = 'finished'
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
workflow.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow = workflow
|
|
formdef.store()
|
|
|
|
for i, formdata in enumerate(formdef.data_class().select(order_by='id')):
|
|
if formdata.status == 'wf-new' and i % 2:
|
|
formdata.status = 'wf-%s' % st1.id
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 9
|
|
resp.forms[0]['filter'] = 'pending'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('data-link') == 17
|
|
|
|
# check status forced as endpoints are not part of the "actionable" list.
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '3'
|
|
st1 = workflow.add_status('Status1')
|
|
st1.id = 'plop'
|
|
st1.forced_endpoint = False
|
|
again = ChoiceWorkflowStatusItem()
|
|
again.id = '_again'
|
|
again.label = 'Again'
|
|
again.by = ['_receiver']
|
|
again.status = st1.id
|
|
st1.items.append(again)
|
|
again.parent = st1
|
|
workflow.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow = workflow
|
|
formdef.store()
|
|
formdef.data_class().rebuild_security()
|
|
|
|
for i, formdata in enumerate(formdef.data_class().select(order_by='id')):
|
|
if formdata.status == 'wf-new' and i % 2:
|
|
formdata.status = 'wf-%s' % st1.id
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 17
|
|
resp.forms[0]['filter'] = 'pending'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('data-link') == 17
|
|
|
|
# mark status as an endpoint
|
|
st1.forced_endpoint = True
|
|
workflow.store()
|
|
formdef.data_class().rebuild_security()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 9
|
|
resp.forms[0]['filter'] = 'pending'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('data-link') == 9
|
|
|
|
def test_backoffice_listing_pagination(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 17
|
|
|
|
resp = app.get('/backoffice/management/form-title/?limit=5')
|
|
assert resp.text.count('data-link') == 5
|
|
assert '<div id="page-links">' in resp.text
|
|
|
|
resp = resp.click(re.compile('^2$')) # second page
|
|
assert resp.text.count('data-link') == 5
|
|
assert resp.form['offset'].value == '5'
|
|
|
|
resp = resp.click(re.compile('^3$')) # third page
|
|
assert resp.text.count('data-link') == 5
|
|
assert resp.form['offset'].value == '10'
|
|
|
|
resp = resp.click(re.compile('^4$')) # fourth page
|
|
assert resp.text.count('data-link') == 2
|
|
assert resp.form['offset'].value == '15'
|
|
|
|
with pytest.raises(IndexError): # no fifth page
|
|
resp = resp.click(re.compile('^5$'))
|
|
|
|
resp = resp.click(re.compile('^10$')) # per page: 10
|
|
assert resp.text.count('data-link') == 10
|
|
|
|
resp = resp.click(re.compile('^20$')) # per page: 20
|
|
assert resp.text.count('data-link') == 17
|
|
|
|
# try an overbound offset
|
|
resp = app.get('/backoffice/management/form-title/?limit=5&offset=30')
|
|
resp = resp.follow()
|
|
assert resp.form['offset'].value == '0'
|
|
|
|
def test_backoffice_listing_order(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
ids = []
|
|
for i, formdata in enumerate(formdef.data_class().select(order_by='id')):
|
|
if formdata.status in ('wf-new', 'wf-accepted'):
|
|
ids.append(formdata.id)
|
|
formdata.receipt_time = datetime.datetime(2015, 1, 1, 10, i).timetuple()
|
|
# ordered with odd-numbered ids then even-numbered ids
|
|
formdata.evolution[-1].time = datetime.datetime(2015, 2, 1, 10 + i % 2, i).timetuple()
|
|
formdata.store()
|
|
|
|
inversed_receipt_time_order = list(reversed([str(x) for x in sorted(ids)]))
|
|
last_update_time_order = [str(x) for x in sorted(ids, key=lambda x: int(x) if int(x) % 2 else int(x)+1000)]
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 17
|
|
ids = [x.strip('/') for x in re.findall(r'data-link="(.*?)"', resp.text)]
|
|
assert ids == inversed_receipt_time_order
|
|
|
|
resp = app.get('/backoffice/management/form-title/?order_by=receipt_time')
|
|
assert resp.text.count('data-link') == 17
|
|
ids = [x.strip('/') for x in re.findall(r'data-link="(.*?)"', resp.text)]
|
|
assert ids == list(reversed(inversed_receipt_time_order))
|
|
|
|
resp = app.get('/backoffice/management/form-title/?order_by=last_update_time')
|
|
assert resp.text.count('data-link') == 17
|
|
ids = [x.strip('/') for x in re.findall(r'data-link="(.*?)"', resp.text)]
|
|
assert ids == last_update_time_order
|
|
|
|
resp = app.get('/backoffice/management/form-title/?order_by=-last_update_time')
|
|
assert resp.text.count('data-link') == 17
|
|
ids = [x.strip('/') for x in re.findall(r'data-link="(.*?)"', resp.text)]
|
|
assert ids == list(reversed(last_update_time_order))
|
|
|
|
if not pub.site_options.has_section('options'):
|
|
pub.site_options.add_section('options')
|
|
pub.site_options.set('options', 'default-sort-order', '-last_update_time')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('data-link') == 17
|
|
ids = [x.strip('/') for x in re.findall(r'data-link="(.*?)"', resp.text)]
|
|
assert ids == list(reversed(last_update_time_order))
|
|
|
|
def test_backoffice_legacy_urls(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/form-title/')
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/'
|
|
resp = app.get('/backoffice/form-title/1/')
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/1/'
|
|
resp = app.get('/backoffice/form-title/listing/?bla')
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/listing/?bla'
|
|
resp = app.get('/backoffice/form-title/listing/foo?bla')
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/listing/foo?bla'
|
|
resp = app.get('/backoffice/not-form-title/', status=404)
|
|
|
|
def test_backoffice_columns(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('</th>') == 8 # six columns
|
|
resp.forms[0]['1'].checked = False
|
|
assert not 'submission_channel' in resp.forms[0].fields
|
|
assert 'last_update_time' in resp.forms[0].fields
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('</th>') == 7 # fixe columns
|
|
assert resp.text.count('data-link') == 17 # 17 rows
|
|
assert resp.text.count('FOO BAR') == 0 # no field 1 column
|
|
|
|
def test_backoffice_channel_column(pub):
|
|
if not pub.site_options.has_section('variables'):
|
|
pub.site_options.add_section('variables')
|
|
pub.site_options.set('variables', 'welco_url', 'xxx')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('</th>') == 8 # six columns
|
|
resp.forms[0]['submission_channel'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('</th>') == 9 # seven columns
|
|
assert resp.text.count('data-link') == 17 # 17 rows
|
|
assert resp.text.count('<td>Web</td>') == 17
|
|
|
|
def test_backoffice_submission_agent_column(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
agent = pub.user_class(name='agent')
|
|
agent.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'submission_agent' in resp.form.fields
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.text.count('</th>') == 8 # six columns
|
|
resp.form['submission_agent'].checked = True
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('</th>') == 9 # seven columns
|
|
assert resp.text.count('data-link') == 17 # 17 rows
|
|
assert not '>agent<' in resp.text
|
|
resp = resp.click('Export as CSV File')
|
|
assert len(resp.text.splitlines()) == 18 # 17 + header line
|
|
assert not ',agent,' in resp.text
|
|
|
|
for formdata in formdef.data_class().select():
|
|
formdata.submission_context = {'agent_id': agent.id}
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp.form['submission_agent'].checked = True
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('>agent<') == 17
|
|
|
|
resp = resp.click('Export as CSV File')
|
|
assert len(resp.text.splitlines()) == 18 # 17 + header line
|
|
assert resp.text.count(',agent,') == 17
|
|
|
|
def test_backoffice_image_column(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields.append(fields.FileField(id='4', label='file field', type='file',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.store()
|
|
|
|
upload = PicklableUpload('test.jpeg', 'image/jpeg')
|
|
jpg = open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb').read()
|
|
upload.receive([jpg])
|
|
for formdata in formdef.data_class().select(lambda x: x.status == 'wf-new'):
|
|
formdata.data['4'] = upload
|
|
formdata.store()
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'download?f=4&thumbnail=1' not in resp.text
|
|
|
|
def test_backoffice_filter(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.forms[0]['filter-status'].checked == True
|
|
resp.forms[0]['filter-status'].checked = False
|
|
resp.forms[0]['filter-2'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
assert '<select name="filter">' not in resp.text
|
|
|
|
resp.forms[0]['filter-2-value'] = 'baz'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('<td>baz</td>') == 8
|
|
assert resp.text.count('<td>foo</td>') == 0
|
|
assert resp.text.count('<td>bar</td>') == 0
|
|
|
|
resp.forms[0]['filter-start'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp.forms[0]['filter-start-value'] = datetime.datetime(2015, 2, 1).strftime('%Y-%m-%d')
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('<td>baz</td>') == 0
|
|
resp.forms[0]['filter-start-value'] = datetime.datetime(2014, 2, 1).strftime('%Y-%m-%d')
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('<td>baz</td>') == 8
|
|
|
|
# check there's no crash on invalid date values
|
|
resp.forms[0]['filter-start-value'] = 'whatever'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('<td>baz</td>') == 8
|
|
|
|
# check two-digit years are handled correctly
|
|
resp.forms[0]['filter-start-value'] = datetime.datetime(2014, 2, 1).strftime('%y-%m-%d')
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('<td>baz</td>') == 8
|
|
|
|
# check it's also ok for end filter
|
|
resp.forms[0]['filter-end'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp.forms[0]['filter-end-value'] = datetime.datetime(2014, 2, 2).strftime('%y-%m-%d')
|
|
resp = resp.forms[0].submit()
|
|
assert resp.text.count('<td>baz</td>') == 0
|
|
|
|
def test_backoffice_default_filter(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'filter-2-value' in resp.form.fields
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[1].in_filters = True
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'filter-2-value' in resp.form.fields
|
|
|
|
# same check for items field
|
|
formdef.fields.append(
|
|
fields.ItemsField(id='4', label='4th field', type='items', items=['foo', 'bar', 'baz']))
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'filter-4-value' in resp.form.fields
|
|
|
|
formdef.fields[-1].in_filters = True
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'filter-4-value' in resp.form.fields
|
|
|
|
def test_backoffice_bool_filter(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields.append(fields.BoolField(id='4', label='4th field',
|
|
type='bool',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.store()
|
|
|
|
for i, formdata in enumerate(formdef.data_class().select()):
|
|
formdata.data['4'] = bool(i%2)
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp.form['filter-4'].checked = True
|
|
resp = resp.form.submit()
|
|
|
|
assert resp.form['filter-4-value'].value == ''
|
|
|
|
resp.form['filter-4-value'].value = 'true'
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('<td>Yes</td>') > 0
|
|
assert resp.text.count('<td>No</td>') == 0
|
|
|
|
resp.form['filter-4-value'].value = 'false'
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('<td>Yes</td>') == 0
|
|
assert resp.text.count('<td>No</td>') > 0
|
|
|
|
def test_backoffice_items_filter(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields.append(fields.ItemsField(id='4', label='4th field', type='items',
|
|
items=['a', 'b', 'c', 'd'],
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.store()
|
|
|
|
for i, formdata in enumerate(formdef.data_class().select()):
|
|
if i%4 == 0:
|
|
formdata.data['4'] = ['a', 'b']
|
|
formdata.data['4_display'] = 'a, b'
|
|
elif i%4 == 1:
|
|
formdata.data['4'] = ['b', 'd']
|
|
formdata.data['4_display'] = 'b, d'
|
|
elif i%4 == 2:
|
|
formdata.data['4'] = ['a']
|
|
formdata.data['4_display'] = 'a'
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp.form['filter-4'].checked = True
|
|
resp = resp.form.submit()
|
|
|
|
assert resp.form['filter-4-value'].value == ''
|
|
|
|
resp.form['filter-4-value'].value = 'a'
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('<td>a, b</td>') > 0
|
|
assert resp.text.count('<td>a</td>') > 0
|
|
assert resp.text.count('<td>b, d</td>') == 0
|
|
|
|
resp.form['filter-4-value'].value = 'b'
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('<td>a, b</td>') > 0
|
|
assert resp.text.count('<td>a</td>') == 0
|
|
assert resp.text.count('<td>b, d</td>') > 0
|
|
|
|
resp.form['filter-4-value'].value = 'c'
|
|
resp = resp.form.submit()
|
|
assert resp.text.count('<td>a, b</td>') == 0
|
|
assert resp.text.count('<td>a</td>') == 0
|
|
assert resp.text.count('<td>b, d</td>') == 0
|
|
assert resp.text.count('data-link') == 0 # no rows
|
|
|
|
def test_backoffice_csv(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Export as CSV File')
|
|
assert resp.headers['content-type'].startswith('text/')
|
|
assert len(resp.text.splitlines()) == 18 # 17 + header line
|
|
assert len(resp.text.splitlines()[0].split(',')) == 7
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[-1].display_locations = ['validation', 'summary', 'listings']
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Export as CSV File')
|
|
assert len(resp.text.splitlines()[0].split(',')) == 9
|
|
|
|
# check item fields with datasources get two columns (id & text)
|
|
assert resp.text.splitlines()[0].split(',')[6] == '3rd field'
|
|
assert resp.text.splitlines()[0].split(',')[7] == '' # 3rd field, continue
|
|
assert resp.text.splitlines()[1].split(',')[6] == 'A'
|
|
assert resp.text.splitlines()[1].split(',')[7] == 'aa'
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp.forms[0]['filter'] = 'all'
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert len(resp_csv.text.splitlines()) == 51
|
|
|
|
# test status filter
|
|
resp.forms[0]['filter'] = 'pending'
|
|
resp.forms[0]['filter-2'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp.forms[0]['filter-2-value'] = 'baz'
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert len(resp_csv.text.splitlines()) == 9
|
|
|
|
# test criteria filters
|
|
resp.forms[0]['filter-start'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp.forms[0]['filter-start-value'] = datetime.datetime(2015, 2, 1).strftime('%Y-%m-%d')
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert len(resp_csv.text.splitlines()) == 1
|
|
|
|
resp.forms[0]['filter-start-value'] = datetime.datetime(2014, 2, 1).strftime('%Y-%m-%d')
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert len(resp_csv.text.splitlines()) == 9
|
|
assert 'Created' in resp_csv.text.splitlines()[0]
|
|
|
|
# test column selection
|
|
resp.form['time'].checked = False
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert 'Created' not in resp_csv.text.splitlines()[0]
|
|
|
|
def test_backoffice_export_long_listings(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
for i in range(100):
|
|
formdata = formdef.data_class()()
|
|
formdata.just_created()
|
|
formdata.receipt_time = datetime.datetime(2015, 1, 1).timetuple()
|
|
formdata.data = {'1': 'BAZ BAZ %d' % i}
|
|
formdata.jump_status('new')
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Export as CSV File')
|
|
assert resp.location.startswith('http://example.net/backoffice/management/form-title/export?job=')
|
|
resp = resp.follow()
|
|
assert 'completed' in resp.text
|
|
resp = resp.click('Download Export')
|
|
resp_lines = resp.text.splitlines()
|
|
assert resp_lines[0] == 'Number,Created,Last Modified,User Label,1st field,2nd field,Status'
|
|
assert len(resp_lines) == 118
|
|
assert resp_lines[1].split(',')[1].startswith(
|
|
time.strftime('%Y-%m-%d', formdata.receipt_time))
|
|
assert resp_lines[1].split(',')[2].startswith(
|
|
time.strftime('%Y-%m-%d', formdata.last_update_time))
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Export a Spreadsheet')
|
|
assert resp.location.startswith('http://example.net/backoffice/management/form-title/export?job=')
|
|
job_id = urlparse.parse_qs(urlparse.urlparse(resp.location).query)['job'][0]
|
|
resp = resp.follow()
|
|
assert 'completed' in resp.text
|
|
resp = resp.click('Download Export')
|
|
assert resp.content_type == 'application/vnd.oasis.opendocument.spreadsheet'
|
|
|
|
# check afterjob ajax call
|
|
status_resp = app.get('/afterjobs/' + job_id)
|
|
assert status_resp.text == 'completed|completed'
|
|
|
|
# check error handling
|
|
app.get('/afterjobs/whatever', status=404)
|
|
|
|
def test_backoffice_csv_export_channel(pub):
|
|
if not pub.site_options.has_section('variables'):
|
|
pub.site_options.add_section('variables')
|
|
pub.site_options.set('variables', 'welco_url', 'xxx')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert 'Channel' not in resp_csv.text.splitlines()[0]
|
|
|
|
# add submission channel column
|
|
resp.form['submission_channel'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert resp_csv.text.splitlines()[0].split(',')[1] == 'Channel'
|
|
assert resp_csv.text.splitlines()[1].split(',')[1] == 'Web'
|
|
|
|
def test_backoffice_csv_export_anonymised(pub):
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert resp_csv.text.splitlines()[0].split(',')[-1] != 'Anonymised'
|
|
|
|
# add anonymised column
|
|
resp.form['anonymised'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp_csv = resp.click('Export as CSV File')
|
|
assert resp_csv.text.splitlines()[0].split(',')[-1] == 'Anonymised'
|
|
assert resp_csv.text.splitlines()[1].split(',')[-1] == 'No'
|
|
|
|
def test_backoffice_ods(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Export a Spreadsheet')
|
|
assert resp.headers['content-type'] == 'application/vnd.oasis.opendocument.spreadsheet'
|
|
assert 'filename=form-title.ods' in resp.headers['content-disposition']
|
|
assert resp.body[:2] == b'PK' # ods has a zip container
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields.append(fields.FileField(id='4', label='file field', type='file',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.fields.append(fields.DateField(id='5', label='date field', type='date',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.fields.append(fields.StringField(id='6', label='number field', type='string',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.fields.append(fields.StringField(id='7', label='phone field', type='string',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.fields.append(fields.DateField(id='8', label='very old field', type='date',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.fields.append(fields.StringField(id='9', label='string field', type='string',
|
|
display_locations=['validation', 'summary', 'listings']))
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class().select(lambda x: x.status == 'wf-new')[0]
|
|
formdata.data['4'] = PicklableUpload('/foo/bar', content_type='text/plain')
|
|
formdata.data['4'].receive([b'hello world'])
|
|
formdata.data['5'] = time.strptime('2015-05-12', '%Y-%m-%d')
|
|
formdata.data['6'] = '12345'
|
|
formdata.data['7'] = '0102030405'
|
|
formdata.data['8'] = time.strptime('1871-03-18', '%Y-%m-%d')
|
|
formdata.data['9'] = 'plop\npl\x1dop' # with control characters
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Export a Spreadsheet')
|
|
assert resp.headers['content-type'] == 'application/vnd.oasis.opendocument.spreadsheet'
|
|
assert 'filename=form-title.ods' in resp.headers['content-disposition']
|
|
assert resp.body[:2] == b'PK' # ods has a zip container
|
|
|
|
zipf = zipfile.ZipFile(BytesIO(resp.body))
|
|
ods_sheet = ET.parse(zipf.open('content.xml'))
|
|
# check the ods contains a link to the document
|
|
elem = ods_sheet.findall('.//{%s}a' % ods.NS['text'])[0]
|
|
assert elem.attrib['{%s}href' % ods.NS['xlink']] == 'http://example.net/backoffice/management/form-title/%s/files/4/bar' % formdata.id
|
|
resp = app.get(elem.attrib['{%s}href' % ods.NS['xlink']])
|
|
assert resp.text == 'hello world'
|
|
|
|
all_texts = [x.text for x in ods_sheet.findall('.//{%s}table-row//{%s}p' % (ods.NS['table'], ods.NS['text']))]
|
|
created_column = all_texts.index('Created')
|
|
date_column = all_texts.index('date field')
|
|
number_column = all_texts.index('number field')
|
|
phone_column = all_texts.index('phone field')
|
|
old_column = all_texts.index('very old field')
|
|
string_column = all_texts.index('string field')
|
|
|
|
for row in ods_sheet.findall('.//{%s}table-row' % ods.NS['table']):
|
|
if row.findall('.//{%s}table-cell/{%s}p' % (
|
|
ods.NS['table'], ods.NS['text']))[0].text == formdata.get_display_id():
|
|
break
|
|
else:
|
|
assert False, 'failed to find data row'
|
|
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[created_column].attrib[
|
|
'{%s}value-type' % ods.NS['office']] == 'date'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[created_column].attrib[
|
|
'{%s}style-name' % ods.NS['table']] == 'DateTime'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[date_column].attrib[
|
|
'{%s}value-type' % ods.NS['office']] == 'date'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[date_column].attrib[
|
|
'{%s}style-name' % ods.NS['table']] == 'Date'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[number_column].attrib[
|
|
'{%s}value-type' % ods.NS['office']] == 'float'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[number_column].attrib[
|
|
'{%s}value' % ods.NS['office']] == '12345'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[phone_column].attrib[
|
|
'{%s}value-type' % ods.NS['office']] == 'string'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[old_column].attrib[
|
|
'{%s}value-type' % ods.NS['office']] == 'date'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[old_column].attrib[
|
|
'{%s}date-value' % ods.NS['office']] == '1871-03-18'
|
|
assert row.findall('.//{%s}table-cell' % ods.NS['table'])[
|
|
string_column].find('{%s}p' % ods.NS['text']).text == 'plop\nplop'
|
|
|
|
@pytest.mark.skipif('xlwt is None')
|
|
def test_backoffice_xls(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'Excel Export' in resp.text
|
|
|
|
if not pub.site_options.has_section('options'):
|
|
pub.site_options.add_section('options')
|
|
pub.site_options.set('options', 'legacy-excel-export', 'true')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Excel Export')
|
|
assert resp.headers['content-type'].startswith('application/vnd.ms-excel')
|
|
|
|
def test_backoffice_statistics(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Statistics')
|
|
assert 'Total number of records: 50' in resp.text
|
|
assert 'New: 17' in resp.text
|
|
assert 'Finished: 33' in resp.text
|
|
assert re.findall('foo.*26.*bar.*26.*bar.*48', resp.text) # percentages
|
|
assert 'Resolution time' in resp.text
|
|
assert 'To Status "New"' in resp.text
|
|
assert 'To Status "Finished"' in resp.text
|
|
assert not '<h2>Filters</h2>' in resp.text
|
|
|
|
resp.forms[0]['filter-end-value'] = '2013-01-01'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 0' in resp.text
|
|
assert '<h2>Filters</h2>' in resp.text
|
|
assert 'End: 2013-01-01' in resp.text
|
|
|
|
def test_backoffice_multi_actions(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'id="multi-actions"' in resp.text
|
|
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
action = workflow.add_global_action('FOOBAR')
|
|
jump = action.append_item('jump')
|
|
jump.status = 'finished'
|
|
trigger = action.triggers[0]
|
|
trigger.roles = ['whatever']
|
|
|
|
workflow.store()
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'id="multi-actions"' in resp.text
|
|
|
|
trigger.roles = [x.id for x in Role.select() if x.name == 'foobar']
|
|
workflow.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'id="multi-actions"' in resp.text
|
|
ids = []
|
|
for checkbox in resp.forms[0].fields['select[]'][1:6]:
|
|
ids.append(checkbox._value)
|
|
checkbox.checked = True
|
|
resp = resp.forms[0].submit('button-action-1')
|
|
assert '?job=' in resp.location
|
|
resp = resp.follow()
|
|
assert 'Executing task "FOOBAR" on forms' in resp.text
|
|
assert '>completed<' in resp.text
|
|
for id in ids:
|
|
assert formdef.data_class().get(id).status == 'wf-finished'
|
|
|
|
draft_ids = [x.id for x in formdef.data_class().select() if x.status == 'draft']
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert resp.forms[0].fields['select[]'][0]._value == '_all'
|
|
resp.forms[0].fields['select[]'][0].checked = True
|
|
resp = resp.forms[0].submit('button-action-1')
|
|
for formdata in formdef.data_class().select():
|
|
if formdata.id in draft_ids:
|
|
assert formdata.status == 'draft'
|
|
else:
|
|
assert formdata.status == 'wf-finished'
|
|
|
|
for formdata in formdef.data_class().select():
|
|
if formdata.status != 'draft':
|
|
formdata.jump_status('new')
|
|
formdata.store()
|
|
|
|
# action for other role
|
|
action2 = workflow.add_global_action('OTHER ACTION')
|
|
jump = action2.append_item('jump')
|
|
jump.status = 'accepted'
|
|
trigger = action2.triggers[0]
|
|
trigger.roles = ['whatever']
|
|
workflow.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'id="multi-actions"' in resp.text
|
|
assert not 'OTHER ACTION' in resp.text
|
|
|
|
# action for function
|
|
trigger.roles = ['_foobar']
|
|
workflow.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'id="multi-actions"' in resp.text
|
|
assert 'OTHER ACTION' not in resp.text
|
|
|
|
workflow.roles['_foobar'] = 'Foobar'
|
|
workflow.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'id="multi-actions"' in resp.text
|
|
assert 'OTHER ACTION' in resp.text
|
|
|
|
# alter some formdata to simulate dispatch action
|
|
stable_ids = []
|
|
for checkbox in resp.forms[0].fields['select[]'][1:6]:
|
|
formdata = formdef.data_class().get(checkbox._value)
|
|
formdata.workflow_roles = {'_foobar': formdef.workflow_roles['_receiver']}
|
|
formdata.store()
|
|
stable_ids.append(formdata.id)
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'OTHER ACTION' in resp.text
|
|
|
|
resp.forms[0].fields['select[]'][0].checked = True # _all
|
|
resp = resp.forms[0].submit('button-action-2')
|
|
assert '?job=' in resp.location
|
|
resp = resp.follow()
|
|
assert 'Executing task "OTHER ACTION" on forms' in resp.text
|
|
# check only dispatched formdata have been moved by global action executed
|
|
# on all formdatas
|
|
for formdata in formdef.data_class().select():
|
|
if formdata.id in draft_ids:
|
|
assert formdata.status == 'draft'
|
|
elif formdata.id in stable_ids:
|
|
assert formdata.status == 'wf-accepted'
|
|
else:
|
|
assert formdata.status != 'wf-accepted'
|
|
|
|
def test_backoffice_statistics_status_filter(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Statistics')
|
|
assert 'filter' not in resp.forms[0].fields # status is not displayed by default
|
|
assert not '<h2>Filters</h2>' in resp.text
|
|
|
|
# add 'status' as a filter
|
|
resp.forms[0]['filter-status'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
assert 'filter' in resp.forms[0].fields
|
|
assert not '<h2>Filters</h2>' in resp.text
|
|
|
|
assert resp.forms[0]['filter'].value == 'all'
|
|
resp.forms[0]['filter'].value = 'pending'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 17' in resp.text
|
|
assert '<h2>Filters</h2>' in resp.text
|
|
assert 'Status: Pending' in resp.text
|
|
|
|
resp.forms[0]['filter'].value = 'done'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 33' in resp.text
|
|
assert '<h2>Filters</h2>' in resp.text
|
|
assert 'Status: Done' in resp.text
|
|
|
|
resp.forms[0]['filter'].value = 'rejected'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 0' in resp.text
|
|
assert '<h2>Filters</h2>' in resp.text
|
|
assert 'Status: Rejected' in resp.text
|
|
|
|
resp.forms[0]['filter'].value = 'all'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 50' in resp.text
|
|
|
|
def test_backoffice_statistics_status_select(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Statistics')
|
|
assert not 'filter-2-value' in resp.form.fields
|
|
|
|
resp.forms[0]['filter-2'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp.forms[0]['filter-2-value'].value = 'bar'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 13' in resp.text
|
|
|
|
resp.forms[0]['filter-2-value'].value = 'baz'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 24' in resp.text
|
|
|
|
resp.forms[0]['filter-2-value'].value = 'foo'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 13' in resp.text
|
|
assert '<h2>Filters</h2>' in resp.text
|
|
assert '2nd field: foo' in resp.text
|
|
|
|
# check it's also possible to get back to the complete list
|
|
resp.forms[0]['filter-2-value'].value = ''
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 50' in resp.text
|
|
|
|
# check it also works with item fields with a data source
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Statistics')
|
|
resp.forms[0]['filter-3'].checked = True
|
|
resp = resp.forms[0].submit()
|
|
resp.forms[0]['filter-3-value'].value = 'A'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total number of records: 13' in resp.text
|
|
assert '<h2>Filters</h2>' in resp.text
|
|
assert '3rd field: aa' in resp.text
|
|
|
|
# set field to be displayed by default in filters
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[1].in_filters = True
|
|
formdef.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Statistics')
|
|
assert 'filter-2-value' in resp.form.fields
|
|
|
|
def test_backoffice_map(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert re.findall('<tbody.*\/tbody>', resp.text, re.DOTALL)[0].count('<tr') == 17
|
|
|
|
# check there's no link to map the sidebar
|
|
assert not 'Plot on a Map' in resp.text
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.geolocations = {'base': 'Geolocafoobar'}
|
|
formdef.store()
|
|
number31.geolocations = {'base': {'lat': 48.83, 'lon': 2.32}}
|
|
number31.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'Plot on a Map' in resp.text
|
|
resp = resp.click('Plot on a Map')
|
|
assert 'data-geojson-url' in resp.text
|
|
assert 'tiles.entrouvert.org/' in resp.text
|
|
|
|
if not pub.site_options.has_section('options'):
|
|
pub.site_options.add_section('options')
|
|
|
|
pub.site_options.set('options', 'map-tile-urltemplate', 'https://{s}.tile.example.net/{z}/{x}/{y}.png')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click('Plot on a Map')
|
|
assert 'tile.example.net/' in resp.text
|
|
|
|
def test_backoffice_geojson(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields.append(fields.MapField(id='4', label='4th field', type='map'))
|
|
formdef.fields.append(fields.MapField(id='5', label='5th field', type='string'))
|
|
form_class = formdef.data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/geojson', status=404)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.geolocations = {'base': 'Geolocafoobar'}
|
|
formdef.store()
|
|
number31 = formdef.data_class().get(number31.id)
|
|
number31.geolocations = {'base': {'lat': 48.83, 'lon': 2.32}}
|
|
number31.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/geojson?1=on&4=on&5=on')
|
|
assert len(resp.json['features']) == 1
|
|
assert resp.json['features'][0]['geometry']['coordinates'] == [2.32, 48.83]
|
|
assert 'status_colour' in resp.json['features'][0]['properties']
|
|
assert resp.json['features'][0]['properties']['status_name'] == 'New'
|
|
assert resp.json['features'][0]['properties']['status_colour'] == '#66FF00'
|
|
assert resp.json['features'][0]['properties']['view_label'] == 'View'
|
|
assert 'display_fields' in resp.json['features'][0]['properties']
|
|
assert len(resp.json['features'][0]['properties']['display_fields']) == 1
|
|
|
|
resp = app.get('/backoffice/management/form-title/geojson?filter=pending&filter-status=on')
|
|
assert len(resp.json['features']) == 1
|
|
|
|
resp = app.get('/backoffice/management/form-title/geojson?filter=done&filter-status=on')
|
|
assert len(resp.json['features']) == 0
|
|
|
|
|
|
def test_backoffice_handling(pub):
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert re.findall('<tbody.*\/tbody>', resp.text, re.DOTALL)[0].count('<tr') == 17
|
|
|
|
# check sidebar links are ok
|
|
assert 'Statistics' in resp.text
|
|
assert 'Export' in resp.text
|
|
app.get('/backoffice/management/form-title/stats', status=200)
|
|
app.get('/backoffice/management/form-title/csv', status=200)
|
|
app.get('/backoffice/management/form-title/ods', status=200)
|
|
app.get('/backoffice/management/form-title/json', status=200)
|
|
|
|
# click on a formdata
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
resp.forms[0]['comment'] = 'HELLO WORLD'
|
|
resp = resp.forms[0].submit('button_accept')
|
|
resp = resp.follow()
|
|
assert FormDef.get_by_urlname('form-title').data_class().get(number31.id).status == 'wf-accepted'
|
|
assert 'HELLO WORLD' in resp.text
|
|
|
|
def test_backoffice_handling_global_action(pub):
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test global action'
|
|
formdef.fields = []
|
|
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
action = workflow.add_global_action('FOOBAR')
|
|
register_comment = action.append_item('register-comment')
|
|
register_comment.comment = 'HELLO WORLD GLOBAL ACTION'
|
|
jump = action.append_item('jump')
|
|
jump.status = 'finished'
|
|
trigger = action.triggers[0]
|
|
trigger.roles = [x.id for x in Role.select() if x.name == 'foobar']
|
|
|
|
workflow.store()
|
|
formdef.workflow_id = workflow.id
|
|
formdef.workflow_roles = {'_receiver': 1}
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/%s/%s/' % (formdef.url_name, formdata.id))
|
|
assert 'button-action-1' in resp.form.fields
|
|
resp = resp.form.submit('button-action-1')
|
|
|
|
resp = app.get('/backoffice/management/%s/%s/' % (formdef.url_name, formdata.id))
|
|
assert 'HELLO WORLD GLOBAL ACTION' in resp.text
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-finished'
|
|
|
|
def test_backoffice_global_remove_action(pub):
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test global remove'
|
|
formdef.fields = []
|
|
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
action = workflow.add_global_action('FOOBAR')
|
|
remove = action.append_item('remove')
|
|
trigger = action.triggers[0]
|
|
trigger.roles = [x.id for x in Role.select() if x.name == 'foobar']
|
|
|
|
workflow.store()
|
|
formdef.workflow_id = workflow.id
|
|
formdef.workflow_roles = {'_receiver': 1}
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/%s/%s/' % (formdef.url_name, formdata.id))
|
|
assert 'remove' in resp.text
|
|
assert 'button-action-1' in resp.form.fields
|
|
resp = resp.form.submit('button-action-1')
|
|
resp = resp.follow()
|
|
assert resp.request.url == 'http://example.net/backoffice/management/test-global-remove/'
|
|
assert 'The form has been deleted.' in resp.text
|
|
|
|
def test_backoffice_submission_context(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert re.findall('<tbody.*\/tbody>', resp.text, re.DOTALL)[0].count('<tr') == 17
|
|
|
|
# click on a formdata
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
|
|
# check there's nothing in the sidebar
|
|
assert not 'Channel' in resp.text
|
|
|
|
number31.submission_channel = 'mail'
|
|
number31.user_id = user.id
|
|
number31.submission_context = {
|
|
'mail_url': 'http://www.example.com/test.pdf',
|
|
'thumbnail_url': 'http://www.example.com/thumbnail.png',
|
|
'comments': 'test_backoffice_submission_context',
|
|
'summary_url': 'http://www.example.com/summary',
|
|
'agent_id': user.id,
|
|
}
|
|
number31.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert 'Channel' in resp.text
|
|
assert 'http://www.example.com/thumbnail.png' in resp.text
|
|
assert 'http://www.example.com/test.pdf' in resp.text
|
|
assert 'Associated User' in resp.text
|
|
assert 'test_backoffice_submission_context' in resp.text
|
|
assert 'http://www.example.com/summary' in resp.text
|
|
assert 'by %s' % user.get_display_name() in resp.text
|
|
|
|
def test_backoffice_geolocation_info(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.geolocations = {'base': 'Geolocafoobar'}
|
|
formdef.store()
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert re.findall('<tbody.*\/tbody>', resp.text, re.DOTALL)[0].count('<tr') == 17
|
|
|
|
# click on a formdata
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
|
|
# check there's nothing in the sidebar
|
|
assert not 'Geolocation' in resp.text
|
|
|
|
number31.geolocations = {'base': {'lat': 48.83, 'lon': 2.32}}
|
|
number31.store()
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert 'Geolocafoobar' in resp.text
|
|
assert 'class="qommon-map"' in resp.text
|
|
assert 'data-init-lng="2.32"' in resp.text
|
|
assert 'data-init-lat="48.83' in resp.text
|
|
|
|
def test_backoffice_info_text(pub):
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='info texts')
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
commentable = CommentableWorkflowStatusItem()
|
|
commentable.id = '_commentable'
|
|
commentable.by = ['_submitter', '_receiver']
|
|
commentable.button_label = 'CLICK ME!'
|
|
st1.items.append(commentable)
|
|
commentable.parent = st1
|
|
|
|
commentable2 = CommentableWorkflowStatusItem()
|
|
commentable2.id = '_commentable2'
|
|
commentable2.by = ['_submitter']
|
|
commentable2.button_label = 'CLICK ME2!'
|
|
st1.items.append(commentable2)
|
|
commentable2.parent = st1
|
|
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
assert 'CLICK ME!' in resp.text
|
|
assert not 'CLICK ME2!' in resp.text
|
|
assert not 'backoffice-description' in resp.text
|
|
|
|
# add an info text to the status
|
|
st1.backoffice_info_text = '<p>Foo</p>'
|
|
workflow.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert 'backoffice-description' in resp.text
|
|
assert '<p>Foo</p>' in resp.text
|
|
|
|
# add an info text to the button
|
|
commentable.backoffice_info_text = '<p>Bar</p>'
|
|
workflow.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert 'backoffice-description' in resp.text
|
|
assert '<p>Foo</p>' in resp.text
|
|
assert '<p>Bar</p>' in resp.text
|
|
|
|
# info text is not visible if form is locked
|
|
second_user = pub.user_class(name='foobar')
|
|
second_user.roles = Role.keys()
|
|
second_user.store()
|
|
account = PasswordAccount(id='foobar')
|
|
account.set_password('foobar')
|
|
account.user_id = second_user.id
|
|
account.store()
|
|
app2 = login(get_app(pub), username='foobar', password='foobar')
|
|
resp = app2.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert 'Be warned forms of this user are also being looked' in resp.text
|
|
assert not 'backoffice-description' in resp.text
|
|
assert not 'CLICK ME!' in resp.text
|
|
assert not 'CLICK ME2!' in resp.text
|
|
|
|
# remove info text from the status
|
|
st1.backoffice_info_text = None
|
|
workflow.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert 'backoffice-description' in resp.text
|
|
assert not '<p>Foo</p>' in resp.text
|
|
assert '<p>Bar</p>' in resp.text
|
|
|
|
# add info text to second button
|
|
commentable2.backoffice_info_text = '<p>Baz</p>'
|
|
workflow.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert 'backoffice-description' in resp.text
|
|
assert not '<p>Foo</p>' in resp.text
|
|
assert '<p>Bar</p>' in resp.text
|
|
assert not '<p>Baz</p>' in resp.text
|
|
|
|
# remove info text from first button
|
|
commentable.backoffice_info_text = None
|
|
workflow.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert not 'backoffice-description' in resp.text
|
|
|
|
def test_backoffice_handling_post_dispatch(pub):
|
|
# check a formdata that has been dispatched to another role is accessible
|
|
# by an user with that role.
|
|
user1 = create_user(pub)
|
|
role = Role(name='foobaz')
|
|
role.store()
|
|
user1.roles = [role.id]
|
|
user1.store()
|
|
create_environment(pub)
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
|
|
# check there's no access at the moment
|
|
resp = app.get('/backoffice/management/').follow()
|
|
assert not 'form-title/' in resp.text
|
|
resp = app.get('/backoffice/management/form-title/', status=403)
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id, status=403)
|
|
|
|
# emulate a dispatch (setting formdata.workflow_roles), receiver of that
|
|
# formdata is now the local role we gave to the user.
|
|
formdata31 = form_class.get(number31.id)
|
|
formdata31.workflow_roles = {'_receiver': role.id}
|
|
formdata31.store()
|
|
|
|
# check listing is accessible, with a single item
|
|
resp = app.get('/backoffice/management/').follow()
|
|
assert 'form-title/' in resp.text
|
|
resp = app.get('/backoffice/management/form-title/', status=200)
|
|
assert re.findall('<tbody.*\/tbody>', resp.text, re.DOTALL)[0].count('<tr') == 1
|
|
|
|
# check statistics and exports are also available
|
|
assert 'Statistics' in resp.text
|
|
assert 'Export' in resp.text
|
|
app.get('/backoffice/management/form-title/stats', status=200)
|
|
app.get('/backoffice/management/form-title/csv', status=200)
|
|
app.get('/backoffice/management/form-title/ods', status=200)
|
|
app.get('/backoffice/management/form-title/json', status=200)
|
|
|
|
# check formdata is accessible, and that it's possible to perform an action
|
|
# on it.
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
resp.forms[0]['comment'] = 'HELLO WORLD'
|
|
resp = resp.forms[0].submit('button_accept')
|
|
resp = resp.follow()
|
|
assert FormDef.get_by_urlname('form-title').data_class().get(number31.id).status == 'wf-accepted'
|
|
assert 'HELLO WORLD' in resp.text
|
|
|
|
def test_global_statisticspub(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
resp = resp.click('Global statistics')
|
|
assert 'Total count: 70' in resp.text
|
|
|
|
resp.forms[0]['start'] = '2014-01-01'
|
|
resp.forms[0]['end'] = '2014-12-31'
|
|
resp = resp.forms[0].submit()
|
|
assert 'Total count: 20' in resp.text
|
|
|
|
def test_backoffice_submission(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
assert not 'Submission' in resp.text
|
|
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/')
|
|
assert 'Submission' in resp.text
|
|
resp = app.get('/backoffice/submission/')
|
|
assert formdef.url_name in resp.text
|
|
|
|
resp = resp.click(formdef.name)
|
|
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 = RedirectToUrlWorkflowStatusItem()
|
|
item.id = '_redirect'
|
|
item.url = 'http://www.example.org/'
|
|
st1.items.append(item)
|
|
item.parent = st1
|
|
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)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
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.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
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_context = {'agent_id': '10000'}
|
|
formdata.store()
|
|
resp = app.get(formdata_location)
|
|
assert 'test submission' in resp.text
|
|
assert not formdata.tracking_code in resp.text
|
|
|
|
# restore user
|
|
formdata.submission_context = {'agent_id': 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 not formdata.tracking_code in resp.text
|
|
|
|
def test_backoffice_submission_welco(pub, welco_url):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
assert not 'Submission' in resp.text
|
|
app.get('/backoffice/submission/', status=403)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
|
|
# if it's empty, redirect to welco
|
|
resp = app.get('/backoffice/')
|
|
assert 'Submission' in resp.text
|
|
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_context = {'agent_id': user.id}
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/')
|
|
assert 'Submission' in resp.text
|
|
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)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
|
|
formdef = FormDef.get_by_urlname('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()
|
|
|
|
def post_formdata():
|
|
signed_url = sign_url('http://example.net/api/formdefs/form-title/submit' +
|
|
'?format=json&orig=coucou&email=%s' % urllib.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)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.enable_tracking_codes = True
|
|
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.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
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.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
resp = resp.form.submit('submit') # -> to validation
|
|
resp = resp.form.submit('submit') # -> to submit
|
|
assert resp.location == 'https://example.org'
|
|
|
|
def test_backoffice_parallel_submission(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
app.get('/backoffice/submission/', status=403)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.status = 'draft'
|
|
formdata.backoffice_submission = True
|
|
formdata.submission_context = {'agent_id': user.id}
|
|
formdata.store()
|
|
|
|
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()
|
|
|
|
resp1.form['f1'] = 'foo'
|
|
resp1.form['f2'] = 'bar'
|
|
resp1.form['f3'] = 'C'
|
|
resp1 = resp1.form.submit('submit') # to validation page
|
|
|
|
# also move the second form to the validation page
|
|
resp2.form['f1'] = 'bar'
|
|
resp2.form['f2'] = 'bar'
|
|
resp2.form['f3'] = 'C'
|
|
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'
|
|
resp3.form['f2'] = 'bar'
|
|
resp3.form['f3'] = 'C'
|
|
|
|
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_dispatch(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='dispatch')
|
|
st1 = wf.add_status('Status1')
|
|
dispatch = DispatchWorkflowStatusItem()
|
|
dispatch.id = '_dispatch'
|
|
dispatch.role_key = '_receiver'
|
|
dispatch.role_id = '2'
|
|
st1.items.append(dispatch)
|
|
dispatch.parent = st1
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
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
|
|
# 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.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
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.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
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)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.enable_tracking_codes = True
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
data_class = formdef.data_class()
|
|
data_class.wipe()
|
|
resp = app.get('/backoffice/submission/')
|
|
assert formdef.url_name in resp.text
|
|
|
|
resp = resp.click(formdef.name)
|
|
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
|
|
|
|
# stop here, don't validate, let user finish it.
|
|
assert data_class.count() == 1
|
|
formdata_no = data_class.select()[0].id
|
|
tracking_code = data_class.select()[0].tracking_code
|
|
|
|
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 == '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)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.enable_tracking_codes = True
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
data_class = formdef.data_class()
|
|
data_class.wipe()
|
|
resp = app.get('/backoffice/submission/')
|
|
assert formdef.url_name in resp.text
|
|
|
|
resp = resp.click(formdef.name)
|
|
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
|
|
|
|
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)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.enable_tracking_codes = True
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
data_class = formdef.data_class()
|
|
data_class.wipe()
|
|
pub.tracking_code_class.wipe()
|
|
resp = app.get('/backoffice/submission/')
|
|
assert formdef.url_name in resp.text
|
|
|
|
resp = resp.click(formdef.name)
|
|
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
|
|
|
|
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 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)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
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 = 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')
|
|
st2 = workflow.add_status('Status2', 'st2')
|
|
|
|
setbo = SetBackofficeFieldsWorkflowStatusItem()
|
|
setbo.parent = st1
|
|
setbo.fields = [{'field_id': 'bo0', 'value': 'go'}]
|
|
st1.items.append(setbo)
|
|
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.condition = {'type': 'django', 'value': "form_var_foo_bovar == 'go'"}
|
|
jump.status = 'st2'
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
|
|
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)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.enable_tracking_codes = True
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
data_class = formdef.data_class()
|
|
data_class.wipe()
|
|
|
|
resp = app.get('/backoffice/submission/')
|
|
assert not 'Submission to complete' in resp.text
|
|
assert not 'Running submission' 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 not 'Running submission' in resp.text
|
|
assert '>#%s' % formdata.id in resp.text
|
|
|
|
formdata.data = {'1': 'xxx'}
|
|
formdata.store()
|
|
resp = app.get('/backoffice/submission/')
|
|
assert not 'Submission to complete' 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)
|
|
create_environment(pub)
|
|
other_user = pub.user_class(name='other user')
|
|
other_user.email = 'other@example.net'
|
|
other_user.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[0].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)
|
|
create_environment(pub)
|
|
other_user = pub.user_class(name='other user')
|
|
other_user.email = 'other@example.net'
|
|
other_user.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[0].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 == ''
|
|
|
|
def test_backoffice_submission_prefill_user_multiple_pages(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
other_user = pub.user_class(name='other user')
|
|
other_user.email = 'other@example.net'
|
|
other_user.store()
|
|
|
|
for enable_tracking_code in (False, True):
|
|
formdef = FormDef.get_by_urlname('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 = {}
|
|
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/')
|
|
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
|
|
|
|
# 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'
|
|
resp_autosave = 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'
|
|
resp_autosave = 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)
|
|
create_environment(pub)
|
|
other_user = pub.user_class(name='other user')
|
|
other_user.email = 'other@example.net'
|
|
other_user.store()
|
|
|
|
formdef = FormDef.get_by_urlname('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)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('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)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
assert not 'Submission' in resp.text
|
|
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/')
|
|
assert 'Submission' in resp.text
|
|
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.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
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).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
|
|
assert data_class.get(formdata_no).submission_channel == 'mail'
|
|
|
|
def test_backoffice_submission_no_manual_channel_with_welco(pub, welco_url):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
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)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[0].prefill = {'type': 'formula', 'value': 'form_user_email'}
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.enable_tracking_codes = True
|
|
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('/')[-1]
|
|
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=
|
|
|
|
assert resp.form['f1'].value == local_user.email # prefill with form_user_email
|
|
resp.form['f2'] = 'baz'
|
|
resp.form['f3'] = 'C'
|
|
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'
|
|
|
|
def test_backoffice_wscall_failure_display(http_requests, pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wscall')
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wscall = WebserviceCallStatusItem()
|
|
wscall.id = '_wscall'
|
|
wscall.varname = 'xxx'
|
|
wscall.url = 'http://remote.example.net/xml'
|
|
wscall.action_on_bad_data = ':stop'
|
|
wscall.record_errors = True
|
|
st1.items.append(wscall)
|
|
wscall.parent = st1
|
|
|
|
again = ChoiceWorkflowStatusItem()
|
|
again.id = '_again'
|
|
again.label = 'Again'
|
|
again.by = ['_receiver']
|
|
again.status = st1.id
|
|
st1.items.append(again)
|
|
again.parent = st1
|
|
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
assert 'Again' in resp.text
|
|
resp = resp.forms[0].submit('button_again')
|
|
resp = resp.follow()
|
|
assert 'Error during webservice call' in resp.text
|
|
|
|
number31.user_id = user.id # change ownership to stay in frontoffice
|
|
number31.store()
|
|
# the failure message shouldn't be displayed in the frontoffice
|
|
resp = app.get('/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
assert not 'Error during webservice call' in resp.text
|
|
|
|
def test_backoffice_wscall_error_email(http_requests, pub, emails):
|
|
pub.cfg['debug'] = {'error_email': 'errors@localhost.invalid'}
|
|
pub.write_cfg()
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wscall')
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wscall = WebserviceCallStatusItem()
|
|
wscall.id = '_wscall'
|
|
wscall.varname = 'xxx'
|
|
wscall.url = 'http://remote.example.net/xml'
|
|
wscall.action_on_bad_data = ':stop'
|
|
wscall.record_errors = True
|
|
st1.items.append(wscall)
|
|
wscall.parent = st1
|
|
|
|
again = ChoiceWorkflowStatusItem()
|
|
again.id = '_again'
|
|
again.label = 'Again'
|
|
again.by = ['_receiver']
|
|
again.status = st1.id
|
|
st1.items.append(again)
|
|
again.parent = st1
|
|
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
assert 'Again' in resp.text
|
|
resp = resp.forms[0].submit('button_again')
|
|
resp = resp.follow()
|
|
assert 'Error during webservice call' in resp.text
|
|
|
|
# check email box
|
|
if six.PY2:
|
|
error_email = emails.get('[ERROR] [WSCALL] ValueError: No JSON object could be decoded')
|
|
else:
|
|
error_email = emails.get('[ERROR] [WSCALL] json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)')
|
|
assert '/form-title/%s/' % number31.id in error_email['payload']
|
|
assert error_email['msg']['References']
|
|
|
|
def test_backoffice_wscall_attachment(http_requests, pub):
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wscall')
|
|
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
|
|
workflow.backoffice_fields_formdef.fields = [
|
|
fields.FileField(id='bo1', label='bo field 1', type='file'),
|
|
]
|
|
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wscall = WebserviceCallStatusItem()
|
|
wscall.id = '_wscall'
|
|
wscall.varname = 'xxx'
|
|
wscall.response_type = 'attachment'
|
|
wscall.backoffice_filefield_id = 'bo1'
|
|
wscall.url = 'http://remote.example.net/xml'
|
|
wscall.action_on_bad_data = ':stop'
|
|
wscall.record_errors = True
|
|
st1.items.append(wscall)
|
|
wscall.parent = st1
|
|
|
|
again = ChoiceWorkflowStatusItem()
|
|
again.id = '_again'
|
|
again.label = 'Again'
|
|
again.by = ['_receiver']
|
|
again.status = st1.id
|
|
st1.items.append(again)
|
|
again.parent = st1
|
|
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
assert 'Again' in resp.text
|
|
resp = resp.forms[0].submit('button_again')
|
|
resp = resp.follow()
|
|
|
|
# get the two generated files from backoffice: in backoffice fields
|
|
# (wscall.backoffice_filefield_id), and in history
|
|
for index in (0, 1):
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
resp = resp.click('xxx.xml', index=index)
|
|
assert resp.location.endswith('/xxx.xml')
|
|
resp = resp.follow()
|
|
assert resp.content_type == 'text/xml'
|
|
assert resp.text == '<?xml version="1.0"><foo/>'
|
|
|
|
formdata = formdef.data_class().get(number31.id)
|
|
assert formdata.evolution[-1].parts[0].orig_filename == 'xxx.xml'
|
|
assert formdata.evolution[-1].parts[0].content_type == 'text/xml'
|
|
assert formdata.get_substitution_variables()['attachments'].xxx.filename == 'xxx.xml'
|
|
resp = app.get(formdata.get_substitution_variables()['attachments'].xxx.url)
|
|
resp = resp.follow()
|
|
assert resp.text == '<?xml version="1.0"><foo/>'
|
|
|
|
def test_backoffice_wfedit(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
number31.submission_context = {
|
|
'mail_url': 'http://www.example.com/test.pdf',
|
|
}
|
|
number31.store()
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wfedit')
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wfedit = EditableWorkflowStatusItem()
|
|
wfedit.id = '_wfedit'
|
|
wfedit.by = [user.roles[0]]
|
|
st1.items.append(wfedit)
|
|
wfedit.parent = st1
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
resp = resp.form.submit('button_wfedit')
|
|
resp = resp.follow()
|
|
assert 'http://www.example.com/test.pdf' in resp.text # make sure sidebar has details
|
|
assert not 'Tracking Code' in resp.text # make sure it doesn't display a tracking code
|
|
assert resp.form['f1'].value == number31.data['1']
|
|
assert resp.form['f2'].value == number31.data['2']
|
|
assert resp.form['f3'].value == number31.data['3']
|
|
assert 'value="Save Changes"' in resp.text
|
|
resp.form['f2'].value = 'bar'
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
assert form_class().get(number31.id).data['2'] == 'bar'
|
|
number31.store()
|
|
|
|
def test_backoffice_wfedit_submission(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.enable_tracking_codes = True
|
|
|
|
formdef.fields.insert(0, fields.PageField(id='0', label='1st page', type='page'))
|
|
formdef.fields.append(fields.PageField(id='4', label='2nd page', type='page'))
|
|
|
|
formdef.store()
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
number31.backoffice_submission = True
|
|
number31.store()
|
|
formdata_count = form_class.count()
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wfedit')
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wfedit = EditableWorkflowStatusItem()
|
|
wfedit.id = '_wfedit'
|
|
wfedit.by = [user.roles[0]]
|
|
st1.items.append(wfedit)
|
|
wfedit.parent = st1
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
resp = resp.form.submit('button_wfedit')
|
|
resp = resp.follow()
|
|
assert resp.form['f1'].value == number31.data['1']
|
|
assert resp.form['f2'].value == number31.data['2']
|
|
assert resp.form['f3'].value == number31.data['3']
|
|
resp.form['f2'].value = 'bar'
|
|
resp = resp.form.submit('submit')
|
|
assert 'value="Save Changes"' in resp.text
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
assert form_class().get(number31.id).data['2'] == 'bar'
|
|
number31.store()
|
|
assert formdata_count == form_class.count()
|
|
|
|
def test_backoffice_wfedit_and_backoffice_fields(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wfedit')
|
|
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
|
|
workflow.backoffice_fields_formdef.fields = [
|
|
fields.StringField(id='bo1', label='1st backoffice field',
|
|
type='string', varname='backoffice_blah', required=False),
|
|
]
|
|
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wfedit = EditableWorkflowStatusItem()
|
|
wfedit.id = '_wfedit'
|
|
wfedit.by = [user.roles[0]]
|
|
st1.items.append(wfedit)
|
|
wfedit.parent = st1
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
number31 = form_class().get(number31.id)
|
|
number31.data['bo1'] = 'plop'
|
|
number31.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
resp = resp.form.submit('button_wfedit')
|
|
resp = resp.follow()
|
|
resp.form['f2'].value = 'bar'
|
|
resp = resp.form.submit('submit')
|
|
resp = resp.follow()
|
|
assert form_class().get(number31.id).data['bo1'] == 'plop'
|
|
|
|
def test_backoffice_wfedit_and_data_source_with_user_info(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
|
|
formdef.fields[2].data_source = {'type': 'json',
|
|
'value': 'https://www.example.invalid/?name_id={% firstof form_user_display_name "XXX" %}'
|
|
}
|
|
formdef.store()
|
|
|
|
form_class = formdef.data_class()
|
|
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
|
|
# attach a custom workflow
|
|
workflow = Workflow(name='wfedit')
|
|
st1 = workflow.add_status('Status1', number31.status.split('-')[1])
|
|
|
|
wfedit = EditableWorkflowStatusItem()
|
|
wfedit.id = '_wfedit'
|
|
wfedit.by = [user.roles[0]]
|
|
st1.items.append(wfedit)
|
|
wfedit.parent = st1
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
number31 = form_class().get(number31.id)
|
|
number31.user_id = user.id
|
|
number31.store()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
|
|
data = {'data': [{'id': 'A', 'text': 'hello'}, {'id': 'B', 'text': 'world'}]}
|
|
def side_effect(url, *args):
|
|
assert '?name_id=admin' in url
|
|
return StringIO(json.dumps(data))
|
|
|
|
urlopen.side_effect = side_effect
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
resp = resp.form.submit('button_wfedit')
|
|
resp = resp.follow()
|
|
assert urlopen.call_count == 1
|
|
resp.form['f3'].value = 'A'
|
|
resp = resp.form.submit('submit')
|
|
assert urlopen.call_count == 2
|
|
resp = resp.follow()
|
|
|
|
def test_global_listing(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/').follow()
|
|
assert 'Global View' in resp.text
|
|
resp = resp.click('Global View')
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 20
|
|
assert not 'Map View' in resp.text
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 37 # 17 formdef1 + 20 formdef2
|
|
|
|
resp = app.get('/backoffice/management/listing?offset=20&limit=20')
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 17
|
|
|
|
# try an overbound offset
|
|
resp = app.get('/backoffice/management/listing?offset=40&limit=20')
|
|
resp = resp.follow()
|
|
assert resp.forms['listing-settings']['offset'].value == '0'
|
|
|
|
resp = app.get('/backoffice/management/listing')
|
|
resp.forms['listing-settings']['end'] = '2014-02-01'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 20
|
|
assert 'http://example.net/backoffice/management/other-form/' in resp.text
|
|
assert not 'http://example.net/backoffice/management/form-title/' in resp.text
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
last_update_time = formdef.data_class().select(lambda x: not x.is_draft())[0].last_update_time
|
|
# check created and last modified columns
|
|
assert '>2014-01-01 00:00<' in resp.text
|
|
assert time.strftime('>%Y-%m-%d', last_update_time) in resp.text
|
|
|
|
# check digest is included
|
|
formdata = formdef.data_class().get(
|
|
re.findall(r'data-link="(.*?)"', app.get('/backoffice/management/listing').text)[0].split('/')[-2])
|
|
formdata.formdef.digest_template = 'digest of number <{{form_number}}>'
|
|
formdata.store()
|
|
assert formdata.get(formdata.id).digest
|
|
resp = app.get('/backoffice/management/listing')
|
|
assert formdata.get_url(backoffice=True) in resp.text
|
|
assert 'digest of number <%s>' % formdata.id_display in resp.text
|
|
|
|
# check a Channel column is added when welco is available
|
|
assert not 'Channel' in resp.text
|
|
|
|
if not pub.site_options.has_section('variables'):
|
|
pub.site_options.add_section('variables')
|
|
pub.site_options.set('variables', 'welco_url', 'xxx')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
formdata = formdef.data_class().select(lambda x: x.status == 'wf-new')[0]
|
|
formdata.submission_channel = 'mail'
|
|
formdata.store()
|
|
assert 'Channel' in resp.text
|
|
assert '>Web<' in resp.text
|
|
resp.forms['listing-settings']['submission_channel'] = 'web'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 36
|
|
resp.forms['listing-settings']['submission_channel'] = 'mail'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 1
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
resp.forms['listing-settings']['q'] = 'foo'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 17
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
resp.forms['listing-settings']['status'] = 'waiting'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 37
|
|
resp.forms['listing-settings']['status'] = 'open'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 37
|
|
resp.forms['listing-settings']['status'] = 'all'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 70
|
|
resp.forms['listing-settings']['status'] = 'done'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 33
|
|
|
|
# change role handling a formdef, make sure they do not appear anylonger in
|
|
# the all/done views.
|
|
role = Role(name='whatever')
|
|
role.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_roles = {'_receiver': role.id}
|
|
formdef.store()
|
|
formdef.data_class().rebuild_security()
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
resp.forms['listing-settings']['status'] = 'waiting'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 20
|
|
assert not 'form-title' in resp.text
|
|
resp.forms['listing-settings']['status'] = 'open'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 20
|
|
assert not 'form-title' in resp.text
|
|
resp.forms['listing-settings']['status'] = 'all'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 20
|
|
assert not 'form-title' in resp.text
|
|
resp.forms['listing-settings']['status'] = 'done'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 0
|
|
assert not 'form-title' in resp.text
|
|
|
|
def test_global_listing_user_label(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
create_user(pub)
|
|
FormDef.wipe()
|
|
|
|
from wcs.admin.settings import UserFieldsFormDef
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields.append(fields.StringField(id='3', label='first_name', type='string'))
|
|
user_formdef.fields.append(fields.StringField(id='4', label='last_name', type='string'))
|
|
user_formdef.store()
|
|
pub.cfg['users']['field_name'] = ['3', '4']
|
|
pub.write_cfg()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foobar'
|
|
formdef.url_name = 'foobar'
|
|
formdef.workflow_roles = {'_receiver': 1}
|
|
formdef.fields = [
|
|
fields.StringField(id='1', label='first_name',
|
|
prefill={'type': 'user', 'value': '3'}),
|
|
fields.StringField(id='2', label='last_name',
|
|
prefill={'type': 'user', 'value': '4'}),
|
|
]
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {'1': 'blah', '2': 'xxx'}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
formdata.jump_status('new')
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/').follow()
|
|
resp = resp.click('Global View')
|
|
assert '<td class="cell-user">blah xxx</td>' in resp.text
|
|
|
|
def test_management_views_with_no_formdefs(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
FormDef.wipe()
|
|
|
|
from wcs.sql import get_connection_and_cursor, drop_global_views
|
|
conn, cur = get_connection_and_cursor()
|
|
drop_global_views(conn, cur)
|
|
conn.commit()
|
|
cur.close()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/forms')
|
|
assert 'This site is currently empty.' in resp.text
|
|
resp = app.get('/backoffice/management/listing')
|
|
assert 'This site is currently empty.' in resp.text
|
|
|
|
def test_category_in_global_listing(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
assert not 'category_id' in resp.forms['listing-settings'].fields
|
|
|
|
cat1 = Category(name='cat1')
|
|
cat1.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.category_id = cat1.id
|
|
formdef.store()
|
|
|
|
cat2 = Category(name='cat2')
|
|
cat2.store()
|
|
formdef = FormDef.get_by_urlname('other-form')
|
|
formdef.category_id = cat2.id
|
|
formdef.store()
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
assert 'category_id' in resp.forms['listing-settings'].fields
|
|
assert 'management/other-form/' in resp.text
|
|
assert 'management/form-title/' in resp.text
|
|
|
|
resp.forms['listing-settings']['category_id'] = cat1.id
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert not 'management/other-form/' in resp.text
|
|
assert 'management/form-title/' in resp.text
|
|
|
|
resp.forms['listing-settings']['category_id'] = cat2.id
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert 'management/other-form/' in resp.text
|
|
assert not 'management/form-title/' in resp.text
|
|
|
|
def test_datetime_in_global_listing(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
resp.forms['listing-settings']['end'] = '01/01/2010'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 0
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=500')
|
|
resp.forms['listing-settings']['start'] = '01/01/2010'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 37
|
|
|
|
resp.forms['listing-settings']['start'] = '01/01/2016'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 0
|
|
|
|
resp.forms['listing-settings']['start'] = '01/01/16'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 0
|
|
|
|
resp.forms['listing-settings']['start'] = '01/01/10'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 37
|
|
|
|
resp.forms['listing-settings']['end'] = '01/01/10'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 0
|
|
|
|
# check invalid values are simply ignored
|
|
resp.forms['listing-settings']['end'] = 'whatever'
|
|
resp = resp.forms['listing-settings'].submit()
|
|
assert resp.text[resp.text.index('<tbody'):].count('<tr') == 37
|
|
|
|
def test_global_listing_geojson(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.geolocations = {'base': 'Geolocafoobar'}
|
|
formdef.store()
|
|
for formdata in formdef.data_class().select():
|
|
formdata.geolocations = {'base': {'lat': 48.83, 'lon': 2.32}}
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/geojson')
|
|
assert len(resp.json['features']) == 17
|
|
assert resp.json['features'][0]['geometry']['coordinates'] == [2.32, 48.83]
|
|
for feature in resp.json['features']:
|
|
assert feature['properties']['status_colour'] == '#66FF00'
|
|
assert feature['properties']['view_label'] == 'View'
|
|
assert feature['properties']['status_name'] == 'New'
|
|
assert feature['properties']['display_fields']
|
|
assert feature['properties']['display_fields'][0]['label'] == 'Name'
|
|
assert feature['properties']['display_fields'][0]['value'].startswith('form title #')
|
|
|
|
resp = app.get('/backoffice/management/geojson?q=aa')
|
|
assert len(resp.json['features']) == 5
|
|
resp = app.get('/backoffice/management/geojson?q=bb')
|
|
assert len(resp.json['features']) == 4
|
|
resp = app.get('/backoffice/management/geojson?q=cc')
|
|
assert len(resp.json['features']) == 8
|
|
|
|
def test_global_map(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.geolocations = {'base': 'Geolocafoobar'}
|
|
formdef.store()
|
|
for formdata in formdef.data_class().select():
|
|
formdata.geolocations = {'base': {'lat': 48.83, 'lon': 2.32}}
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/listing')
|
|
assert 'Map View' in resp.text
|
|
resp = app.get('/backoffice/management/forms')
|
|
assert 'Map View' in resp.text
|
|
resp = resp.click('Map View')
|
|
assert re.findall(r'data-geojson-url="(.*?)"', resp.text) == ['http://example.net/backoffice/management/geojson?']
|
|
|
|
resp = app.get('/backoffice/management/map?q=test')
|
|
assert re.findall(r'data-geojson-url="(.*?)"', resp.text) == ['http://example.net/backoffice/management/geojson?q=test']
|
|
|
|
def test_formdata_lookup(pub):
|
|
create_user(pub)
|
|
create_environment(pub, set_receiver=False)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
formdata, formdata2 = formdef.data_class().select(order_by='id')[:2]
|
|
code = pub.tracking_code_class()
|
|
code.formdata = formdata
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/').follow()
|
|
assert 'id="lookup-box"' in resp.text
|
|
resp.forms[0]['query'] = formdata.tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.text
|
|
assert 'This form has been accessed via its tracking code' in resp.text
|
|
|
|
# check there's no access to other formdata
|
|
app.get('http://example.net/backoffice/management/form-title/%s/' % formdata2.id, status=403)
|
|
|
|
resp = app.get('/backoffice/management/').follow()
|
|
resp.forms[0]['query'] = 'AAAAAAAA'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/backoffice/management/'
|
|
resp = resp.follow().follow()
|
|
assert 'No such tracking code or identifier.' in resp.text
|
|
|
|
# check looking up a formdata id
|
|
resp.form['query'] = formdata.get_display_id()
|
|
resp = resp.form.submit()
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id
|
|
|
|
if pub.is_using_postgresql():
|
|
# check looking up on a custom display_id
|
|
formdata.id_display = '999999'
|
|
formdata.store()
|
|
assert formdata.get_display_id() == '999999'
|
|
resp = app.get('/backoffice/management/').follow()
|
|
resp.form['query'] = formdata.get_display_id()
|
|
resp = resp.form.submit()
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id
|
|
|
|
# try it from the global listing
|
|
resp = app.get('/backoffice/management/listing')
|
|
assert 'id="lookup-box"' in resp.text
|
|
resp.forms[0]['query'] = formdata.tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.text
|
|
|
|
resp = app.get('/backoffice/management/listing')
|
|
resp.forms[0]['query'] = 'AAAAAAAA'
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/backoffice/management/listing'
|
|
resp = resp.follow()
|
|
assert 'No such tracking code or identifier.' in resp.text
|
|
|
|
def test_backoffice_sidebar_user_context(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert re.findall('<tbody.*\/tbody>', resp.text, re.DOTALL)[0].count('<tr') == 17
|
|
|
|
# click on a formdata
|
|
resp = resp.click(href='%s/' % number31.id)
|
|
assert (' with the number %s.' % number31.get_display_id()) in resp.text
|
|
|
|
# check there's nothing in the sidebar
|
|
assert not '/user-pending-forms' in resp.text
|
|
|
|
number31.formdef.digest_template = 'digest of number {{form_number}}'
|
|
number31.user_id = user.id
|
|
number31.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert '/user-pending-forms' in resp.text
|
|
user_pending_form_url = re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0]
|
|
partial_resp = app.get(user_pending_form_url)
|
|
assert not number31.get_url(backoffice=True) in partial_resp.text
|
|
assert number31.digest in partial_resp.text
|
|
assert '<span class="formname">%s</span>' % number31.formdef.name in partial_resp.text
|
|
|
|
# another item with status = new
|
|
number34 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 33'][0]
|
|
number34.user_id = user.id
|
|
number34.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert '/user-pending-forms' in resp.text
|
|
user_pending_form_url = re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0]
|
|
partial_resp = app.get(user_pending_form_url)
|
|
assert not number31.get_url(backoffice=True) in partial_resp.text
|
|
assert number34.get_url(backoffice=True) in partial_resp.text
|
|
|
|
cat1 = Category(name='cat1')
|
|
cat1.store()
|
|
|
|
formdef = FormDef.get_by_urlname('other-form')
|
|
formdef.category_id = cat1.id
|
|
formdef.store()
|
|
other_formdata = formdef.data_class().select()[0]
|
|
other_formdata.user_id = user.id
|
|
other_formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert '/user-pending-forms' in resp.text
|
|
user_pending_form_url = re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0]
|
|
partial_resp = app.get(user_pending_form_url)
|
|
assert number34.get_url(backoffice=True) in partial_resp.text
|
|
assert other_formdata.get_url(backoffice=True) in partial_resp.text
|
|
# categories are displayed, and current formdata category is on top
|
|
assert '>cat1<' in partial_resp.text
|
|
assert '>Misc<' in partial_resp.text
|
|
assert partial_resp.text.index('>Misc<') < partial_resp.text.index('>cat1<')
|
|
|
|
def test_count_open(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
create_user(pub)
|
|
|
|
FormDef.wipe()
|
|
resp = login(get_app(pub)).get('/backoffice/management/count')
|
|
assert resp.json['count'] == 0
|
|
|
|
create_environment(pub)
|
|
resp = login(get_app(pub)).get('/backoffice/management/count')
|
|
assert resp.json['count'] == 37
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_roles = {'_receiver': 2} # role the user doesn't have
|
|
formdef.store()
|
|
formdef.data_class().rebuild_security()
|
|
resp = login(get_app(pub)).get('/backoffice/management/count')
|
|
assert resp.json['count'] == 20
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_roles = {'_receiver': 2, '_foobar': 1}
|
|
formdef.store()
|
|
formdef.data_class().rebuild_security()
|
|
resp = login(get_app(pub)).get('/backoffice/management/count')
|
|
assert resp.json['count'] == 20
|
|
resp = login(get_app(pub)).get('/backoffice/management/count?waiting=yes')
|
|
assert resp.json['count'] == 20
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.roles['_foobar'] = 'Foobar'
|
|
workflow.id = '2'
|
|
workflow.store()
|
|
formdef.workflow_id = workflow.id
|
|
formdef.workflow_roles = {'_receiver': 2, '_foobar': '1'}
|
|
formdef.store()
|
|
formdef.data_class().rebuild_security()
|
|
resp = login(get_app(pub)).get('/backoffice/management/count?waiting=no')
|
|
assert resp.json['count'] == 37
|
|
resp = login(get_app(pub)).get('/backoffice/management/count?waiting=yes')
|
|
assert resp.json['count'] == 20
|
|
resp = login(get_app(pub)).get('/backoffice/management/count')
|
|
assert resp.json['count'] == 20
|
|
|
|
# check the callback parameter is ignored, that we still get the default
|
|
# criterias when it's set.
|
|
resp = login(get_app(pub)).get('/backoffice/management/count?callback=toto')
|
|
assert "20" in resp.text
|
|
|
|
def test_count_backoffice_drafts(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.store()
|
|
|
|
resp = login(get_app(pub)).get('/backoffice/submission/count')
|
|
assert resp.json['count'] == 0
|
|
|
|
formdata1, formdata2, formdata3 = formdef.data_class().select()[:3]
|
|
for formdata in (formdata1, formdata2, formdata3):
|
|
formdata.status = 'draft'
|
|
formdata.store()
|
|
|
|
resp = login(get_app(pub)).get('/backoffice/submission/count')
|
|
assert resp.json['count'] == 0
|
|
|
|
for formdata in (formdata1, formdata2, formdata3):
|
|
formdata.backoffice_submission = True
|
|
formdata.store()
|
|
|
|
resp = login(get_app(pub)).get('/backoffice/submission/count')
|
|
assert resp.json['count'] == 3
|
|
|
|
formdata1.data = {}
|
|
formdata1.store()
|
|
|
|
resp = login(get_app(pub)).get('/backoffice/submission/count?mode=empty')
|
|
assert resp.json['count'] == 1
|
|
resp = login(get_app(pub)).get('/backoffice/submission/count?mode=existing')
|
|
assert resp.json['count'] == 2
|
|
|
|
def test_menu_json(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
resp = login(get_app(pub)).get('/backoffice/menu.json')
|
|
menu_json_str = resp.text
|
|
assert len(resp.json) == 1
|
|
assert resp.json[0]['slug'] == 'management'
|
|
assert resp.headers['content-type'] == 'application/json'
|
|
|
|
resp = login(get_app(pub)).get('/backoffice/menu.json?jsonpCallback=foo')
|
|
assert resp.text == 'foo(%s);' % menu_json_str
|
|
assert resp.headers['content-type'] == 'application/javascript'
|
|
|
|
def test_per_user_view(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/').follow()
|
|
assert 'Per User View' not in resp.text
|
|
|
|
if not pub.site_options.has_section('options'):
|
|
pub.site_options.add_section('options')
|
|
pub.site_options.set('options', 'per-user-view', 'true')
|
|
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
|
|
pub.site_options.write(fd)
|
|
fd.close()
|
|
|
|
resp = app.get('/backoffice/management/').follow()
|
|
assert 'Per User View' in resp.text
|
|
resp = resp.click(' User View')
|
|
assert 'Use the search field on the right' in resp.text
|
|
|
|
resp.form['q'] = 'admin'
|
|
resp = resp.form.submit()
|
|
|
|
assert resp.text.count('<tr') == 2 # header + user
|
|
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
to_match = []
|
|
for formdata in form_class.select():
|
|
if formdata.data['1'] in ('FOO BAR 30', 'FOO BAR 33'):
|
|
formdata.user_id = user.id
|
|
formdata.store()
|
|
to_match.append('/management/form-title/%s/' % formdata.id)
|
|
|
|
resp = app.get('/backoffice/management/users/%s/' % user.id)
|
|
for item in to_match:
|
|
assert item in resp.text
|
|
count_li = resp.text.count('<li')
|
|
|
|
# check list items are displayed, without links, if we cannot view them.
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_roles['_receiver'] = 'XXX'
|
|
formdef.store()
|
|
formdef.data_class().rebuild_security()
|
|
|
|
resp = app.get('/backoffice/management/users/%s/' % user.id)
|
|
for item in to_match:
|
|
assert not item in resp.text # not linked
|
|
assert resp.text.count('<li') == count_li
|
|
|
|
# mark formdef so it's not listed in per-user view
|
|
formdef.skip_from_360_view = True
|
|
formdef.store()
|
|
|
|
# check formdatas are no longer part of the page
|
|
resp = app.get('/backoffice/management/users/%s/' % user.id)
|
|
assert resp.text.count('<li') == (count_li - 2)
|
|
|
|
def test_per_user_view_tracking_code(pub, emails, sms_mocking):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
app = login(get_app(pub))
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
form_class = formdef.data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
number31.user_id = user.id
|
|
number31.store()
|
|
|
|
resp = app.get('/backoffice/management/users/%s/' % user.id)
|
|
assert not 'Send tracking code' in resp.text
|
|
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
user_view_resp = app.get('/backoffice/management/users/%s/' % user.id)
|
|
assert 'Send tracking code' in user_view_resp.text
|
|
|
|
pub.cfg['sms'] = {'mode': 'none'}
|
|
pub.write_cfg()
|
|
resp = user_view_resp.click('Send tracking code')
|
|
assert not 'sms' in resp.form.fields
|
|
assert resp.form['email'].value == user.email
|
|
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
assert emails.count() == 1
|
|
assert emails.get('Tracking Code reminder')['email_rcpt'] == [user.email]
|
|
assert form_class.get(number31.id).tracking_code in emails.get('Tracking Code reminder')['payload']
|
|
|
|
pub.cfg['sms'] = {'mode': 'xx'}
|
|
pub.write_cfg()
|
|
resp = user_view_resp.click('Send tracking code', index=0)
|
|
resp.form['method'].value = 'SMS'
|
|
resp.form['sms'].value = '0123456789'
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
assert sms_mocking.sms[-1]['destinations'] == ['0123456789']
|
|
assert form_class.get(number31.id).tracking_code in sms_mocking.sms[-1]['text']
|
|
|
|
def test_backoffice_resume_folded(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
|
app = login(get_app(pub))
|
|
|
|
# first access: summary is not folded
|
|
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
|
|
assert '<div class="section foldable" id="summary">' in resp.text
|
|
# do something: summary is folded
|
|
resp = resp.form.submit('button_commentable')
|
|
resp = resp.follow()
|
|
assert '<div class="section foldable folded" id="summary">' in resp.text
|
|
|
|
def test_backoffice_backoffice_submission_in_listings(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
first_link = re.findall('data-link="(\d+)/?"', resp.text)[0]
|
|
assert not 'backoffice-submission' in resp.text
|
|
|
|
formdata = FormDef.get_by_urlname('form-title').data_class().get(first_link)
|
|
formdata.backoffice_submission = True
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert 'backoffice-submission' in resp.text
|
|
|
|
def test_backoffice_backoffice_submission_in_global_listing(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/listing?limit=100')
|
|
assert not 'backoffice-submission' in resp.text
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdata = formdef.data_class().get(
|
|
re.findall(r'data-link="(.*?)"', app.get('/backoffice/management/listing').text)[0].split('/')[-2])
|
|
formdata.backoffice_submission = True
|
|
formdata.store()
|
|
|
|
resp = app.get('/backoffice/management/listing?limit=100')
|
|
assert 'backoffice-submission' in resp.text
|
|
|
|
def test_backoffice_advisory_lock(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub)
|
|
|
|
second_user = pub.user_class(name='foobar')
|
|
second_user.roles = Role.keys()
|
|
second_user.store()
|
|
account = PasswordAccount(id='foobar')
|
|
account.set_password('foobar')
|
|
account.user_id = second_user.id
|
|
account.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
first_link = re.findall('data-link="(\d+/)?"', resp.text)[0]
|
|
assert not 'advisory-lock' in resp.text
|
|
|
|
app2 = login(get_app(pub), username='foobar', password='foobar')
|
|
resp = app2.get('/backoffice/management/form-title/')
|
|
assert not 'advisory-lock' in resp.text
|
|
|
|
resp = app.get('/backoffice/management/form-title/' + first_link)
|
|
resp = app2.get('/backoffice/management/form-title/')
|
|
assert 'advisory-lock' in resp.text
|
|
resp = app.get('/backoffice/management/form-title/')
|
|
assert not 'advisory-lock' in resp.text
|
|
|
|
if pub.is_using_postgresql():
|
|
# check global view
|
|
resp = app2.get('/backoffice/management/listing?limit=100')
|
|
assert 'advisory-lock' in resp.text
|
|
resp = app.get('/backoffice/management/listing?limit=100')
|
|
assert not 'advisory-lock' in resp.text
|
|
|
|
resp = app.get('/backoffice/management/form-title/' + first_link)
|
|
assert not 'Be warned forms of this user are also being looked' in resp.text
|
|
assert 'button_commentable' in resp.text
|
|
assert len(resp.forms)
|
|
resp = app2.get('/backoffice/management/form-title/' + first_link)
|
|
assert 'Be warned forms of this user are also being looked' in resp.text
|
|
assert not 'button_commentable' in resp.text
|
|
assert len(resp.forms) == 0
|
|
# revisit with first user, no change
|
|
resp = app.get('/backoffice/management/form-title/' + first_link)
|
|
assert not 'Be warned forms of this user are also being looked' in resp.text
|
|
assert 'button_commentable' in resp.text
|
|
# back to second
|
|
resp = app2.get('/backoffice/management/form-title/' + first_link)
|
|
assert 'Be warned forms of this user are also being looked' in resp.text
|
|
assert not 'button_commentable' in resp.text
|
|
resp = resp.click('(unlock actions)')
|
|
resp = resp.follow()
|
|
assert 'Be warned forms of this user are also being looked' in resp.text
|
|
assert 'button_commentable' in resp.text
|
|
assert not '(unlock actions)' in resp.text
|
|
assert len(resp.forms)
|
|
|
|
# submit action form
|
|
resp.form['comment'] = 'HELLO'
|
|
resp = resp.form.submit('button_commentable')
|
|
# locks are reset after an action
|
|
assert not 'advisory-lock' in app2.get('/backoffice/management/form-title/')
|
|
assert not 'advisory-lock' in app.get('/backoffice/management/form-title/')
|
|
# but as the current user is redirected to the form, a lock will be
|
|
# acquired (unless the user didn't have actions anymore, but it's not the
|
|
# case here)
|
|
resp = resp.follow()
|
|
assert not 'advisory-lock' in app2.get('/backoffice/management/form-title/')
|
|
assert 'advisory-lock' in app.get('/backoffice/management/form-title/')
|
|
|
|
def test_backoffice_advisory_lock_related_formdatas(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
pub.session_manager.session_class.wipe()
|
|
user = create_superuser(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdatas = formdef.data_class().select(lambda x: x.status == 'wf-new')
|
|
|
|
second_user = pub.user_class(name='foobar')
|
|
second_user.roles = Role.keys()
|
|
second_user.store()
|
|
account = PasswordAccount(id='foobar')
|
|
account.set_password('foobar')
|
|
account.user_id = second_user.id
|
|
account.store()
|
|
|
|
third_user = pub.user_class(name='user')
|
|
third_user.store()
|
|
|
|
for formdata in formdatas[:2]:
|
|
formdata.user_id = third_user.id
|
|
formdata.store()
|
|
|
|
second_formdef = FormDef.get_by_urlname('other-form')
|
|
second_formdef.workflow_roles = {}
|
|
second_formdef.store()
|
|
other_formdatas = second_formdef.data_class().select(lambda x: x.status == 'wf-new')
|
|
other_formdatas[0].user_id = third_user.id
|
|
other_formdatas[0].store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdatas[0].id)
|
|
assert not 'Be warned forms of this user are also being looked' in resp.text
|
|
app.get(re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0])
|
|
|
|
app2 = login(get_app(pub), username='foobar', password='foobar')
|
|
resp2 = app2.get('/backoffice/management/form-title/%s/' % formdatas[0].id)
|
|
assert 'Be warned forms of this user are also being looked' in resp2.text
|
|
app2.get(re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0])
|
|
|
|
# another by the same user
|
|
resp2 = app2.get('/backoffice/management/form-title/%s/' % formdatas[1].id)
|
|
assert 'Be warned forms of this user are also being looked' in resp2.text
|
|
app2.get(re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0])
|
|
|
|
# another by another user
|
|
resp2 = app2.get('/backoffice/management/form-title/%s/' % formdatas[3].id)
|
|
assert not 'Be warned forms of this user are also being looked' in resp2.text
|
|
app2.get(re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0])
|
|
|
|
# check another formdef is only marked as visited if the user has potential
|
|
# actions on it.
|
|
session = pub.session_manager.session_class.select(lambda x: x.user == user.id)[0]
|
|
second_formdef.workflow_roles = {'_receiver': 1}
|
|
second_formdef.store()
|
|
other_formdata = second_formdef.data_class().get(other_formdatas[0].id)
|
|
other_formdata.store() # update concerned_roles
|
|
|
|
assert not 'formdata-other-form-%d' % other_formdata.id in session.visiting_objects.keys()
|
|
session.visiting_objects = {}
|
|
session.store()
|
|
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdatas[0].id)
|
|
app.get(re.findall('data-async-url="(.*/user-pending-forms)"', resp.text)[0])
|
|
session = pub.session_manager.session_class.select(lambda x: x.user == user.id)[0]
|
|
assert 'formdata-other-form-%d' % other_formdata.id in session.visiting_objects.keys()
|
|
|
|
def test_backoffice_resubmit(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='resubmit')
|
|
st1 = wf.add_status('Status1')
|
|
st2 = wf.add_status('Status2')
|
|
|
|
resubmit = ResubmitWorkflowStatusItem()
|
|
resubmit.id = '_resubmit'
|
|
resubmit.by = [user.roles[0]]
|
|
st1.items.append(resubmit)
|
|
resubmit.parent = st1
|
|
|
|
jump = JumpOnSubmitWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.status = st2.id
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
|
|
register_comment = RegisterCommenterWorkflowStatusItem()
|
|
register_comment.id = '_register'
|
|
register_comment.comment = '<p><a href="[resubmit_formdata_backoffice_url]">resubmitted</a></p>'
|
|
st2.items.append(register_comment)
|
|
register_comment.parent = st2
|
|
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.fields[0].varname = 'foo'
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
|
|
formdef2 = FormDef()
|
|
formdef2.name = 'form title bis'
|
|
formdef2.backoffice_submission_roles = user.roles[:]
|
|
formdef2.fields = [
|
|
fields.StringField(id='2', label='1st field', type='string', varname='foo')
|
|
]
|
|
formdef2.store()
|
|
formdef2.data_class().wipe()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.just_created()
|
|
formdata.data= {'1': 'XXX'}
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
resp.form['resubmit'].value = formdef2.id
|
|
resp = resp.form.submit('button_resubmit')
|
|
resp = resp.follow()
|
|
assert 'resubmitted' in resp.text
|
|
assert formdef2.data_class().select()[0].status == 'draft'
|
|
assert formdef2.data_class().select()[0].data == {'2': 'XXX'}
|
|
resp = resp.click('resubmitted')
|
|
resp = resp.follow()
|
|
resp = resp.follow()
|
|
assert resp.form['f2'].value == 'XXX'
|
|
assert 'Original form' in resp.text
|
|
assert formdata.get_url(backoffice=True) in resp.text
|
|
|
|
def test_backoffice_workflow_display_form(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow.get_default_workflow()
|
|
wf.id = '2'
|
|
wf.store()
|
|
wf = Workflow.get(wf.id)
|
|
status = wf.get_status('new')
|
|
status.items = []
|
|
display_form = FormWorkflowStatusItem()
|
|
display_form.id = '_display_form'
|
|
display_form.by = [user.roles[0]]
|
|
display_form.varname = 'blah'
|
|
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
|
display_form.formdef.fields.append(
|
|
fields.StringField(
|
|
id='1', label='Test', varname='str', type='string', required=True))
|
|
display_form.formdef.fields.append(
|
|
# mimick special case: https://dev.entrouvert.org/issues/14691
|
|
# item field displayed as radio buttons, with prefill of a value
|
|
# that doesn't exist.
|
|
fields.ItemField(
|
|
id='2', label='Test2', type='item',
|
|
prefill={'type': 'string', 'value': ''},
|
|
display_mode='radio',
|
|
varname='radio',
|
|
items=['a', 'b', 'c'], required=True))
|
|
status.items.append(display_form)
|
|
display_form.parent = status
|
|
|
|
jump = JumpOnSubmitWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.status = 'accepted'
|
|
status.items.append(jump)
|
|
jump.parent = status
|
|
|
|
wf.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
|
|
for formdata in formdef.data_class().select():
|
|
if formdata.status == 'wf-new':
|
|
break
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'f1' in resp.form.fields
|
|
resp.form['f1'] = 'blah'
|
|
# don't fill required radio button
|
|
resp = resp.form.submit('submit')
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-new'
|
|
assert 'There were errors processing your form.' in resp.text
|
|
resp.form['f2'] = 'c'
|
|
resp = resp.form.submit('submit')
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-accepted'
|
|
assert formdef.data_class().get(formdata.id).workflow_data == {
|
|
'blah_var_str': 'blah', 'blah_var_radio': 'c', 'blah_var_radio_raw': 'c'}
|
|
|
|
def test_backoffice_workflow_form_with_conditions(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow.get_default_workflow()
|
|
wf.id = '2'
|
|
wf.store()
|
|
wf = Workflow.get(wf.id)
|
|
status = wf.get_status('new')
|
|
status.items = []
|
|
display_form = FormWorkflowStatusItem()
|
|
display_form.id = '_display_form'
|
|
display_form.by = [user.roles[0]]
|
|
display_form.varname = 'blah'
|
|
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
|
display_form.formdef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
|
|
fields.StringField(id='2', label='Test2', varname='str2', type='string', required=True),
|
|
]
|
|
status.items.append(display_form)
|
|
display_form.parent = status
|
|
|
|
wf.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.fields[0].varname = 'plop'
|
|
formdef.store()
|
|
|
|
for formdata in formdef.data_class().select():
|
|
if formdata.status == 'wf-new':
|
|
break
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
|
|
# check with static condition
|
|
display_form.formdef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
|
|
fields.StringField(id='2', label='Test2', varname='str2',
|
|
type='string', required=True,
|
|
condition={'type': 'django', 'value': '0'}),
|
|
]
|
|
wf.store()
|
|
|
|
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' not in resp.form.fields
|
|
|
|
# check condition based on formdata
|
|
display_form.formdef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
|
|
fields.StringField(id='2', label='Test2', varname='str2',
|
|
type='string', required=True,
|
|
condition={'type': 'django', 'value': 'form_var_plop'}),
|
|
]
|
|
wf.store()
|
|
|
|
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
|
|
display_form.formdef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
|
|
fields.StringField(id='2', label='Test2', varname='str2',
|
|
type='string', required=True,
|
|
condition={'type': 'django', 'value': 'form_var_plop != "xxx"'}),
|
|
]
|
|
wf.store()
|
|
|
|
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
|
|
# check with live conditions
|
|
display_form.formdef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
|
|
fields.StringField(id='2', label='Test2', varname='str2',
|
|
type='string', required=True,
|
|
condition={'type': 'django', 'value': 'blah_var_str == "xxx"'}),
|
|
]
|
|
wf.store()
|
|
|
|
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
|
|
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'
|
|
live_url = resp.html.find('form').attrs['data-live-url']
|
|
assert '/backoffice/' in live_url
|
|
resp.form['f1'] = ''
|
|
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'] = 'xxx'
|
|
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']
|
|
|
|
# check submit doesn't work
|
|
resp = resp.form.submit('submit')
|
|
assert 'There were errors processing your form.' in resp.text
|
|
|
|
resp.form['f1'] = 'xxx2'
|
|
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']
|
|
|
|
# check submit does work when second field is hidden
|
|
resp = resp.form.submit('submit').follow()
|
|
|
|
assert formdef.data_class().get(formdata.id).workflow_data == {'blah_var_str': 'xxx2', 'blah_var_str2': None}
|
|
|
|
def test_backoffice_workflow_form_with_live_data_source(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow.get_default_workflow()
|
|
wf.id = '2'
|
|
wf.store()
|
|
wf = Workflow.get(wf.id)
|
|
status = wf.get_status('new')
|
|
status.items = []
|
|
display_form = FormWorkflowStatusItem()
|
|
display_form.id = '_display_form'
|
|
display_form.by = [user.roles[0]]
|
|
display_form.varname = 'blah'
|
|
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
|
display_form.formdef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
|
|
fields.ItemField(id='2', label='Test2', varname='str2', type='item', required=True,
|
|
data_source={'type': 'json', 'value': 'https://www.example.invalid/{{ blah_var_str }}'}),
|
|
]
|
|
status.items.append(display_form)
|
|
display_form.parent = status
|
|
|
|
wf.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.fields[0].varname = 'plop'
|
|
formdef.store()
|
|
|
|
for formdata in formdef.data_class().select():
|
|
if formdata.status == 'wf-new':
|
|
break
|
|
|
|
app = get_app(pub)
|
|
|
|
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
|
|
data1 = {'data': [{'id': 'A', 'text': 'hello'}, {'id': 'B', 'text': 'world'}]}
|
|
data2 = {'data': [{'id': 'C', 'text': 'hello'}, {'id': 'D', 'text': 'world'}]}
|
|
def side_effect(url, *args):
|
|
if 'toto' not in url:
|
|
return StringIO(json.dumps(data1))
|
|
else:
|
|
return StringIO(json.dumps(data2))
|
|
urlopen.side_effect = side_effect
|
|
|
|
resp = login(app).get(formdata.get_url(backoffice=True))
|
|
assert 'f1' in resp.form.fields
|
|
assert 'f2' in resp.form.fields
|
|
assert resp.form.fields['f2'][0].options == [(u'A', False, u'hello'), (u'B', False, u'world')]
|
|
|
|
live_url = resp.html.find('form').attrs['data-live-url']
|
|
resp.form['f1'] = 'toto'
|
|
live_resp = app.post(live_url + '?modified_field_id=1', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2']['items'] == [{u'text': u'hello', u'id': u'C'}, {u'text': u'world', u'id': u'D'}]
|
|
|
|
def test_backoffice_criticality_in_formdef_listing(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow.get_default_workflow()
|
|
wf.id = '2'
|
|
wf.criticality_levels = [
|
|
WorkflowCriticalityLevel(name='green'),
|
|
WorkflowCriticalityLevel(name='yellow'),
|
|
WorkflowCriticalityLevel(name='red'),
|
|
]
|
|
wf.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
|
|
formdata1, formdata2, formdata3, formdata4 = [
|
|
x for x in formdef.data_class().select() if x.status == 'wf-new'][:4]
|
|
|
|
formdata1.set_criticality_level(1)
|
|
formdata1.store()
|
|
formdata1_str = '>%s<' % formdata1.get_display_id()
|
|
formdata2.set_criticality_level(2)
|
|
formdata2.store()
|
|
formdata2_str = '>%s<' % formdata2.get_display_id()
|
|
formdata3.set_criticality_level(2)
|
|
formdata3.store()
|
|
formdata3_str = '>%s<' % formdata3.get_display_id()
|
|
formdata4_str = '>%s<' % formdata4.get_display_id()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/?order_by=-criticality_level&limit=100')
|
|
assert resp.text.index(formdata1_str) > resp.text.index(formdata2_str)
|
|
assert resp.text.index(formdata1_str) > resp.text.index(formdata3_str)
|
|
assert resp.text.index(formdata1_str) < resp.text.index(formdata4_str)
|
|
|
|
resp = app.get('/backoffice/management/form-title/?order_by=criticality_level&limit=100')
|
|
assert resp.text.index(formdata1_str) < resp.text.index(formdata2_str)
|
|
assert resp.text.index(formdata1_str) < resp.text.index(formdata3_str)
|
|
assert resp.text.index(formdata1_str) > resp.text.index(formdata4_str)
|
|
|
|
def test_backoffice_criticality_in_global_listing(pub):
|
|
if not pub.is_using_postgresql():
|
|
pytest.skip('this requires SQL')
|
|
return
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow.get_default_workflow()
|
|
wf.id = '2'
|
|
wf.criticality_levels = [
|
|
WorkflowCriticalityLevel(name='green'),
|
|
WorkflowCriticalityLevel(name='yellow'),
|
|
WorkflowCriticalityLevel(name='red'),
|
|
]
|
|
wf.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
|
|
formdata1, formdata2, formdata3, formdata4 = [
|
|
x for x in formdef.data_class().select() if x.status == 'wf-new'][:4]
|
|
|
|
formdata1.set_criticality_level(1)
|
|
formdata1.store()
|
|
formdata1_str = '>%s<' % formdata1.get_display_id()
|
|
formdata2.set_criticality_level(2)
|
|
formdata2.store()
|
|
formdata2_str = '>%s<' % formdata2.get_display_id()
|
|
formdata3.set_criticality_level(2)
|
|
formdata3.store()
|
|
formdata3_str = '>%s<' % formdata3.get_display_id()
|
|
formdata4_str = '>%s<' % formdata4.get_display_id()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/listing?order_by=-criticality_level&limit=100')
|
|
assert resp.text.index(formdata1_str) > resp.text.index(formdata2_str)
|
|
assert resp.text.index(formdata1_str) > resp.text.index(formdata3_str)
|
|
assert resp.text.index(formdata1_str) < resp.text.index(formdata4_str)
|
|
|
|
resp = app.get('/backoffice/management/listing?order_by=criticality_level&limit=100')
|
|
assert resp.text.index(formdata1_str) < resp.text.index(formdata2_str)
|
|
assert resp.text.index(formdata1_str) < resp.text.index(formdata3_str)
|
|
assert resp.text.index(formdata1_str) > resp.text.index(formdata4_str)
|
|
|
|
def test_backoffice_criticality_formdata_view(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow.get_default_workflow()
|
|
wf.id = '2'
|
|
wf.criticality_levels = [
|
|
WorkflowCriticalityLevel(name='green'),
|
|
WorkflowCriticalityLevel(name='yellow'),
|
|
WorkflowCriticalityLevel(name='red'),
|
|
]
|
|
wf.store()
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdata = [x for x in formdef.data_class().select() if x.status == 'wf-new'][0]
|
|
|
|
formdata.set_criticality_level(1)
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'Criticality Level: yellow' in resp.text
|
|
|
|
formdata.set_criticality_level(2)
|
|
formdata.store()
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'Criticality Level: red' in resp.text
|
|
|
|
|
|
class IHateUnicode(object):
|
|
def __unicode__(self):
|
|
raise Exception('HATE!!')
|
|
|
|
def __repr__(self):
|
|
return 'ok'
|
|
|
|
@pytest.fixture
|
|
def local_user():
|
|
get_publisher().user_class.wipe()
|
|
user = get_publisher().user_class()
|
|
user.name = 'Jean Darmette'
|
|
user.email = 'jean.darmette@triffouilis.fr'
|
|
user.name_identifiers = ['0123456789']
|
|
user.store()
|
|
return user
|
|
|
|
def test_inspect_page(pub, local_user):
|
|
create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdata = [x for x in formdef.data_class().select() if x.status == 'wf-new'][0]
|
|
# temper with field 3 structured values
|
|
|
|
formdata.data['3_structured'] = {
|
|
'unicode': u'uné',
|
|
'str_but_non_utf8': b'\xed\xa0\x00', # not actually supposed to happen
|
|
'non_unicode_convertible': IHateUnicode(),
|
|
'very_long_string': '0' * 100000,
|
|
}
|
|
formdata.user_id = local_user.id
|
|
formdata.store()
|
|
|
|
from wcs.admin.settings import UserFieldsFormDef
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields.append(fields.StringField(id='_first_name', label='name', type='string'))
|
|
user_formdef.fields.append(fields.StringField(id='3', label='test', type='string'))
|
|
user_formdef.store()
|
|
local_user.form_data = {'_first_name': 'toto', '3': 'nono'}
|
|
local_user.set_attributes_from_formdata(local_user.form_data)
|
|
local_user.store()
|
|
|
|
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True), status=200)
|
|
assert 'Data Inspector' not in resp.text
|
|
resp = login(get_app(pub)).get('%sinspect' % formdata.get_url(backoffice=True), status=403)
|
|
|
|
create_user(pub, is_admin=True)
|
|
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True), status=200)
|
|
resp = resp.click('Data Inspector')
|
|
|
|
assert '0' * 1000 in resp.text
|
|
assert len(resp.text) < 100000
|
|
pq = resp.pyquery.remove_namespaces()
|
|
assert (pq('[title="form_var_foo_unicode"]')
|
|
.parents('li').children('div.value span')
|
|
.text() == u'uné')
|
|
assert (pq('[title="form_var_foo_non_unicode_convertible"]')
|
|
.parents('li').children('div.value span')
|
|
.text().startswith('ok '))
|
|
if six.PY2:
|
|
assert (pq('[title="form_var_foo_str_but_non_utf8"]')
|
|
.parents('li').children('div.value span')
|
|
.text() == '\'\\xed\\xa0\\x00\'')
|
|
else:
|
|
assert (pq('[title="form_var_foo_str_but_non_utf8"]')
|
|
.parents('li').children('div.value span')
|
|
.text() == "b'\\xed\\xa0\\x00' (<class 'bytes'>)")
|
|
|
|
# don't show «unusable» variables
|
|
assert 'form_f1' not in resp.text
|
|
assert 'form_field_' not in resp.text
|
|
assert 'form_user_field_' not in resp.text
|
|
assert 'form_user_f3' not in resp.text
|
|
assert 'form_user_f_' not in resp.text
|
|
|
|
# check functions
|
|
assert re.findall('Recipient.*foobar', resp.text)
|
|
|
|
role = Role(name='plop')
|
|
role.store()
|
|
formdata.workflow_roles = {'_receiver': role.id}
|
|
formdata.store()
|
|
resp = login(get_app(pub)).get('%sinspect' % formdata.get_url(backoffice=True), status=200)
|
|
assert re.findall('Recipient.*plop', resp.text)
|
|
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = None
|
|
workflow.roles.update({'_plop': 'New Function'})
|
|
workflow.store()
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
resp = login(get_app(pub)).get('%sinspect' % formdata.get_url(backoffice=True), status=200)
|
|
assert re.findall('New Function.*unset', resp.text)
|
|
|
|
formdata.workflow_roles = {'_receiver': role.id, '_plop': '123'}
|
|
formdata.store()
|
|
resp = login(get_app(pub)).get('%sinspect' % formdata.get_url(backoffice=True), status=200)
|
|
assert re.findall('New Function.*(deleted)', resp.text)
|
|
|
|
# test tools
|
|
app = login(get_app(pub))
|
|
resp = app.get('%sinspect' % formdata.get_url(backoffice=True), status=200)
|
|
assert "Test tool" in resp.text
|
|
|
|
resp.form['test_mode'] = 'python-condition'
|
|
|
|
resp.form['python-condition'] = 'len(form_name) == 10' # "form title"
|
|
resp = resp.form.submit()
|
|
assert 'Condition result' in resp.text
|
|
assert 'result-true' in resp.text
|
|
assert '<code>True</code>' in resp.text
|
|
resp.form['python-condition'] = 'len(form_name) == 5'
|
|
resp = resp.form.submit()
|
|
assert 'Condition result' in resp.text
|
|
assert 'result-false' in resp.text
|
|
assert '<code>False</code>' in resp.text
|
|
resp.form['python-condition'] = 'form_do_not_exist == 3'
|
|
resp = resp.form.submit()
|
|
assert 'Condition result' not in resp.text
|
|
assert 'Failed to evaluate condition' in resp.text
|
|
assert 'NameError' in resp.text
|
|
|
|
resp.form['test_mode'] = 'django-condition'
|
|
resp.form['django-condition'] = 'form_name|length == 10'
|
|
resp = resp.form.submit()
|
|
assert 'Condition result' in resp.text
|
|
assert 'result-true' in resp.text
|
|
resp.form['django-condition'] = 'form_name|length == 5'
|
|
resp = resp.form.submit()
|
|
assert 'Condition result' in resp.text
|
|
assert 'result-false' in resp.text
|
|
resp.form['django-condition'] = 'foo bar'
|
|
resp = resp.form.submit()
|
|
assert 'Condition result' not in resp.text
|
|
assert 'TemplateSyntaxError: Unused' in resp.text
|
|
|
|
resp.form['django-condition'] = 'form_name|length == 5'
|
|
ajax_resp = app.post('%sinspect-tool' % formdata.get_url(backoffice=True), params=resp.form.submit_fields())
|
|
assert ajax_resp.text.startswith('<div class="test-tool-result')
|
|
|
|
resp.form['test_mode'] = 'template'
|
|
resp.form['template'] = '{{ form_name }}'
|
|
resp = resp.form.submit()
|
|
assert 'Template rendering' in resp.text
|
|
assert '<div class="test-tool-result-plain">form title</div>' in resp.text
|
|
assert 'HTML Source' not in resp.text
|
|
resp.form['template'] = '<p>{{ form_name }}</p>'
|
|
resp = resp.form.submit()
|
|
assert 'Template rendering' in resp.text
|
|
assert '<p>form title</p>' in resp.text
|
|
assert 'HTML Source' in resp.text
|
|
resp.form['template'] = '{% for x in 1 %}ok{% endfor %}'
|
|
resp = resp.form.submit()
|
|
assert 'Failed to evaluate template' in resp.text
|
|
assert 'TypeError' in resp.text
|
|
resp.form['template'] = '{% for x in 1 %}ok{% end %}'
|
|
resp = resp.form.submit()
|
|
assert 'syntax error' in resp.text
|
|
assert 'Invalid block tag' in resp.text
|
|
resp.form['template'] = ''
|
|
|
|
resp.form['test_mode'] = 'html_template'
|
|
resp.form['html_template'] = '<p>{{ form_name }}</p>'
|
|
resp = resp.form.submit()
|
|
resp = resp.form.submit()
|
|
assert 'Template rendering' in resp.text
|
|
assert '<p>form title</p>' in resp.text
|
|
assert 'HTML Source' in resp.text
|
|
resp.form['html_template'] = '{% for x in 1 %}ok{% endfor %}'
|
|
resp = resp.form.submit()
|
|
assert 'Failed to evaluate HTML template' in resp.text
|
|
assert 'TypeError' in resp.text
|
|
resp.form['html_template'] = '{% for x in 1 %}ok{% end %}'
|
|
resp = resp.form.submit()
|
|
assert 'syntax error' in resp.text
|
|
assert 'Invalid block tag' in resp.text
|
|
|
|
def test_workflow_jump_previous(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='jump around')
|
|
# North
|
|
# / \
|
|
# West <----> East
|
|
# | |
|
|
# | autojump
|
|
# | |
|
|
# \ /
|
|
# South
|
|
|
|
st1 = wf.add_status('North')
|
|
st1.id = 'north'
|
|
st2 = wf.add_status('West')
|
|
st2.id = 'west'
|
|
st3 = wf.add_status('East')
|
|
st3.id = 'east'
|
|
st4 = wf.add_status('Autojump')
|
|
st4.id = 'autojump'
|
|
st5 = wf.add_status('South')
|
|
st5.id = 'south'
|
|
|
|
button_by_id = {}
|
|
|
|
def add_jump(label, src, dst_id):
|
|
jump = ChoiceWorkflowStatusItem()
|
|
jump.id = str(random.random())
|
|
jump.label = label
|
|
jump.by = ['logged-users']
|
|
jump.status = dst_id
|
|
src.items.append(jump)
|
|
jump.parent = src
|
|
if dst_id != '_previous':
|
|
jump.set_marker_on_status = True
|
|
button_by_id[label] = 'button%s' % jump.id
|
|
return jump
|
|
|
|
add_jump('Go West', st1, st2.id)
|
|
add_jump('Go East', st1, st3.id)
|
|
add_jump('Go South', st2, st5.id)
|
|
add_jump('Go Autojump', st3, st4.id)
|
|
add_jump('Go Back', st5, '_previous')
|
|
|
|
add_jump('Jump West', st3, st2.id)
|
|
add_jump('Jump East', st2, st3.id)
|
|
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.id = '_auto-jump'
|
|
jump.status = st5.id
|
|
st4.items.append(jump)
|
|
jump.parent = st4
|
|
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.data_class().wipe()
|
|
formdef.workflow = wf
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdata.id)
|
|
|
|
# jump around using buttons
|
|
resp = resp.form.submit(button_by_id['Go West']).follow() # push (north)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st2.id
|
|
resp = resp.form.submit(button_by_id['Go South']).follow() # push (north, west)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st5.id
|
|
resp = resp.form.submit(button_by_id['Go Back']).follow() # pop (north)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st2.id
|
|
resp = resp.form.submit(button_by_id['Go South']).follow() # push (north, west)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st5.id
|
|
resp = resp.form.submit(button_by_id['Go Back']).follow() # pop (north)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st2.id
|
|
resp = resp.form.submit(button_by_id['Jump East']).follow() # push (north, west)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st3.id
|
|
resp = resp.form.submit(button_by_id['Go Autojump']).follow() # push (north, west, east)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st5.id
|
|
|
|
# check markers are displayed in /inspect page
|
|
user.is_admin = True
|
|
user.store()
|
|
resp2 = app.get('/backoffice/management/form-title/%s/inspect' % formdata.id)
|
|
assert 'Markers Stack' in resp2.text
|
|
assert '<span class="status">East</span>' in resp2.text
|
|
assert '<span class="status">West</span>' in resp2.text
|
|
assert '<span class="status">North</span>' in resp2.text
|
|
assert resp2.text.find('<span class="status">East</span>') < resp2.text.find('<span class="status">West</span>')
|
|
assert resp2.text.find('<span class="status">West</span>') < resp2.text.find('<span class="status">North</span>')
|
|
|
|
resp = resp.form.submit(button_by_id['Go Back']).follow() # pop (north, west)
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st3.id
|
|
|
|
# and do a last jump using the API
|
|
formdata = formdef.data_class().get(formdata.id)
|
|
formdata.jump_status('_previous') # pop (north)
|
|
assert formdata.status == 'wf-%s' % st2.id
|
|
|
|
formdata = formdef.data_class().get(formdata.id)
|
|
formdata.jump_status('_previous') # pop ()
|
|
assert formdata.status == 'wf-%s' % st1.id
|
|
|
|
def test_workflow_jump_previous_on_submit(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='blah')
|
|
st1 = wf.add_status('North')
|
|
st1.id = 'north'
|
|
st2 = wf.add_status('South')
|
|
st2.id = 'south'
|
|
|
|
commentable = CommentableWorkflowStatusItem()
|
|
commentable.id = '_commentable'
|
|
commentable.by = ['_submitter', '_receiver']
|
|
commentable.button_label = 'CLICK ME!'
|
|
|
|
st1.items.append(commentable)
|
|
commentable.parent = st1
|
|
|
|
jump = JumpOnSubmitWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.status = st2.id
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
jump.set_marker_on_status = True
|
|
|
|
back = ChoiceWorkflowStatusItem()
|
|
back.id = '_back'
|
|
back.label = 'Back'
|
|
back.by = ['_receiver']
|
|
back.status = '_previous'
|
|
st2.items.append(back)
|
|
back.parent = st2
|
|
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.data_class().wipe()
|
|
formdef.workflow = wf
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdata.id)
|
|
resp.form['comment'] = 'HELLO WORLD'
|
|
resp = resp.form.submit('button_commentable')
|
|
resp = resp.follow()
|
|
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-south'
|
|
assert formdef.data_class().get(formdata.id).workflow_data['_markers_stack']
|
|
resp = resp.form.submit('button_back')
|
|
resp = resp.follow()
|
|
|
|
assert formdef.data_class().get(formdata.id).status == 'wf-north'
|
|
assert not formdef.data_class().get(formdata.id).workflow_data['_markers_stack']
|
|
|
|
def test_workflow_jump_previous_auto(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='blah')
|
|
st1 = wf.add_status('North')
|
|
st1.id = 'north'
|
|
st2 = wf.add_status('South')
|
|
st2.id = 'south'
|
|
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.id = '_auto-jump'
|
|
jump.set_marker_on_status = True
|
|
jump.status = st2.id
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
|
|
back = ChoiceWorkflowStatusItem()
|
|
back.id = '_back'
|
|
back.label = 'Back'
|
|
back.by = ['_receiver']
|
|
back.status = '_previous'
|
|
st2.items.append(back)
|
|
back.parent = st2
|
|
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.data_class().wipe()
|
|
formdef.workflow = wf
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
formdata.perform_workflow()
|
|
assert formdata.status == 'wf-south'
|
|
assert formdata.workflow_data['_markers_stack'] == [{'status_id': 'north'}]
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdata.id)
|
|
resp = resp.form.submit('button_back')
|
|
resp = resp.follow()
|
|
|
|
# jumped and got back to north, then re-jump to south again (auto-jump)
|
|
formdata = formdef.data_class().get(formdata.id)
|
|
statuses = [evo.status for evo in formdata.evolution]
|
|
assert statuses == ['wf-north', 'wf-south', 'wf-north', 'wf-south']
|
|
# formdata went through north->south auto-jump again, status and marker are still here
|
|
assert formdata.status == 'wf-south'
|
|
assert formdata.workflow_data['_markers_stack'] == [{'status_id': 'north'}]
|
|
|
|
def test_backoffice_fields(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='bo fields')
|
|
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
|
|
wf.backoffice_fields_formdef.fields = [
|
|
fields.StringField(id='bo1', label='1st backoffice field',
|
|
type='string', varname='backoffice_blah', required=False),
|
|
]
|
|
st1 = wf.add_status('Status1')
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow_id = wf.id
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert not 'Backoffice Data' in resp.text
|
|
assert not '1st backoffice field' in resp.text
|
|
|
|
formdata.data = {'bo1': 'HELLO WORLD'}
|
|
formdata.store()
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'Backoffice Data' in resp.text
|
|
assert '1st backoffice field' in resp.text
|
|
assert 'HELLO WORLD' in resp.text
|
|
|
|
wf.backoffice_fields_formdef.fields = [
|
|
fields.StringField(id='bo1', label='1st backoffice field',
|
|
type='string', varname='backoffice_blah', required=True),
|
|
]
|
|
wf.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'Backoffice Data' in resp.text
|
|
assert 'Not set' in resp.text
|
|
|
|
def test_backoffice_logged_errors(pub):
|
|
Workflow.wipe()
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '12'
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.status = 'rejected'
|
|
jump.condition = {'type': 'python', 'value': '1//0'} # ZeroDivisionError
|
|
st1 = workflow.possible_status[0]
|
|
st1.items.insert(0, jump)
|
|
jump.parent = st1
|
|
workflow.store()
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.id = '34'
|
|
formdef.workflow = workflow
|
|
formdef.name = 'test'
|
|
formdef.confirmation = False
|
|
formdef.fields = []
|
|
formdef.store()
|
|
|
|
LoggedError.wipe()
|
|
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/forms/%s/' % formdef.id)
|
|
assert not 'ZeroDivisionError' in resp.text
|
|
resp = app.get('/backoffice/workflows/%s/' % workflow.id)
|
|
assert not 'ZeroDivisionError' in resp.text
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
resp = resp.form.submit('submit').follow()
|
|
resp = resp.form.submit('submit')
|
|
assert LoggedError.count() == 1
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/forms/%s/' % formdef.id)
|
|
assert 'Failed to evaluate condition' in resp.text
|
|
assert 'error ZeroDivisionError' in resp.text
|
|
resp = resp.click('1 error')
|
|
|
|
resp = app.get('/backoffice/workflows/%s/' % workflow.id)
|
|
resp2 = resp.click('1 error')
|
|
assert 'Failed to evaluate condition' in resp2.text
|
|
assert 'error ZeroDivisionError' in resp2.text
|
|
resp = resp2.click('Failed to evaluate condition')
|
|
assert 'ZeroDivisionError: integer division or modulo by zero' in resp.text
|
|
assert 'Python Expression: <code>1//0</code>' in resp.text
|
|
assert not 'Acked' in resp.text
|
|
resp = resp.click('Ack').follow()
|
|
assert 'Acked' in resp.text
|
|
assert LoggedError.select()[0].acked is True
|
|
resp = resp.click('Delete').follow()
|
|
assert LoggedError.count() == 0
|
|
|
|
pub.cfg.update({'debug': {'error_email': None}})
|
|
pub.write_cfg()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
resp = resp.form.submit('submit').follow()
|
|
resp = resp.form.submit('submit')
|
|
assert LoggedError.count() == 1
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/workflows/%s/' % workflow.id)
|
|
assert 'Failed to evaluate condition' in resp2.text
|
|
assert 'error ZeroDivisionError' in resp2.text
|
|
resp2 = resp.click('1 error')
|
|
resp = resp2.click('Failed to evaluate condition')
|
|
assert 'href="http://example.net/backoffice/management/test/' in resp.text
|
|
|
|
# very long error string (check it creates a viable tech_id)
|
|
jump.condition = {'type': 'python', 'value': 'x'*500} # NameError + very long string
|
|
workflow.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
resp = resp.form.submit('submit').follow()
|
|
resp = resp.form.submit('submit')
|
|
assert LoggedError.count() == 2
|
|
|
|
# remove formdef
|
|
FormDef.wipe()
|
|
resp = resp2.click('Failed to evaluate condition')
|
|
assert not 'href="http://example.net/backoffice/management/test/' in resp.text
|
|
|
|
def test_backoffice_formdata_named_wscall(http_requests, pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
NamedWsCall.wipe()
|
|
|
|
wscall = NamedWsCall()
|
|
wscall.name = 'Hello world'
|
|
wscall.request = {'url': 'http://remote.example.net/json'}
|
|
wscall.store()
|
|
assert wscall.slug == 'hello_world'
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.fields = [
|
|
fields.CommentField(id='7', label='X[webservice.hello_world.foo]Y', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/submission/test/')
|
|
assert resp.html.find('div', {'data-field-id': '7'}).text.strip() == 'XbarY'
|
|
|
|
# check with publisher variable in named webservice call
|
|
if not pub.site_options.has_section('variables'):
|
|
pub.site_options.add_section('variables')
|
|
pub.site_options.set('variables', 'example_url', 'http://remote.example.net/')
|
|
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
|
pub.site_options.write(fd)
|
|
|
|
wscall = NamedWsCall()
|
|
wscall.name = 'Hello world'
|
|
wscall.request = {'url': '[example_url]json'}
|
|
wscall.store()
|
|
|
|
resp = app.get('/backoffice/submission/test/')
|
|
assert resp.html.find('div', {'data-field-id': '7'}).text.strip() == 'XbarY'
|
|
|
|
# django-templated URL
|
|
wscall.request = {'url': '{{ example_url }}json'}
|
|
wscall.store()
|
|
resp = app.get('/backoffice/submission/test/')
|
|
assert resp.html.find('div', {'data-field-id': '7'}).text.strip() == 'XbarY'
|
|
|
|
# webservice call in django template
|
|
formdef.fields = [
|
|
fields.CommentField(id='7', label='dja-{{ webservice.hello_world.foo}}-ngo', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = app.get('/backoffice/submission/test/')
|
|
assert resp.html.find('div', {'data-field-id': '7'}).text.strip() == 'dja-bar-ngo'
|
|
|
|
def test_backoffice_session_var(pub):
|
|
open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').write('''[options]
|
|
query_string_allowed_vars = foo,bar
|
|
''')
|
|
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.backoffice_submission_roles = user.roles[:]
|
|
formdef.fields = [
|
|
fields.CommentField(id='7', label='X[session_var_foo]Y', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/submission/test/?session_var_foo=bar')
|
|
assert resp.location.endswith('/backoffice/submission/test/')
|
|
resp = resp.follow()
|
|
assert resp.html.find('div', {'data-field-id': '7'}).text.strip() == 'XbarY'
|
|
|
|
# django template
|
|
formdef.fields = [
|
|
fields.CommentField(id='7', label='d{{ session_var_foo }}o', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = app.get('/backoffice/submission/test/?session_var_foo=jang')
|
|
assert resp.location.endswith('/backoffice/submission/test/')
|
|
resp = resp.follow()
|
|
assert resp.html.find('div', {'data-field-id': '7'}).text.strip() == 'django'
|
|
|
|
def test_backoffice_display_message(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
workflow = Workflow(name='test')
|
|
st1 = workflow.add_status('Status1', 'st1')
|
|
|
|
display1 = DisplayMessageWorkflowStatusItem()
|
|
display1.message = 'message-to-all'
|
|
display1.to = []
|
|
st1.items.append(display1)
|
|
display1.parent = st1
|
|
|
|
display2 = DisplayMessageWorkflowStatusItem()
|
|
display2.message = 'message-to-submitter'
|
|
display2.to = ['_submitter']
|
|
st1.items.append(display2)
|
|
display2.parent = st1
|
|
|
|
display3 = DisplayMessageWorkflowStatusItem()
|
|
display3.message = 'message-to-receiver'
|
|
display3.to = [user.roles[0]]
|
|
st1.items.append(display3)
|
|
display3.parent = st1
|
|
|
|
workflow.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow = workflow
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class().select()[0]
|
|
formdata.status = 'wf-st1'
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
|
|
assert 'message-to-all' in resp.text
|
|
assert 'message-to-submitter' not in resp.text
|
|
assert 'message-to-receiver' in resp.text
|
|
|
|
# display first message at the bottom of the page
|
|
display1.position = 'bottom'
|
|
workflow.store()
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert resp.text.index('message-to-all') > resp.text.index('message-to-receiver')
|
|
|
|
# display first message on top of actions
|
|
display1.position = 'actions'
|
|
workflow.store()
|
|
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert not 'message-to-all' in resp.text # no actions no message
|
|
|
|
again = ChoiceWorkflowStatusItem()
|
|
again.id = '_again'
|
|
again.label = 'Again'
|
|
again.by = ['_receiver']
|
|
again.status = st1.id
|
|
st1.items.append(again)
|
|
again.parent = st1
|
|
workflow.store()
|
|
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'message-to-all' in resp.text
|
|
assert resp.text.index('message-to-all') > resp.text.index('message-to-receiver')
|
|
|
|
def test_backoffice_forms_condition_on_button(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub, set_receiver=True)
|
|
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
workflow.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.workflow = workflow
|
|
formdef.store()
|
|
|
|
# move some forms from new to accepted
|
|
for i, formdata in enumerate(formdef.data_class().select(lambda x: x.status == 'wf-new')):
|
|
if i % 2:
|
|
formdata.status = 'wf-accepted'
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
resp = resp.click('Management', index=0)
|
|
resp = resp.follow()
|
|
assert '17 open on 50' in resp.text
|
|
|
|
formdata = [x for x in formdef.data_class().select() if x.status == 'wf-new'][0]
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'button_commentable' in resp.text
|
|
assert 'button_accept' in resp.text
|
|
assert 'button_reject' in resp.text
|
|
|
|
# commentable
|
|
workflow.possible_status[1].items[0].condition = {'type': 'python', 'value': 'False'}
|
|
# reject
|
|
workflow.possible_status[1].items[2].condition = {'type': 'python', 'value': 'False'}
|
|
workflow.store()
|
|
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'button_commentable' not in resp.text
|
|
assert 'button_accept' in resp.text
|
|
assert 'button_reject' not in resp.text
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
assert formdef.data_class().get(formdata.id).actions_roles == set(['1'])
|
|
|
|
# accept
|
|
workflow.possible_status[1].items[1].condition = {'type': 'python', 'value': 'False'}
|
|
workflow.store()
|
|
|
|
resp = app.get(formdata.get_url(backoffice=True))
|
|
assert 'button_commentable' not in resp.text
|
|
assert 'button_accept' not in resp.text
|
|
assert 'button_reject' not in resp.text
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
assert formdef.data_class().get(formdata.id).actions_roles == set()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
resp = resp.click('Management', index=0)
|
|
resp = resp.follow()
|
|
assert '8 open on 50' in resp.text # only the accepted ones
|
|
|
|
def test_workflow_inspect_page(pub):
|
|
create_superuser(pub)
|
|
create_environment(pub, set_receiver=True)
|
|
|
|
workflow = Workflow.get_default_workflow()
|
|
workflow.id = '2'
|
|
|
|
st1 = workflow.add_status('Status1')
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.id = '_jump'
|
|
jump.timeout = '=86400'
|
|
jump.status = 'finished'
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
workflow.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
|
assert '=86400' in resp.text
|
|
|
|
jump.timeout = '82800'
|
|
workflow.store()
|
|
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
|
assert '23 hours' in resp.text
|
|
|
|
def test_workflow_comment_required(pub):
|
|
user = create_user(pub)
|
|
create_environment(pub)
|
|
|
|
wf = Workflow(name='blah')
|
|
st1 = wf.add_status('Comment')
|
|
st1.id = 'comment'
|
|
commentable = CommentableWorkflowStatusItem()
|
|
commentable.id = '_commentable'
|
|
commentable.by = ['_submitter', '_receiver']
|
|
st1.items.append(commentable)
|
|
commentable.parent = st1
|
|
wf.store()
|
|
|
|
formdef = FormDef.get_by_urlname('form-title')
|
|
formdef.data_class().wipe()
|
|
formdef.workflow = wf
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {}
|
|
formdata.just_created()
|
|
formdata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdata.id)
|
|
assert 'widget-required' not in resp.text
|
|
resp.form['comment'] = 'HELLO WORLD 1'
|
|
resp = resp.form.submit('button_commentable')
|
|
resp = resp.follow()
|
|
assert 'HELLO WORLD 1' in resp.text
|
|
assert 'widget-required' not in resp.text
|
|
resp.form['comment'] = None
|
|
resp = resp.form.submit('button_commentable')
|
|
resp = resp.follow()
|
|
|
|
commentable.required = True
|
|
wf.store()
|
|
resp = app.get('/backoffice/management/form-title/%s/' % formdata.id)
|
|
assert 'widget-required' in resp.text
|
|
resp.form['comment'] = ' ' # spaces == empty
|
|
resp = resp.form.submit('button_commentable')
|
|
assert 'widget-with-error' in resp.text
|
|
resp.form['comment'] = 'HELLO WORLD 2'
|
|
resp = resp.form.submit('button_commentable')
|
|
resp = resp.follow()
|
|
assert 'widget-with-error' not in resp.text
|
|
assert 'HELLO WORLD 2' in resp.text
|
|
|
|
def test_carddata_management(pub, studio):
|
|
user = create_user(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/')
|
|
assert not 'Cards' in resp.text
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.fields = [
|
|
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
|
]
|
|
carddef.store()
|
|
|
|
resp = app.get('/backoffice/')
|
|
assert not 'Cards' in resp.text
|
|
|
|
carddef.backoffice_submission_roles = user.roles
|
|
carddef.store()
|
|
resp = app.get('/backoffice/')
|
|
assert 'Cards' in resp.text
|
|
|
|
carddef.backoffice_submission_roles = None
|
|
carddef.workflow_roles = {'_editor': user.roles[0]}
|
|
carddef.store()
|
|
resp = app.get('/backoffice/')
|
|
assert 'Cards' in resp.text
|
|
|
|
resp = app.get('/backoffice/data/')
|
|
resp = resp.click('foo')
|
|
assert 'Add' not in resp.text
|
|
|
|
carddef.backoffice_submission_roles = user.roles
|
|
carddef.store()
|
|
|
|
resp = app.get('/backoffice/data/')
|
|
resp = resp.click('foo')
|
|
assert resp.text.count('<tr') == 1 # header
|
|
assert 'Add' in resp.text
|
|
resp = resp.click('Add')
|
|
resp.form['f1'] = 'blah'
|
|
resp = resp.form.submit('submit')
|
|
assert resp.location.endswith('/backoffice/data/foo/1/')
|
|
resp = resp.follow()
|
|
assert 'Edit Card' in resp.text
|
|
assert 'Delete Card' in resp.text
|
|
|
|
resp = app.get('/backoffice/data/')
|
|
resp = resp.click('foo')
|
|
assert resp.text.count('<tr') == 2 # header + row of data
|