wcs/tests/api/test_export_import.py

750 lines
26 KiB
Python

import io
import json
import os
import tarfile
import xml.etree.ElementTree as ET
import pytest
from wcs.blocks import BlockDef
from wcs.carddef import CardDef
from wcs.categories import (
BlockCategory,
CardDefCategory,
Category,
CommentTemplateCategory,
DataSourceCategory,
MailTemplateCategory,
WorkflowCategory,
)
from wcs.comment_templates import CommentTemplate
from wcs.data_sources import NamedDataSource
from wcs.fields import BlockField, CommentField, PageField, StringField
from wcs.formdef import FormDef
from wcs.mail_templates import MailTemplate
from wcs.wf.form import WorkflowFormFieldsFormDef
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef, WorkflowVariablesFieldsFormDef
from wcs.wscalls import NamedWsCall
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app
from .utils import sign_uri
@pytest.fixture
def pub():
pub = create_temporary_pub()
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
fd.write(
'''\
[api-secrets]
coucou = 1234
'''
)
Category.wipe()
FormDef.wipe()
CardDefCategory.wipe()
CardDef.wipe()
BlockCategory.wipe()
BlockDef.wipe()
WorkflowCategory.wipe()
Workflow.wipe()
MailTemplateCategory.wipe()
MailTemplate.wipe()
CommentTemplateCategory.wipe()
CommentTemplate.wipe()
DataSourceCategory.wipe()
NamedDataSource.wipe()
NamedWsCall.wipe()
return pub
def teardown_module(module):
clean_temporary_pub()
def test_export_import_index(pub):
get_app(pub).get('/api/export-import/', status=403)
resp = get_app(pub).get(sign_uri('/api/export-import/'))
assert resp.json['data'][0]['id'] == 'forms'
assert resp.json['data'][0]['text'] == 'Forms'
assert resp.json['data'][0]['urls']['list'] == 'http://example.net/api/export-import/forms/'
def test_export_import_list_forms(pub):
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
assert not resp.json['data']
formdef = FormDef()
formdef.name = 'Test'
formdef.store()
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
assert resp.json['data'][0]['id'] == 'test'
assert resp.json['data'][0]['text'] == 'Test'
assert resp.json['data'][0]['category'] is None
category = Category(name='Test')
category.store()
formdef.category = category
formdef.store()
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
assert resp.json['data'][0]['id'] == 'test'
assert resp.json['data'][0]['text'] == 'Test'
assert resp.json['data'][0]['category'] == 'Test'
def test_export_import_list_404(pub):
get_app(pub).get(sign_uri('/api/export-import/xxx/'), status=404)
def test_export_import_form(pub):
formdef = FormDef()
formdef.name = 'Test'
formdef.store()
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['export']))
assert resp.text.startswith('<formdef ')
def test_export_import_form_404(pub):
get_app(pub).get(sign_uri('/api/export-import/xxx/plop/'), status=404)
get_app(pub).get(sign_uri('/api/export-import/forms/plop/'), status=404)
def test_export_import_form_dependencies_404(pub):
get_app(pub).get(sign_uri('/api/export-import/forms/plop/dependencies/'), status=404)
def test_export_import_dependencies(pub):
role = pub.role_class(name='Test role')
role.store()
role2 = pub.role_class(name='Second role')
role2.store()
role3 = pub.role_class(name='Third role')
role3.store()
wscall = NamedWsCall(name='Test')
wscall.store()
wscall = NamedWsCall(name='Test bis')
wscall.store()
wscall = NamedWsCall(name='Test ter')
wscall.store()
wscall = NamedWsCall(name='Test quater')
wscall.store()
wscall = NamedWsCall(name='Test quinquies')
wscall.store()
wscall = NamedWsCall(name='Test sexies')
wscall.store()
carddef = CardDef()
carddef.name = 'Test'
carddef.store()
carddef = CardDef()
carddef.name = 'Test bis'
carddef.store()
carddef = CardDef()
carddef.name = 'Test ter'
carddef.store()
carddef = CardDef()
carddef.name = 'Test quater'
carddef.store()
formdef = FormDef()
formdef.name = 'Test bis'
formdef.store()
formdef = FormDef()
formdef.name = 'Test ter'
formdef.store()
formdef = FormDef()
formdef.name = 'Test quater'
formdef.store()
formdef = FormDef()
formdef.name = 'Test quinquies'
formdef.store()
formdef = FormDef()
formdef.name = 'Test'
formdef.store()
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
assert not resp.json['data']
formdef.roles = ['logged-users']
formdef.backoffice_submission_roles = [role2.id]
formdef.workflow_roles = {'_receiver': role3.id}
formdef.store()
block = BlockDef(name='test')
block.store()
workflow = Workflow(name='test')
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
workflow.backoffice_fields_formdef.fields = [
BlockField(id='bo1', label='test', type='block:test'),
]
workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
workflow.variables_formdef.fields = [StringField(label='Test', id='1')]
status = workflow.add_status('New')
action = status.add_action('form')
action.by = [role.id]
data_source = NamedDataSource(name='foobar')
data_source.store()
display_form = status.add_action('form', id='_x')
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
display_form.formdef.fields.append(
StringField(
label='Test',
data_source={'type': 'foobar'},
prefill={'type': 'string', 'value': '{{ webservice.test_bis.plop }}'},
)
)
display_form.formdef.fields.append(
StringField(
label='Test',
data_source={'type': 'foobar'},
prefill={'type': 'string', 'value': '{{ webservice.unknown }}'},
)
)
display_form.formdef.fields.append(
StringField(
label='Test',
data_source={'type': 'foobar'},
prefill={'type': 'string', 'value': '{{ cards|objects:"unknown" }}'},
)
)
display_form.formdef.fields.append(
StringField(
label='Test',
data_source={'type': 'foobar'},
prefill={'type': 'string', 'value': '{{ cards|objects:"test-bis" }}'},
)
)
display_form.formdef.fields.append(
StringField(
label='Test',
data_source={'type': 'foobar'},
prefill={'type': 'string', 'value': '{{ forms|objects:"test-bis" }}'},
)
)
display_form.formdef.fields.append(
StringField(
label='Test',
data_source={'type': 'foobar'},
prefill={'type': 'string', 'value': '{{ forms|objects:"unknown" }}'},
)
)
send_mail = status.add_action('sendmail')
send_mail.to = [role.id]
send_mail.subject = '{{ webservice.test }}'
send_mail.body = '{{ cards|objects:"test" }} {{ forms|objects:"test-ter" }}'
send_mail.condition = {
'type': 'django',
'value': '{{ cards|objects:"test-ter" }} {{ webservice.test_ter }}',
}
register_comment = status.add_action('register-comment')
register_comment.to = [role.id]
register_comment.comment = (
'{{ cards|objects:"test-quater" }} {{ forms|objects:"test-quinquies" }} {{ webservice.test_sexies }}'
)
dispatch_auto = status.add_action('dispatch')
dispatch_auto.rules = [{'role_id': role.id, 'value': 'xxx'}]
status.add_action('dispatch') # unconfigured/manual dispatch
workflow.store()
formdef.fields = [
PageField(
id='0',
label='Page',
type='page',
post_conditions=[
{
'condition': {
'type': 'django',
'value': '{{ cards|objects:"test-bis" }} {{ forms|objects:"test-quater" }} {{ webservice.test_quater }}',
},
'error_message': 'You shall not pass.',
}
],
),
BlockField(
id='1',
label='test',
type='block:test',
condition={
'type': 'django',
'value': '{{ forms|objects:"test-bis" }} {{ webservice.test_quinquies }}',
},
),
CommentField(
id='2',
label='X {{ webservice.test }} X {{ cards|objects:"test" }} X {{ forms|objects:"test-ter" }} X',
type='comment',
),
]
formdef.workflow = workflow
formdef.store()
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
form_data = [d for d in resp.json['data'] if d['id'] == 'test']
resp = get_app(pub).get(sign_uri(form_data[0]['urls']['dependencies']))
assert {(x['id'], x['type']) for x in resp.json['data']} == {
('test', 'workflows'),
('test', 'blocks'),
('test', 'wscalls'),
('test_quater', 'wscalls'),
('test_quinquies', 'wscalls'),
('test', 'cards'),
('test-bis', 'cards'),
('test-bis', 'forms'),
('test-ter', 'forms'),
('test-quater', 'forms'),
('second-role', 'roles'),
('third-role', 'roles'),
}
for dependency in resp.json['data']:
get_app(pub).get(sign_uri(dependency['urls']['export']))
resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
assert {(x['id'], x['type']) for x in resp.json['data']} == {
('foobar', 'data-sources'),
('test', 'wscalls'),
('test_bis', 'wscalls'),
('test_ter', 'wscalls'),
('test_sexies', 'wscalls'),
('test', 'cards'),
('test-bis', 'cards'),
('test-ter', 'cards'),
('test-quater', 'cards'),
('test-ter', 'forms'),
('test-bis', 'forms'),
('test-quinquies', 'forms'),
('test', 'blocks'),
('test-role', 'roles'),
}
for dependency in resp.json['data']:
resp = get_app(pub).get(sign_uri(dependency['urls']['export']))
if 'test-role' in dependency['urls']['export']:
assert resp.json == {'name': 'Test role', 'slug': 'test-role', 'uuid': None}
assert resp.content_type == 'application/json'
else:
assert resp.content_type == 'text/xml'
mail_template = MailTemplate(name='test mail template')
mail_template.store()
send_mail.mail_template = mail_template.slug
comment_template = CommentTemplate(name='test comment template')
comment_template.store()
register_comment.comment_template = comment_template.slug
workflow.store()
resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
assert {(x['id'], x['type']) for x in resp.json['data']} == {
('foobar', 'data-sources'),
('test_bis', 'wscalls'),
('test_ter', 'wscalls'),
('test-bis', 'cards'),
('test-ter', 'cards'),
('test-bis', 'forms'),
('test', 'blocks'),
('test-mail-template', 'mail-templates'),
('test-comment-template', 'comment-templates'),
('test-role', 'roles'),
}
for dependency in resp.json['data']:
get_app(pub).get(sign_uri(dependency['urls']['export']))
resp = get_app(pub).get(sign_uri(resp.json['data'][-1]['urls']['dependencies']))
assert resp.json['data'] == []
cat = MailTemplateCategory(name='Cat')
cat.store()
mail_template.category_id = cat.id
mail_template.subject = '{{ webservice.test }}'
mail_template.body = '{{ cards|objects:"test" }} {{ forms|objects:"test-ter" }}'
mail_template.store()
resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
mail_template_entry = [x for x in resp.json['data'] if x['type'] == 'mail-templates'][0]
resp = get_app(pub).get(sign_uri(mail_template_entry['urls']['dependencies']))
assert {(x['id'], x['type']) for x in resp.json['data']} == {
('cat', 'mail-templates-categories'),
('test', 'cards'),
('test', 'wscalls'),
('test-ter', 'forms'),
}
for dependency in resp.json['data']:
get_app(pub).get(sign_uri(dependency['urls']['export']))
cat = CommentTemplateCategory(name='Cat')
cat.store()
comment_template.category_id = cat.id
comment_template.comment = (
'{{ cards|objects:"test-quater" }} {{ forms|objects:"test-quinquies" }} {{ webservice.test_sexies }}'
)
comment_template.store()
resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
comment_template_entry = [x for x in resp.json['data'] if x['type'] == 'comment-templates'][0]
resp = get_app(pub).get(sign_uri(comment_template_entry['urls']['dependencies']))
assert {(x['id'], x['type']) for x in resp.json['data']} == {
('cat', 'comment-templates-categories'),
('test-quater', 'cards'),
('test-quinquies', 'forms'),
('test_sexies', 'wscalls'),
}
for dependency in resp.json['data']:
get_app(pub).get(sign_uri(dependency['urls']['export']))
resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
resp = get_app(pub).get(sign_uri(resp.json['data'][1]['urls']['dependencies']))
assert resp.json['data'] == []
cat = DataSourceCategory(name='Cat')
cat.store()
data_source.category_id = cat.id
data_source.store()
resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
data_sources_entry = [x for x in resp.json['data'] if x['type'] == 'data-sources'][0]
resp = get_app(pub).get(sign_uri(data_sources_entry['urls']['dependencies']))
assert {(x['id'], x['type']) for x in resp.json['data']} == {('cat', 'data-sources-categories')}
def test_export_import_dependencies_default_workflow(pub):
formdef = FormDef()
formdef.name = 'Test'
formdef.workflow_id = '_default'
formdef.store()
carddef = CardDef()
carddef.name = 'Test'
carddef.workflow_id = '_carddef_default'
carddef.store()
resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
assert resp.json['data'] == []
resp = get_app(pub).get(sign_uri('/api/export-import/cards/'))
resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
assert resp.json['data'] == []
def test_export_import_redirect_url(pub):
workflow = Workflow(name='test')
workflow.store()
block = BlockDef(name='test')
block.store()
formdef = FormDef()
formdef.name = 'Test'
formdef.store()
carddef = CardDef()
carddef.name = 'Test'
carddef.store()
category = Category(name='Test')
category.store()
data_source = NamedDataSource(name='Test')
data_source.store()
ds_category = DataSourceCategory(name='Test')
ds_category.store()
mail_template = MailTemplate(name='Test')
mail_template.store()
mail_template_category = MailTemplateCategory(name='Test')
mail_template_category.store()
elements = [
('forms', '/backoffice/forms/%s/' % formdef.id),
('cards', '/backoffice/cards/%s/' % carddef.id),
('blocks', '/backoffice/forms/blocks/%s/' % block.id),
('workflows', '/backoffice/workflows/%s/' % workflow.id),
('forms-categories', '/backoffice/forms/categories/%s/' % category.id),
('data-sources', '/backoffice/settings/data-sources/%s/' % data_source.id),
(
'data-sources-categories',
'/backoffice/forms/data-sources/categories/%s/' % ds_category.id,
),
('mail-templates', '/backoffice/workflows/mail-templates/%s/' % mail_template.id),
(
'mail-templates-categories',
'/backoffice/workflows/mail-templates/categories/%s/' % mail_template_category.id,
),
]
for object_type, obj_url in elements:
resp = get_app(pub).get(sign_uri('/api/export-import/%s/' % object_type))
assert (
resp.json['data'][0]['urls']['redirect']
== 'http://example.net/api/export-import/%s/test/redirect/' % object_type
)
resp = get_app(pub).get(resp.json['data'][0]['urls']['redirect'], status=302)
assert resp.location == 'http://example.net%s' % obj_url
get_app(pub).get('/api/export-import/%s/unknown/redirect/' % object_type, status=404)
role = pub.role_class(name='test')
role.store()
resp = get_app(pub).get(sign_uri('/api/export-import/roles/'))
assert resp.json['data'][0]['urls'].get('redirect') is None
get_app(pub).get('/api/export-import/roles/test/redirect/', status=404)
def create_bundle(elements, *args):
tar_io = io.BytesIO()
with tarfile.open(mode='w', fileobj=tar_io) as tar:
manifest_json = {
'application': 'Test',
'slug': 'test',
'description': '',
'elements': elements,
}
manifest_fd = io.BytesIO(json.dumps(manifest_json, indent=2).encode())
tarinfo = tarfile.TarInfo('manifest.json')
tarinfo.size = len(manifest_fd.getvalue())
tar.addfile(tarinfo, fileobj=manifest_fd)
for (path, obj) in args:
tarinfo = tarfile.TarInfo(path)
if hasattr(obj, 'export_for_application'):
export, _ = obj.export_for_application()
export = export.encode()
else:
export = ET.tostring(obj.export_to_xml(include_id=True))
tarinfo.size = len(export)
tar.addfile(tarinfo, fileobj=io.BytesIO(export))
return tar_io.getvalue()
def test_export_import_bundle_import(pub):
workflow_category = WorkflowCategory(name='test')
workflow_category.store()
workflow = Workflow(name='test')
workflow.roles = {'_receiver': 'Receiver'}
workflow.category = workflow_category
workflow.store()
block_category = BlockCategory(name='test')
block_category.store()
block = BlockDef(name='test')
block.category = block_category
block.store()
role = pub.role_class(name='test')
role.store()
category = Category(name='Test')
category.store()
formdef = FormDef()
formdef.name = 'Test'
formdef.fields = [
BlockField(id='1', label='test', type='block:test'),
]
formdef.workflow = workflow
formdef.workflow_roles = {'_receiver': role.id}
formdef.disabled = False
formdef.category = category
formdef.store()
custom_view = pub.custom_view_class()
custom_view.title = 'shared formdef custom view'
custom_view.formdef = formdef
custom_view.columns = {'list': [{'id': '1'}]}
custom_view.filters = {}
custom_view.visibility = 'any'
custom_view.store()
card_category = CardDefCategory(name='Test')
card_category.store()
carddef = CardDef()
carddef.name = 'Test'
carddef.category = card_category
carddef.store()
ds_category = DataSourceCategory(name='Test')
ds_category.store()
data_source = NamedDataSource(name='Test')
data_source.category = ds_category
data_source.store()
mail_template_category = MailTemplateCategory(name='Test')
mail_template_category.store()
mail_template = MailTemplate(name='Test')
mail_template.category = mail_template_category
mail_template.store()
wscall = NamedWsCall(name='Test')
wscall.store()
bundle = create_bundle(
[
{'type': 'forms-categories', 'slug': 'test', 'name': 'test'},
{'type': 'forms', 'slug': 'test', 'name': 'test'},
{'type': 'cards-categories', 'slug': 'test', 'name': 'test'},
{'type': 'cards', 'slug': 'test', 'name': 'test'},
{'type': 'blocks-categories', 'slug': 'test', 'name': 'test'},
{'type': 'blocks', 'slug': 'test', 'name': 'test'},
{'type': 'roles', 'slug': 'test', 'name': 'test'},
{'type': 'workflows-categories', 'slug': 'test', 'name': 'test'},
{'type': 'workflows', 'slug': 'test', 'name': 'test'},
{'type': 'mail-templates-categories', 'slug': 'test', 'name': 'test'},
{'type': 'mail-templates', 'slug': 'test', 'name': 'test'},
{'type': 'data-sources-categories', 'slug': 'test', 'name': 'test'},
{'type': 'data-sources', 'slug': 'test', 'name': 'test'},
{'type': 'wscalls', 'slug': 'test', 'name': 'test'},
],
('forms-categories/test', category),
('forms/test', formdef),
('cards-categories/test', card_category),
('cards/test', carddef),
('blocks-categories/test', block_category),
('blocks/test', block),
('workflows-categories/test', workflow_category),
('workflows/test', workflow),
('data-sources-categories/test', ds_category),
('data-sources/test', data_source),
('mail-templates-categories/test', mail_template_category),
('mail-templates/test', mail_template),
('roles/test', role),
('wscalls/test', wscall),
)
Category.wipe()
FormDef.wipe()
CardDefCategory.wipe()
CardDef.wipe()
BlockCategory.wipe()
BlockDef.wipe()
WorkflowCategory.wipe()
Workflow.wipe()
MailTemplateCategory.wipe()
MailTemplate.wipe()
DataSourceCategory.wipe()
NamedDataSource.wipe()
pub.role_class.wipe()
pub.custom_view_class.wipe()
NamedWsCall.wipe()
# roles will be created beforehand with authentic provisionning
extra_role = pub.role_class(name='not this one')
extra_role.store()
role = pub.role_class(name='test')
role.store()
resp = get_app(pub).put(sign_uri('/api/export-import/bundle-import/'), bundle)
afterjob_url = resp.json['url']
resp = get_app(pub).put(sign_uri(afterjob_url))
assert resp.json['data']['status'] == 'completed'
assert resp.json['data']['completion_status'] == '17/17 (100%)'
assert Category.count() == 1
assert FormDef.count() == 1
assert FormDef.select()[0].fields[0].type == 'block:test'
assert FormDef.select()[0].workflow_roles == {'_receiver': role.id}
assert FormDef.select()[0].category_id == Category.select()[0].id
assert CardDefCategory.count() == 1
assert CardDef.count() == 1
assert CardDef.select()[0].category_id == CardDefCategory.select()[0].id
assert BlockCategory.count() == 1
assert BlockDef.count() == 1
assert BlockDef.select()[0].category_id == BlockCategory.select()[0].id
assert WorkflowCategory.count() == 1
assert Workflow.count() == 1
assert Workflow.select()[0].category_id == WorkflowCategory.select()[0].id
assert MailTemplateCategory.count() == 1
assert MailTemplate.count() == 1
assert MailTemplate.select()[0].category_id == MailTemplateCategory.select()[0].id
assert DataSourceCategory.count() == 1
assert NamedDataSource.count() == 1
assert NamedDataSource.select()[0].category_id == DataSourceCategory.select()[0].id
assert NamedWsCall.count() == 1
assert pub.custom_view_class().count() == 1
# run new import to check it doesn't duplicate objects
resp = get_app(pub).put(sign_uri('/api/export-import/bundle-import/'), bundle)
afterjob_url = resp.json['url']
resp = get_app(pub).put(sign_uri(afterjob_url))
assert resp.json['data']['status'] == 'completed'
assert Category.count() == 1
assert FormDef.count() == 1
assert CardDefCategory.count() == 1
assert CardDef.count() == 1
assert BlockCategory.count() == 1
assert BlockDef.count() == 1
assert WorkflowCategory.count() == 1
assert Workflow.count() == 1
assert MailTemplateCategory.count() == 1
assert MailTemplate.count() == 1
assert DataSourceCategory.count() == 1
assert NamedDataSource.count() == 1
assert pub.custom_view_class().count() == 1
assert NamedWsCall.count() == 1
# change immutable attributes and check they are not reset
formdef = FormDef.select()[0]
formdef.workflow_roles = {'_receiver': extra_role.id}
formdef.disabled = True
formdef.store()
resp = get_app(pub).put(sign_uri('/api/export-import/bundle-import/'), bundle)
afterjob_url = resp.json['url']
resp = get_app(pub).put(sign_uri(afterjob_url))
assert resp.json['data']['status'] == 'completed'
formdef = FormDef.select()[0]
assert formdef.disabled is True
assert formdef.workflow_roles == {'_receiver': extra_role.id}
def test_export_import_formdef_do_not_overwrite_table_name(pub):
formdef = FormDef()
formdef.name = 'Test2'
formdef.fields = []
formdef.disabled = False
formdef.store()
assert formdef.table_name == 'formdata_%s_test2' % formdef.id
formdata = formdef.data_class()()
formdata.just_created()
formdata.store()
# change formdef url name, internal table name won't be changed
formdef.url_name = 'test'
formdef.store()
assert formdef.table_name == 'formdata_%s_test2' % formdef.id
assert formdef.data_class().count() == 1
bundle = create_bundle([{'type': 'forms', 'slug': 'test', 'name': 'test'}], ('forms/test', formdef))
resp = get_app(pub).put(sign_uri('/api/export-import/bundle-import/'), bundle)
afterjob_url = resp.json['url']
resp = get_app(pub).put(sign_uri(afterjob_url))
assert resp.json['data']['status'] == 'completed'
# check table name is not overwritten
formdef = FormDef.select()[0]
assert formdef.table_name == 'formdata_%s_test2' % formdef.id
assert formdef.data_class().count() == 1