wcs/tests/admin_pages/test_card.py

925 lines
33 KiB
Python

import os
import re
import xml.etree.ElementTree as ET
import pytest
from webtest import Upload
from wcs import fields
from wcs.admin.settings import UserFieldsFormDef
from wcs.blocks import BlockDef
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 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 pub_fixture(**kwargs):
pub = create_temporary_pub(**kwargs)
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
@pytest.fixture
def pub(request, emails):
return pub_fixture(sql_mode=True)
@pytest.fixture
def nosql_pub(request, emails):
return pub_fixture()
def teardown_module(module):
clean_temporary_pub()
def test_cards_list(pub):
create_superuser(pub)
role = pub.role_class(name='foobar')
role.store()
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):
create_superuser(pub)
CardDef.wipe()
carddef = CardDef()
carddef.name = 'card title'
carddef.fields = []
carddef.store()
carddef2 = CardDef()
carddef2.name = 'card title'
carddef2.fields = []
carddef2.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = []
formdef.store()
pub.custom_view_class.wipe()
custom_view = pub.custom_view_class()
custom_view.title = 'foo'
custom_view.formdef = carddef
custom_view.store()
custom_view2 = pub.custom_view_class()
custom_view2.title = 'foo'
custom_view2.formdef = carddef2
custom_view2.store()
custom_view3 = pub.custom_view_class()
custom_view3.title = 'foo'
custom_view3.formdef = formdef
custom_view3.store()
carddata = carddef.data_class()()
carddata.just_created()
carddata.data = {}
carddata.store()
app = login(get_app(pub))
resp = app.get('http://example.net/backoffice/cards/1/')
resp = resp.click('Delete')
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() == 1
assert CardDef.select()[0].id == carddef2.id
assert pub.custom_view_class.count() == 2
assert pub.custom_view_class.get(custom_view2.id)
assert pub.custom_view_class.get(custom_view3.id)
carddata.remove_self() # don't keep leftovers
def test_cards_delete_nosql(nosql_pub):
pub = nosql_pub
create_superuser(pub)
CardDef.wipe()
carddef = CardDef()
carddef.name = 'card title'
carddef.fields = []
carddef.store()
carddata = carddef.data_class()()
carddata.just_created()
carddata.data = {}
carddata.store()
app = login(get_app(pub))
resp = app.get('http://example.net/backoffice/cards/1/')
resp = resp.click('Delete')
assert 'Deletion is not possible as there are cards.' not in resp
assert 'delete-button' in resp.text
def test_cards_in_use_delete(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'card title'
carddef.fields = []
carddef.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.ItemField(id='0', label='string', type='item', data_source={'type': 'carddef:card-title'}),
]
formdef.store()
create_superuser(pub)
app = login(get_app(pub))
resp = app.get('http://example.net/backoffice/cards/1/')
resp = resp.click('Delete')
assert 'Deletion is not possible as it is still used as datasource.' in resp.text
assert 'delete-button' not in resp.text
formdef.fields = []
formdef.store()
resp = app.get('http://example.net/backoffice/cards/1/')
resp = resp.click('Delete')
assert 'delete-button' in resp.text
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 resp.form['name'].value == 'card title (copy)'
resp = resp.form.submit('submit')
assert CardDef.get(2).name == 'card title (copy)'
assert CardDef.get(2).url_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_templates['default'] == '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_templates['default'] == '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_templates = {'default': '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_templates['default'] 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).digests['default'] == 'XbarY'
carddef.digest_templates = {'default': '{{ 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_templates['default'] 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_templates = {'default': '{{ 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 = baz_status.add_action('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'})
)
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()
def test_card_management_view(pub):
create_superuser(pub)
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = []
carddef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/cards/1/')
assert 'backoffice/data/foo/' in resp
def test_card_category_management_roles(pub, backoffice_user, backoffice_role):
app = login(get_app(pub), username='backoffice-user', password='backoffice-user')
app.get('/backoffice/cards/', status=403)
CardDefCategory.wipe()
cat = CardDefCategory(name='Foo')
cat.store()
CardDef.wipe()
carddef = CardDef()
carddef.name = 'card title'
carddef.category_id = cat.id
carddef.fields = []
carddef.store()
cat = CardDefCategory(name='Bar')
cat.management_roles = [backoffice_role]
cat.store()
resp = app.get('/backoffice/cards/')
assert 'Foo' not in resp.text # not a category managed by user
assert 'card title' not in resp.text # carddef in that category
assert 'Bar' not in resp.text # not yet any form in this category
resp = resp.click('New Card')
resp.forms[0]['name'] = 'card in category'
assert len(resp.forms[0]['category_id'].options) == 1 # single option
assert resp.forms[0]['category_id'].value == cat.id # the category managed by user
resp = resp.forms[0].submit().follow()
new_carddef = CardDef.get_by_urlname('card-in-category')
# check category select only let choose one
resp = resp.click(href='/category')
assert len(resp.forms[0]['category_id'].options) == 1 # single option
assert resp.forms[0]['category_id'].value == cat.id # the category managed by user
resp = app.get('/backoffice/cards/')
assert 'Bar' in resp.text # now there's a form in this category
assert 'card in category' in resp.text
# no access to subdirectories
assert 'href="categories/"' not in resp.text
app.get('/backoffice/cards/categories/', status=403)
# no import into other category
carddef_xml = ET.tostring(carddef.export_to_xml(include_id=True))
resp = resp.click(href='import')
resp.forms[0]['file'] = Upload('carddef.wcs', carddef_xml)
resp = resp.forms[0].submit()
assert 'Invalid File (unauthorized category)' in resp.text
# check access to inspect page
carddef.workflow_roles = {'_viewer': str(backoffice_role.id)}
carddef.store()
carddata = carddef.data_class()()
carddata.just_created()
carddata.store()
resp = app.get(carddata.get_backoffice_url())
assert 'inspect' not in resp.text
resp = app.get(carddata.get_backoffice_url() + 'inspect', status=403)
new_carddef.workflow_roles = {'_viewer': str(backoffice_role.id)}
new_carddef.store()
carddata = new_carddef.data_class()()
carddata.just_created()
carddata.store()
resp = app.get(carddata.get_backoffice_url())
assert 'inspect' in resp.text
resp = app.get(carddata.get_backoffice_url() + 'inspect')
def test_cards_svg(pub):
create_superuser(pub)
CardDefCategory.wipe()
cat1 = CardDefCategory(name='Foo')
cat1.store()
cat2 = CardDefCategory(name='Foo')
cat2.store()
ds1 = {'type': 'carddef:card-1-2'}
ds2 = {'type': 'carddef:card-2-2'}
ds3 = {'type': 'carddef:card-3-2'}
BlockDef.wipe()
block1 = BlockDef()
block1.name = 'block 1'
block1.fields = [
fields.StringField(id='1', label='string', type='string', varname='block foo 1', data_source=ds1),
fields.ItemField(id='2', label='item', type='item', varname='block foo 2', data_source=ds1),
fields.ItemsField(id='3', label='items', type='items', varname='block foo 3', data_source=ds1),
fields.ComputedField(
id='4', label='computed', type='computed', varname='block foo 4', data_source=ds1
),
fields.StringField(id='10', label='string', type='string', varname='block fooo 10', data_source=ds2),
fields.ItemField(id='20', label='item', type='item', varname='block fooo 20', data_source=ds2),
fields.ItemsField(id='30', label='items', type='items', varname='block fooo 30', data_source=ds2),
fields.ComputedField(
id='40', label='computed', type='computed', varname='block fooo 40', data_source=ds2
),
]
block1.store()
block2 = BlockDef()
block2.name = 'block 2'
block2.fields = [
fields.StringField(id='1', label='string', type='string', varname='block bar 1', data_source=ds2),
fields.ItemField(id='2', label='item', type='item', varname='block bar 2', data_source=ds2),
fields.ItemsField(id='3', label='items', type='items', varname='block bar 3', data_source=ds2),
fields.ComputedField(
id='4', label='computed', type='computed', varname='block bar 4', data_source=ds2
),
]
block2.store()
block3 = BlockDef()
block3.name = 'block 3'
block3.fields = [
fields.StringField(id='1', label='string', type='string', varname='block baz 1', data_source=ds3),
fields.ItemField(id='2', label='item', type='item', varname='block baz 2', data_source=ds3),
fields.ItemsField(id='3', label='items', type='items', varname='block baz 3', data_source=ds3),
fields.ComputedField(
id='4', label='computed', type='computed', varname='block baz 4', data_source=ds3
),
]
block3.store()
CardDef.wipe()
carddef11 = CardDef()
carddef11.name = 'card 1-1'
carddef11.category_id = cat1.id
carddef11.fields = [
fields.StringField(id='1', label='string', type='string', varname='foo 1', data_source=ds1),
fields.ItemField(id='2', label='item', type='item', varname='foo 2', data_source=ds1),
fields.ItemsField(id='3', label='items', type='items', varname='foo 3', data_source=ds1),
fields.ComputedField(id='4', label='computed', type='computed', varname='foo 4', data_source=ds1),
fields.BlockField(id='5', label='block', type='block:%s' % block1.slug),
fields.StringField(id='10', label='string', type='string', varname='fooo 10', data_source=ds2),
fields.ItemField(id='20', label='item', type='item', varname='fooo 20', data_source=ds2),
fields.ItemsField(id='30', label='items', type='items', varname='fooo 30', data_source=ds2),
fields.ComputedField(id='40', label='computed', type='computed', varname='fooo 40', data_source=ds2),
fields.BlockField(id='50', label='block', type='block:%s' % block2.slug),
]
carddef11.store()
carddef12 = CardDef()
carddef12.name = 'card 1-2'
carddef12.category_id = cat1.id
carddef12.fields = []
carddef12.store()
carddef13 = CardDef()
carddef13.name = 'card 1-3'
carddef13.category_id = cat1.id
carddef13.fields = []
carddef13.store()
carddef21 = CardDef()
carddef21.name = 'card 2-1'
carddef21.category_id = cat2.id
carddef21.fields = [
fields.StringField(id='1', label='string', type='string', varname='bar 1', data_source=ds2),
fields.ItemField(id='2', label='item', type='item', varname='bar 2', data_source=ds2),
fields.ItemsField(id='3', label='items', type='items', varname='bar 3', data_source=ds2),
fields.ComputedField(id='4', label='computed', type='computed', varname='bar 4', data_source=ds2),
fields.BlockField(id='5', label='block', type='block:%s' % block2.slug),
]
carddef21.store()
carddef22 = CardDef()
carddef22.name = 'card 2-2'
carddef22.category_id = cat2.id
carddef22.fields = []
carddef22.store()
carddef31 = CardDef()
carddef31.name = 'card 3-1'
carddef31.fields = [
fields.StringField(id='1', label='string', type='string', varname='baz 1', data_source=ds3),
fields.ItemField(id='2', label='item', type='item', varname='baz 2', data_source=ds3),
fields.ItemsField(id='3', label='items', type='items', varname='baz 3', data_source=ds3),
fields.ComputedField(id='4', label='computed', type='computed', varname='baz 4', data_source=ds3),
fields.BlockField(id='5', label='block', type='block:%s' % block3.slug),
]
carddef31.store()
carddef32 = CardDef()
carddef32.name = 'card 3-2'
carddef32.fields = []
carddef32.store()
app = login(get_app(pub))
resp = app.get('/backoffice/cards/svg')
# cards
assert '<title>card_card_1_1</title' in resp
assert (
'xlink:href="http://example.net/backoffice/cards/%s/" xlink:title="&lt;card&gt;card 1&#45;1"'
% carddef11.id
in resp
)
assert '<title>card_card_1_2</title' in resp
assert '<title>card_card_1_3</title' not in resp
assert '<title>card_card_2_1</title' in resp
assert '<title>card_card_2_2</title' in resp
assert '<title>card_card_3_1</title' in resp
assert '<title>card_card_3_2</title' in resp
# and relations
assert resp.text.count('<title>card_card_1_1&#45;&gt;card_card_1_2</title>') == 8
assert resp.text.count('<title>card_card_1_1&#45;&gt;card_card_2_2</title>') == 12
assert resp.text.count('<title>card_card_2_1&#45;&gt;card_card_2_2</title>') == 8
assert resp.text.count('<title>card_card_3_1&#45;&gt;card_card_3_2</title>') == 8
resp = app.get('/backoffice/cards/svg?show-orphans=on')
assert '<title>card_card_1_3</title' in resp
resp = app.get('/backoffice/cards/categories/%s/svg' % cat1.id)
# cards
assert '<title>card_card_1_1</title' in resp
assert (
'xlink:href="http://example.net/backoffice/cards/%s/" xlink:title="&lt;card&gt;card 1&#45;1"'
% carddef11.id
in resp
)
assert '<title>card_card_1_2</title' in resp
assert '<title>card_card_1_3</title' not in resp
assert '<title>card_card_2_1</title' not in resp
assert '<title>card_card_2_2</title' not in resp
assert '<title>card_card_3_1</title' not in resp
assert '<title>card_card_3_2</title' not in resp
# and relations
assert resp.text.count('<title>card_card_1_1&#45;&gt;card_card_1_2</title>') == 8
assert resp.text.count('<title>card_card_1_1&#45;&gt;card_card_2_2</title>') == 0
assert resp.text.count('<title>card_card_2_1&#45;&gt;card_card_2_2</title>') == 0
assert resp.text.count('<title>card_card_3_1&#45;&gt;card_card_3_2</title>') == 0
resp = app.get('/backoffice/cards/categories/%s/svg?show-orphans=on' % cat1.id)
assert '<title>card_card_1_3</title' in resp
resp = app.get('/backoffice/cards/categories/%s/svg' % cat2.id)
# cards
assert '<title>card_card_1_1</title' not in resp
assert '<title>card_card_1_2</title' not in resp
assert '<title>card_card_2_1</title' in resp
assert '<title>card_card_2_2</title' in resp
assert '<title>card_card_3_1</title' not in resp
assert '<title>card_card_3_2</title' not in resp
# and relations
assert resp.text.count('<title>card_card_1_1&#45;&gt;card_card_1_2</title>') == 0
assert resp.text.count('<title>card_card_1_1&#45;&gt;card_card_2_2</title>') == 0
assert resp.text.count('<title>card_card_2_1&#45;&gt;card_card_2_2</title>') == 8
assert resp.text.count('<title>card_card_3_1&#45;&gt;card_card_3_2</title>') == 0
def test_card_edit_field_warnings(pub):
create_superuser(pub)
if not pub.site_options.has_section('options'):
pub.site_options.add_section('options')
pub.site_options.set('options', 'ignore-hard-limits', 'false')
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
pub.site_options.write(fd)
CardDef.wipe()
carddef = CardDef()
carddef.name = 'card title'
carddef.fields = [
fields.StringField(id='%d' % i, label='field %d' % i, type='string') for i in range(1, 10)
]
carddef.store()
app = login(get_app(pub))
resp = app.get('/backoffice/cards/%s/fields/' % carddef.id)
assert 'more than 200 fields' not in resp.text
assert 'first field should be of type "page"' not in resp.text
carddef.fields.append(fields.PageField(id='1000', label='page', type='page'))
carddef.store()
resp = app.get('/backoffice/cards/%s/fields/' % carddef.id)
assert 'more than 200 fields' not in resp.text
assert 'first field should be of type "page"' in resp.text
assert '<div id="new-field"><h3>New Field</h3>' in resp.text
carddef.fields.extend(
[fields.StringField(id='%d' % i, label='field %d' % i, type='string') for i in range(10, 210)]
)
carddef.store()
resp = app.get('/backoffice/cards/%s/fields/' % carddef.id)
assert 'more than 200 fields' in resp.text
assert 'first field should be of type "page"' in resp.text
assert '>Duplicate<' in resp.text
carddef.fields.extend(
[fields.StringField(id='%d' % i, label='field %d' % i, type='string') for i in range(210, 310)]
)
carddef.store()
resp = app.get('/backoffice/cards/%s/fields/' % carddef.id)
assert 'This card model contains 310 fields.' in resp.text
assert 'first field should be of type "page"' in resp.text
assert '<div id="new-field"><h3>New Field</h3>' not in resp.text
assert '>Duplicate<' not in resp.text