508 lines
18 KiB
Python
508 lines
18 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import json
|
|
import os
|
|
import xml.etree.ElementTree as ET
|
|
|
|
try:
|
|
import lasso
|
|
except ImportError:
|
|
lasso = None
|
|
|
|
from django.utils.six import StringIO
|
|
|
|
import pytest
|
|
from webtest import Upload
|
|
|
|
from wcs.qommon.http_request import HTTPRequest
|
|
from wcs.admin.settings import UserFieldsFormDef
|
|
from wcs.data_sources import NamedDataSource
|
|
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef
|
|
from wcs.formdef import FormDef
|
|
from wcs.carddef import CardDef
|
|
from wcs import fields
|
|
|
|
from utilities import get_app, login, create_temporary_pub, clean_temporary_pub, HttpRequestsMocking
|
|
from test_admin_pages import create_superuser, create_role
|
|
|
|
|
|
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_data_sources(pub):
|
|
create_superuser(pub)
|
|
app = login(get_app(pub))
|
|
app.get('/backoffice/settings/data-sources/')
|
|
# also check it's accessible from forms and workflows sections
|
|
app.get('/backoffice/forms/data-sources/')
|
|
app.get('/backoffice/workflows/data-sources/')
|
|
|
|
# unknown datasource
|
|
app.get('/backoffice/settings/data-sources/42/', status=404)
|
|
app.get('/backoffice/forms/data-sources/42/', status=404)
|
|
app.get('/backoffice/workflows/data-sources/42/', status=404)
|
|
|
|
|
|
def test_data_sources_new(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
app = login(get_app(pub))
|
|
|
|
# go to the page and cancel
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click('New Data Source')
|
|
resp = resp.forms[0].submit('cancel')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/'
|
|
|
|
# go to the page and add a data source
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click('New Data Source')
|
|
resp.forms[0]['name'] = 'a new data source'
|
|
resp.forms[0]['description'] = 'description of the data source'
|
|
|
|
assert resp.form['data_source$type'].options == [
|
|
('None', True, 'None'),
|
|
('json', False, 'JSON URL'),
|
|
('jsonp', False, 'JSONP URL'),
|
|
('geojson', False, 'GeoJSON URL'),
|
|
('python', False, 'Python Expression')
|
|
]
|
|
resp.forms[0]['data_source$type'] = 'python'
|
|
resp = resp.forms[0].submit('data_source$apply')
|
|
resp.forms[0]['data_source$value'] = repr(
|
|
[{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}])
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/'
|
|
resp = resp.follow()
|
|
assert 'a new data source' in resp.text
|
|
resp = resp.click('a new data source')
|
|
assert 'Data Source - a new data source' in resp.text
|
|
resp = resp.click('Edit')
|
|
assert 'Edit Data Source' in resp.text
|
|
|
|
assert NamedDataSource.get(1).name == 'a new data source'
|
|
assert NamedDataSource.get(1).description == 'description of the data source'
|
|
|
|
# add a second one
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click('New Data Source')
|
|
resp.forms[0]['name'] = 'an other data source'
|
|
resp.forms[0]['description'] = 'description of the data source'
|
|
resp.forms[0]['data_source$type'] = 'python'
|
|
resp = resp.forms[0].submit('data_source$apply')
|
|
resp.forms[0]['data_source$value'] = repr(
|
|
[{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}])
|
|
resp = resp.forms[0].submit('submit')
|
|
|
|
assert NamedDataSource.count() == 2
|
|
|
|
|
|
def test_data_sources_view(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
|
|
data_source = NamedDataSource(name='foobar')
|
|
app = login(get_app(pub))
|
|
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Type of source: Python Expression' in resp.text
|
|
assert 'Python Expression' in resp.text
|
|
assert 'Preview' not in resp.text
|
|
|
|
data_source.data_source = {'type': 'formula', 'value': '["AAA", "BBB"]'}
|
|
data_source.store()
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert resp.text.count('AAA') == 3 # expression + id + text
|
|
|
|
# check unicode
|
|
data_source.data_source = {
|
|
'type': 'formula',
|
|
'value': repr([('Y', 'Domicilié'), ('N', u'Pas domicilié')])}
|
|
data_source.store()
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert 'Domicilié' in resp.text
|
|
|
|
# check json
|
|
json_file_path = os.path.join(pub.app_dir, 'test.json')
|
|
json_file = open(json_file_path, 'w')
|
|
json.dump({'data': [{'id': '1', 'text': 'foo'}, {'id': '2', 'text': 'bar'}]}, json_file)
|
|
json_file.close()
|
|
|
|
data_source.data_source = {'type': 'json', 'value': 'file://%s' % json_file_path}
|
|
data_source.store()
|
|
with HttpRequestsMocking():
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert 'foo' in resp.text
|
|
|
|
# with other attributes
|
|
json_file = open(json_file_path, 'w')
|
|
json.dump({'results': [{'pk': '1', 'label': 'foo'}, {'pk': '2'}]}, json_file)
|
|
json_file.close()
|
|
|
|
data_source.data_attribute = 'results'
|
|
data_source.id_attribute = 'pk'
|
|
data_source.text_attribute = 'label'
|
|
data_source.store()
|
|
with HttpRequestsMocking():
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert '<tt>1</tt>: foo</li>' in resp.text
|
|
assert '<tt>2</tt>: 2</li>' in resp.text
|
|
assert '<p>Additional keys are available: label, pk</p>' in resp.text
|
|
|
|
# variadic url
|
|
data_source.data_attribute = None
|
|
data_source.data_source = {'type': 'json', 'value': '{{ site_url }}/foo/bar'}
|
|
data_source.store()
|
|
with HttpRequestsMocking():
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert '<a href="http://example.net/foo/bar"' in resp.text
|
|
|
|
# check geojson
|
|
geojson_file_path = os.path.join(pub.app_dir, 'test.geojson')
|
|
geojson_file = open(geojson_file_path, 'w')
|
|
json.dump({'features': [
|
|
{'properties': {'id': '1', 'text': 'foo', 'label': 'foo'}},
|
|
{'properties': {'id': '2', 'text': 'bar', 'label': 'bar'}}]}, geojson_file)
|
|
geojson_file.close()
|
|
data_source.data_source = {'type': 'geojson', 'value': 'file://%s' % geojson_file_path}
|
|
data_source.store()
|
|
with HttpRequestsMocking():
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert 'foo' in resp.text
|
|
assert 'bar' in resp.text
|
|
assert 'Additional keys are available: label' in resp.text
|
|
|
|
data_source.data_source = {'type': 'formula', 'value': '[str(x) for x in range(100)]'}
|
|
data_source.store()
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert resp.text.count('<li>') < 100
|
|
assert '<li>...</li>' in resp.text
|
|
|
|
data_source.data_source = {'type': 'formula', 'value': repr([
|
|
{'id': 'a', 'text': 'BBB', 'foo': 'bar1'},
|
|
{'id': 'b', 'text': 'BBB', 'foo': 'bar2'},
|
|
])}
|
|
data_source.store()
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Preview' in resp.text
|
|
assert 'Additional keys are available: foo' in resp.text
|
|
|
|
# check formdef listing
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test data source'
|
|
formdef.fields = [
|
|
fields.ItemField(id='1', label='item', data_source={'type': data_source.slug})
|
|
]
|
|
formdef.store()
|
|
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Usage in forms' in resp.text
|
|
assert '/backoffice/forms/%s/' % formdef.id in resp.text
|
|
|
|
# additional formdef types
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields.append(
|
|
fields.ItemField(id='1', type='item', label='item', data_source={'type': data_source.slug}))
|
|
user_formdef.store()
|
|
|
|
from wcs.workflows import WorkflowVariablesFieldsFormDef
|
|
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': data_source.slug}))
|
|
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
|
|
workflow.backoffice_fields_formdef.fields.append(
|
|
fields.ItemField(id='1', type='item', label='item', data_source={'type': data_source.slug}))
|
|
|
|
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
|
|
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': data_source.slug}))
|
|
baz_status.items.append(display_form)
|
|
display_form.parent = baz_status
|
|
|
|
workflow.store()
|
|
|
|
carddef = CardDef()
|
|
carddef.name = 'Baz'
|
|
carddef.fields = [
|
|
fields.ItemField(id='1', label='item', data_source={'type': data_source.slug})
|
|
]
|
|
carddef.store()
|
|
|
|
resp = app.get('/backoffice/settings/data-sources/%s/' % data_source.id)
|
|
assert 'Usage in forms' in resp.text
|
|
assert '/backoffice/forms/%s/' % formdef.id in resp.text
|
|
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/' % carddef.id in resp.text
|
|
|
|
# cleanup
|
|
user_formdef = UserFieldsFormDef(pub)
|
|
user_formdef.fields = []
|
|
user_formdef.store()
|
|
Workflow.wipe()
|
|
CardDef.wipe()
|
|
|
|
|
|
def test_data_sources_edit(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
|
|
FormDef.wipe()
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
|
|
resp = resp.click(href='edit')
|
|
assert resp.forms[0]['name'].value == 'foobar'
|
|
resp.forms[0]['description'] = 'data source description'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
resp = resp.follow()
|
|
|
|
assert NamedDataSource.get(1).description == 'data source description'
|
|
|
|
|
|
def test_data_sources_edit_duplicate_name(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
data_source = NamedDataSource(name='foobar2')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='edit')
|
|
assert resp.forms[0]['name'].value == 'foobar'
|
|
resp.forms[0]['name'] = 'foobar2'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'This name is already used' in resp.text
|
|
|
|
resp = resp.forms[0].submit('cancel')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
|
|
|
|
def test_data_sources_delete(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
category = NamedDataSource(name='foobar')
|
|
category.store()
|
|
|
|
FormDef.wipe()
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
|
|
resp = resp.click(href='delete')
|
|
resp = resp.forms[0].submit('cancel')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/'
|
|
assert NamedDataSource.count() == 1
|
|
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='delete')
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/'
|
|
resp = resp.follow()
|
|
assert NamedDataSource.count() == 0
|
|
|
|
|
|
def test_data_sources_in_use_delete(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
category = NamedDataSource(name='foobar')
|
|
category.store()
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'form title'
|
|
formdef.fields = [
|
|
fields.ItemField(id='0', label='string', type='item', data_source={'type': 'foobar'}),
|
|
]
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='delete')
|
|
assert 'This datasource is still used, it cannot be deleted.' in resp.text
|
|
assert 'delete-button' not in resp.text
|
|
|
|
formdef.fields = []
|
|
formdef.store()
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='delete')
|
|
assert 'delete-button' in resp.text
|
|
|
|
|
|
def test_data_sources_export(pub):
|
|
create_superuser(pub)
|
|
create_role()
|
|
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
|
|
resp = resp.click(href='export')
|
|
xml_export = resp.text
|
|
|
|
ds = StringIO(xml_export)
|
|
data_source2 = NamedDataSource.import_from_xml(ds)
|
|
assert data_source2.name == 'foobar'
|
|
|
|
|
|
def test_data_sources_import(pub):
|
|
create_superuser(pub)
|
|
create_role()
|
|
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.slug = 'baaaz'
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
data_source_xml = ET.tostring(data_source.export_to_xml(include_id=True))
|
|
|
|
NamedDataSource.wipe()
|
|
assert NamedDataSource.count() == 0
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click(href='import')
|
|
resp.forms[0]['file'] = Upload('datasource.wcs', data_source_xml)
|
|
resp = resp.forms[0].submit()
|
|
assert NamedDataSource.count() == 1
|
|
assert NamedDataSource.get(1).slug == 'baaaz'
|
|
|
|
# check slug
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click(href='import')
|
|
resp.forms[0]['file'] = Upload('datasource.wcs', data_source_xml)
|
|
resp = resp.forms[0].submit()
|
|
assert NamedDataSource.count() == 2
|
|
assert NamedDataSource.get(1).slug == 'baaaz'
|
|
assert NamedDataSource.get(2).slug == 'foobar'
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click(href='import')
|
|
resp.forms[0]['file'] = Upload('datasource.wcs', data_source_xml)
|
|
resp = resp.forms[0].submit()
|
|
assert NamedDataSource.count() == 3
|
|
assert NamedDataSource.get(1).slug == 'baaaz'
|
|
assert NamedDataSource.get(2).slug == 'foobar'
|
|
assert NamedDataSource.get(3).slug == 'foobar-1'
|
|
|
|
# import an invalid file
|
|
resp = app.get('/backoffice/settings/data-sources/')
|
|
resp = resp.click(href='import')
|
|
resp.form['file'] = Upload('datasource.wcs', b'garbage')
|
|
resp = resp.form.submit()
|
|
assert 'Invalid File' in resp.text
|
|
|
|
|
|
def test_data_sources_edit_slug(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
assert NamedDataSource.get(1).slug == 'foobar'
|
|
|
|
FormDef.wipe()
|
|
app = login(get_app(pub))
|
|
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='edit')
|
|
assert resp.forms[0]['name'].value == 'foobar'
|
|
resp.forms[0]['slug'] = 'foo_bar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
assert NamedDataSource.get(1).slug == 'foo_bar'
|
|
|
|
data_source = NamedDataSource(name='barfoo')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='edit')
|
|
assert resp.forms[0]['name'].value == 'foobar'
|
|
resp.forms[0]['slug'] = 'barfoo'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'This value is already used' in resp.text
|
|
|
|
resp.forms[0]['slug'] = 'foobar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
|
|
|
|
|
|
def test_data_sources_in_use_edit_slug(pub):
|
|
create_superuser(pub)
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': '[]'}
|
|
data_source.store()
|
|
assert NamedDataSource.get(1).slug == 'foobar'
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'form title'
|
|
formdef.fields = [
|
|
fields.ItemField(id='0', label='string', type='item', data_source={'type': 'foobar'}),
|
|
]
|
|
formdef.store()
|
|
|
|
app = login(get_app(pub))
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='edit')
|
|
assert 'form_slug' not in resp.form.fields
|
|
resp = resp.form.submit('submit')
|
|
|
|
formdef.fields = []
|
|
formdef.store()
|
|
resp = app.get('/backoffice/settings/data-sources/1/')
|
|
resp = resp.click(href='edit')
|
|
assert 'form_slug' in resp.text
|
|
resp = resp.form.submit('submit')
|