1363 lines
50 KiB
Python
1363 lines
50 KiB
Python
import pytest
|
|
import hashlib
|
|
import os
|
|
import re
|
|
import StringIO
|
|
from webtest import Upload
|
|
|
|
from quixote.http_request import Upload as QuixoteUpload
|
|
from wcs.qommon.form import UploadedFile
|
|
from wcs.qommon.ident.password_accounts import PasswordAccount
|
|
from wcs.formdef import FormDef
|
|
from wcs.workflows import Workflow, EditableWorkflowStatusItem, ExportToModel
|
|
from wcs.wf.jump import JumpWorkflowStatusItem
|
|
from wcs.wf.attachment import AddAttachmentWorkflowStatusItem
|
|
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
|
|
from wcs.categories import Category
|
|
from wcs.roles import Role, logged_users_role
|
|
from wcs.tracking_code import TrackingCode
|
|
from wcs.data_sources import NamedDataSource
|
|
from wcs import fields
|
|
from wcs.sessions import BasicSession
|
|
|
|
from utilities import get_app, login, create_temporary_pub, clean_temporary_pub, emails
|
|
|
|
def pytest_generate_tests(metafunc):
|
|
if 'pub' in metafunc.fixturenames:
|
|
metafunc.parametrize('pub', ['pickle', 'sql'], indirect=True)
|
|
|
|
@pytest.fixture
|
|
def pub(request):
|
|
pub = create_temporary_pub(sql_mode=(request.param == 'sql'))
|
|
pub.cfg['identification'] = {'methods': ['password']}
|
|
pub.cfg['misc'] = {'charset': 'utf-8'}
|
|
pub.cfg['language'] = {'language': 'en'}
|
|
pub.write_cfg()
|
|
|
|
if Category.count() == 0:
|
|
cat = Category(name='foobar')
|
|
cat.store()
|
|
|
|
return pub
|
|
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
|
|
def create_formdef():
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = []
|
|
formdef.store()
|
|
return formdef
|
|
|
|
def create_user(pub):
|
|
pub.user_class.wipe()
|
|
PasswordAccount.wipe()
|
|
|
|
user = pub.user_class()
|
|
user.email = 'foo@localhost'
|
|
user.store()
|
|
account = PasswordAccount(id='foo')
|
|
account.set_password('foo')
|
|
account.user_id = user.id
|
|
account.store()
|
|
return user
|
|
|
|
def test_home(pub):
|
|
create_formdef()
|
|
home = get_app(pub).get('/')
|
|
assert 'category-misc' in home.body
|
|
assert '<a class="" href="test/">test</a>' in home.body
|
|
|
|
def test_home_category(pub):
|
|
formdef = create_formdef()
|
|
formdef.category_id = '1'
|
|
formdef.store()
|
|
home = get_app(pub).get('/')
|
|
assert 'category-foobar' in home.body
|
|
assert not 'category-misc' in home.body
|
|
assert '<a class="" href="foobar/test/">test</a>' in home.body
|
|
|
|
def test_home_disabled(pub):
|
|
formdef = create_formdef()
|
|
formdef.disabled = True
|
|
formdef.store()
|
|
home = get_app(pub).get('/')
|
|
assert not '<a href="test/">test</a>' in home.body
|
|
|
|
def test_home_inaccessible(pub):
|
|
formdef = create_formdef()
|
|
formdef.roles = ['xxx']
|
|
formdef.store()
|
|
home = get_app(pub).get('/')
|
|
assert home.status_int == 302
|
|
assert home.location == 'http://example.net/login'
|
|
|
|
def test_home_always_advertise(pub):
|
|
formdef = create_formdef()
|
|
formdef.roles = ['xxx']
|
|
formdef.always_advertise = True
|
|
formdef.store()
|
|
home = get_app(pub).get('/')
|
|
assert '<a href="test/">test</a>' in home.body
|
|
assert '<a href="test/">test</a><span> (authentication required)</span>' in home.body
|
|
|
|
def test_home_redirect(pub):
|
|
pub.cfg['misc']['homepage-redirect-url'] = 'http://www.example.com/'
|
|
pub.write_cfg()
|
|
create_formdef()
|
|
home = get_app(pub).get('/')
|
|
assert home.status_int == 302
|
|
assert home.location == 'http://www.example.com/'
|
|
|
|
def test_home_redirect_var(pub):
|
|
pub.cfg['misc']['homepage-redirect-url'] = 'http://www.example.com/[site_lang]/'
|
|
pub.write_cfg()
|
|
create_formdef()
|
|
home = get_app(pub).get('/')
|
|
assert home.status_int == 302
|
|
assert home.location == 'http://www.example.com/en/'
|
|
|
|
def test_category_page(pub):
|
|
formdef = create_formdef()
|
|
formdef.category_id = '1'
|
|
formdef.store()
|
|
resp = get_app(pub).get('/foobar/')
|
|
assert '<h2>foobar</h2>' in resp.body
|
|
assert '<a class="" href="test/">test</a>' in resp.body
|
|
|
|
def test_category_page_redirect(pub):
|
|
formdef = create_formdef()
|
|
formdef.category_id = '1'
|
|
formdef.store()
|
|
cat = Category.get(1)
|
|
cat.redirect_url = 'http://www.example.com/'
|
|
cat.store()
|
|
resp = get_app(pub).get('/foobar/')
|
|
assert resp.status_int == 302
|
|
assert resp.location == 'http://www.example.com/'
|
|
|
|
def test_category_page_redirect_var(pub):
|
|
formdef = create_formdef()
|
|
formdef.category_id = '1'
|
|
formdef.store()
|
|
cat = Category.get(1)
|
|
cat.redirect_url = 'http://www.example.com/[site_lang]/[category_slug]/'
|
|
cat.store()
|
|
resp = get_app(pub).get('/foobar/')
|
|
assert resp.status_int == 302
|
|
assert resp.location == 'http://www.example.com/en/foobar/'
|
|
|
|
def test_form_access(pub):
|
|
formdef = create_formdef()
|
|
get_app(pub).get('/test/', status=200)
|
|
|
|
Role.wipe()
|
|
role = Role(name='xxx')
|
|
role.store()
|
|
|
|
# check a formdef protected by a role cannot be accessed
|
|
formdef.roles = [role.id]
|
|
formdef.store()
|
|
# an unlogged user will ge ta redirect to login
|
|
resp = get_app(pub).get('/test/', status=302)
|
|
assert '/login' in resp.location
|
|
|
|
# while a logged-in user will get a 403
|
|
user = create_user(pub)
|
|
login(get_app(pub), username='foo', password='foo').get('/test/', status=403)
|
|
|
|
# unless the user has the right role
|
|
user = create_user(pub)
|
|
user.roles = [role.id]
|
|
user.store()
|
|
login(get_app(pub), username='foo', password='foo').get('/test/', status=200)
|
|
|
|
# check admin has access, even without specific roles
|
|
user = create_user(pub)
|
|
user.roles = []
|
|
user.is_admin = True
|
|
user.store()
|
|
login(get_app(pub), username='foo', password='foo').get('/test/', status=200)
|
|
|
|
# check special "logged users" role
|
|
formdef.roles = [logged_users_role()]
|
|
formdef.store()
|
|
user = create_user(pub)
|
|
login(get_app(pub), username='foo', password='foo').get('/test/', status=403)
|
|
resp = get_app(pub).get('/test/', status=302) # redirect to login
|
|
|
|
# check "receiver" can also access the formdef
|
|
formdef = create_formdef()
|
|
formdef.roles = [-2]
|
|
formdef.workflow_roles = {'_receiver': role.id}
|
|
formdef.store()
|
|
user = create_user(pub)
|
|
user.roles = [role.id]
|
|
user.store()
|
|
login(get_app(pub), username='foo', password='foo').get('/test/', status=200)
|
|
|
|
def test_form_submit(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
page = get_app(pub).get('/test/')
|
|
next_page = page.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in next_page.body
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
assert formdef.data_class().count() == 1
|
|
|
|
def test_form_submit_no_confirmation(pub):
|
|
formdef = create_formdef()
|
|
formdef.confirmation = False
|
|
formdef.store()
|
|
page = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
next_page = page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
assert formdef.data_class().count() == 1
|
|
|
|
def test_form_string_field_submit(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
formdef.store()
|
|
page = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
next_page = page.forms[0].submit('submit') # but the field is required
|
|
assert '<div class="error">required field</div>' in next_page.body
|
|
next_page.forms[0]['f0'] = 'foobar'
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in next_page.body
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
data = formdef.data_class().get(data_id)
|
|
assert data.data == {'0': 'foobar'}
|
|
|
|
def assert_current_page(resp, page_label):
|
|
assert re.findall('<li class=".*?current.*?">.*?<span class="label">(.*?)</span></li>',
|
|
resp.body)[0] == page_label
|
|
|
|
def test_form_multi_page(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.StringField(id='1', label='string'),
|
|
fields.PageField(id='2', label='2nd page', type='page'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
page = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
page.forms[0]['f1'] = 'foo'
|
|
assert page.forms[0].fields['submit'][0].value_if_submitted() == 'Next'
|
|
next_page = page.forms[0].submit('submit')
|
|
assert_current_page(next_page, '2nd page')
|
|
assert next_page.forms[0]['previous']
|
|
next_page.forms[0]['f3'] = 'bar'
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert_current_page(next_page, 'Validating')
|
|
assert 'Check values then click submit.' in next_page.body
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
data = formdef.data_class().get(data_id)
|
|
assert data.data == {'1': 'foo', '3': 'bar'}
|
|
|
|
def test_form_multi_page_condition(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.StringField(id='1', label='string'),
|
|
fields.PageField(id='2', label='2nd page', type='page', condition='False'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.forms[0]['f1'] = 'foo'
|
|
resp = resp.forms[0].submit('submit') # should go straight to validation
|
|
assert 'Check values then click submit.' in resp.body
|
|
assert resp.forms[0]['previous']
|
|
resp = resp.forms[0].submit('previous')
|
|
assert resp.forms[0]['f1']
|
|
|
|
def test_form_multi_page_condition_select(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.ItemField(id='1', label='select', type='item',
|
|
required=True,
|
|
varname='foo', items=['Foo', 'Bar']),
|
|
fields.PageField(id='2', label='2nd page', type='page',
|
|
condition='var_foo == "Foo"'),
|
|
fields.PageField(id='3', label='3rd page', type='page',
|
|
condition='var_foo == "Bar"'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = get_app(pub).get('/test/')
|
|
assert not '2nd page' in resp.body
|
|
assert not '3rd page' in resp.body
|
|
assert resp.forms[0]['f1'].value == 'Foo' # preset
|
|
resp = resp.forms[0].submit('submit')
|
|
assert '2nd page' in resp.body
|
|
assert not '3rd page' in resp.body
|
|
assert_current_page(resp, '2nd page')
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f1'] = 'Bar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert not '2nd page' in resp.body
|
|
assert '3rd page' in resp.body
|
|
assert_current_page(resp, '3rd page')
|
|
|
|
def test_form_multi_page_condition_select_new_varname(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.ItemField(id='1', label='select', type='item',
|
|
required=True,
|
|
varname='foo', items=['Foo', 'Bar']),
|
|
fields.PageField(id='2', label='2nd page', type='page',
|
|
condition='form_var_foo == "Foo"'),
|
|
fields.PageField(id='3', label='3rd page', type='page',
|
|
condition='form_var_foo == "Bar"'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
resp = get_app(pub).get('/test/')
|
|
assert not '2nd page' in resp.body
|
|
assert not '3rd page' in resp.body
|
|
resp.forms[0]['f1'] = 'Foo'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert '2nd page' in resp.body
|
|
assert not '3rd page' in resp.body
|
|
assert_current_page(resp, '2nd page')
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f1'] = 'Bar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert not '2nd page' in resp.body
|
|
assert '3rd page' in resp.body
|
|
assert_current_page(resp, '3rd page')
|
|
|
|
def test_form_multi_page_condition_checkbox(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.BoolField(id='1', label='checkbox', varname='checkbox'),
|
|
fields.PageField(id='2', label='2nd page', type='page',
|
|
condition='var_checkbox == "False"'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.forms[0]['f1'].checked = True
|
|
resp = resp.forms[0].submit('submit') # should go straight to validation
|
|
assert 'Check values then click submit.' in resp.body
|
|
assert resp.forms[0]['previous']
|
|
resp = resp.forms[0].submit('previous')
|
|
assert resp.forms[0]['f1']
|
|
resp.forms[0]['f1'].checked = False
|
|
resp = resp.forms[0].submit('submit') # should go to second page
|
|
assert 'f3' in resp.forms[0].fields
|
|
|
|
def test_form_multi_page_condition_data_source(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.BoolField(id='1', label='checkbox', varname='checkbox'),
|
|
fields.PageField(id='2', label='2nd page', type='page',
|
|
condition='len(data_source.foobar) > 0'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
|
|
# add the named data source, empty
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': repr([])}
|
|
data_source.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp = resp.forms[0].submit('submit') # should go straight to validation
|
|
assert 'Check values then click submit.' in resp.body
|
|
assert resp.forms[0]['previous']
|
|
resp = resp.forms[0].submit('previous')
|
|
assert resp.forms[0]['f1']
|
|
|
|
# replace the named data source with one with items
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': repr(['un', 'deux'])}
|
|
data_source.store()
|
|
|
|
resp = resp.forms[0].submit('submit') # should go to second page
|
|
assert 'f3' in resp.forms[0].fields
|
|
|
|
def test_form_multi_page_condition_data_source_with_form_variable(pub):
|
|
# this tries to recreate #8272 which is about a json datasource being
|
|
# used in a page condition and taking a value from the given page to
|
|
# filter its content. It is emulated here with a Python datasource
|
|
# being empty if a field was not set.
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.StringField(id='1', label='string', varname='xxx',
|
|
required=False),
|
|
fields.PageField(id='2', label='2nd page', type='page',
|
|
condition='len(data_source.foobar) > 0'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
|
|
# add the named data source, related to a field on the first page
|
|
NamedDataSource.wipe()
|
|
data_source = NamedDataSource(name='foobar')
|
|
data_source.data_source = {'type': 'formula', 'value': 'form_var_xxx and [form_var_xxx] or []'}
|
|
data_source.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp = resp.forms[0].submit('submit') # should go straight to validation
|
|
assert 'Check values then click submit.' in resp.body
|
|
assert resp.forms[0]['previous']
|
|
resp = resp.forms[0].submit('previous')
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f1'] = 'HELLO'
|
|
resp = resp.forms[0].submit('submit') # should go to second page
|
|
assert 'f3' in resp.forms[0].fields
|
|
|
|
def test_form_submit_with_user(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
page = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
formdef.data_class().wipe()
|
|
next_page = page.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in next_page.body
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
assert formdef.data_class().count() == 1
|
|
# check the user received a copy by email
|
|
assert emails.emails.get('New form (test)')
|
|
assert emails.emails.get('New form (test)')['email_rcpt'] == ['foo@localhost']
|
|
|
|
def test_form_visit_existing(pub):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
page = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
formdef.data_class().wipe()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.store()
|
|
|
|
formdata_user = formdef.data_class()()
|
|
formdata_user.user_id = user.id
|
|
formdata_user.store()
|
|
|
|
resp = get_app(pub).get('/test/%s/' % formdata.id)
|
|
assert resp.location == 'http://example.net/login'
|
|
|
|
resp = get_app(pub).get('/test/%s/' % formdata_user.id)
|
|
assert resp.location == 'http://example.net/login'
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/%s/' % formdata_user.id)
|
|
assert 'The form has been recorded on' in resp
|
|
|
|
def test_form_auth(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
resp = get_app(pub).get('/test/auth')
|
|
assert resp.location == 'http://example.net/login/?ReturnUrl=http%3A//example.net/test/'
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/auth')
|
|
assert resp.location == 'http://example.net/test/'
|
|
|
|
def test_form_tryauth(pub):
|
|
create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
resp = get_app(pub).get('/test/tryauth')
|
|
assert resp.location == 'http://example.net/test/'
|
|
|
|
app = login(get_app(pub), username='foo', password='foo')
|
|
pub.cfg['identification'] = {'methods': ['idp']}
|
|
pub.write_cfg()
|
|
# if the user is logged in, the form should be presented
|
|
resp = app.get('/test/tryauth')
|
|
assert resp.location == 'http://example.net/test/'
|
|
|
|
# if the user is unlogged, there should be a passive redirection to SSO
|
|
resp = get_app(pub).get('/test/tryauth')
|
|
assert 'IsPassive=true' in resp.location
|
|
|
|
pub.cfg['identification'] = {'methods': ['password']}
|
|
pub.write_cfg()
|
|
|
|
def test_form_no_tracking_code(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
formdef.enable_tracking_codes = False
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
assert not '<h3>Tracking code</h3>' in resp.body
|
|
|
|
def test_form_tracking_code(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
assert '<h3>Tracking code</h3>' in resp.body
|
|
resp.forms[0]['f0'] = 'foobar'
|
|
resp = resp.forms[0].submit('submit')
|
|
tracking_code = None
|
|
for a_tag in resp.html.findAll('a'):
|
|
if 'code/' in a_tag['href']:
|
|
tracking_code = a_tag.text
|
|
break
|
|
assert tracking_code is not None
|
|
|
|
assert formdef.data_class().count() == 1
|
|
assert formdef.data_class().select()[0].is_draft()
|
|
assert formdef.data_class().select()[0].tracking_code == tracking_code
|
|
assert formdef.data_class().select()[0].data['0'] == 'foobar'
|
|
formdata_id = formdef.data_class().select()[0].id
|
|
|
|
# check we can load the formdata as a draft
|
|
resp = get_app(pub).get('/')
|
|
resp.forms[0]['code'] = tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
|
resp = resp.follow()
|
|
assert resp.location == 'http://example.net/test/%s' % formdata_id
|
|
resp = resp.follow()
|
|
assert resp.location.startswith('http://example.net/test/?mt=')
|
|
resp = resp.follow()
|
|
resp = resp.forms[0].submit('previous')
|
|
assert resp.forms[0]['f0'].value == 'foobar'
|
|
|
|
# check submitted form keeps the tracking code
|
|
resp.forms[0]['f0'] = 'barfoo'
|
|
resp = resp.forms[0].submit('submit') # -> confirmation page
|
|
resp = resp.forms[0].submit('submit') # -> done
|
|
resp = resp.follow()
|
|
assert 'barfoo' in resp.body
|
|
assert formdef.data_class().count() == 1 # check the draft one has been removed
|
|
assert formdef.data_class().select()[0].tracking_code == tracking_code
|
|
assert formdef.data_class().select()[0].status == 'wf-new'
|
|
assert formdef.data_class().select()[0].data['0'] == 'barfoo'
|
|
formdata_id = formdef.data_class().select()[0].id
|
|
|
|
# check we can still go back to it
|
|
app = get_app(pub)
|
|
resp = app.get('/')
|
|
resp.forms[0]['code'] = tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
|
resp = resp.follow()
|
|
assert resp.location == 'http://example.net/test/%s' % formdata_id
|
|
resp = resp.follow()
|
|
resp = resp.follow()
|
|
assert 'form_comment' in resp.body # makes sure user is treated as submitter
|
|
resp.forms[0]['comment'] = 'hello world'
|
|
session_id = app.cookies.values()[0].strip('"')
|
|
session = BasicSession.get(session_id)
|
|
resp.forms[0]['captcha$q'] = session.get_captcha_token(resp.forms[0]['captcha$token'].value)['answer']
|
|
resp = resp.forms[0].submit()
|
|
assert formdef.data_class().get(formdata_id).evolution[-1].comment == 'hello world'
|
|
|
|
|
|
def test_form_tracking_code_as_user(pub):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
formdef.data_class().wipe()
|
|
assert '<h3>Tracking code</h3>' in resp.body
|
|
resp.forms[0]['f0'] = 'foobar'
|
|
resp = resp.forms[0].submit('submit')
|
|
tracking_code = None
|
|
for a_tag in resp.html.findAll('a'):
|
|
if 'code/' in a_tag['href']:
|
|
tracking_code = a_tag.text
|
|
break
|
|
assert tracking_code is not None
|
|
|
|
assert formdef.data_class().count() == 1
|
|
assert formdef.data_class().select()[0].is_draft()
|
|
assert formdef.data_class().select()[0].tracking_code == tracking_code
|
|
assert formdef.data_class().select()[0].data['0'] == 'foobar'
|
|
formdata_id = formdef.data_class().select()[0].id
|
|
|
|
# check we can load the formdata as a draft
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/')
|
|
resp.forms[0]['code'] = tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
|
resp = resp.follow()
|
|
assert resp.location == 'http://example.net/test/%s' % formdata_id
|
|
resp = resp.follow()
|
|
assert resp.location.startswith('http://example.net/test/?mt=')
|
|
resp = resp.follow()
|
|
resp = resp.forms[0].submit('previous')
|
|
assert resp.forms[0]['f0'].value == 'foobar'
|
|
|
|
# check submitted form keeps the tracking code
|
|
resp.forms[0]['f0'] = 'barfoo'
|
|
resp = resp.forms[0].submit('submit') # -> confirmation page
|
|
resp = resp.forms[0].submit('submit') # -> done
|
|
resp = resp.follow()
|
|
assert 'barfoo' in resp.body
|
|
assert formdef.data_class().count() == 1 # check the draft one has been removed
|
|
assert formdef.data_class().select()[0].tracking_code == tracking_code
|
|
assert str(formdef.data_class().select()[0].user_id) == str(user.id)
|
|
assert formdef.data_class().select()[0].status == 'wf-new'
|
|
assert formdef.data_class().select()[0].data['0'] == 'barfoo'
|
|
formdata_id = formdef.data_class().select()[0].id
|
|
|
|
# check we can still go back to it
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/')
|
|
resp.forms[0]['code'] = tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
|
resp = resp.follow()
|
|
assert resp.location == 'http://example.net/test/%s' % formdata_id
|
|
resp = resp.follow()
|
|
resp = resp.follow()
|
|
assert 'form_comment' in resp.body # makes sure user is treated as submitter
|
|
resp.forms[0]['comment'] = 'hello world'
|
|
resp = resp.forms[0].submit()
|
|
assert formdef.data_class().get(formdata_id).evolution[-1].comment == 'hello world'
|
|
|
|
# and check we can also get back to it as anonymous
|
|
app = get_app(pub)
|
|
resp = app.get('/')
|
|
resp.forms[0]['code'] = tracking_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
|
resp = resp.follow()
|
|
assert resp.location == 'http://example.net/test/%s' % formdata_id
|
|
resp = resp.follow()
|
|
resp = resp.follow()
|
|
assert 'form_comment' in resp.body # makes sure user is treated as submitter
|
|
|
|
|
|
def test_form_tracking_code_email(pub):
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {'0': 'foobar'}
|
|
formdata.tracking_code = 'ABCDEF'
|
|
formdata.store()
|
|
|
|
resp = get_app(pub).get('/test/code/ABCDEF/')
|
|
assert '<h2>Keep your tracking code</h2>' in resp.body
|
|
resp.forms[0]['email'] = 'foo@localhost'
|
|
resp = resp.forms[0].submit()
|
|
assert emails.emails.get('Tracking Code reminder')
|
|
assert 'ABCDEF' in emails.emails.values()[0]['payload']
|
|
assert resp.location == 'http://example.net/test/code/ABCDEF/load'
|
|
|
|
def test_form_invalid_tracking_code(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.StringField(id='0', label='string')]
|
|
formdef.enable_tracking_codes = True
|
|
formdef.store()
|
|
|
|
# create a secondary formdef, to always have the tracking code form
|
|
# displayed on homepage
|
|
formdef2 = FormDef()
|
|
formdef2.name = 'test2'
|
|
formdef2.fields = []
|
|
formdef2.enable_tracking_codes = True
|
|
formdef2.store()
|
|
|
|
resp = get_app(pub).get('/')
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {'0': 'foobar'}
|
|
formdata.store()
|
|
|
|
# check we can go back to it
|
|
formdef.data_class().wipe()
|
|
|
|
code = pub.tracking_code_class()
|
|
code.formdata = formdata
|
|
code.store()
|
|
|
|
resp.forms[0]['code'] = code.id
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % code.id
|
|
resp = resp.follow()
|
|
assert resp.location == 'http://example.net/test/%s' % formdata.id
|
|
resp = resp.follow()
|
|
|
|
# check we get a not found error message on non-existent code
|
|
fake_code = TrackingCode().get_new_id()
|
|
resp = get_app(pub).get('/')
|
|
resp.forms[0]['code'] = fake_code
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % fake_code
|
|
resp = resp.follow(status=404)
|
|
|
|
# check we also get an error if tracking code access is disabled after the
|
|
# fact
|
|
formdef.enable_tracking_codes = False
|
|
formdef.store()
|
|
resp = get_app(pub).get('/')
|
|
resp.forms[0]['code'] = code.id
|
|
resp = resp.forms[0].submit()
|
|
assert resp.location == 'http://example.net/code/%s/load' % code.id
|
|
resp = resp.follow(status=404)
|
|
|
|
def form_password_field_submit(pub, password):
|
|
password = unicode(password).encode(pub.site_charset)
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PasswordField(id='0', label='password',
|
|
formats=['sha1', 'md5', 'cleartext'])]
|
|
formdef.store()
|
|
page = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
next_page = page.forms[0].submit('submit') # but the field is required
|
|
assert '<div class="error">required field</div>' in next_page.body
|
|
next_page.forms[0]['f0$pwd1'] = password
|
|
next_page.forms[0]['f0$pwd2'] = password
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in next_page.body
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
data = formdef.data_class().get(data_id)
|
|
assert data.data == {'0': {
|
|
'sha1': hashlib.sha1(password).hexdigest(),
|
|
'md5': hashlib.md5(password).hexdigest(),
|
|
'cleartext': unicode(password, 'utf-8'),
|
|
}}
|
|
|
|
def test_form_password_field_submit(pub):
|
|
form_password_field_submit(pub, 'foobar')
|
|
form_password_field_submit(pub, u'foobar\u00eb')
|
|
|
|
def test_form_multi_page_formdef_count_condition(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.StringField(id='1', label='string'),
|
|
fields.PageField(id='2', label='2nd page', type='page',
|
|
condition='form_objects.count > 0'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.forms[0]['f1'] = 'foo'
|
|
resp = resp.forms[0].submit('submit') # should go straight to validation
|
|
assert 'Check values then click submit.' in resp.body
|
|
|
|
# add a formdata this will make the second page appear.
|
|
formdef.data_class()().store()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f1'] = 'foo'
|
|
resp = resp.forms[0].submit('submit') # should NOT go straight to validation
|
|
assert 'Check values then click submit.' not in resp.body
|
|
|
|
def test_form_multi_page_post_edit(pub):
|
|
user = create_user(pub)
|
|
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.StringField(id='1', label='string'),
|
|
fields.PageField(id='2', label='2nd page', type='page'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
|
|
workflow = Workflow(name='test')
|
|
st1 = workflow.add_status('Status1', 'st1')
|
|
editable = EditableWorkflowStatusItem()
|
|
editable.id = '_editable'
|
|
editable.by = ['_submitter', '_receiver']
|
|
st1.items.append(editable)
|
|
editable.parent = st1
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
formdef.data_class().wipe()
|
|
|
|
page = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
page.forms[0]['f1'] = 'foo'
|
|
next_page = page.forms[0].submit('submit')
|
|
next_page.forms[0]['f3'] = 'barXYZ'
|
|
next_page = next_page.forms[0].submit('submit')
|
|
next_page = next_page.forms[0].submit('submit')
|
|
next_page = next_page.follow()
|
|
assert 'The form has been recorded' in next_page.body
|
|
|
|
data_id = formdef.data_class().select()[0].id
|
|
|
|
page = login(get_app(pub), username='foo', password='foo').get('/test/%s/' % data_id)
|
|
assert 'button_editable-button' in page.body
|
|
assert 'barXYZ' in page.body
|
|
|
|
resp = page.forms[0].submit('button_editable')
|
|
assert resp.location == 'http://example.net/test/%s/wfedit' % data_id
|
|
resp = resp.follow()
|
|
assert resp.forms[0]['f1'].value == 'foo'
|
|
resp.forms[0]['f1'] = 'foo2'
|
|
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.forms[0]['f3'].value == 'barXYZ'
|
|
resp = resp.forms[0].submit('previous')
|
|
assert resp.forms[0]['f1'].value == 'foo2'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Save Changes' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.location == 'http://example.net/test/%s/' % data_id
|
|
resp = resp.follow()
|
|
assert 'foo2' in resp.body # modified value is there
|
|
assert 'barXYZ' in resp.body # unchanged value is still there
|
|
|
|
|
|
def test_form_count_dispatching(pub):
|
|
user = create_user(pub)
|
|
|
|
formdef = create_formdef()
|
|
formdef.fields = []
|
|
formdef.store()
|
|
|
|
workflow = Workflow(name='test')
|
|
st1 = workflow.add_status('Status1', 'st1')
|
|
jump = JumpWorkflowStatusItem()
|
|
jump.condition = 'form_objects.count_status_st2 < 1'
|
|
jump.status = 'st2'
|
|
st1.items.append(jump)
|
|
jump.parent = st1
|
|
st2 = workflow.add_status('Status2', 'st2')
|
|
workflow.store()
|
|
|
|
formdef.workflow_id = workflow.id
|
|
formdef.store()
|
|
|
|
formdef.data_class().wipe()
|
|
|
|
page = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
page = page.forms[0].submit('submit') # form page
|
|
page = page.forms[0].submit('submit') # confirmation page
|
|
page = page.follow()
|
|
assert 'The form has been recorded' in page.body # success
|
|
|
|
assert len(formdef.data_class().select(clause=lambda x: x.status == 'wf-st1')) == 0
|
|
assert len(formdef.data_class().select(clause=lambda x: x.status == 'wf-st2')) == 1
|
|
|
|
page = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
page = page.forms[0].submit('submit') # form page
|
|
page = page.forms[0].submit('submit') # confirmation page
|
|
page = page.follow()
|
|
assert 'The form has been recorded' in page.body # success
|
|
|
|
assert len(formdef.data_class().select(clause=lambda x: x.status == 'wf-st2')) == 1
|
|
assert len(formdef.data_class().select(clause=lambda x: x.status == 'wf-st1')) == 1
|
|
|
|
def test_preview_form(pub):
|
|
user = create_user(pub)
|
|
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = []
|
|
formdef.disabled = True
|
|
formdef.store()
|
|
|
|
# check the preview page is not accessible to regular users
|
|
get_app(pub).get('/preview/test/', status=403)
|
|
|
|
# check it's accessible to admins
|
|
user.is_admin = True
|
|
user.store()
|
|
page = login(get_app(pub), username='foo', password='foo').get('/preview/test/')
|
|
|
|
# check no formdata gets stored
|
|
next_page = page.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in next_page.body
|
|
next_page = next_page.forms[0].submit('submit')
|
|
assert next_page.status_int == 302
|
|
assert next_page.location == 'http://example.net/preview/test/'
|
|
assert formdef.data_class().count() == 0
|
|
|
|
def test_form_item_data_source_field_submit(pub):
|
|
def submit_item_data_source_field(ds):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.ItemField(id='0', label='string', data_source=ds)]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.forms[0]['f0'] = '1'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
return formdef.data_class().get(data_id).data
|
|
|
|
ds = {
|
|
'type': 'formula',
|
|
'value': repr([('1', 'un'), ('2', 'deux')]),
|
|
}
|
|
assert submit_item_data_source_field(ds) == {'0': '1', '0_display': 'un'}
|
|
|
|
ds['value'] = repr([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}])
|
|
assert submit_item_data_source_field(ds) == {'0': '1', '0_display': 'un'}
|
|
|
|
ds['value'] = repr([
|
|
{'id': '1', 'text': 'un', 'more': 'foo'},
|
|
{'id': '2', 'text': 'deux', 'more': 'bar'}])
|
|
assert submit_item_data_source_field(ds) == {
|
|
'0': '1', '0_display': 'un', '0_structured': {'id': '1', 'text': 'un', 'more': 'foo'}}
|
|
|
|
def test_form_items_data_source_field_submit(pub):
|
|
def submit_items_data_source_field(ds):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.ItemsField(id='0', label='string', data_source=ds)]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.forms[0]['f0$element1'].checked = True
|
|
resp.forms[0]['f0$element3'].checked = True
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
return formdef.data_class().get(data_id).data
|
|
|
|
ds = {
|
|
'type': 'formula',
|
|
'value': repr([('1', 'un'), ('2', 'deux'), ('3', 'trois')]),
|
|
}
|
|
assert submit_items_data_source_field(ds) == {'0': ['1', '3'], '0_display': 'un, trois'}
|
|
|
|
ds['value'] = repr([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'},
|
|
{'id': '3', 'text': 'trois'}])
|
|
assert submit_items_data_source_field(ds) == {'0': ['1', '3'], '0_display': 'un, trois'}
|
|
|
|
ds['value'] = repr([
|
|
{'id': '1', 'text': 'un', 'more': 'foo'},
|
|
{'id': '2', 'text': 'deux', 'more': 'bar'},
|
|
{'id': '3', 'text': 'trois', 'more': 'baz'}])
|
|
assert submit_items_data_source_field(ds) == {
|
|
'0': ['1', '3'],
|
|
'0_display': 'un, trois',
|
|
'0_structured': [
|
|
{'id': '1', 'more': 'foo', 'text': 'un'},
|
|
{'id': '3', 'more': 'baz', 'text': 'trois'}]}
|
|
|
|
def test_form_page_query_string_prefill(pub):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='string',
|
|
prefill={'type': 'formula', 'value': 'session_var_foo'})]
|
|
formdef.store()
|
|
|
|
# check it's empty if it doesn't exist
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
# check it's not set if it's not whitelisted
|
|
resp = get_app(pub).get('/?session_var_foo=hello')
|
|
assert resp.location == 'http://example.net/'
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
# check it works
|
|
open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').write('''[options]
|
|
query_string_allowed_vars = foo,bar
|
|
''')
|
|
|
|
resp = get_app(pub).get('/?session_var_foo=hello')
|
|
assert resp.location == 'http://example.net/'
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == 'hello'
|
|
|
|
# check it survives a login
|
|
resp = get_app(pub).get('/?session_var_foo=hello2')
|
|
assert resp.location == 'http://example.net/'
|
|
resp = resp.follow()
|
|
resp = resp.click('Login')
|
|
resp = resp.follow()
|
|
resp.forms[0]['username'] = 'foo'
|
|
resp.forms[0]['password'] = 'foo'
|
|
resp = resp.forms[0].submit()
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == 'hello2'
|
|
|
|
# check repeated options are ignored
|
|
resp = get_app(pub).get('/?session_var_foo=hello&session_var_foo=hello2')
|
|
assert resp.location == 'http://example.net/'
|
|
resp = resp.follow()
|
|
resp = resp.click('test')
|
|
assert resp.forms[0]['f0'].value == ''
|
|
|
|
# check extra query string parameters are not lost
|
|
resp = get_app(pub).get('/?session_var_foo=hello&foo=bar')
|
|
assert resp.location == 'http://example.net/?foo=bar'
|
|
|
|
os.unlink(os.path.join(pub.app_dir, 'site-options.cfg'))
|
|
|
|
def test_form_captcha(pub):
|
|
user = create_user(pub)
|
|
formdef = create_formdef()
|
|
formdef.data_class().wipe()
|
|
formdef.fields = [fields.StringField(id='0', label='Some field')]
|
|
formdef.has_captcha = True
|
|
formdef.store()
|
|
|
|
# test authentic users are not presented with a captcha
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/')
|
|
resp = resp.click('test')
|
|
assert 'Some field' in resp.body
|
|
|
|
# check anonymous user gets the captcha
|
|
app = get_app(pub)
|
|
resp = app.get('/')
|
|
resp = resp.click('test')
|
|
assert 'form_captcha' in resp.body
|
|
|
|
session_id = app.cookies.values()[0].strip('"')
|
|
session = BasicSession.get(session_id)
|
|
resp.forms[0]['captcha$q'] = session.get_captcha_token(resp.forms[0]['captcha$token'].value)['answer']
|
|
resp = resp.forms[0].submit()
|
|
assert 'Some field' in resp.body
|
|
|
|
# and check it gets it only once
|
|
resp = app.get('/')
|
|
resp = resp.click('test')
|
|
assert 'Some field' in resp.body
|
|
|
|
def test_form_file_field_submit(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.FileField(id='0', label='file')]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
upload = Upload('test.txt', 'foobar', 'text/plain')
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f0$file'] = upload
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
resp = resp.click('test.txt')
|
|
assert resp.location.endswith('/test.txt')
|
|
resp = resp.follow()
|
|
assert resp.content_type == 'text/plain'
|
|
assert resp.body == 'foobar'
|
|
|
|
def test_formdata_attachment_download(pub):
|
|
create_user(pub)
|
|
wf = Workflow(name='status')
|
|
st1 = wf.add_status('Status1', 'st1')
|
|
attach = AddAttachmentWorkflowStatusItem()
|
|
attach.id = '_attach'
|
|
attach.by = ['_submitter']
|
|
st1.items.append(attach)
|
|
attach.parent = st1
|
|
wf.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.workflow_id = wf.id
|
|
formdef.fields = []
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
|
|
resp.forms[0]['attachment_attach'] = Upload('test.txt', 'foobar', 'text/plain')
|
|
resp = resp.forms[0].submit('button_attach')
|
|
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.evolution[-1].parts[0].__class__.__name__ == 'AttachmentEvolutionPart'
|
|
attachment = formdata.evolution[-1].parts[0]
|
|
assert attachment.content_type == 'text/plain'
|
|
assert attachment.orig_filename == 'test.txt'
|
|
|
|
resp = resp.follow() # back to form page
|
|
resp = resp.click('test.txt')
|
|
assert resp.location.endswith('/test.txt')
|
|
resp = resp.follow()
|
|
assert resp.content_type == 'text/plain'
|
|
assert resp.body == 'foobar'
|
|
|
|
def test_formdata_generated_document_download(pub):
|
|
create_user(pub)
|
|
wf = Workflow(name='status')
|
|
st1 = wf.add_status('Status1', 'st1')
|
|
export_to = ExportToModel()
|
|
export_to.label = 'create doc'
|
|
upload = QuixoteUpload('/foo/test.rtf', content_type='text/rtf')
|
|
upload.fp = StringIO.StringIO()
|
|
upload.fp.write('HELLO WORLD')
|
|
upload.fp.seek(0)
|
|
export_to.model_file = UploadedFile(pub.app_dir, None, upload)
|
|
export_to.id = '_export_to'
|
|
export_to.by = ['_submitter']
|
|
st1.items.append(export_to)
|
|
export_to.parent = st1
|
|
wf.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.workflow_id = wf.id
|
|
formdef.fields = []
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
form_location = resp.location
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
|
|
resp = resp.form.submit('button_export_to')
|
|
|
|
resp = resp.follow() # $form/$id/create_doc
|
|
resp = resp.follow() # $form/$id/create_doc/
|
|
assert resp.body == 'HELLO WORLD'
|
|
|
|
export_to.attach_to_history = True
|
|
wf.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get(form_location)
|
|
resp = resp.form.submit('button_export_to')
|
|
assert resp.location == form_location
|
|
resp = resp.follow() # back to form page
|
|
|
|
resp = resp.click('test.rtf')
|
|
assert resp.location.endswith('/test.rtf')
|
|
resp = resp.follow()
|
|
assert resp.content_type == 'text/rtf'
|
|
assert resp.body == 'HELLO WORLD'
|
|
|
|
# change file content, same name
|
|
upload = QuixoteUpload('/foo/test.rtf', content_type='text/rtf')
|
|
upload.fp = StringIO.StringIO()
|
|
upload.fp.write('HELLO NEW WORLD')
|
|
upload.fp.seek(0)
|
|
export_to.model_file = UploadedFile(pub.app_dir, None, upload)
|
|
wf.store()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get(form_location)
|
|
resp = resp.form.submit('button_export_to')
|
|
assert resp.location == form_location
|
|
resp = resp.follow() # back to form page
|
|
|
|
assert resp.click('test.rtf', index=0).follow().body == 'HELLO WORLD'
|
|
assert resp.click('test.rtf', index=1).follow().body == 'HELLO NEW WORLD'
|
|
|
|
def test_formdata_form_file_download(pub):
|
|
create_user(pub)
|
|
wf = Workflow(name='status')
|
|
st1 = wf.add_status('Status1', 'st1')
|
|
|
|
display_form = FormWorkflowStatusItem()
|
|
display_form.id = '_x'
|
|
display_form.by = ['_submitter']
|
|
display_form.varname = 'xxx'
|
|
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
|
|
display_form.formdef.fields.append(fields.FileField(id='1', label='File',
|
|
type='file', varname='yyy'))
|
|
st1.items.append(display_form)
|
|
display_form.parent = st1
|
|
|
|
wf.store()
|
|
|
|
formdef = create_formdef()
|
|
formdef.workflow_id = wf.id
|
|
formdef.fields = []
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
|
|
resp.forms[0]['f1$file'] = Upload('test.txt', 'foobar', 'text/plain')
|
|
resp = resp.forms[0].submit('submit')
|
|
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert 'xxx_var_yyy_raw' in formdata.workflow_data
|
|
|
|
download = resp.test_app.get(resp.location + 'files/form-xxx-yyy/test.txt')
|
|
assert download.content_type == 'text/plain'
|
|
assert download.body == 'foobar'
|
|
|
|
# go back to the status page, this will exercise the substitution variables
|
|
# codepath.
|
|
resp = resp.follow()
|
|
|
|
def test_form_map_field_back_and_submit(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [
|
|
fields.MapField(id='0', label='map'),
|
|
fields.StringField(id='1', label='street', required=False,
|
|
prefill={'type': 'geolocation', 'value': 'road'}),
|
|
]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
assert 'qommon.map.js' in resp.body
|
|
assert 'qommon.geolocation.js' in resp.body
|
|
# with a real user interaction this would get set by javascript
|
|
resp.forms[0]['f0$latlng'] = '1.234;-1.234'
|
|
assert 'data-geolocation="road"' in resp.body
|
|
|
|
# check summary page
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
assert 'data-init-lng="-1.234"' in resp.body
|
|
assert 'data-init-lat="1.234"' in resp.body
|
|
|
|
# get back to the map field
|
|
resp = resp.forms[0].submit('previous')
|
|
# check the field is still marked as holding the road
|
|
assert 'data-geolocation="road"' in resp.body
|
|
assert resp.forms[0]['f0$latlng'].value == '1.234;-1.234'
|
|
|
|
# back to summary page
|
|
resp = resp.forms[0].submit('submit')
|
|
|
|
# and submitting the form
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
data = formdef.data_class().get(data_id)
|
|
assert data.data == {'1': None, '0': '1.234;-1.234'}
|
|
|
|
def test_form_map_multi_page(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.MapField(id='1', label='map'),
|
|
fields.PageField(id='2', label='2nd page', type='page'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
resp = get_app(pub).get('/test/')
|
|
formdef.data_class().wipe()
|
|
resp.forms[0]['f1$latlng'] = '1.234;-1.234'
|
|
assert resp.forms[0].fields['submit'][0].value_if_submitted() == 'Next'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.forms[0]['previous']
|
|
resp.forms[0]['f3'] = 'bar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.forms[0]['f1$latlng'].value == '1.234;-1.234'
|
|
assert 'Check values then click submit.' in resp.body
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.status_int == 302
|
|
resp = resp.follow()
|
|
assert 'The form has been recorded' in resp.body
|
|
assert formdef.data_class().count() == 1
|
|
data_id = formdef.data_class().select()[0].id
|
|
data = formdef.data_class().get(data_id)
|
|
assert data.data == {'1': '1.234;-1.234', '3': 'bar'}
|
|
|
|
def test_form_middle_session_change(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.StringField(id='1', label='string'),
|
|
fields.PageField(id='2', label='2nd page', type='page'),
|
|
fields.StringField(id='3', label='string 2')]
|
|
formdef.store()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
resp.forms[0]['f1'] = 'foo'
|
|
assert resp.forms[0].fields['submit'][0].value_if_submitted() == 'Next'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.forms[0]['previous']
|
|
app.cookiejar.clear()
|
|
resp.forms[0]['f3'] = 'bar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.location == 'http://example.net/test/'
|
|
resp = resp.follow()
|
|
assert 'Sorry, your session have been lost.' in resp.body
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
resp.forms[0]['f1'] = 'foo'
|
|
assert resp.forms[0].fields['submit'][0].value_if_submitted() == 'Next'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert resp.forms[0]['previous']
|
|
resp.forms[0]['f3'] = 'bar'
|
|
resp = resp.forms[0].submit('submit')
|
|
assert 'Check values then click submit.' in resp.body
|
|
app.cookiejar.clear()
|
|
resp = resp.forms[0].submit('submit')
|
|
resp = resp.follow()
|
|
assert 'Sorry, your session have been lost.' in resp.body
|
|
|
|
def test_form_autocomplete_variadic_url(pub):
|
|
formdef = create_formdef()
|
|
formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
|
|
fields.ItemField(id='1', label='string', type='item',
|
|
varname='foo', items=['Foo', 'Bar']),
|
|
fields.StringField(id='2', label='string2',
|
|
data_source={'type': 'jsonp', 'value': '[var_foo]'}),
|
|
fields.PageField(id='3', label='2nd page', type='page',
|
|
condition='foo == "Foo"'),
|
|
]
|
|
formdef.store()
|
|
|
|
formdef.data_class().wipe()
|
|
resp = get_app(pub).get('/test/')
|
|
# test javascript will be used to compute the full URL
|
|
assert 'options.wcs_base_url' in resp.body
|