hobo/tests/test_application.py

263 lines
8.5 KiB
Python

import io
import json
import tarfile
import pytest
from httmock import HTTMock
from test_manager import login
from webtest import Upload
from hobo.applications.models import Application
from hobo.environment.models import Wcs
pytestmark = pytest.mark.django_db
WCS_AVAILABLE_OBJECTS = {
"data": [
{
"id": "forms",
"text": "Forms",
"singular": "Form",
"urls": {"list": "https://wcs.example.invalid/api/export-import/forms/"},
},
{
"id": "cards",
"text": "Card Models",
"singular": "Card Model",
"urls": {"list": "https://wcs.example.invalid/api/export-import/cards/"},
},
{
"id": "workflows",
"text": "Workflows",
"singular": "Workflow",
"urls": {"list": "https://wcs.example.invalid/api/export-import/workflows/"},
},
{
"id": "blocks",
"text": "Blocks",
"singular": "Block of fields",
"minor": True,
"urls": {"list": "https://wcs.example.invalid/api/export-import/blocks/"},
},
{
"id": "data-sources",
"text": "Data Sources",
"singular": "Data Source",
"minor": True,
"urls": {"list": "https://wcs.example.invalid/api/export-import/data-sources/"},
},
{
"id": "mail-templates",
"text": "Mail Templates",
"singular": "Mail Template",
"minor": True,
"urls": {"list": "https://wcs.example.invalid/api/export-import/mail-templates/"},
},
{
"id": "wscalls",
"text": "Webservice Calls",
"singular": "Webservice Call",
"minor": True,
"urls": {"list": "https://wcs.example.invalid/api/export-import/wscalls/"},
},
]
}
WCS_AVAILABLE_FORMS = {
"data": [
{
"id": "test-form",
"text": "Test Form",
"type": "forms",
"urls": {
"export": "https://wcs.example.invalid/api/export-import/forms/test-form/",
"dependencies": "https://wcs.example.invalid/api/export-import/forms/test-form/dependencies/",
},
},
{
"id": "test2-form",
"text": "Second Test Form",
"type": "forms",
"urls": {
"export": "https://wcs.example.invalid/api/export-import/forms/test2-form/",
"dependencies": "https://wcs.example.invalid/api/export-import/forms/test2-form/dependencies/",
},
},
]
}
WCS_FORM_DEPENDENCIES = {
"data": [
{
"id": "test-card",
"text": "Test Card",
"type": "cards",
"urls": {
"export": "https://wcs.example.invalid/api/export-import/cards/test-card/",
"dependencies": "https://wcs.example.invalid/api/export-import/cards/test-card/dependencies/",
},
}
]
}
def mocked_http(url, request):
assert '&signature=' in url.query
if url.netloc == 'wcs.example.invalid' and url.path == '/api/export-import/':
return {'content': json.dumps(WCS_AVAILABLE_OBJECTS), 'status_code': 200}
if url.path == '/api/export-import/forms/':
return {'content': json.dumps(WCS_AVAILABLE_FORMS), 'status_code': 200}
if url.path == '/api/export-import/forms/test-form/dependencies/':
return {'content': json.dumps(WCS_FORM_DEPENDENCIES), 'status_code': 200}
if url.path.endswith('/dependencies/'):
return {'content': json.dumps({'data': []}), 'status_code': 200}
if url.path == '/api/export-import/forms/test-form/':
return {'content': '<formdef/>', 'status_code': 200, 'headers': {'content-length': '10'}}
if url.path == '/api/export-import/cards/test-card/':
return {'content': '<carddef/>', 'status_code': 200, 'headers': {'content-length': '10'}}
if url.path == '/api/export-import/bundle-import/':
return {'content': '{}', 'status_code': 200}
def test_create_application(app, admin_user, settings):
Wcs.objects.create(base_url='https://wcs.example.invalid', slug='foobar', title='Foobar')
settings.KNOWN_SERVICES = {
'wcs': {
'foobar': {
'title': 'Foobar',
'url': 'https://wcs.example.invalid/',
'orig': 'example.org',
'secret': 'xxx',
}
}
}
login(app)
resp = app.get('/applications/')
resp = resp.click('Create')
resp.form['name'] = 'Test'
resp = resp.form.submit()
with HTTMock(mocked_http):
resp = resp.follow()
assert 'You should now assemble the different parts of your application.' in resp.text
# edit metadata
resp = resp.click('Metadata')
resp.form['description'] = 'Lorem ipsum'
resp = resp.form.submit().follow()
# add forms
assert '/add/forms/' in resp
resp = resp.click('Forms')
assert resp.form.fields['elements'][0]._value == 'test-form'
assert resp.form.fields['elements'][1]._value == 'test2-form'
resp.form.fields['elements'][0].checked = True
resp = resp.form.submit().follow()
assert Application.objects.get(slug='test').elements.count() == 1
element = Application.objects.get(slug='test').elements.all()[0]
assert element.slug == 'test-form'
resp = resp.click('Scan dependencies').follow()
assert Application.objects.get(slug='test').elements.count() == 2
assert 'Test Card' in resp.text
resp = resp.click('Generate application bundle').follow()
resp = resp.click('Download')
assert resp.content_type == 'application/x-tar'
# uncompressed tar, primitive check of contents
assert b'<formdef/>' in resp.content
assert b'<carddef/>' in resp.content
def test_delete_application(app, admin_user, settings):
Wcs.objects.create(base_url='https://wcs.example.invalid', slug='foobar', title='Foobar')
settings.KNOWN_SERVICES = {
'wcs': {
'foobar': {
'title': 'Foobar',
'url': 'https://wcs.example.invalid/',
'orig': 'example.org',
'secret': 'xxx',
}
}
}
login(app)
Application.objects.create(name='AppToDelete', slug='app_to_delete')
Application.objects.create(name='OtherApp', slug='other_app')
assert Application.objects.count() == 2
resp = app.get('/applications/manifest/app_to_delete/delete/')
resp = resp.forms[0].submit()
resp = resp.follow()
assert '/applications/' in resp
assert 'AppToDelete' not in resp.text
assert Application.objects.count() == 1
assert Application.objects.first().name == 'OtherApp'
@pytest.fixture
def app_bundle():
tar_io = io.BytesIO()
with tarfile.open(mode='w', fileobj=tar_io) as tar:
manifest_json = {
'application': 'Test',
'slug': 'test',
'description': '',
'elements': [
{'type': 'forms', 'slug': 'test', 'name': 'test', 'auto-dependency': False},
{'type': 'blocks', 'slug': 'test', 'name': 'test', 'auto-dependency': True},
{'type': 'workflows', 'slug': 'test', 'name': 'test', 'auto-dependency': True},
],
}
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)
return tar_io.getvalue()
def test_deploy_application(app, admin_user, settings, app_bundle):
Application.objects.all().delete()
Wcs.objects.create(base_url='https://wcs.example.invalid', slug='foobar', title='Foobar')
settings.KNOWN_SERVICES = {
'wcs': {
'foobar': {
'title': 'Foobar',
'url': 'https://wcs.example.invalid/',
'orig': 'example.org',
'secret': 'xxx',
}
}
}
login(app)
resp = app.get('/applications/')
for i in range(2):
resp = resp.click('Install')
resp.form['bundle'] = Upload('app.tar', app_bundle, 'application/x-tar')
with HTTMock(mocked_http):
resp = resp.form.submit().follow()
assert Application.objects.count() == 1
assert Application.objects.get(slug='test').name == 'Test'
assert Application.objects.get(slug='test').elements.count() == 3