misc: split backoffice tests
This commit is contained in:
parent
3584fde29c
commit
3b9f87fb89
|
@ -0,0 +1,13 @@
|
|||
import pytest
|
||||
from quixote import get_publisher
|
||||
|
||||
|
||||
@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
|
|
@ -9,8 +9,6 @@ import zipfile
|
|||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from quixote import get_publisher
|
||||
from quixote.http_request import Upload as QuixoteUpload
|
||||
|
||||
import wcs.qommon.storage as st
|
||||
from wcs import fields
|
||||
|
@ -19,7 +17,6 @@ from wcs.blocks import BlockDef
|
|||
from wcs.carddef import CardDef
|
||||
from wcs.categories import Category
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon.form import UploadedFile
|
||||
from wcs.qommon.http_request import HTTPRequest
|
||||
from wcs.qommon.ident.password_accounts import PasswordAccount
|
||||
from wcs.qommon.upload_storage import PicklableUpload
|
||||
|
@ -28,7 +25,6 @@ from wcs.wf.backoffice_fields import SetBackofficeFieldsWorkflowStatusItem
|
|||
from wcs.wf.create_carddata import CreateCarddataWorkflowStatusItem
|
||||
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping
|
||||
from wcs.wf.dispatch import DispatchWorkflowStatusItem
|
||||
from wcs.wf.export_to_model import ExportToModel
|
||||
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
|
||||
from wcs.wf.jump import JumpWorkflowStatusItem
|
||||
from wcs.wf.redirect_to_url import RedirectToUrlWorkflowStatusItem
|
||||
|
@ -4473,557 +4469,6 @@ def test_backoffice_criticality_formdata_view(pub):
|
|||
assert 'Criticality Level: red' in resp.text
|
||||
|
||||
|
||||
class IHateUnicode:
|
||||
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')
|
||||
formdef.fields.append(fields.FileField(id='4', label='file field', type='file', varname='file'))
|
||||
formdef.store()
|
||||
|
||||
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': 'uné',
|
||||
'str_but_non_utf8': b'\xed\xa0\x00', # not actually supposed to happen
|
||||
'non_unicode_convertible': IHateUnicode(),
|
||||
'very_long_string': '0' * 100000,
|
||||
}
|
||||
# add a PicklableUpload in field 4
|
||||
upload = PicklableUpload('hello.txt', content_type='text/plain')
|
||||
upload.receive([b'hello world'])
|
||||
formdata.data['4'] = upload
|
||||
formdata.user_id = local_user.id
|
||||
formdata.workflow_data = {
|
||||
'foo': {
|
||||
'bar_coin': 'yy',
|
||||
},
|
||||
'foo_bar': 'xx',
|
||||
}
|
||||
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() == 'uné'
|
||||
assert (
|
||||
pq('[title="form_var_foo_non_unicode_convertible"]')
|
||||
.parents('li')
|
||||
.children('div.value span')
|
||||
.text()
|
||||
.startswith('ok ')
|
||||
)
|
||||
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
|
||||
|
||||
# make sure workflow data itself is not displayed, as it's available in
|
||||
# expanded variables
|
||||
assert not pq('[title="form_workflow_data"]')
|
||||
|
||||
# but do display it if it has some invalid contents
|
||||
formdata.workflow_data['invalid key'] = 'foobar'
|
||||
formdata.store()
|
||||
resp = login(get_app(pub)).get(resp.request.url)
|
||||
assert resp.pyquery('[title="form_workflow_data"]')
|
||||
|
||||
# check functions
|
||||
assert re.findall('Recipient.*foobar', resp.text)
|
||||
|
||||
role = pub.role_class(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
|
||||
assert 'rendered as an object' 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
|
||||
assert 'rendered as an object' not in resp.text
|
||||
resp.form['template'] = '{{ form_var_file }}'
|
||||
resp = resp.form.submit()
|
||||
assert 'Template rendering' in resp.text
|
||||
assert '<div class="test-tool-result-plain">hello.txt</div>' in resp.text
|
||||
assert 'rendered as an object' in resp.text
|
||||
assert '<div class="test-tool-result-plain">hello.txt (PicklableUpload)</div>' in resp.text
|
||||
assert 'HTML Source' not 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_inspect_page_with_related_objects(pub):
|
||||
if not pub.is_using_postgresql():
|
||||
pytest.skip('this requires SQL')
|
||||
return
|
||||
|
||||
user = create_user(pub, is_admin=True)
|
||||
|
||||
FormDef.wipe()
|
||||
CardDef.wipe()
|
||||
|
||||
# test ExternalWorkflowGlobalAction
|
||||
external_wf = Workflow(name='External Workflow')
|
||||
st1 = external_wf.add_status(name='New')
|
||||
action = external_wf.add_global_action('Delete', 'delete')
|
||||
action.append_item('remove')
|
||||
trigger = action.append_trigger('webservice')
|
||||
trigger.identifier = 'delete'
|
||||
external_wf.store()
|
||||
|
||||
external_formdef = FormDef()
|
||||
external_formdef.name = 'External Form'
|
||||
external_formdef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='form_string'),
|
||||
]
|
||||
external_formdef.workflow = external_wf
|
||||
external_formdef.store()
|
||||
|
||||
external_carddef = CardDef()
|
||||
external_carddef.name = 'External Card'
|
||||
external_carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='card_string'),
|
||||
]
|
||||
external_carddef.backoffice_submission_roles = user.roles
|
||||
external_carddef.workflow = external_wf
|
||||
external_carddef.store()
|
||||
|
||||
wf = Workflow(name='External actions')
|
||||
st1 = wf.add_status('Create external formdata')
|
||||
|
||||
# add a message to history, to check it doesn't interfer when searching for
|
||||
# linked data.
|
||||
register_comment = RegisterCommenterWorkflowStatusItem()
|
||||
register_comment.id = '_register'
|
||||
register_comment.comment = '<p>test</p>'
|
||||
st1.items.append(register_comment)
|
||||
register_comment.parent = st1
|
||||
|
||||
create_formdata = CreateFormdataWorkflowStatusItem()
|
||||
create_formdata.label = 'create linked form'
|
||||
create_formdata.formdef_slug = external_formdef.url_name
|
||||
create_formdata.varname = 'created_form'
|
||||
create_formdata.id = '_create_form'
|
||||
mappings = [Mapping(field_id='0', expression='{{ form_var_string }}')]
|
||||
create_formdata.mappings = mappings
|
||||
create_formdata.parent = st1
|
||||
|
||||
create_carddata = CreateCarddataWorkflowStatusItem()
|
||||
create_carddata.label = 'create linked card'
|
||||
create_carddata.formdef_slug = external_carddef.url_name
|
||||
create_carddata.varname = 'created_card'
|
||||
create_carddata.id = '_create_card'
|
||||
create_carddata.mappings = mappings
|
||||
create_carddata.parent = st1
|
||||
|
||||
st1.items.append(create_formdata)
|
||||
st1.items.append(create_carddata)
|
||||
|
||||
global_action = wf.add_global_action('Delete external linked object', 'delete')
|
||||
action = global_action.append_item('external_workflow_global_action')
|
||||
action.slug = 'formdef:%s' % external_formdef.url_name
|
||||
action.trigger_id = 'action:%s' % trigger.identifier
|
||||
wf.store()
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'External action form'
|
||||
formdef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='string'),
|
||||
]
|
||||
formdef.workflow = wf
|
||||
formdef.store()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'External action card'
|
||||
carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='string'),
|
||||
]
|
||||
carddef.backoffice_submission_roles = user.roles
|
||||
carddef.workflow = wf
|
||||
carddef.store()
|
||||
|
||||
assert formdef.data_class().count() == 0
|
||||
assert carddef.data_class().count() == 0
|
||||
assert external_formdef.data_class().count() == 0
|
||||
assert external_carddef.data_class().count() == 0
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': 'test form'}
|
||||
formdata.user = user
|
||||
formdata.store()
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert formdef.data_class().count() == 1
|
||||
assert carddef.data_class().count() == 0
|
||||
# related form and card
|
||||
assert external_formdef.data_class().count() == 1
|
||||
assert external_carddef.data_class().count() == 1
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/management/external-action-form/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
# related form and card
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-form/1/">External Form #1-1 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-card/1/">External Card #1-1 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related form
|
||||
resp = app.get('/backoffice/management/external-form/1/')
|
||||
assert (
|
||||
'<h3>Original form</h3><p><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/management/external-form/1/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related card
|
||||
resp = app.get('/backoffice/data/external-card/1/')
|
||||
assert (
|
||||
'<h3>Original form</h3><p><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/data/external-card/1/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
external_formdef.data_class().wipe()
|
||||
external_carddef.data_class().wipe()
|
||||
|
||||
# missing form/card data
|
||||
resp = app.get('/backoffice/management/external-action-form/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
assert (
|
||||
'<li><a href="">Linked "External Form" object by id 1 (Evolution - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
assert (
|
||||
'<li><a href="">Linked "External Card" object by id 1 (Evolution - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
formdef.data_class().wipe()
|
||||
carddef.data_class().wipe()
|
||||
|
||||
carddata = carddef.data_class()()
|
||||
carddata.data = {'0': 'test card'}
|
||||
carddata.user = user
|
||||
carddata.store()
|
||||
carddata.just_created()
|
||||
carddata.perform_workflow()
|
||||
|
||||
assert formdef.data_class().count() == 0
|
||||
assert carddef.data_class().count() == 1
|
||||
# related form and card
|
||||
assert external_formdef.data_class().count() == 1
|
||||
assert external_carddef.data_class().count() == 1
|
||||
|
||||
resp = app.get('/backoffice/data/external-action-card/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
# related form and card
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-form/2/">External Form #1-2 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-card/2/">External Card #1-2 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related form
|
||||
resp = app.get('/backoffice/management/external-form/2/')
|
||||
assert (
|
||||
'<h3>Original card</h3><p><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/management/external-form/2/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related card
|
||||
resp = app.get('/backoffice/data/external-card/2/')
|
||||
assert (
|
||||
'<h3>Original card</h3><p><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/data/external-card/2/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
FormDef.wipe()
|
||||
CardDef.wipe()
|
||||
Workflow.wipe()
|
||||
|
||||
# test linked Card in datasource
|
||||
wf = Workflow(name='WF')
|
||||
st1 = wf.add_status('NEW')
|
||||
wf.store()
|
||||
wfc = Workflow(name='WFC')
|
||||
wfc.add_status('NEW')
|
||||
wfc.store()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'CARD A'
|
||||
carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='string'),
|
||||
]
|
||||
carddef.backoffice_submission_roles = user.roles
|
||||
carddef.workflow = wfc
|
||||
carddef.store()
|
||||
|
||||
datasource = {'type': 'carddef:%s' % carddef.url_name}
|
||||
formdef = FormDef()
|
||||
formdef.name = 'FORM A'
|
||||
formdef.fields = [
|
||||
fields.ItemField(id='0', label='Card', type='item', varname='card', data_source=datasource),
|
||||
]
|
||||
formdef.workflow = wf
|
||||
formdef.store()
|
||||
|
||||
carddata = carddef.data_class()()
|
||||
carddata.data = {'0': 'Text'}
|
||||
carddata.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': '1'}
|
||||
formdata.store()
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert formdef.data_class().count() == 1
|
||||
assert carddef.data_class().count() == 1
|
||||
|
||||
resp = app.get('/backoffice/management/form-a/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
# related card
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/card-a/1/">CARD A #1-1 (Data Source - varname "card")</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
# missing carddata
|
||||
carddef.data_class().wipe()
|
||||
resp = app.get('/backoffice/management/form-a/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
assert (
|
||||
'<li><a href="">Linked "CARD A" object by id 1 (Data Source - varname "card" - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
# missing carddef
|
||||
CardDef.wipe()
|
||||
resp = app.get('/backoffice/management/form-a/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
assert (
|
||||
'<li><a href="">Linked object def by id card-a (Data Source - varname "card" - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
|
||||
def test_inspect_page_actions_traces(pub):
|
||||
create_environment(pub)
|
||||
create_user(pub, is_admin=True)
|
||||
|
||||
workflow = Workflow.get_default_workflow()
|
||||
workflow.id = '2'
|
||||
workflow.criticality_levels = [
|
||||
WorkflowCriticalityLevel(name='green'),
|
||||
WorkflowCriticalityLevel(name='yellow'),
|
||||
WorkflowCriticalityLevel(name='red'),
|
||||
]
|
||||
action = workflow.add_global_action('Timeout Test')
|
||||
action.append_item('modify_criticality')
|
||||
trigger = action.append_trigger('timeout')
|
||||
trigger.anchor = 'creation'
|
||||
trigger.timeout = '2'
|
||||
workflow.store()
|
||||
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.store()
|
||||
|
||||
formdef.data_class().wipe()
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {}
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
formdata.store()
|
||||
|
||||
# change receipt time to get global timeout to run
|
||||
formdata.receipt_time = time.localtime(time.time() - 3 * 86400)
|
||||
formdata.store()
|
||||
pub.apply_global_action_timeouts()
|
||||
formdata.refresh_from_storage()
|
||||
assert formdata.get_criticality_level_object().name == 'yellow'
|
||||
|
||||
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True), status=200)
|
||||
resp = resp.click('Data Inspector')
|
||||
assert '<h2>Actions Tracing</h2>' in resp
|
||||
assert [x.text for x in resp.pyquery('#inspect-timeline strong')] == ['Just Submitted', 'New']
|
||||
assert [x.text for x in resp.pyquery('#inspect-timeline a.tracing-link') if x.text] == [
|
||||
'Email',
|
||||
'Email',
|
||||
'Automatic Jump',
|
||||
'Criticality Levels',
|
||||
]
|
||||
action_links = [x.attrib['href'] for x in resp.pyquery('#inspect-timeline a.tracing-link')]
|
||||
assert action_links[0] == 'http://example.net/backoffice/workflows/2/status/just_submitted/'
|
||||
assert (
|
||||
action_links[1]
|
||||
== 'http://example.net/backoffice/workflows/2/status/just_submitted/items/_notify_new_receiver_email/'
|
||||
)
|
||||
assert action_links[-1] == 'http://example.net/backoffice/workflows/2/global-actions/1/items/1/'
|
||||
|
||||
|
||||
def test_workflow_jump_previous(pub):
|
||||
user = create_user(pub)
|
||||
create_environment(pub)
|
||||
|
@ -5659,112 +5104,6 @@ def test_backoffice_forms_condition_on_button(pub):
|
|||
assert '8 open on 50' in resp.text # only the accepted ones
|
||||
|
||||
|
||||
def test_workflow_inspect_page(pub):
|
||||
admin = create_user(pub, is_admin=True)
|
||||
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
|
||||
|
||||
target_formdef = FormDef()
|
||||
target_formdef.name = 'target form'
|
||||
target_formdef.workflow_roles = {'_receiver': 1}
|
||||
target_formdef.backoffice_submission_roles = admin.roles[:]
|
||||
target_formdef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='foo_string'),
|
||||
fields.FileField(id='1', label='file', type='file', varname='foo_file'),
|
||||
]
|
||||
|
||||
st2 = workflow.add_status('Status2')
|
||||
|
||||
target_formdef.store()
|
||||
create_formdata = CreateFormdataWorkflowStatusItem()
|
||||
create_formdata.id = '_create_formdata'
|
||||
create_formdata.varname = 'resubmitted'
|
||||
create_formdata.draft = True
|
||||
create_formdata.formdef_slug = target_formdef.url_name
|
||||
create_formdata.user_association_mode = 'keep-user'
|
||||
create_formdata.backoffice_submission = True
|
||||
create_formdata.mappings = [
|
||||
Mapping(field_id='0', expression='=form_var_toto_string'),
|
||||
Mapping(field_id='1', expression='=form_var_toto_file_raw'),
|
||||
Mapping(field_id='2', expression='=form_var_foobar_raw'),
|
||||
]
|
||||
create_formdata.parent = st2
|
||||
st2.items.append(create_formdata)
|
||||
workflow.store()
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
||||
assert (
|
||||
'<ul class="mappings"><li>string → =form_var_toto_string</li>'
|
||||
'<li>file → =form_var_toto_file_raw</li>'
|
||||
'<li>#2 → =form_var_foobar_raw</li></ul>'
|
||||
) in resp.text
|
||||
|
||||
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
|
||||
workflow.backoffice_fields_formdef.fields = [
|
||||
fields.StringField(id='bo1', label='Foo Bar 1', varname='foo_bar'),
|
||||
fields.StringField(id='bo2', label='Foo Bar 2', varname='foo_bar'),
|
||||
fields.StringField(id='bo3', label='Foo Bar 3', varname='foo_bar'),
|
||||
]
|
||||
setbo = SetBackofficeFieldsWorkflowStatusItem()
|
||||
setbo.parent = st2
|
||||
setbo.fields = [
|
||||
{'field_id': 'bo1', 'value': 'go'},
|
||||
{'field_id': 'bo2', 'value': ''},
|
||||
{'field_id': 'bo3', 'value': None},
|
||||
{'field_id': 'unknown', 'value': 'foobar'},
|
||||
]
|
||||
st2.items.append(setbo)
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
||||
assert (
|
||||
'<ul class="fields"><li>Foo Bar 1 → go</li>'
|
||||
'<li>Foo Bar 2 → </li>'
|
||||
'<li>Foo Bar 3 → None</li>'
|
||||
'<li>#unknown → foobar</li></ul>'
|
||||
) in resp.text
|
||||
|
||||
st3 = workflow.add_status('Status3', 'st3')
|
||||
export_to = ExportToModel()
|
||||
export_to.convert_to_pdf = False
|
||||
export_to.label = 'create doc'
|
||||
upload = QuixoteUpload('/foo/test.rtf', content_type='application/rtf')
|
||||
upload.fp = io.BytesIO()
|
||||
upload.fp.write(b'HELLO WORLD')
|
||||
upload.fp.seek(0)
|
||||
export_to.model_file = UploadedFile(pub.app_dir, None, upload)
|
||||
export_to.id = '_export_to'
|
||||
export_to.by = ['_submitter']
|
||||
st3.items.append(export_to)
|
||||
export_to.parent = st3
|
||||
workflow.store()
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
||||
assert (
|
||||
'<li><span class="parameter">Model:</span> '
|
||||
'<a href="status/st3/items/_export_to/?file=model_file">test.rtf</a></li>'
|
||||
) in resp.text
|
||||
|
||||
|
||||
def test_workflow_comment_required(pub):
|
||||
create_user(pub)
|
||||
create_environment(pub)
|
||||
|
|
|
@ -0,0 +1,601 @@
|
|||
import re
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from wcs import fields
|
||||
from wcs.admin.settings import UserFieldsFormDef
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon.http_request import HTTPRequest
|
||||
from wcs.qommon.upload_storage import PicklableUpload
|
||||
from wcs.wf.create_carddata import CreateCarddataWorkflowStatusItem
|
||||
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping
|
||||
from wcs.wf.register_comment import RegisterCommenterWorkflowStatusItem
|
||||
from wcs.workflows import Workflow, WorkflowCriticalityLevel
|
||||
|
||||
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
|
||||
from .test_all import create_user
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'pub' in metafunc.fixturenames:
|
||||
metafunc.parametrize('pub', ['pickle', 'sql'], indirect=True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def pub(request, emails):
|
||||
pub = create_temporary_pub(sql_mode=bool('sql' in request.param))
|
||||
|
||||
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
|
||||
pub.cfg['identification'] = {'methods': ['password']}
|
||||
pub.cfg['language'] = {'language': 'en'}
|
||||
pub.write_cfg()
|
||||
pub.set_app_dir(req)
|
||||
return pub
|
||||
|
||||
|
||||
def teardown_module(module):
|
||||
clean_temporary_pub()
|
||||
|
||||
|
||||
class IHateUnicode:
|
||||
def __unicode__(self):
|
||||
raise Exception('HATE!!')
|
||||
|
||||
def __repr__(self):
|
||||
return 'ok'
|
||||
|
||||
|
||||
def test_inspect_page(pub, local_user):
|
||||
create_user(pub)
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
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'),
|
||||
fields.FileField(id='4', label='file field', type='file', varname='file'),
|
||||
]
|
||||
formdef.workflow_roles = {'_receiver': 1}
|
||||
formdef.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.just_created()
|
||||
upload = PicklableUpload('hello.txt', content_type='text/plain')
|
||||
upload.receive([b'hello world'])
|
||||
formdata.data = {
|
||||
'1': 'FOO BAR 0',
|
||||
'2': 'baz',
|
||||
'2_display': 'baz',
|
||||
'3': 'C',
|
||||
'3_display': 'cc',
|
||||
# temper with field 3 structured values
|
||||
'3_structured': {
|
||||
'unicode': 'uné',
|
||||
'str_but_non_utf8': b'\xed\xa0\x00', # not actually supposed to happen
|
||||
'non_unicode_convertible': IHateUnicode(),
|
||||
'very_long_string': '0' * 100000,
|
||||
},
|
||||
# add a PicklableUpload in field 4
|
||||
'4': upload,
|
||||
}
|
||||
formdata.jump_status('new')
|
||||
formdata.user_id = local_user.id
|
||||
formdata.workflow_data = {
|
||||
'foo': {
|
||||
'bar_coin': 'yy',
|
||||
},
|
||||
'foo_bar': 'xx',
|
||||
}
|
||||
formdata.store()
|
||||
|
||||
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() == 'uné'
|
||||
assert (
|
||||
pq('[title="form_var_foo_non_unicode_convertible"]')
|
||||
.parents('li')
|
||||
.children('div.value span')
|
||||
.text()
|
||||
.startswith('ok ')
|
||||
)
|
||||
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
|
||||
|
||||
# make sure workflow data itself is not displayed, as it's available in
|
||||
# expanded variables
|
||||
assert not pq('[title="form_workflow_data"]')
|
||||
|
||||
# but do display it if it has some invalid contents
|
||||
formdata.workflow_data['invalid key'] = 'foobar'
|
||||
formdata.store()
|
||||
resp = login(get_app(pub)).get(resp.request.url)
|
||||
assert resp.pyquery('[title="form_workflow_data"]')
|
||||
|
||||
# check functions
|
||||
assert re.findall('Recipient.*foobar', resp.text)
|
||||
|
||||
role = pub.role_class(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
|
||||
assert 'rendered as an object' 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
|
||||
assert 'rendered as an object' not in resp.text
|
||||
resp.form['template'] = '{{ form_var_file }}'
|
||||
resp = resp.form.submit()
|
||||
assert 'Template rendering' in resp.text
|
||||
assert '<div class="test-tool-result-plain">hello.txt</div>' in resp.text
|
||||
assert 'rendered as an object' in resp.text
|
||||
assert '<div class="test-tool-result-plain">hello.txt (PicklableUpload)</div>' in resp.text
|
||||
assert 'HTML Source' not 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_inspect_page_with_related_objects(pub):
|
||||
if not pub.is_using_postgresql():
|
||||
pytest.skip('this requires SQL')
|
||||
return
|
||||
|
||||
user = create_user(pub, is_admin=True)
|
||||
|
||||
FormDef.wipe()
|
||||
CardDef.wipe()
|
||||
|
||||
# test ExternalWorkflowGlobalAction
|
||||
external_wf = Workflow(name='External Workflow')
|
||||
st1 = external_wf.add_status(name='New')
|
||||
action = external_wf.add_global_action('Delete', 'delete')
|
||||
action.append_item('remove')
|
||||
trigger = action.append_trigger('webservice')
|
||||
trigger.identifier = 'delete'
|
||||
external_wf.store()
|
||||
|
||||
external_formdef = FormDef()
|
||||
external_formdef.name = 'External Form'
|
||||
external_formdef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='form_string'),
|
||||
]
|
||||
external_formdef.workflow = external_wf
|
||||
external_formdef.store()
|
||||
|
||||
external_carddef = CardDef()
|
||||
external_carddef.name = 'External Card'
|
||||
external_carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='card_string'),
|
||||
]
|
||||
external_carddef.backoffice_submission_roles = user.roles
|
||||
external_carddef.workflow = external_wf
|
||||
external_carddef.store()
|
||||
|
||||
wf = Workflow(name='External actions')
|
||||
st1 = wf.add_status('Create external formdata')
|
||||
|
||||
# add a message to history, to check it doesn't interfer when searching for
|
||||
# linked data.
|
||||
register_comment = RegisterCommenterWorkflowStatusItem()
|
||||
register_comment.id = '_register'
|
||||
register_comment.comment = '<p>test</p>'
|
||||
st1.items.append(register_comment)
|
||||
register_comment.parent = st1
|
||||
|
||||
create_formdata = CreateFormdataWorkflowStatusItem()
|
||||
create_formdata.label = 'create linked form'
|
||||
create_formdata.formdef_slug = external_formdef.url_name
|
||||
create_formdata.varname = 'created_form'
|
||||
create_formdata.id = '_create_form'
|
||||
mappings = [Mapping(field_id='0', expression='{{ form_var_string }}')]
|
||||
create_formdata.mappings = mappings
|
||||
create_formdata.parent = st1
|
||||
|
||||
create_carddata = CreateCarddataWorkflowStatusItem()
|
||||
create_carddata.label = 'create linked card'
|
||||
create_carddata.formdef_slug = external_carddef.url_name
|
||||
create_carddata.varname = 'created_card'
|
||||
create_carddata.id = '_create_card'
|
||||
create_carddata.mappings = mappings
|
||||
create_carddata.parent = st1
|
||||
|
||||
st1.items.append(create_formdata)
|
||||
st1.items.append(create_carddata)
|
||||
|
||||
global_action = wf.add_global_action('Delete external linked object', 'delete')
|
||||
action = global_action.append_item('external_workflow_global_action')
|
||||
action.slug = 'formdef:%s' % external_formdef.url_name
|
||||
action.trigger_id = 'action:%s' % trigger.identifier
|
||||
wf.store()
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'External action form'
|
||||
formdef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='string'),
|
||||
]
|
||||
formdef.workflow = wf
|
||||
formdef.store()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'External action card'
|
||||
carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='string'),
|
||||
]
|
||||
carddef.backoffice_submission_roles = user.roles
|
||||
carddef.workflow = wf
|
||||
carddef.store()
|
||||
|
||||
assert formdef.data_class().count() == 0
|
||||
assert carddef.data_class().count() == 0
|
||||
assert external_formdef.data_class().count() == 0
|
||||
assert external_carddef.data_class().count() == 0
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': 'test form'}
|
||||
formdata.user = user
|
||||
formdata.store()
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert formdef.data_class().count() == 1
|
||||
assert carddef.data_class().count() == 0
|
||||
# related form and card
|
||||
assert external_formdef.data_class().count() == 1
|
||||
assert external_carddef.data_class().count() == 1
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/management/external-action-form/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
# related form and card
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-form/1/">External Form #1-1 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-card/1/">External Card #1-1 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related form
|
||||
resp = app.get('/backoffice/management/external-form/1/')
|
||||
assert (
|
||||
'<h3>Original form</h3><p><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/management/external-form/1/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related card
|
||||
resp = app.get('/backoffice/data/external-card/1/')
|
||||
assert (
|
||||
'<h3>Original form</h3><p><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/data/external-card/1/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-action-form/1/">External action form #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
external_formdef.data_class().wipe()
|
||||
external_carddef.data_class().wipe()
|
||||
|
||||
# missing form/card data
|
||||
resp = app.get('/backoffice/management/external-action-form/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
assert (
|
||||
'<li><a href="">Linked "External Form" object by id 1 (Evolution - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
assert (
|
||||
'<li><a href="">Linked "External Card" object by id 1 (Evolution - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
formdef.data_class().wipe()
|
||||
carddef.data_class().wipe()
|
||||
|
||||
carddata = carddef.data_class()()
|
||||
carddata.data = {'0': 'test card'}
|
||||
carddata.user = user
|
||||
carddata.store()
|
||||
carddata.just_created()
|
||||
carddata.perform_workflow()
|
||||
|
||||
assert formdef.data_class().count() == 0
|
||||
assert carddef.data_class().count() == 1
|
||||
# related form and card
|
||||
assert external_formdef.data_class().count() == 1
|
||||
assert external_carddef.data_class().count() == 1
|
||||
|
||||
resp = app.get('/backoffice/data/external-action-card/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
# related form and card
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/management/external-form/2/">External Form #1-2 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-card/2/">External Card #1-2 (Evolution)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related form
|
||||
resp = app.get('/backoffice/management/external-form/2/')
|
||||
assert (
|
||||
'<h3>Original card</h3><p><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/management/external-form/2/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
# check related card
|
||||
resp = app.get('/backoffice/data/external-card/2/')
|
||||
assert (
|
||||
'<h3>Original card</h3><p><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1</a></p>'
|
||||
in resp.text
|
||||
)
|
||||
resp = app.get('/backoffice/data/external-card/2/inspect')
|
||||
# parent
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/external-action-card/1/">External action card #2-1 (Parent)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
FormDef.wipe()
|
||||
CardDef.wipe()
|
||||
Workflow.wipe()
|
||||
|
||||
# test linked Card in datasource
|
||||
wf = Workflow(name='WF')
|
||||
st1 = wf.add_status('NEW')
|
||||
wf.store()
|
||||
wfc = Workflow(name='WFC')
|
||||
wfc.add_status('NEW')
|
||||
wfc.store()
|
||||
|
||||
carddef = CardDef()
|
||||
carddef.name = 'CARD A'
|
||||
carddef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='string'),
|
||||
]
|
||||
carddef.backoffice_submission_roles = user.roles
|
||||
carddef.workflow = wfc
|
||||
carddef.store()
|
||||
|
||||
datasource = {'type': 'carddef:%s' % carddef.url_name}
|
||||
formdef = FormDef()
|
||||
formdef.name = 'FORM A'
|
||||
formdef.fields = [
|
||||
fields.ItemField(id='0', label='Card', type='item', varname='card', data_source=datasource),
|
||||
]
|
||||
formdef.workflow = wf
|
||||
formdef.store()
|
||||
|
||||
carddata = carddef.data_class()()
|
||||
carddata.data = {'0': 'Text'}
|
||||
carddata.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': '1'}
|
||||
formdata.store()
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
|
||||
assert formdef.data_class().count() == 1
|
||||
assert carddef.data_class().count() == 1
|
||||
|
||||
resp = app.get('/backoffice/management/form-a/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
# related card
|
||||
assert (
|
||||
'<li><a href="http://example.net/backoffice/data/card-a/1/">CARD A #1-1 (Data Source - varname "card")</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
# missing carddata
|
||||
carddef.data_class().wipe()
|
||||
resp = app.get('/backoffice/management/form-a/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
assert (
|
||||
'<li><a href="">Linked "CARD A" object by id 1 (Data Source - varname "card" - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
# missing carddef
|
||||
CardDef.wipe()
|
||||
resp = app.get('/backoffice/management/form-a/1/inspect')
|
||||
assert 'Related Forms/Cards' in resp.text
|
||||
assert (
|
||||
'<li><a href="">Linked object def by id card-a (Data Source - varname "card" - not found)</a></li>'
|
||||
in resp.text
|
||||
)
|
||||
|
||||
|
||||
def test_inspect_page_actions_traces(pub):
|
||||
create_user(pub, is_admin=True)
|
||||
|
||||
workflow = Workflow.get_default_workflow()
|
||||
workflow.id = '2'
|
||||
workflow.criticality_levels = [
|
||||
WorkflowCriticalityLevel(name='green'),
|
||||
WorkflowCriticalityLevel(name='yellow'),
|
||||
WorkflowCriticalityLevel(name='red'),
|
||||
]
|
||||
action = workflow.add_global_action('Timeout Test')
|
||||
action.append_item('modify_criticality')
|
||||
trigger = action.append_trigger('timeout')
|
||||
trigger.anchor = 'creation'
|
||||
trigger.timeout = '2'
|
||||
workflow.store()
|
||||
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.store()
|
||||
|
||||
formdef.data_class().wipe()
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {}
|
||||
formdata.just_created()
|
||||
formdata.perform_workflow()
|
||||
formdata.store()
|
||||
|
||||
# change receipt time to get global timeout to run
|
||||
formdata.receipt_time = time.localtime(time.time() - 3 * 86400)
|
||||
formdata.store()
|
||||
pub.apply_global_action_timeouts()
|
||||
formdata.refresh_from_storage()
|
||||
assert formdata.get_criticality_level_object().name == 'yellow'
|
||||
|
||||
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True), status=200)
|
||||
resp = resp.click('Data Inspector')
|
||||
assert '<h2>Actions Tracing</h2>' in resp
|
||||
assert [x.text for x in resp.pyquery('#inspect-timeline strong')] == ['Just Submitted', 'New']
|
||||
assert [x.text for x in resp.pyquery('#inspect-timeline a.tracing-link') if x.text] == [
|
||||
'Email',
|
||||
'Email',
|
||||
'Automatic Jump',
|
||||
'Criticality Levels',
|
||||
]
|
||||
action_links = [x.attrib['href'] for x in resp.pyquery('#inspect-timeline a.tracing-link')]
|
||||
assert action_links[0] == 'http://example.net/backoffice/workflows/2/status/just_submitted/'
|
||||
assert (
|
||||
action_links[1]
|
||||
== 'http://example.net/backoffice/workflows/2/status/just_submitted/items/_notify_new_receiver_email/'
|
||||
)
|
||||
assert action_links[-1] == 'http://example.net/backoffice/workflows/2/global-actions/1/items/1/'
|
|
@ -45,17 +45,6 @@ def pub(request, emails):
|
|||
return pub
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def local_user(pub):
|
||||
pub.user_class.wipe()
|
||||
user = pub.user_class()
|
||||
user.name = 'Jean Darmette'
|
||||
user.email = 'jean.darmette@triffouilis.fr'
|
||||
user.name_identifiers = ['0123456789']
|
||||
user.store()
|
||||
return user
|
||||
|
||||
|
||||
def teardown_module(module):
|
||||
clean_temporary_pub()
|
||||
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
import io
|
||||
|
||||
import pytest
|
||||
from quixote.http_request import Upload as QuixoteUpload
|
||||
|
||||
from wcs import fields
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon.form import UploadedFile
|
||||
from wcs.qommon.http_request import HTTPRequest
|
||||
from wcs.wf.backoffice_fields import SetBackofficeFieldsWorkflowStatusItem
|
||||
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping
|
||||
from wcs.wf.export_to_model import ExportToModel
|
||||
from wcs.wf.jump import JumpWorkflowStatusItem
|
||||
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef
|
||||
|
||||
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
|
||||
from .test_all import create_superuser
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'pub' in metafunc.fixturenames:
|
||||
metafunc.parametrize('pub', ['pickle', 'sql'], indirect=True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def pub(request, emails):
|
||||
pub = create_temporary_pub(sql_mode=bool('sql' in request.param))
|
||||
|
||||
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
|
||||
pub.cfg['identification'] = {'methods': ['password']}
|
||||
pub.cfg['language'] = {'language': 'en'}
|
||||
pub.write_cfg()
|
||||
pub.set_app_dir(req)
|
||||
return pub
|
||||
|
||||
|
||||
def teardown_module(module):
|
||||
clean_temporary_pub()
|
||||
|
||||
|
||||
def test_workflow_inspect_page(pub):
|
||||
admin = create_superuser(pub)
|
||||
|
||||
workflow = Workflow(name='blah')
|
||||
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
|
||||
|
||||
target_formdef = FormDef()
|
||||
target_formdef.name = 'target form'
|
||||
target_formdef.workflow_roles = {'_receiver': 1}
|
||||
target_formdef.backoffice_submission_roles = admin.roles[:]
|
||||
target_formdef.fields = [
|
||||
fields.StringField(id='0', label='string', varname='foo_string'),
|
||||
fields.FileField(id='1', label='file', type='file', varname='foo_file'),
|
||||
]
|
||||
|
||||
st2 = workflow.add_status('Status2')
|
||||
|
||||
target_formdef.store()
|
||||
create_formdata = CreateFormdataWorkflowStatusItem()
|
||||
create_formdata.id = '_create_formdata'
|
||||
create_formdata.varname = 'resubmitted'
|
||||
create_formdata.draft = True
|
||||
create_formdata.formdef_slug = target_formdef.url_name
|
||||
create_formdata.user_association_mode = 'keep-user'
|
||||
create_formdata.backoffice_submission = True
|
||||
create_formdata.mappings = [
|
||||
Mapping(field_id='0', expression='=form_var_toto_string'),
|
||||
Mapping(field_id='1', expression='=form_var_toto_file_raw'),
|
||||
Mapping(field_id='2', expression='=form_var_foobar_raw'),
|
||||
]
|
||||
create_formdata.parent = st2
|
||||
st2.items.append(create_formdata)
|
||||
workflow.store()
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
||||
assert (
|
||||
'<ul class="mappings"><li>string → =form_var_toto_string</li>'
|
||||
'<li>file → =form_var_toto_file_raw</li>'
|
||||
'<li>#2 → =form_var_foobar_raw</li></ul>'
|
||||
) in resp.text
|
||||
|
||||
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
|
||||
workflow.backoffice_fields_formdef.fields = [
|
||||
fields.StringField(id='bo1', label='Foo Bar 1', varname='foo_bar'),
|
||||
fields.StringField(id='bo2', label='Foo Bar 2', varname='foo_bar'),
|
||||
fields.StringField(id='bo3', label='Foo Bar 3', varname='foo_bar'),
|
||||
]
|
||||
setbo = SetBackofficeFieldsWorkflowStatusItem()
|
||||
setbo.parent = st2
|
||||
setbo.fields = [
|
||||
{'field_id': 'bo1', 'value': 'go'},
|
||||
{'field_id': 'bo2', 'value': ''},
|
||||
{'field_id': 'bo3', 'value': None},
|
||||
{'field_id': 'unknown', 'value': 'foobar'},
|
||||
]
|
||||
st2.items.append(setbo)
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
||||
assert (
|
||||
'<ul class="fields"><li>Foo Bar 1 → go</li>'
|
||||
'<li>Foo Bar 2 → </li>'
|
||||
'<li>Foo Bar 3 → None</li>'
|
||||
'<li>#unknown → foobar</li></ul>'
|
||||
) in resp.text
|
||||
|
||||
st3 = workflow.add_status('Status3', 'st3')
|
||||
export_to = ExportToModel()
|
||||
export_to.convert_to_pdf = False
|
||||
export_to.label = 'create doc'
|
||||
upload = QuixoteUpload('/foo/test.rtf', content_type='application/rtf')
|
||||
upload.fp = io.BytesIO()
|
||||
upload.fp.write(b'HELLO WORLD')
|
||||
upload.fp.seek(0)
|
||||
export_to.model_file = UploadedFile(pub.app_dir, None, upload)
|
||||
export_to.id = '_export_to'
|
||||
export_to.by = ['_submitter']
|
||||
st3.items.append(export_to)
|
||||
export_to.parent = st3
|
||||
workflow.store()
|
||||
|
||||
resp = app.get('/backoffice/workflows/%s/inspect' % workflow.id)
|
||||
assert (
|
||||
'<li><span class="parameter">Model:</span> '
|
||||
'<a href="status/st3/items/_export_to/?file=model_file">test.rtf</a></li>'
|
||||
) in resp.text
|
Loading…
Reference in New Issue