464 lines
18 KiB
Python
464 lines
18 KiB
Python
import json
|
|
|
|
import pytest
|
|
from django.core.exceptions import ValidationError
|
|
from django.core.management import call_command
|
|
from django.db.utils import IntegrityError
|
|
from django.utils import timezone
|
|
from test_manager import login
|
|
from webtest import Upload
|
|
|
|
from hobo.environment.models import AVAILABLE_SERVICES, Combo, Passerelle, ServiceBase, Variable
|
|
from hobo.environment.utils import get_installed_services_dict
|
|
from hobo.profile.models import AttributeDefinition
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_service_id():
|
|
for service in AVAILABLE_SERVICES:
|
|
assert service.Extra.service_id
|
|
|
|
|
|
def test_unique_slug():
|
|
combo = Combo(
|
|
title='Combo test',
|
|
slug='wesh',
|
|
last_operational_success_timestamp=timezone.now(),
|
|
last_operational_check_timestamp=timezone.now(),
|
|
secret_key='1nesüper5Cr!eteKAaY~',
|
|
base_url='http://example.com',
|
|
)
|
|
combo.save()
|
|
|
|
passerelle = Passerelle(
|
|
title='Passerelle test',
|
|
slug='wesh',
|
|
last_operational_success_timestamp=timezone.now(),
|
|
last_operational_check_timestamp=timezone.now(),
|
|
secret_key='1nesüper5Cr!eteKAaY~',
|
|
base_url='http://example.com',
|
|
)
|
|
|
|
with pytest.raises(ValidationError) as e:
|
|
passerelle.clean()
|
|
|
|
assert e.value.messages[0] == 'This slug is already used. It must be unique.'
|
|
|
|
|
|
def test_unique_title():
|
|
Combo.objects.create(
|
|
title='Combo test',
|
|
slug='bar',
|
|
last_operational_success_timestamp=timezone.now(),
|
|
last_operational_check_timestamp=timezone.now(),
|
|
secret_key='1nesüper5Cr!eteKAaY~',
|
|
base_url='http://example.com',
|
|
)
|
|
|
|
combo = Combo(
|
|
title='Combo test',
|
|
slug='foo',
|
|
last_operational_success_timestamp=timezone.now(),
|
|
last_operational_check_timestamp=timezone.now(),
|
|
secret_key='1nesüper5Cr!eteKAaY~',
|
|
base_url='http://example.com',
|
|
)
|
|
|
|
with pytest.raises(ValidationError) as e:
|
|
combo.clean()
|
|
|
|
assert e.value.messages[0] == 'This title is already used. It must be unique.'
|
|
|
|
# secondary services can be added
|
|
combo.secondary = True
|
|
combo.clean()
|
|
# secondary service does not prevent homonym creation
|
|
Combo.objects.create(
|
|
title='Combo test secondary',
|
|
slug='second',
|
|
last_operational_success_timestamp=timezone.now(),
|
|
last_operational_check_timestamp=timezone.now(),
|
|
secret_key='1nesüper5Cr!eteKAaY~',
|
|
base_url='http://example.com',
|
|
secondary=True,
|
|
)
|
|
combo.title = 'Combo test secondary'
|
|
combo.secondary = False
|
|
combo.clean()
|
|
# two secondary services are ok
|
|
combo.secondary = True
|
|
combo.clean()
|
|
|
|
|
|
def test_base_url_field_validator():
|
|
kwargs = {
|
|
'last_operational_success_timestamp': timezone.now(),
|
|
'last_operational_check_timestamp': timezone.now(),
|
|
'secret_key': '1nesüper5Cr!eteKAaY~',
|
|
}
|
|
cpt = 0 # slugs must be unique
|
|
|
|
# accept well formated url
|
|
for url in ('https://example.com', 'http://example.com'):
|
|
cpt += 1
|
|
slug = 'wesh' + str(cpt)
|
|
title = 'Combo test ' + str(cpt)
|
|
combo = Combo(base_url=url, slug=slug, title=title, **kwargs)
|
|
combo.full_clean()
|
|
combo.save()
|
|
assert True # no exception raised
|
|
|
|
# reject baddly formated url
|
|
for url in ('example.com', 'http:/example.com', 'file:///home/me'):
|
|
cpt += 1
|
|
slug = 'wesh' + str(cpt)
|
|
title = 'Combo test ' + str(cpt)
|
|
with pytest.raises(ValidationError):
|
|
combo = Combo(base_url=url, slug=slug, title=title, **kwargs)
|
|
combo.full_clean()
|
|
combo.save()
|
|
|
|
|
|
def test_service_creation_filling(app, admin_user, monkeypatch):
|
|
from django.http.request import HttpRequest
|
|
|
|
monkeypatch.setattr(HttpRequest, 'get_host', lambda x: 'test.example.net')
|
|
app = login(app)
|
|
response = app.get('/sites/new-combo')
|
|
assert 'value="http://portal.example.net"' in response.text
|
|
|
|
monkeypatch.setattr(HttpRequest, 'get_host', lambda x: 'hobo-test.example.net')
|
|
app = login(app)
|
|
response = app.get('/sites/new-combo')
|
|
assert 'value="http://portal-test.example.net"' in response.text
|
|
|
|
|
|
def test_service_creation_url_validation(app, admin_user, monkeypatch):
|
|
app = login(app)
|
|
response = app.get('/sites/new-combo')
|
|
form = response.form
|
|
form['title'] = "test"
|
|
form['base_url'] = "http://portal-test.example.net"
|
|
response = form.submit()
|
|
assert 'not resolvable' in response
|
|
|
|
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
|
|
form = response.form
|
|
response = form.submit()
|
|
assert 'no valid certificate' in response
|
|
|
|
assert not Combo.objects.exists()
|
|
monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
|
|
form = response.form
|
|
response = form.submit()
|
|
assert Combo.objects.exists()
|
|
|
|
|
|
def test_home_view(app, admin_user):
|
|
app = login(app)
|
|
combo = Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
response = app.get('/sites').follow()
|
|
assert 'Add new service:' in response.text
|
|
for service in AVAILABLE_SERVICES:
|
|
if service.is_enabled():
|
|
assert str(service._meta.verbose_name) in response.text
|
|
assert response.html.find('span', {'class': 'slug'}).a.text == 'https://combo.agglo.love/'
|
|
|
|
# add legacy urls
|
|
combo.change_base_url('https://combo1.agglo.love')
|
|
combo.save()
|
|
response = app.get('/sites').follow()
|
|
assert response.html.find('span', {'class': 'slug'}).a.text == 'https://combo1.agglo.love/'
|
|
h4 = response.html.find_all('h4')[-1]
|
|
assert h4.text.strip() == 'Legacy URL'
|
|
|
|
combo.change_base_url('https://combo2.agglo.love')
|
|
combo.save()
|
|
response = app.get('/sites').follow()
|
|
assert response.html.find('span', {'class': 'slug'}).a.text == 'https://combo2.agglo.love/'
|
|
h4 = response.html.find_all('h4')[-1]
|
|
assert h4.text.strip() == 'Legacy URLS'
|
|
|
|
|
|
def test_variables_view(app, admin_user):
|
|
app = login(app)
|
|
Variable.objects.create(name='foo', value='bar')
|
|
response = app.get('/sites/variables')
|
|
assert response.html.find('label').text == 'foo'
|
|
assert response.html.find('input')['value'] == 'bar'
|
|
assert 'Add new variable' in response.text
|
|
|
|
|
|
def test_new_variable_view(app, admin_user):
|
|
app = login(app)
|
|
response = app.get('/sites/new-variable')
|
|
response.form['name'] = 'foo'
|
|
response.form['label'] = 'bar'
|
|
response.form['value'] = 'barbar'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/variables'
|
|
assert Variable.objects.all()[0].name == 'foo'
|
|
assert Variable.objects.all()[0].label == 'bar'
|
|
assert Variable.objects.all()[0].value == 'barbar'
|
|
response = app.get('/sites/new-variable')
|
|
response.form['name'] = 'foo'
|
|
response.form['label'] = 'bar'
|
|
response.form['value'] = 'foofoo'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/variables'
|
|
assert Variable.objects.all()[0].value == 'foofoo'
|
|
|
|
|
|
def test_new_variable_service_view(app, admin_user):
|
|
app = login(app)
|
|
Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
response = app.get('/sites/new-variable-combo/portal')
|
|
response.form['name'] = 'foo'
|
|
response.form['label'] = 'bar'
|
|
response.form['value'] = 'barbar'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/'
|
|
assert Variable.objects.all()[0].name == 'foo'
|
|
assert Variable.objects.all()[0].label == 'bar'
|
|
assert Variable.objects.all()[0].value == 'barbar'
|
|
|
|
|
|
def test_variable_update_view(app, admin_user):
|
|
app = login(app)
|
|
var = Variable.objects.create(name='foo', value='bar')
|
|
response = app.get('/sites/update-variable/%s' % var.pk)
|
|
assert response.html.find('input', {'name': 'name'})['value'] == 'foo'
|
|
assert response.html.find('textarea').text == '\nbar'
|
|
response.form['value'] = 'barbar'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/variables'
|
|
assert Variable.objects.all()[0].value == 'barbar'
|
|
|
|
|
|
def test_variable_delete_view(app, admin_user):
|
|
app = login(app)
|
|
var = Variable.objects.create(name='foo', value='bar')
|
|
response = app.get('/sites/delete-variable/%s' % var.pk)
|
|
assert response.html.find('h2').text == 'Removal of "foo"'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/variables'
|
|
assert Variable.objects.count() == 0
|
|
|
|
|
|
def test_service_update_view(app, admin_user):
|
|
app = login(app)
|
|
Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
response = app.get('/sites/save-combo/portal')
|
|
response.form['title'] = 'foobar'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/'
|
|
assert Combo.objects.all()[0].title == 'foobar'
|
|
|
|
|
|
def test_service_save_extra_variables(app, admin_user, settings):
|
|
settings.SERVICE_EXTRA_VARIABLES = {
|
|
'passerelle': ['legal_url', 'commune_url', 'domain_key'],
|
|
'combo': [{'name': 'theme', 'label': 'Theme'}],
|
|
}
|
|
app = login(app)
|
|
Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
Passerelle.objects.create(base_url='https://passerelle.agglo.love', slug='passerelle')
|
|
app.get('/sites/save-combo/portal')
|
|
Variable.objects.all()[0].name = 'theme'
|
|
Variable.objects.all()[0].label = 'Theme'
|
|
app.get('/sites/save-passerelle/passerelle')
|
|
Variable.objects.all()[0].name = 'legal_url'
|
|
Variable.objects.all()[1].name = 'commune_url'
|
|
Variable.objects.all()[2].name = 'domain_key'
|
|
|
|
|
|
def test_service_delete_view(app, admin_user):
|
|
app = login(app)
|
|
Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', title='foo', slug='portal'
|
|
)
|
|
response = app.get('/sites/delete-combo/portal')
|
|
assert response.html.find('h2').text == 'Removal of "foo"'
|
|
response = response.form.submit()
|
|
assert response.location == '/sites/'
|
|
assert Combo.objects.count() == 0
|
|
|
|
|
|
def test_check_operational_view(app, admin_user, monkeypatch):
|
|
app = login(app)
|
|
Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
response = app.get('/sites/check_operational/combo/portal')
|
|
assert response.json['operational'] == False
|
|
|
|
monkeypatch.setattr(ServiceBase, 'is_operational', lambda x: True)
|
|
response = app.get('/sites/check_operational/combo/portal')
|
|
assert response.json['operational'] == True
|
|
|
|
response = app.get('/sites/check_operational/foo/bar', status=404)
|
|
|
|
|
|
def test_debug_json_view(app, admin_user):
|
|
app = login(app)
|
|
Variable.objects.create(name='foo', value='bar')
|
|
Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
response = app.get('/sites/debug-json')
|
|
assert response.json[0]['variables']['foo'] == 'bar'
|
|
assert response.json[0]['services'][0]['slug'] == 'hobo'
|
|
assert response.json[0]['services'][1]['slug'] == 'portal'
|
|
|
|
|
|
def test_check_operational_command(monkeypatch, capsys):
|
|
combo = Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', title='foo', slug='portal'
|
|
)
|
|
monkeypatch.setattr(ServiceBase, 'is_operational', lambda x: True)
|
|
call_command('check_operational', '-v2')
|
|
captured = capsys.readouterr()
|
|
assert captured.out == 'foo is operational\n'
|
|
|
|
monkeypatch.setattr(ServiceBase, 'is_operational', lambda x: False)
|
|
combo.last_operational_success_timestamp = '2022-2-22'
|
|
combo.save()
|
|
call_command('check_operational', '-v2')
|
|
captured = capsys.readouterr()
|
|
assert captured.out.split('\n')[:-1] == [
|
|
'foo is NOT operational',
|
|
' last operational success: 2022-02-22 00:00:00+00:00',
|
|
]
|
|
|
|
|
|
def test_export_import_view(app, admin_user):
|
|
combo = Combo.objects.create(
|
|
base_url='https://combo.agglo.love', template_name='...portal-user...', slug='portal'
|
|
)
|
|
Variable.objects.create(name='foo', value='bar').save()
|
|
Variable.objects.create(name='foo2', value='bar2', service=combo).save()
|
|
app = login(app, 'admin', 'password')
|
|
resp = app.get('/sites/export/', status=200)
|
|
assert sorted(resp.json.keys()) == ['profile', 'variables']
|
|
assert resp.json['variables'] == [{'name': 'foo', 'label': '', 'value': 'bar', 'auto': False}]
|
|
assert resp.json['profile']['fields'][0]['name'] == 'title'
|
|
assert resp.json['profile']['fields'][0]['required'] is False
|
|
assert resp.json['profile']['fields'][0]['description'] == ''
|
|
assert resp.json['profile']['fields'][2]['name'] == 'last_name'
|
|
assert resp.json['profile']['fields'][2]['required'] is True
|
|
assert resp.json['profile']['fields'][2]['label'] == 'Nom'
|
|
|
|
# modify exported file
|
|
export = resp.json
|
|
export['variables'][0]['label'] = 'bar'
|
|
fields = export['profile']['fields']
|
|
assert fields[0]['name'] == 'title'
|
|
assert fields[2]['name'] == 'last_name'
|
|
fields[0]['description'] = 'genre'
|
|
fields[2]['label'] = 'Nom de naissance'
|
|
fields[0], fields[2] = fields[2], fields[0]
|
|
export_json = json.dumps(export)
|
|
|
|
# add new content
|
|
Variable.objects.create(name='foo3', value='bar3').save()
|
|
AttributeDefinition.objects.create(name='prefered_color', label='not empty').save()
|
|
assert Variable.objects.count() == 3
|
|
assert AttributeDefinition.objects.count() == 12
|
|
assert Variable.objects.get(name='foo').label == ''
|
|
assert AttributeDefinition.objects.get(name='title').description == ''
|
|
assert AttributeDefinition.objects.get(name='title').order == 1
|
|
assert AttributeDefinition.objects.get(name='last_name').order == 3
|
|
assert AttributeDefinition.objects.get(name='prefered_color').order == 12
|
|
|
|
# import valid content
|
|
resp = app.get('/', status=200)
|
|
resp = resp.click('Import')
|
|
resp.form['parameters_json'] = Upload('export.json', export_json.encode('utf-8'), 'application/json')
|
|
resp = resp.form.submit()
|
|
assert Variable.objects.count() == 3
|
|
assert AttributeDefinition.objects.count() == 12
|
|
assert Variable.objects.get(name='foo').label == 'bar'
|
|
assert AttributeDefinition.objects.get(name='title').description == 'genre'
|
|
assert AttributeDefinition.objects.get(name='title').order == 1
|
|
assert AttributeDefinition.objects.get(name='last_name').label == 'Nom de naissance'
|
|
assert AttributeDefinition.objects.get(name='last_name').order == 3
|
|
assert AttributeDefinition.objects.get(name='prefered_color').order == 12
|
|
|
|
# import empty json
|
|
resp = app.get('/', status=200)
|
|
resp = resp.click('Import')
|
|
resp.form['parameters_json'] = Upload('export.json', b'{}', 'application/json')
|
|
resp = resp.form.submit()
|
|
assert Variable.objects.count() == 3
|
|
assert AttributeDefinition.objects.count() == 12
|
|
assert Variable.objects.get(name='foo').label == 'bar'
|
|
assert AttributeDefinition.objects.get(name='title').description == 'genre'
|
|
assert AttributeDefinition.objects.get(name='title').order == 1
|
|
assert AttributeDefinition.objects.get(name='last_name').label == 'Nom de naissance'
|
|
assert AttributeDefinition.objects.get(name='last_name').order == 3
|
|
assert AttributeDefinition.objects.get(name='prefered_color').order == 12
|
|
|
|
# import from scratch
|
|
Variable.objects.all().delete()
|
|
AttributeDefinition.objects.all().delete()
|
|
Variable.objects.create(name='foo2', value='bar2', service=combo).save()
|
|
AttributeDefinition.objects.create(name='prefered_color', label='not empty').save()
|
|
assert Variable.objects.count() == 1
|
|
assert AttributeDefinition.objects.count() == 1
|
|
resp = app.get('/', status=200)
|
|
resp = resp.click('Import')
|
|
resp.form['parameters_json'] = Upload('export.json', export_json.encode('utf-8'), 'application/json')
|
|
resp = resp.form.submit()
|
|
assert Variable.objects.count() == 2
|
|
assert AttributeDefinition.objects.count() == 12
|
|
assert Variable.objects.get(name='foo').label == 'bar'
|
|
assert AttributeDefinition.objects.get(name='title').order == 4
|
|
assert AttributeDefinition.objects.get(name='last_name').order == 2
|
|
assert AttributeDefinition.objects.get(name='prefered_color').order == 1
|
|
|
|
# import invalid json
|
|
resp = app.get('/', status=200)
|
|
resp = resp.click('Import')
|
|
resp.form['parameters_json'] = Upload('export.json', b'garbage', 'application/json')
|
|
resp = resp.form.submit()
|
|
assert Variable.objects.count() == 2
|
|
assert AttributeDefinition.objects.count() == 12
|
|
|
|
# import corrupted json
|
|
export['variables'][0]['label'] = 'foofoo'
|
|
fields = export['profile']['fields']
|
|
assert fields[2]['name'] == 'title'
|
|
fields[2]['label'] = 'Nom de naissance'
|
|
export_json = json.dumps(export)
|
|
resp = app.get('/', status=200)
|
|
resp = resp.click('Import')
|
|
resp.form['parameters_json'] = Upload('export.json', export_json.encode('utf-8'), 'application/json')
|
|
with pytest.raises(IntegrityError):
|
|
resp = resp.form.submit()
|
|
assert Variable.objects.count() == 2
|
|
assert AttributeDefinition.objects.count() == 12
|
|
assert Variable.objects.get(name='foo').label == 'bar'
|
|
|
|
|
|
def test_services_dict_templated_url(settings):
|
|
settings.TEMPLATE_VARS = {'passerelle_url': 'http://example.com/'}
|
|
variable = Variable.objects.create(name='sms_url', value='{{passerelle_url}}send/')
|
|
Variable.objects.create(name='foo', value='bar')
|
|
|
|
hobo_dict = get_installed_services_dict()
|
|
assert hobo_dict['variables'] == {'sms_url': 'http://example.com/send/', 'foo': 'bar'}
|
|
|
|
variable.value = '{{invalid{syntax}}send/'
|
|
variable.save()
|
|
hobo_dict = get_installed_services_dict()
|
|
assert hobo_dict['variables'] == {'foo': 'bar'}
|