wcs/tests/test_carddef.py

952 lines
34 KiB
Python

import io
import xml.etree.ElementTree as ET
import pytest
from wcs.blocks import BlockDef
from wcs.carddef import CardDef
from wcs.categories import CardDefCategory
from wcs.fields import BlockField, ComputedField, ItemField, ItemsField, StringField
from wcs.formdef import FormDef
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.misc import indent_xml as indent
from wcs.qommon.template import Template
from .utilities import clean_temporary_pub, create_temporary_pub
@pytest.fixture
def pub(request):
pub = create_temporary_pub(sql_mode=True)
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
pub.set_app_dir(req)
pub.cfg['language'] = {'language': 'en'}
pub.write_cfg()
return pub
def teardown_module(module):
clean_temporary_pub()
def export_to_indented_xml(carddef, include_id=False):
carddef_xml = ET.fromstring(ET.tostring(carddef.export_to_xml(include_id=include_id)))
indent(carddef_xml)
return carddef_xml
def assert_compare_carddef(carddef1, carddef2, include_id=False):
assert ET.tostring(export_to_indented_xml(carddef1, include_id=include_id)) == ET.tostring(
export_to_indented_xml(carddef2, include_id=include_id)
)
assert carddef1.export_to_json(include_id=include_id, indent=2) == carddef2.export_to_json(
include_id=include_id, indent=2
)
def assert_xml_import_export_works(carddef, include_id=False):
carddef_xml = carddef.export_to_xml(include_id=include_id)
carddef2 = CardDef.import_from_xml_tree(carddef_xml, include_id=include_id)
assert_compare_carddef(carddef, carddef2, include_id=include_id)
return carddef2
def test_basics(pub):
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.store()
assert CardDef.get(carddef.id).name == 'foo'
carddata_class = carddef.data_class()
carddata = carddata_class()
carddata.data = {'1': 'hello world'}
carddata.just_created()
carddata.store()
assert carddata.status == 'wf-recorded'
assert carddata_class.get(carddata.id).data['1'] == 'hello world'
assert carddata_class.get(carddata.id).status == 'wf-recorded'
def test_advertised_urls(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.store()
assert CardDef.get(carddef.id).name == 'foo'
assert carddef.get_url() == 'http://example.net/backoffice/data/foo/'
assert carddef.get_backoffice_submission_url() == 'http://example.net/backoffice/data/foo/add/'
assert carddef.get_admin_url() == 'http://example.net/backoffice/cards/%s/' % carddef.id
assert carddef.get_api_url() == 'http://example.net/api/cards/foo/'
def test_xml_export_import(pub):
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
ItemField(id='2', label='card field', type='item', data_source={'type': 'carddef:foo'}),
]
carddef.store()
# define also custom views
pub.custom_view_class.wipe()
custom_view = pub.custom_view_class()
custom_view.title = 'datasource card view'
custom_view.formdef = carddef
custom_view.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}, {'id': '1'}, {'id': '2'}]}
custom_view.filters = {
'filter': 'recorded',
'filter-1': 'on',
'filter-status': 'on',
'filter-1-value': 'a',
}
custom_view.visibility = 'datasource'
custom_view.order_by = '-receipt_time'
custom_view.store()
custom_view = pub.custom_view_class()
custom_view.title = 'shared card view'
custom_view.formdef = carddef
custom_view.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
custom_view.filters = {'filter': 'done', 'filter-1': 'on', 'filter-status': 'on', 'filter-1-value': 'b'}
custom_view.visibility = 'any'
custom_view.order_by = 'receipt_time'
custom_view.store()
custom_view = pub.custom_view_class()
custom_view.title = 'private card view'
custom_view.formdef = carddef
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {}
custom_view.visibility = 'owner'
custom_view.usier_id = 42
custom_view.order_by = 'id'
custom_view.store()
carddef_xml = carddef.export_to_xml()
assert carddef_xml.tag == 'carddef'
carddef.data_class().wipe()
pub.custom_view_class.wipe()
carddef2 = CardDef.import_from_xml(io.BytesIO(ET.tostring(carddef_xml)))
assert carddef2.name == 'foo'
assert carddef2.fields[1].data_source == {'type': 'carddef:foo'}
assert carddef2._custom_views
custom_views = sorted(carddef2._custom_views, key=lambda a: a.visibility)
assert len(custom_views) == 2
assert custom_views[0].title == 'shared card view'
assert custom_views[0].slug == 'shared-card-view'
assert custom_views[0].columns == {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
assert custom_views[0].filters == {
'filter': 'done',
'filter-1': 'on',
'filter-status': 'on',
'filter-1-value': 'b',
}
assert custom_views[0].visibility == 'any'
assert custom_views[0].order_by == 'receipt_time'
assert custom_views[0].formdef_id is None
assert custom_views[0].formdef_type is None
assert custom_views[1].title == 'datasource card view'
assert custom_views[1].slug == 'datasource-card-view'
assert custom_views[1].columns == {
'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}, {'id': '1'}, {'id': '2'}]
}
assert custom_views[1].filters == {
'filter': 'recorded',
'filter-1': 'on',
'filter-status': 'on',
'filter-1-value': 'a',
}
assert custom_views[1].visibility == 'datasource'
assert custom_views[1].order_by == '-receipt_time'
assert custom_views[1].formdef_id is None
assert custom_views[1].formdef_type is None
carddef2.store()
custom_views = sorted(pub.custom_view_class.select(), key=lambda a: a.visibility)
assert len(custom_views) == 2
assert custom_views[0].title == 'shared card view'
assert custom_views[0].slug == 'shared-card-view'
assert custom_views[0].columns == {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
assert custom_views[0].filters == {
'filter': 'done',
'filter-1': 'on',
'filter-status': 'on',
'filter-1-value': 'b',
}
assert custom_views[0].visibility == 'any'
assert custom_views[0].order_by == 'receipt_time'
assert custom_views[0].formdef_id == carddef2.id
assert custom_views[0].formdef_type == 'carddef'
assert custom_views[1].title == 'datasource card view'
assert custom_views[1].slug == 'datasource-card-view'
assert custom_views[1].columns == {
'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}, {'id': '1'}, {'id': '2'}]
}
assert custom_views[1].filters == {
'filter': 'recorded',
'filter-1': 'on',
'filter-status': 'on',
'filter-1-value': 'a',
}
assert custom_views[1].visibility == 'datasource'
assert custom_views[1].order_by == '-receipt_time'
assert custom_views[1].formdef_id == carddef2.id
assert custom_views[1].formdef_type == 'carddef'
def test_xml_export_import_category_reference(pub):
CardDefCategory.wipe()
CardDef.wipe()
cat = CardDefCategory()
cat.name = 'test category'
cat.store()
carddef = CardDef()
carddef.name = 'foo'
carddef.category_id = cat.id
f2 = assert_xml_import_export_works(carddef)
assert f2.category_id == carddef.category_id
f2 = assert_xml_import_export_works(carddef, include_id=True)
assert f2.category_id == carddef.category_id
carddef_xml_with_id = carddef.export_to_xml(include_id=True)
# check there's no reference to a non-existing category
CardDefCategory.wipe()
assert CardDef.import_from_xml_tree(carddef_xml_with_id, include_id=False).category_id is None
assert CardDef.import_from_xml_tree(carddef_xml_with_id, include_id=True).category_id is None
# check an import that is not using id fields will find the category by its
# name
cat = CardDefCategory()
cat.id = '2'
cat.name = 'test category'
cat.store()
assert CardDef.import_from_xml_tree(carddef_xml_with_id, include_id=False).category_id == '2'
assert CardDef.import_from_xml_tree(carddef_xml_with_id, include_id=True).category_id is None
def test_template_access(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
StringField(id='2', label='key', type='string', varname='key'),
]
carddef.store()
carddef.data_class().wipe()
for i in range(10):
carddata = carddef.data_class()()
if i % 3 == 0:
carddata.data = {'1': 'blah'}
if i % 3 == 1:
carddata.data = {'1': 'foo'}
if i % 3 == 2:
carddata.data = {'1': 'bar'}
carddata.data['2'] = str(i)
carddata.just_created()
carddata.store()
context = pub.substitutions.get_context_variables(mode='lazy')
tmpl = Template('{{cards.foo.objects|filter_by:"foo"|filter_value:"blah"|count}}')
assert tmpl.render(context) == '4'
tmpl = Template('{{cards|objects:"foo"|filter_by:"foo"|filter_value:"blah"|count}}')
assert tmpl.render(context) == '4'
pub.custom_view_class.wipe()
custom_view1 = pub.custom_view_class()
custom_view1.title = 'datasource card view'
custom_view1.formdef = carddef
custom_view1.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
custom_view1.filters = {'filter-1': 'on', 'filter-1-value': 'blah'}
custom_view1.visibility = 'datasource'
custom_view1.order_by = '-f2'
custom_view1.store()
custom_view2 = pub.custom_view_class()
custom_view2.title = 'shared card view'
custom_view2.formdef = carddef
custom_view2.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
custom_view2.filters = {'filter-1': 'on', 'filter-1-value': 'foo'}
custom_view2.visibility = 'any'
custom_view2.order_by = 'f2'
custom_view2.store()
custom_view3 = pub.custom_view_class()
custom_view3.title = 'private card view'
custom_view3.formdef = carddef
custom_view3.columns = {'list': [{'id': 'id'}]}
custom_view3.filters = {}
custom_view3.visibility = 'owner'
custom_view3.usier_id = 42
custom_view3.order_by = 'id'
custom_view3.store()
tmpl = Template('{{cards.foo.objects|with_custom_view:"datasource-card-view"|count}}')
assert tmpl.render(context) == '4'
tmpl = Template('{{cards|objects:"foo"|with_custom_view:"datasource-card-view"|count}}')
assert tmpl.render(context) == '4'
tmpl = Template(
'{% for data in cards|objects:"foo"|with_custom_view:"datasource-card-view" %}{{ data.internal_id }},{% endfor %}'
)
assert tmpl.render(context) == '10,7,4,1,'
tmpl = Template('{{cards.foo.objects|with_custom_view:"shared-card-view"|count}}')
assert tmpl.render(context) == '3'
tmpl = Template('{{cards|objects:"foo"|with_custom_view:"shared-card-view"|count}}')
assert tmpl.render(context) == '3'
tmpl = Template(
'{% for data in cards|objects:"foo"|with_custom_view:"shared-card-view" %}{{ data.internal_id }},{% endfor %}'
)
assert tmpl.render(context) == '2,5,8,'
tmpl = Template('{{cards.foo.objects|with_custom_view:"private-card-view"|count}}')
assert tmpl.render(context) == '0'
tmpl = Template('{{cards|objects:"foo"|with_custom_view:"private-card-view"|count}}')
assert tmpl.render(context) == '0'
tmpl = Template('{{cards.foo.objects|with_custom_view:"unknown"|count}}')
assert tmpl.render(context) == '0'
tmpl = Template('{{cards|objects:"foo"|with_custom_view:"unknown"|count}}')
assert tmpl.render(context) == '0'
def test_data_source_access_by_id(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
carddata = carddef.data_class()()
carddata.data = {'1': 'hello world'}
carddata.just_created()
carddata.store()
carddata2 = carddef.data_class()()
carddata2.data = {'1': 'bye'}
carddata2.just_created()
carddata2.store()
cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata.id)
assert len(cards) == 1
assert cards[0]['text'] == 'hello world'
cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata2.id)
assert len(cards) == 1
assert cards[0]['text'] == 'bye'
cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata.get_display_id())
assert len(cards) == 1
assert cards[0]['text'] == 'hello world'
cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata2.get_display_id())
assert len(cards) == 1
assert cards[0]['text'] == 'bye'
def test_data_source_access_invalid_id(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.store()
carddef.data_class().wipe()
assert CardDef.get_data_source_items('carddef:foo', get_by_id='424508729041982') == []
def test_get_data_source_custom_view(pub):
CardDef.wipe()
carddef1 = CardDef()
carddef1.name = 'foo 1'
carddef1.fields = []
carddef1.store()
carddef2 = CardDef()
carddef2.name = 'foo 2'
carddef2.fields = []
carddef2.store()
pub.custom_view_class.wipe()
custom_view_orphan = pub.custom_view_class()
custom_view_orphan.title = 'view'
custom_view_orphan.formdef = carddef1
custom_view_orphan.columns = {'list': [{'id': 'id'}]}
custom_view_orphan.filters = {}
custom_view_orphan.visibility = 'datasource'
custom_view_orphan.formdef_id = '99999'
custom_view_orphan.store()
custom_view1 = pub.custom_view_class()
custom_view1.title = 'view'
custom_view1.formdef = carddef1
custom_view1.columns = {'list': [{'id': 'id'}]}
custom_view1.filters = {}
custom_view1.visibility = 'datasource'
custom_view1.store()
custom_view2 = pub.custom_view_class()
custom_view2.title = 'view'
custom_view2.formdef = carddef2
custom_view2.columns = {'list': [{'id': 'id'}]}
custom_view2.filters = {}
custom_view2.visibility = 'datasource'
custom_view2.store()
assert CardDef.get_data_source_custom_view('carddef:foo-1:view').id == custom_view1.id
assert CardDef.get_data_source_custom_view('carddef:foo-2:view').id == custom_view2.id
assert CardDef.get_data_source_custom_view('carddef:foo-1:view', carddef=carddef1).id == custom_view1.id
assert CardDef.get_data_source_custom_view('carddef:foo-1:view', carddef=carddef2) is None
assert CardDef.get_data_source_custom_view('carddef:foo-2:view', carddef=carddef2).id == custom_view2.id
assert CardDef.get_data_source_custom_view('carddef:foo-2:view', carddef=carddef1) is None
def test_data_source_custom_view_unknown_filter(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
carddata = carddef.data_class()()
carddata.data = {'1': 'Hello'}
carddata.just_created()
carddata.store()
pub.custom_view_class.wipe()
custom_view = pub.custom_view_class()
custom_view.title = 'view'
custom_view.formdef = carddef
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {'filter-42': 'on', 'filter-42-value': 'Hello', 'filter-foobar': 'baz'}
custom_view.visibility = 'datasource'
custom_view.store()
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Hello']
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == []
assert pub.loggederror_class.count() == 2
logged_error = pub.loggederror_class.select(order_by='id')[0]
assert logged_error.summary == 'Invalid filter "42"'
assert logged_error.formdef_id == str(carddef.id)
logged_error = pub.loggederror_class.select(order_by='id')[1]
assert logged_error.summary == 'Invalid filter "foobar"'
assert logged_error.formdef_id == str(carddef.id)
def test_data_source_anonymised_cards(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
carddata = carddef.data_class()()
carddata.data = {'1': 'Hello 1'}
carddata.just_created()
carddata.store()
carddata = carddef.data_class()()
carddata.data = {'1': 'Hello 2'}
carddata.just_created()
carddata.store()
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Hello 1', 'Hello 2']
carddata.anonymise()
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Hello 1']
def test_data_source_custom_view_digest(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
carddata = carddef.data_class()()
carddata.data = {'1': 'Hello'}
carddata.just_created()
carddata.store()
carddata2 = carddef.data_class()()
carddata2.data = {'1': 'Bye'}
carddata2.just_created()
carddata2.store()
pub.custom_view_class.wipe()
custom_view = pub.custom_view_class()
custom_view.title = 'view'
custom_view.formdef = carddef
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {}
custom_view.visibility = 'datasource'
custom_view.store()
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Bye', 'Hello']
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == ['Bye', 'Hello']
cards = CardDef.get_data_source_items('carddef:foo', query='hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello'
cards = CardDef.get_data_source_items('carddef:foo:view', query='hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello'
cards = CardDef.get_data_source_items('carddef:foo', query='foo')
assert len(cards) == 0
cards = CardDef.get_data_source_items('carddef:foo:view', query='foo')
assert len(cards) == 0
cards = CardDef.get_data_source_items('carddef:foo', get_by_text='Hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello'
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='Hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello'
cards = CardDef.get_data_source_items('carddef:foo', get_by_text='Hello Foo Bar')
assert len(cards) == 0
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='Hello Foo Bar')
assert len(cards) == 0
carddef.digest_templates = {
'default': '{{ form_var_foo }}',
'custom-view:view': '{{ form_var_foo }} Foo Bar',
}
carddef.store()
# rebuild digests
carddata.store()
carddata2.store()
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Bye', 'Hello']
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == [
'Bye Foo Bar',
'Hello Foo Bar',
]
cards = CardDef.get_data_source_items('carddef:foo', query='hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello'
cards = CardDef.get_data_source_items('carddef:foo:view', query='hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello Foo Bar'
cards = CardDef.get_data_source_items('carddef:foo', query='foo')
assert len(cards) == 0
cards = CardDef.get_data_source_items('carddef:foo:view', query='foo')
assert len(cards) == 2
assert cards[0]['text'] == 'Bye Foo Bar'
assert cards[1]['text'] == 'Hello Foo Bar'
cards = CardDef.get_data_source_items('carddef:foo', get_by_text='Hello')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello'
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='Hello')
assert len(cards) == 0
cards = CardDef.get_data_source_items('carddef:foo', get_by_text='Hello Foo Bar')
assert len(cards) == 0
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='Hello Foo Bar')
assert len(cards) == 1
assert cards[0]['text'] == 'Hello Foo Bar'
# digests are not defined
carddef.digest_templates = {}
carddef.store()
carddata.id_display = None
carddata.digests = None
carddata.store()
carddata2.id_display = None
carddata2.digests = None
carddata2.store()
carddef.digest_templates = {'custom-view:view': '{{ form_var_foo }} Foo Bar'}
carddef.store()
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['', '']
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == ['', '']
assert pub.loggederror_class.count() == 2
logged_error = pub.loggederror_class.select(order_by='id')[0]
assert logged_error.summary == 'Digest (default) not defined'
assert logged_error.formdata_id in (str(carddata.id), str(carddata2.id))
logged_error = pub.loggederror_class.select(order_by='id')[1]
assert logged_error.summary == 'Digest (custom view "view") not defined'
assert logged_error.formdata_id in (str(carddata.id), str(carddata2.id))
assert CardDef.get_data_source_items('carddef:foo', get_by_text='') == []
assert CardDef.get_data_source_items('carddef:foo:view', get_by_text='') == []
def test_data_source_query_escape(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
carddata = carddef.data_class()()
carddata.data = {'1': 'Astreinte\\Lundi %'}
carddata.just_created()
carddata.store()
carddata2 = carddef.data_class()()
carddata2.data = {'1': 'Astreinte\\Mardi _'}
carddata2.just_created()
carddata2.store()
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte')
assert len(cards) == 2
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte\\')
assert len(cards) == 2
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='astreinte\\l')
assert len(cards) == 1
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='%')
assert len(cards) == 1
assert cards[0]['text'] == 'Astreinte\\Lundi %'
cards = CardDef.get_data_source_items('carddef:foo', query='_')
assert len(cards) == 1
assert cards[0]['text'] == 'Astreinte\\Mardi _'
def test_reverse_relations(pub):
FormDef.wipe()
CardDef.wipe()
BlockDef.wipe()
formdef1 = FormDef()
formdef1.name = 'formdef 1'
formdef1.store()
formdef2 = FormDef()
formdef2.name = 'formdef 2'
formdef2.store()
carddef1 = CardDef()
carddef1.name = 'carddef 1'
carddef1.store()
carddef2 = CardDef()
carddef2.name = 'carddef 2'
carddef2.store()
block1 = BlockDef()
block1.name = 'block 1'
block1.fields = [
ItemField(id='0', label='unknown', type='item', data_source={'type': 'carddef:unknown'}),
ItemField(
id='1',
label='item',
type='item',
varname='block_foo_1',
data_source={'type': 'carddef:carddef-1'},
),
ItemsField(id='2', label='items', type='items', data_source={'type': 'carddef:carddef-1'}),
ComputedField(
id='3',
label='computed',
type='computed',
varname='block_computed_foo_1',
data_source={'type': 'carddef:carddef-1'},
),
]
block1.store()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == []
assert carddef2.reverse_relations == []
formdef1.fields = [
ItemField(id='0', label='unknown', type='item', data_source={'type': 'carddef:unknown'}),
ItemField(id='1', label='item', type='item', data_source={'type': 'carddef:carddef-1'}),
]
formdef1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == []
formdef2.fields = [
ItemsField(
id='1', label='items', type='items', varname='bar', data_source={'type': 'carddef:carddef-2'}
),
]
formdef2.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
carddef1.fields = [
ItemField(id='0', label='unknown', type='item', data_source={'type': 'carddef:unknown'}),
ItemField(id='1', label='item', type='item', data_source={'type': 'carddef:carddef-2'}),
]
carddef1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'carddef:carddef-1'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
carddef1.fields = [
ItemsField(id='1', label='items', type='items', data_source={'type': 'carddef:carddef-2'}),
]
carddef1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': '', 'type': 'items', 'obj': 'carddef:carddef-1'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
# custom views ?
carddef1.fields = [
ComputedField(
id='1',
label='computed',
type='computed',
varname='computed_foobar',
data_source={'type': 'carddef:carddef-2:view'},
),
]
carddef1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': 'computed_foobar', 'type': 'computed', 'obj': 'carddef:carddef-1'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
# circular relation ?
carddef2.fields = [
ItemsField(id='1', label='items', type='items', data_source={'type': 'carddef:carddef-2'}),
]
carddef2.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': 'computed_foobar', 'type': 'computed', 'obj': 'carddef:carddef-1'},
{'varname': '', 'type': 'items', 'obj': 'carddef:carddef-2'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
# block field
formdef1.fields.append(BlockField(id='2', label='block', type='block:%s' % block1.slug))
formdef1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'computed', 'obj': 'formdef:formdef-1'},
# no varname for block field, item/formdef-1 is already in reverse_relations
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
{'varname': '', 'type': 'items', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': 'computed_foobar', 'type': 'computed', 'obj': 'carddef:carddef-1'},
{'varname': '', 'type': 'items', 'obj': 'carddef:carddef-2'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
formdef1.fields[2] = BlockField(id='2', label='block', type='block:%s' % block1.slug, varname='foo')
formdef1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
# varname defined for block field
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
{'varname': '', 'type': 'items', 'obj': 'formdef:formdef-1'},
{'varname': 'foo_block_computed_foo_1', 'type': 'computed', 'obj': 'formdef:formdef-1'},
{'varname': 'foo_block_foo_1', 'type': 'item', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': 'computed_foobar', 'type': 'computed', 'obj': 'carddef:carddef-1'},
{'varname': '', 'type': 'items', 'obj': 'carddef:carddef-2'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
# update blockdef fields
block1.fields = [
ItemField(
id='1',
label='item',
type='item',
varname='block_foo_1',
data_source={'type': 'carddef:carddef-2'},
),
ItemsField(id='2', label='items', type='items', data_source={'type': 'carddef:carddef-1'}),
]
block1.store()
formdef1.refresh_from_storage()
formdef2.refresh_from_storage()
carddef1.refresh_from_storage()
carddef2.refresh_from_storage()
assert formdef1.reverse_relations == []
assert formdef2.reverse_relations == []
# varname defined for block field
assert carddef1.reverse_relations == [
{'varname': '', 'type': 'item', 'obj': 'formdef:formdef-1'},
{'varname': '', 'type': 'items', 'obj': 'formdef:formdef-1'},
]
assert carddef2.reverse_relations == [
{'varname': 'computed_foobar', 'type': 'computed', 'obj': 'carddef:carddef-1'},
{'varname': '', 'type': 'items', 'obj': 'carddef:carddef-2'},
{'varname': 'foo_block_foo_1', 'type': 'item', 'obj': 'formdef:formdef-1'},
{'varname': 'bar', 'type': 'items', 'obj': 'formdef:formdef-2'},
]
def test_data_source_custom_view_data_access(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
StringField(id='2', label='Test2', type='string', varname='foo2'),
]
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
pub.custom_view_class.wipe()
custom_view = pub.custom_view_class()
custom_view.title = 'view'
custom_view.formdef = carddef
custom_view.columns = {'list': [{'id': 'id'}]}
custom_view.filters = {'filter-1': 'on', 'filter-1-value': 'xxx'}
custom_view.visibility = 'datasource'
custom_view.store()
carddata = carddef.data_class()()
carddata.data = {'1': 'hello world'}
carddata.just_created()
carddata.store()
# no filter, there's a card
cards = CardDef.get_data_source_items('carddef:foo')
assert len(cards) == 1
cards = CardDef.get_data_source_items('carddef:foo', get_by_text='hello world')
assert len(cards) == 1
# nothing returned as the filter doesn't match anything
cards = CardDef.get_data_source_items('carddef:foo:view')
assert len(cards) == 0
# filter is ignored for id lookup
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_id=carddata.id)
assert len(cards) == 1
assert cards[0]['text'] == 'hello world'
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_id=carddata.get_display_id())
assert len(cards) == 1
assert cards[0]['text'] == 'hello world'
# filter is not ignored for text lookup
cards = CardDef.get_data_source_items('carddef:foo:view', get_by_text='hello world')
assert len(cards) == 0