523 lines
18 KiB
Python
523 lines
18 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import re
|
|
|
|
import pytest
|
|
|
|
from wcs import fields
|
|
from wcs.admin.settings import UserFieldsFormDef
|
|
from wcs.carddef import CardDef
|
|
from wcs.categories import CardDefCategory
|
|
from wcs.formdef import FormDef
|
|
from wcs.qommon.http_request import HTTPRequest
|
|
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
|
|
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef, WorkflowVariablesFieldsFormDef
|
|
|
|
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', 'pickle-templates'], indirect=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def pub(request):
|
|
pub = create_temporary_pub(
|
|
sql_mode=bool('sql' in request.param), templates_mode=bool('templates' in request.param)
|
|
)
|
|
|
|
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()
|
|
|
|
return pub
|
|
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
|
|
def test_cards_list(pub):
|
|
create_superuser(pub)
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'card title'
|
|
carddef.fields = []
|
|
carddef.store()
|
|
|
|
carddef2 = CardDef()
|
|
carddef2.name = 'card title 2'
|
|
carddef2.fields = []
|
|
carddef2.store()
|
|
|
|
CardDefCategory.wipe()
|
|
cat = CardDefCategory(name='Foo')
|
|
cat.store()
|
|
cat2 = CardDefCategory(name='Bar')
|
|
cat2.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/')
|
|
assert '<h2>Misc</h2>' not in resp.text
|
|
assert '<h2>Foo</h2>' not in resp.text
|
|
assert '<h2>Bar</h2>' not in resp.text
|
|
|
|
carddef.category = cat2
|
|
carddef.store()
|
|
resp = app.get('/backoffice/cards/')
|
|
assert '<h2>Misc</h2>' in resp.text
|
|
assert '<h2>Foo</h2>' not in resp.text
|
|
assert '<h2>Bar</h2>' in resp.text
|
|
|
|
carddef2.category = cat
|
|
carddef2.store()
|
|
resp = app.get('/backoffice/cards/')
|
|
assert '<h2>Misc</h2>' not in resp.text
|
|
assert '<h2>Foo</h2>' in resp.text
|
|
assert '<h2>Bar</h2>' in resp.text
|
|
|
|
|
|
def test_cards_new(pub):
|
|
CardDef.wipe()
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/')
|
|
resp = resp.click('New Card Model')
|
|
resp.form['name'] = 'card title'
|
|
resp = resp.form.submit()
|
|
assert resp.location == 'http://example.net/backoffice/cards/1/'
|
|
resp = resp.follow()
|
|
assert '<h2>card title' in resp.text
|
|
assert CardDef.get(1).workflow_id is None
|
|
assert CardDef.get(1).disabled is False
|
|
|
|
|
|
def test_cards_delete(pub):
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'card title'
|
|
carddef.fields = []
|
|
carddef.store()
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
|
|
carddata = carddef.data_class()()
|
|
carddata.just_created()
|
|
carddata.data = {}
|
|
carddata.store()
|
|
|
|
resp = app.get('http://example.net/backoffice/cards/1/')
|
|
resp = resp.click('Delete')
|
|
if pub.is_using_postgresql():
|
|
assert 'Deletion is not possible as there are cards.' in resp
|
|
carddef.data_class().wipe()
|
|
resp = app.get('http://example.net/backoffice/cards/1/')
|
|
resp = resp.click('Delete')
|
|
|
|
resp = resp.form.submit('submit')
|
|
assert CardDef.count() == 0
|
|
|
|
carddata.remove_self() # don't keep leftovers
|
|
|
|
|
|
def test_cards_duplicate(pub):
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'card title'
|
|
carddef.fields = []
|
|
carddef.store()
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('http://example.net/backoffice/cards/1/')
|
|
resp = resp.click('Duplicate')
|
|
assert CardDef.get(2).name == 'card title (copy)'
|
|
assert CardDef.get(2).disabled is False
|
|
|
|
|
|
def test_card_workflow_change(pub):
|
|
Workflow.wipe()
|
|
workflow = Workflow(name='Workflow Two')
|
|
workflow.add_status('plop')
|
|
workflow.store()
|
|
|
|
CardDef.wipe()
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/')
|
|
resp = resp.click('New Card Model')
|
|
resp.form['name'] = 'card title'
|
|
resp = resp.form.submit()
|
|
resp = resp.follow()
|
|
resp = resp.click(href='workflow', index=1)
|
|
assert resp.form['workflow_id'].options[0][2] == 'Default (cards)'
|
|
resp = resp.form.submit('submit').follow()
|
|
assert CardDef.select()[0].workflow_id is None
|
|
|
|
carddata = CardDef.select()[0].data_class()()
|
|
carddata.status = 'wf-recorded'
|
|
carddata.store()
|
|
|
|
resp = resp.click(href='workflow', index=1)
|
|
resp.form['workflow_id'] = '%s' % workflow.id
|
|
resp = resp.form.submit('submit')
|
|
assert (
|
|
resp.location
|
|
== 'http://example.net/backoffice/cards/1/workflow-status-remapping?new=%s' % workflow.id
|
|
)
|
|
resp = resp.follow()
|
|
resp = resp.form.submit('submit').follow()
|
|
|
|
resp = resp.click(href='workflow', index=1)
|
|
resp.form['workflow_id'] = ''
|
|
resp = resp.form.submit('submit')
|
|
assert (
|
|
resp.location
|
|
== 'http://example.net/backoffice/cards/1/workflow-status-remapping?new=%s' % '_carddef_default'
|
|
)
|
|
resp = resp.follow()
|
|
resp = resp.form.submit('submit').follow()
|
|
|
|
|
|
def assert_option_display(resp, label, value):
|
|
option_line = re.findall('%s.*%s' % (label, value), resp.text, re.DOTALL)
|
|
assert option_line
|
|
assert '</li>' not in option_line
|
|
|
|
|
|
def test_card_templates(pub):
|
|
create_superuser(pub)
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.fields = [
|
|
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
|
]
|
|
carddef.store()
|
|
carddata = carddef.data_class()()
|
|
carddata.data = {'1': 'bar'}
|
|
carddata.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/1/')
|
|
|
|
assert_option_display(resp, 'Templates', 'None')
|
|
assert resp.pyquery('[href="options/templates"]').attr.rel == '' # no popup
|
|
resp = resp.click('Templates')
|
|
resp.form['digest_template'] = 'X{{form_var_test}}Y'
|
|
resp = resp.form.submit()
|
|
assert resp.location == 'http://example.net/backoffice/cards/1/'
|
|
resp = resp.follow()
|
|
assert_option_display(resp, 'Templates', 'Custom')
|
|
carddef = CardDef.get(carddef.id)
|
|
assert carddef.digest_template == 'X{{form_var_test}}Y'
|
|
assert carddef.lateral_template is None
|
|
assert carddef.submission_lateral_template is None
|
|
assert 'Existing cards will be updated in the background.' in resp.text
|
|
|
|
resp = app.get('/backoffice/cards/1/options/templates')
|
|
resp.form['lateral_template'] = 'X{{form_var_test}}Y'
|
|
resp.form['submission_lateral_template'] = 'X{{form_var_test}}YZ'
|
|
resp = resp.form.submit().follow()
|
|
assert_option_display(resp, 'Templates', 'Custom')
|
|
carddef = CardDef.get(carddef.id)
|
|
assert carddef.digest_template == 'X{{form_var_test}}Y'
|
|
assert carddef.lateral_template == 'X{{form_var_test}}Y'
|
|
assert carddef.submission_lateral_template == 'X{{form_var_test}}YZ'
|
|
assert 'Existing cards will be updated in the background.' not in resp.text
|
|
|
|
|
|
def test_card_digest_template(pub):
|
|
create_superuser(pub)
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.fields = [
|
|
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
|
]
|
|
carddef.digest_template = 'X{{ form_var_foo }}Y'
|
|
carddef.store()
|
|
carddata = carddef.data_class()()
|
|
carddata.data = {'1': 'bar'}
|
|
carddata.store()
|
|
|
|
custom_view = pub.custom_view_class()
|
|
custom_view.title = 'card view'
|
|
custom_view.formdef = carddef
|
|
custom_view.columns = {'list': [{'id': 'id'}]}
|
|
custom_view.filters = {'filter-1': True, 'filter-1-value': 'FOO'}
|
|
custom_view.visibility = 'datasource'
|
|
custom_view.store()
|
|
|
|
# carddef not used in formdef, it's ok to empty digest_template
|
|
FormDef.wipe()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/%s/options/templates' % carddef.id)
|
|
resp.form['digest_template'] = ''
|
|
resp = resp.form.submit().follow()
|
|
carddef = CardDef.get(carddef.id)
|
|
assert carddef.digest_template is None
|
|
assert 'Existing cards will be updated in the background.' in resp.text
|
|
|
|
# afterjobs are actually run synchronously during tests; we don't have
|
|
# to wait to check the digest has been updated:
|
|
assert carddef.data_class().get(carddata.id).digest == 'XbarY'
|
|
|
|
carddef.digest_template = '{{ form_var_foo }}'
|
|
carddef.store()
|
|
|
|
# a formdef using the carddef as datasource
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test card def on data source'
|
|
formdef.fields = [fields.ItemField(id='1', label='item', data_source={'type': 'carddef:foo'})]
|
|
formdef.store()
|
|
|
|
# carddef used in formdef, can not empty digest_template
|
|
resp = app.get('/backoffice/cards/%s/options/templates' % carddef.id)
|
|
resp.form['digest_template'] = ''
|
|
resp = resp.form.submit()
|
|
assert 'Can not empty digest template: this card model is used as data source in some forms.' in resp.text
|
|
carddef = CardDef.get(carddef.id)
|
|
assert carddef.digest_template is not None
|
|
|
|
# error: not stored, and no after jobs
|
|
resp = app.get('/backoffice/cards/%s/' % carddef.id)
|
|
assert 'Existing cards will be updated in the background.' not in resp.text
|
|
|
|
|
|
def test_card_category(pub):
|
|
create_superuser(pub)
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'card title'
|
|
carddef.fields = []
|
|
carddef.store()
|
|
|
|
CardDefCategory.wipe()
|
|
cat = CardDefCategory(name='Foo')
|
|
cat.store()
|
|
cat = CardDefCategory(name='Bar')
|
|
cat.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/1/')
|
|
assert '<span class="label">Category</span> <span class="value">None</span>' in resp.text
|
|
assert '<span class="label">Category</span> <span class="value">Foo</span>' not in resp.text
|
|
assert '<span class="label">Category</span> <span class="value">Bar</span>' not in resp.text
|
|
resp = resp.click(href='category')
|
|
resp.forms[0].submit('cancel')
|
|
assert CardDef.get(carddef.id).category_id is None
|
|
|
|
resp = app.get('/backoffice/cards/1/')
|
|
assert '<span class="label">Category</span> <span class="value">None</span>' in resp.text
|
|
assert '<span class="label">Category</span> <span class="value">Foo</span>' not in resp.text
|
|
assert '<span class="label">Category</span> <span class="value">Bar</span>' not in resp.text
|
|
resp = resp.click(href='category')
|
|
resp.forms[0]['category_id'] = cat.id
|
|
resp.forms[0].submit('submit')
|
|
assert CardDef.get(carddef.id).category_id == cat.id
|
|
|
|
resp = app.get('/backoffice/cards/1/')
|
|
assert '<span class="label">Category</span> <span class="value">None</span>' not in resp.text
|
|
assert '<span class="label">Category</span> <span class="value">Foo</span>' not in resp.text
|
|
assert '<span class="label">Category</span> <span class="value">Bar</span>' in resp.text
|
|
|
|
|
|
def test_card_user_support(pub):
|
|
create_superuser(pub)
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'card title'
|
|
carddef.fields = []
|
|
carddef.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/cards/1/')
|
|
assert '<span class="label">User support</span> <span class="value">No</span>' in resp.text
|
|
resp = resp.click(href='user_support')
|
|
resp.forms[0]['user_support'] = 'optional'
|
|
resp.forms[0].submit('submit')
|
|
assert CardDef.get(carddef.id).user_support == 'optional'
|
|
|
|
resp = app.get('/backoffice/cards/1/')
|
|
assert '<span class="label">User support</span> <span class="value">Optional</span>' in resp.text
|
|
|
|
|
|
def test_card_custom_view_data_source(pub):
|
|
user = create_superuser(pub)
|
|
pub.role_class.wipe()
|
|
role = pub.role_class(name='foobar')
|
|
role.store()
|
|
user.roles = [role.id]
|
|
user.store()
|
|
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.fields = [
|
|
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
|
]
|
|
carddef.backoffice_submission_roles = user.roles
|
|
carddef.workflow_roles = {'_editor': user.roles[0]}
|
|
carddef.digest_template = '{{ form_var_foo }}'
|
|
carddef.store()
|
|
carddef.data_class().wipe()
|
|
|
|
for i in range(3):
|
|
carddata = carddef.data_class()()
|
|
carddata.just_created()
|
|
if i == 0:
|
|
carddata.data = {'1': 'BAR'}
|
|
else:
|
|
carddata.data = {'1': 'FOO'}
|
|
if i == 1:
|
|
carddata.jump_status('deleted')
|
|
carddata.store()
|
|
|
|
pub.custom_view_class.wipe()
|
|
custom_view = pub.custom_view_class()
|
|
custom_view.title = 'card view'
|
|
custom_view.formdef = carddef
|
|
custom_view.columns = {'list': [{'id': 'id'}]}
|
|
custom_view.filters = {'filter-1': True, 'filter-1-value': 'FOO'}
|
|
custom_view.visibility = 'datasource'
|
|
custom_view.store()
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'form title'
|
|
formdef.fields = [
|
|
fields.ItemField(id='1', label='field', type='item', varname='foo'),
|
|
]
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/forms/%s/fields/1/' % formdef.id)
|
|
assert 'carddef:foo' in [x[0] for x in resp.form['data_source$type'].options]
|
|
assert 'carddef:foo:card-view' in [x[0] for x in resp.form['data_source$type'].options]
|
|
|
|
assert len(CardDef.get_data_source_items('carddef:foo')) == 3
|
|
assert len(CardDef.get_data_source_items('carddef:foo:card-view')) == 2
|
|
|
|
custom_view.filters = {'filter-1': True, 'filter-1-value': 'FOO', 'filter-status': 'on', 'filter': 'done'}
|
|
custom_view.store()
|
|
assert len(CardDef.get_data_source_items('carddef:foo:card-view')) == 1
|
|
|
|
|
|
def test_carddef_usage(pub):
|
|
user = create_superuser(pub)
|
|
pub.role_class.wipe()
|
|
role = pub.role_class(name='foobar')
|
|
role.store()
|
|
user.roles = [role.id]
|
|
user.store()
|
|
|
|
# the one used as data source
|
|
CardDef.wipe()
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.fields = [
|
|
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
|
]
|
|
carddef.workflow_roles = {'_editor': user.roles[0]}
|
|
carddef.store()
|
|
|
|
# another one
|
|
carddef2 = CardDef()
|
|
carddef2.name = 'foobar' # url_name startswith 'foo'
|
|
carddef2.fields = [
|
|
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
|
]
|
|
carddef2.store()
|
|
|
|
# custom view
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/data/foo/')
|
|
resp = resp.forms['listing-settings'].submit()
|
|
resp.forms['save-custom-view']['title'] = 'card view'
|
|
resp = resp.forms['save-custom-view'].submit()
|
|
|
|
# a formdef using the carddef as datasource
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test card def on data source'
|
|
formdef.fields = [fields.ItemField(id='1', label='item', data_source={'type': 'carddef:foo'})]
|
|
formdef.store()
|
|
# another using the custom view
|
|
formdef2 = FormDef()
|
|
formdef2.name = 'test card def on data source2'
|
|
formdef2.fields = [fields.ItemField(id='1', label='item', data_source={'type': 'carddef:foo:card-view'})]
|
|
formdef2.store()
|
|
# another, using the other carddef as datasource
|
|
formdef3 = FormDef()
|
|
formdef3.name = 'test card def on data source2'
|
|
formdef3.fields = [
|
|
fields.ItemField(
|
|
id='1', label='item', data_source={'type': 'carddef:foobar'}
|
|
) # startswith carddef:foo
|
|
]
|
|
formdef3.store()
|
|
|
|
# user form
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields.append(
|
|
fields.ItemField(id='1', type='item', label='item', data_source={'type': 'carddef:foo'})
|
|
)
|
|
user_formdef.store()
|
|
|
|
# workflow
|
|
Workflow.wipe()
|
|
workflow = Workflow(name='Workflow One')
|
|
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
|
|
workflow.variables_formdef.fields.append(
|
|
fields.ItemField(id='1', type='idem', label='item', data_source={'type': 'carddef:foo'})
|
|
)
|
|
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
|
|
workflow.backoffice_fields_formdef.fields.append(
|
|
fields.ItemField(id='1', type='item', label='item', data_source={'type': 'carddef:foo'})
|
|
)
|
|
|
|
baz_status = workflow.add_status(name='baz')
|
|
display_form = FormWorkflowStatusItem()
|
|
display_form.id = '_x'
|
|
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
|
display_form.formdef.fields.append(
|
|
fields.ItemField(id='1', type='item', label='item', data_source={'type': 'carddef:foo'})
|
|
)
|
|
baz_status.items.append(display_form)
|
|
display_form.parent = baz_status
|
|
|
|
workflow.store()
|
|
|
|
# carddef
|
|
carddef3 = CardDef()
|
|
carddef3.name = 'Baz'
|
|
carddef3.fields = [fields.ItemField(id='1', label='item', data_source={'type': 'carddef:foo'})]
|
|
carddef3.store()
|
|
|
|
resp = app.get('http://example.net/backoffice/cards/1/')
|
|
assert 'This card model is used as data source in the following forms' in resp.text
|
|
assert '/backoffice/forms/%s/' % formdef.id in resp.text
|
|
assert '/backoffice/forms/%s/' % formdef2.id in resp.text
|
|
assert '/backoffice/forms/%s/' % formdef3.id not in resp.text # no, not the good one
|
|
assert '/backoffice/workflows/%s/backoffice-fields/fields/' % workflow.id in resp.text
|
|
assert '/backoffice/workflows/%s/variables/fields/' % workflow.id in resp.text
|
|
assert '/backoffice/workflows/%s/status/1/items/_x/fields/' % workflow.id in resp.text
|
|
assert '/backoffice/settings/users/fields/' in resp.text
|
|
assert '/backoffice/cards/%s/' % carddef3.id in resp.text
|
|
|
|
# cleanup
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields = []
|
|
user_formdef.store()
|