profile_views: address autocomplete field (#41919)
This commit is contained in:
parent
3b6d2cc4cd
commit
7b130d6ffc
|
@ -28,6 +28,7 @@ urlpatterns = [
|
||||||
name='a2-api-role-members'),
|
name='a2-api-role-members'),
|
||||||
url(r'^check-password/$', api_views.check_password, name='a2-api-check-password'),
|
url(r'^check-password/$', api_views.check_password, name='a2-api-check-password'),
|
||||||
url(r'^validate-password/$', api_views.validate_password, name='a2-api-validate-password'),
|
url(r'^validate-password/$', api_views.validate_password, name='a2-api-validate-password'),
|
||||||
|
url(r'^address-autocomplete/$', api_views.address_autocomplete, name='a2-api-address-autocomplete'),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += api_views.router.urls
|
urlpatterns += api_views.router.urls
|
||||||
|
|
|
@ -21,6 +21,7 @@ import smtplib
|
||||||
from pytz.exceptions import AmbiguousTimeError
|
from pytz.exceptions import AmbiguousTimeError
|
||||||
import django
|
import django
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.hashers import identify_hasher
|
from django.contrib.auth.hashers import identify_hasher
|
||||||
from django.core.exceptions import MultipleObjectsReturned
|
from django.core.exceptions import MultipleObjectsReturned
|
||||||
|
@ -33,6 +34,8 @@ from django.views.decorators.cache import cache_control
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from django_rbac.utils import get_ou_model, get_role_model
|
from django_rbac.utils import get_ou_model, get_role_model
|
||||||
|
import requests
|
||||||
|
from requests.exceptions import RequestException
|
||||||
|
|
||||||
from rest_framework import serializers, pagination
|
from rest_framework import serializers, pagination
|
||||||
from rest_framework.validators import UniqueTogetherValidator
|
from rest_framework.validators import UniqueTogetherValidator
|
||||||
|
@ -1038,3 +1041,23 @@ class ValidatePasswordAPI(BaseRpcView):
|
||||||
return result, status.HTTP_200_OK
|
return result, status.HTTP_200_OK
|
||||||
|
|
||||||
validate_password = ValidatePasswordAPI.as_view()
|
validate_password = ValidatePasswordAPI.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class AddressAutocompleteAPI(APIView):
|
||||||
|
permission_classes = (permissions.IsAuthenticated,)
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
if not getattr(settings, 'ADDRESS_AUTOCOMPLETE_URL', None):
|
||||||
|
return Response({})
|
||||||
|
try:
|
||||||
|
response = requests.get(
|
||||||
|
settings.ADDRESS_AUTOCOMPLETE_URL,
|
||||||
|
params=request.GET
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return Response(response.json())
|
||||||
|
except RequestException:
|
||||||
|
return Response({})
|
||||||
|
|
||||||
|
|
||||||
|
address_autocomplete = AddressAutocompleteAPI.as_view()
|
||||||
|
|
|
@ -23,8 +23,10 @@ import os
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import RegexValidator
|
from django.core.validators import RegexValidator
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import six, formats
|
from django.utils import six, formats
|
||||||
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
|
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
|
||||||
from django.utils import html
|
from django.utils import html
|
||||||
|
@ -110,6 +112,28 @@ class BirthdateRestField(DateRestField):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class AddressAutocompleteInput(forms.Select):
|
||||||
|
template_name = 'authentic2/widgets/address_autocomplete.html'
|
||||||
|
|
||||||
|
class Media:
|
||||||
|
js = [
|
||||||
|
settings.SELECT2_JS,
|
||||||
|
'authentic2/js/address_autocomplete.js',
|
||||||
|
]
|
||||||
|
css = {
|
||||||
|
'screen': [settings.SELECT2_CSS],
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.attrs['data-select2-url'] = reverse('a2-api-address-autocomplete')
|
||||||
|
self.attrs['class'] = 'address-autocomplete'
|
||||||
|
|
||||||
|
|
||||||
|
class AddressAutocompleteField(forms.CharField):
|
||||||
|
widget = AddressAutocompleteInput
|
||||||
|
|
||||||
|
|
||||||
@to_iter
|
@to_iter
|
||||||
def get_title_choices():
|
def get_title_choices():
|
||||||
return app_settings.A2_ATTRIBUTE_KIND_TITLE_CHOICES or DEFAULT_TITLE_CHOICES
|
return app_settings.A2_ATTRIBUTE_KIND_TITLE_CHOICES or DEFAULT_TITLE_CHOICES
|
||||||
|
@ -269,6 +293,11 @@ DEFAULT_ATTRIBUTE_KINDS = [
|
||||||
'rest_framework_field_class': BirthdateRestField,
|
'rest_framework_field_class': BirthdateRestField,
|
||||||
'free_text_search': date_free_text_search,
|
'free_text_search': date_free_text_search,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'label': _('address (autocomplete)'),
|
||||||
|
'name': 'address_auto',
|
||||||
|
'field_class': AddressAutocompleteField,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'label': _('french postcode'),
|
'label': _('french postcode'),
|
||||||
'name': 'fr_postcode',
|
'name': 'fr_postcode',
|
||||||
|
|
|
@ -248,7 +248,8 @@ span.select2-container {
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-dialog-content span.select2-container {
|
.ui-dialog-content span.select2-container,
|
||||||
|
form .widget span.select2-container {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,8 @@ class UserDetailView(OtherActionsMixin, BaseDetailView):
|
||||||
if not self.object.username and self.object.ou and not self.object.ou.show_username:
|
if not self.object.username and self.object.ou and not self.object.ou.show_username:
|
||||||
fields.remove('username')
|
fields.remove('username')
|
||||||
for attribute in Attribute.objects.all():
|
for attribute in Attribute.objects.all():
|
||||||
|
if attribute.name == 'address_autocomplete':
|
||||||
|
continue
|
||||||
fields.append(attribute.name)
|
fields.append(attribute.name)
|
||||||
if self.request.user.is_superuser and \
|
if self.request.user.is_superuser and \
|
||||||
'is_superuser' not in self.fields:
|
'is_superuser' not in self.fields:
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
$(function() {
|
||||||
|
$('select.address-autocomplete').select2({
|
||||||
|
ajax: {
|
||||||
|
delay: 250,
|
||||||
|
dataType: 'json',
|
||||||
|
data: function(params) {
|
||||||
|
return {q: params.term, page_limit: 10};
|
||||||
|
},
|
||||||
|
processResults: function (data, params) {
|
||||||
|
return {results: data.data};
|
||||||
|
},
|
||||||
|
url: function (params) {
|
||||||
|
return $(this).data('select2-url')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).on('select2:select', function(e) {
|
||||||
|
var data = e.params.data;
|
||||||
|
if (data) {
|
||||||
|
var address = undefined;
|
||||||
|
if (typeof data.address == "object") {
|
||||||
|
address = data.address;
|
||||||
|
} else {
|
||||||
|
address = data;
|
||||||
|
}
|
||||||
|
var road = address.road || address.nom_rue;
|
||||||
|
var house_number = address.house_number || address.numero;
|
||||||
|
var city = address.city || address.nom_commune;
|
||||||
|
var postcode = address.postcode || address.code_postal;
|
||||||
|
var number_and_street = null;
|
||||||
|
if (house_number && road) {
|
||||||
|
number_and_street = house_number + ' ' + road;
|
||||||
|
} else {
|
||||||
|
number_and_street = road;
|
||||||
|
}
|
||||||
|
$('#id_address').val(number_and_street);
|
||||||
|
$('#id_city').val(city);
|
||||||
|
$('#id_zipcode').val(postcode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#id_address, #id_city, #id_zipcode').attr('readonly', 'readonly');
|
||||||
|
$('#manual-address').on('change', function() {
|
||||||
|
$('#id_address, #id_city, #id_zipcode').attr('readonly', this.checked ? null : 'readonly');
|
||||||
|
});
|
||||||
|
if ($('#id_address').val() || $('#id_city').val() || $('#id_zipcode').val()) {
|
||||||
|
var data = {
|
||||||
|
id: 1,
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
$.each(['#id_address', '#id_zipcode', '#id_city'], function(idx, value) {
|
||||||
|
if ($(value).val()) {
|
||||||
|
if (data.text) {
|
||||||
|
data.text += ' ';
|
||||||
|
}
|
||||||
|
data.text += $(value).val();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
var newOption = new Option(data.text, data.id, false, false);
|
||||||
|
$('select.address-autocomplete').append(newOption).trigger('change');
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
{% load i18n %}
|
||||||
|
{% include "django/forms/widgets/select.html" %}
|
||||||
|
<div>
|
||||||
|
<label><input id="manual-address" type="checkbox">{% trans "Manually enter the address" %}</label>
|
||||||
|
</div>
|
|
@ -133,7 +133,6 @@ class EditProfile(cbv.HookMixin, cbv.TemplateNamesMixin, UpdateView):
|
||||||
|
|
||||||
def get_form_kwargs(self, **kwargs):
|
def get_form_kwargs(self, **kwargs):
|
||||||
kwargs = super(EditProfile, self).get_form_kwargs(**kwargs)
|
kwargs = super(EditProfile, self).get_form_kwargs(**kwargs)
|
||||||
kwargs['prefix'] = 'edit-profile'
|
|
||||||
kwargs['next_url'] = utils.select_next_url(self.request, reverse('account_management'))
|
kwargs['next_url'] = utils.select_next_url(self.request, reverse('account_management'))
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -141,7 +140,7 @@ class EditProfile(cbv.HookMixin, cbv.TemplateNamesMixin, UpdateView):
|
||||||
return utils.select_next_url(
|
return utils.select_next_url(
|
||||||
self.request,
|
self.request,
|
||||||
default=reverse('account_management'),
|
default=reverse('account_management'),
|
||||||
field_name='edit-profile-next_url',
|
field_name='next_url',
|
||||||
include_post=True)
|
include_post=True)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
import random
|
import random
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -36,6 +37,7 @@ from django.utils.http import urlencode
|
||||||
|
|
||||||
from django_rbac.models import SEARCH_OP
|
from django_rbac.models import SEARCH_OP
|
||||||
from django_rbac.utils import get_role_model, get_ou_model
|
from django_rbac.utils import get_role_model, get_ou_model
|
||||||
|
from requests.models import Response
|
||||||
|
|
||||||
from authentic2.a2_rbac.models import Role
|
from authentic2.a2_rbac.models import Role
|
||||||
from authentic2.a2_rbac.utils import get_default_ou
|
from authentic2.a2_rbac.utils import get_default_ou
|
||||||
|
@ -1926,3 +1928,48 @@ def test_find_duplicates_birthdate(app, admin, settings):
|
||||||
resp = app.get('/api/users/find_duplicates/', params=params)
|
resp = app.get('/api/users/find_duplicates/', params=params)
|
||||||
assert len(resp.json['data']) == 2
|
assert len(resp.json['data']) == 2
|
||||||
assert resp.json['data'][0]['id'] == homonym.pk
|
assert resp.json['data'][0]['id'] == homonym.pk
|
||||||
|
|
||||||
|
|
||||||
|
class MockedRequestResponse(mock.Mock):
|
||||||
|
status_code = 200
|
||||||
|
|
||||||
|
def json(self):
|
||||||
|
return json.loads(self.content)
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_address_autocomplete(app, admin, settings):
|
||||||
|
app.authorization = ('Basic', (admin.username, admin.username))
|
||||||
|
|
||||||
|
settings.ADDRESS_AUTOCOMPLETE_URL = 'example.com'
|
||||||
|
|
||||||
|
params = {'q': '42 avenue'}
|
||||||
|
with mock.patch('authentic2.api_views.requests.get') as requests_get:
|
||||||
|
mock_resp = Response()
|
||||||
|
mock_resp.status_code = 500
|
||||||
|
requests_get.return_value = mock_resp
|
||||||
|
resp = app.get('/api/address-autocomplete/', params=params)
|
||||||
|
assert resp.json == {}
|
||||||
|
assert requests_get.call_args_list[0][0][0] == 'example.com'
|
||||||
|
assert requests_get.call_args_list[0][1]['params'] == {'q': ['42 avenue']}
|
||||||
|
with mock.patch('authentic2.api_views.requests.get') as requests_get:
|
||||||
|
mock_resp = Response()
|
||||||
|
mock_resp.status_code = 404
|
||||||
|
requests_get.return_value = mock_resp
|
||||||
|
resp = app.get('/api/address-autocomplete/', params=params)
|
||||||
|
assert resp.json == {}
|
||||||
|
with mock.patch('authentic2.api_views.requests.get') as requests_get:
|
||||||
|
requests_get.return_value = MockedRequestResponse(content=json.dumps({'data': {'foo': 'bar'}}))
|
||||||
|
resp = app.get('/api/address-autocomplete/', params=params)
|
||||||
|
assert resp.json == {'data': {'foo': 'bar'}}
|
||||||
|
|
||||||
|
settings.ADDRESS_AUTOCOMPLETE_URL = None
|
||||||
|
with mock.patch('authentic2.api_views.requests.get') as requests_get:
|
||||||
|
resp = app.get('/api/address-autocomplete/', params=params)
|
||||||
|
assert resp.json == {}
|
||||||
|
assert requests_get.call_args_list == []
|
||||||
|
|
||||||
|
del settings.ADDRESS_AUTOCOMPLETE_URL
|
||||||
|
with mock.patch('authentic2.api_views.requests.get') as requests_get:
|
||||||
|
resp = app.get('/api/address-autocomplete/', params=params)
|
||||||
|
assert resp.json == {}
|
||||||
|
assert requests_get.call_args_list == []
|
||||||
|
|
|
@ -456,9 +456,9 @@ def test_profile_image(db, app, admin, mailoutbox):
|
||||||
# verify we can clear the image
|
# verify we can clear the image
|
||||||
response = app.get('/accounts/edit/')
|
response = app.get('/accounts/edit/')
|
||||||
form = response.form
|
form = response.form
|
||||||
form.set('edit-profile-first_name', 'John')
|
form.set('first_name', 'John')
|
||||||
form.set('edit-profile-last_name', 'Doe')
|
form.set('last_name', 'Doe')
|
||||||
form.set('edit-profile-cityscape_image-clear', True)
|
form.set('cityscape_image-clear', True)
|
||||||
response = form.submit()
|
response = form.submit()
|
||||||
assert john().attributes.cityscape_image == None
|
assert john().attributes.cityscape_image == None
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ def test_profile_image(db, app, admin, mailoutbox):
|
||||||
# verify 201x201 image is accepted and resized
|
# verify 201x201 image is accepted and resized
|
||||||
response = app.get('/accounts/edit/')
|
response = app.get('/accounts/edit/')
|
||||||
form = response.form
|
form = response.form
|
||||||
form.set('edit-profile-cityscape_image', Upload('tests/201x201.jpg'))
|
form.set('cityscape_image', Upload('tests/201x201.jpg'))
|
||||||
response = form.submit()
|
response = form.submit()
|
||||||
with PIL.Image.open(os.path.join(settings.MEDIA_ROOT, john().attributes.cityscape_image.name)) as image:
|
with PIL.Image.open(os.path.join(settings.MEDIA_ROOT, john().attributes.cityscape_image.name)) as image:
|
||||||
assert image.width == 200
|
assert image.width == 200
|
||||||
|
@ -480,7 +480,7 @@ def test_profile_image(db, app, admin, mailoutbox):
|
||||||
# verify file input mentions image files
|
# verify file input mentions image files
|
||||||
response = app.get('/accounts/edit/')
|
response = app.get('/accounts/edit/')
|
||||||
form = response.form
|
form = response.form
|
||||||
assert form['edit-profile-cityscape_image'].attrs['accept'] == 'image/*'
|
assert form['cityscape_image'].attrs['accept'] == 'image/*'
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_attribute_setter(db, app, simple_user):
|
def test_multiple_attribute_setter(db, app, simple_user):
|
||||||
|
|
|
@ -47,10 +47,10 @@ def test_account_edit_view(app, simple_user):
|
||||||
kind='boolean', user_visible=True, user_editable=True)
|
kind='boolean', user_visible=True, user_editable=True)
|
||||||
|
|
||||||
resp = old_resp = app.get(url, status=200)
|
resp = old_resp = app.get(url, status=200)
|
||||||
resp.form['edit-profile-phone'] = '1234'
|
resp.form['phone'] = '1234'
|
||||||
assert resp.form['edit-profile-phone'].attrs['type'] == 'tel'
|
assert resp.form['phone'].attrs['type'] == 'tel'
|
||||||
resp.form['edit-profile-title'] = 'Mrs'
|
resp.form['title'] = 'Mrs'
|
||||||
resp.form['edit-profile-agreement'] = False
|
resp.form['agreement'] = False
|
||||||
resp = resp.form.submit()
|
resp = resp.form.submit()
|
||||||
# verify that missing next_url in POST is ok
|
# verify that missing next_url in POST is ok
|
||||||
assert resp['Location'].endswith(reverse('account_management'))
|
assert resp['Location'].endswith(reverse('account_management'))
|
||||||
|
@ -70,12 +70,12 @@ def test_account_edit_view(app, simple_user):
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = app.get(url, status=200)
|
resp = app.get(url, status=200)
|
||||||
resp.form.set('edit-profile-phone', '0123456789')
|
resp.form.set('phone', '0123456789')
|
||||||
resp = resp.form.submit().follow()
|
resp = resp.form.submit().follow()
|
||||||
assert phone.get_value(simple_user) == '0123456789'
|
assert phone.get_value(simple_user) == '0123456789'
|
||||||
|
|
||||||
resp = app.get(url, status=200)
|
resp = app.get(url, status=200)
|
||||||
resp.form.set('edit-profile-phone', '9876543210')
|
resp.form.set('phone', '9876543210')
|
||||||
resp = resp.form.submit('cancel').follow()
|
resp = resp.form.submit('cancel').follow()
|
||||||
assert phone.get_value(simple_user) == '0123456789'
|
assert phone.get_value(simple_user) == '0123456789'
|
||||||
|
|
||||||
|
@ -83,16 +83,16 @@ def test_account_edit_view(app, simple_user):
|
||||||
title.set_value(simple_user, 'Mr', verified=True)
|
title.set_value(simple_user, 'Mr', verified=True)
|
||||||
agreement.set_value(simple_user, True, verified=True)
|
agreement.set_value(simple_user, True, verified=True)
|
||||||
resp = app.get(url, status=200)
|
resp = app.get(url, status=200)
|
||||||
assert 'edit-profile-phone' not in resp.form.fields
|
assert 'phone' not in resp.form.fields
|
||||||
assert 'edit-profile-title' not in resp.form.fields
|
assert 'title' not in resp.form.fields
|
||||||
assert 'edit-profile-agreement' not in resp.form.fields
|
assert 'agreement' not in resp.form.fields
|
||||||
assert 'readonly' in resp.form['edit-profile-phone@disabled'].attrs
|
assert 'readonly' in resp.form['phone@disabled'].attrs
|
||||||
assert resp.form['edit-profile-phone@disabled'].value == '0123456789'
|
assert resp.form['phone@disabled'].value == '0123456789'
|
||||||
assert resp.form['edit-profile-title@disabled'].value == 'Mr'
|
assert resp.form['title@disabled'].value == 'Mr'
|
||||||
assert resp.form['edit-profile-agreement@disabled'].value == 'Yes'
|
assert resp.form['agreement@disabled'].value == 'Yes'
|
||||||
resp.form.set('edit-profile-phone@disabled', '1234')
|
resp.form.set('phone@disabled', '1234')
|
||||||
resp.form.set('edit-profile-title@disabled', 'Mrs')
|
resp.form.set('title@disabled', 'Mrs')
|
||||||
resp.form.set('edit-profile-agreement@disabled', 'False')
|
resp.form.set('agreement@disabled', 'False')
|
||||||
resp = resp.form.submit().follow()
|
resp = resp.form.submit().follow()
|
||||||
assert phone.get_value(simple_user) == '0123456789'
|
assert phone.get_value(simple_user) == '0123456789'
|
||||||
assert title.get_value(simple_user) == 'Mr'
|
assert title.get_value(simple_user) == 'Mr'
|
||||||
|
@ -106,9 +106,9 @@ def test_account_edit_view(app, simple_user):
|
||||||
phone.disabled = True
|
phone.disabled = True
|
||||||
phone.save()
|
phone.save()
|
||||||
resp = app.get(url, status=200)
|
resp = app.get(url, status=200)
|
||||||
assert 'edit-profile-phone@disabled' not in resp
|
assert 'phone@disabled' not in resp
|
||||||
assert 'edit-profile-title@disabled' in resp
|
assert 'title@disabled' in resp
|
||||||
assert 'edit-profile-agreement@disabled' in resp
|
assert 'agreement@disabled' in resp
|
||||||
assert phone.get_value(simple_user) == '0123456789'
|
assert phone.get_value(simple_user) == '0123456789'
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,13 +122,13 @@ def test_account_edit_next_url(app, simple_user, external_redirect_next_url, ass
|
||||||
user_editable=True)
|
user_editable=True)
|
||||||
|
|
||||||
resp = app.get(url + '?next=%s' % external_redirect_next_url, status=200)
|
resp = app.get(url + '?next=%s' % external_redirect_next_url, status=200)
|
||||||
resp.form.set('edit-profile-phone', '0123456789')
|
resp.form.set('phone', '0123456789')
|
||||||
resp = resp.form.submit()
|
resp = resp.form.submit()
|
||||||
assert_external_redirect(resp, reverse('account_management'))
|
assert_external_redirect(resp, reverse('account_management'))
|
||||||
assert attribute.get_value(simple_user) == '0123456789'
|
assert attribute.get_value(simple_user) == '0123456789'
|
||||||
|
|
||||||
resp = app.get(url + '?next=%s' % external_redirect_next_url, status=200)
|
resp = app.get(url + '?next=%s' % external_redirect_next_url, status=200)
|
||||||
resp.form.set('edit-profile-phone', '1234')
|
resp.form.set('phone', '1234')
|
||||||
resp = resp.form.submit('cancel')
|
resp = resp.form.submit('cancel')
|
||||||
assert_external_redirect(resp, reverse('account_management'))
|
assert_external_redirect(resp, reverse('account_management'))
|
||||||
assert attribute.get_value(simple_user) == '0123456789'
|
assert attribute.get_value(simple_user) == '0123456789'
|
||||||
|
@ -153,8 +153,8 @@ def test_account_edit_scopes(app, simple_user):
|
||||||
scopes='address')
|
scopes='address')
|
||||||
|
|
||||||
def get_fields(resp):
|
def get_fields(resp):
|
||||||
return set(key.split('edit-profile-')[1]
|
return set(key for key in resp.form.fields.keys() if key and key not in ['csrfmiddlewaretoken', 'cancel'])
|
||||||
for key in resp.form.fields.keys() if key and key.startswith('edit-profile-'))
|
|
||||||
resp = app.get(url, status=200)
|
resp = app.get(url, status=200)
|
||||||
assert get_fields(resp) == set(['first_name', 'last_name', 'phone', 'mobile', 'city', 'zipcode', 'next_url'])
|
assert get_fields(resp) == set(['first_name', 'last_name', 'phone', 'mobile', 'city', 'zipcode', 'next_url'])
|
||||||
|
|
||||||
|
@ -185,15 +185,15 @@ def test_account_edit_locked_title(app, simple_user):
|
||||||
utils.login(app, simple_user)
|
utils.login(app, simple_user)
|
||||||
url = reverse('profile_edit')
|
url = reverse('profile_edit')
|
||||||
response = app.get(url, status=200)
|
response = app.get(url, status=200)
|
||||||
assert len(response.pyquery('input[type="radio"][name="edit-profile-title"]')) == 2
|
assert len(response.pyquery('input[type="radio"][name="title"]')) == 2
|
||||||
assert len(response.pyquery('input[type="radio"][name="edit-profile-title"][readonly="true"]')) == 0
|
assert len(response.pyquery('input[type="radio"][name="title"][readonly="true"]')) == 0
|
||||||
assert len(response.pyquery('select[name="edit-profile-title"]')) == 0
|
assert len(response.pyquery('select[name="title"]')) == 0
|
||||||
|
|
||||||
simple_user.verified_attributes.title = 'Monsieur'
|
simple_user.verified_attributes.title = 'Monsieur'
|
||||||
|
|
||||||
response = app.get(url, status=200)
|
response = app.get(url, status=200)
|
||||||
assert len(response.pyquery('input[type="radio"][name="edit-profile-title"]')) == 0
|
assert len(response.pyquery('input[type="radio"][name="title"]')) == 0
|
||||||
assert len(response.pyquery('input[type="text"][name="edit-profile-title@disabled"][readonly]')) == 1
|
assert len(response.pyquery('input[type="text"][name="title@disabled"][readonly]')) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_account_view(app, simple_user, settings):
|
def test_account_view(app, simple_user, settings):
|
||||||
|
|
|
@ -379,13 +379,13 @@ def test_attribute_model(app, db, settings, mailoutbox):
|
||||||
assert u'Prénom' not in response.text
|
assert u'Prénom' not in response.text
|
||||||
|
|
||||||
response = app.get(reverse('profile_edit'))
|
response = app.get(reverse('profile_edit'))
|
||||||
assert 'edit-profile-profession' in response.form.fields
|
assert 'profession' in response.form.fields
|
||||||
assert 'edit-profile-prenom' not in response.form.fields
|
assert 'prenom' not in response.form.fields
|
||||||
assert 'edit-profile-nom' not in response.form.fields
|
assert 'nom' not in response.form.fields
|
||||||
|
|
||||||
assert response.pyquery('[for=id_edit-profile-profession]')
|
assert response.pyquery('[for=id_profession]')
|
||||||
assert not response.pyquery('[for=id_edit-profile-profession].form-field-required')
|
assert not response.pyquery('[for=id_profession].form-field-required')
|
||||||
response.form.set('edit-profile-profession', 'pompier')
|
response.form.set('profession', 'pompier')
|
||||||
response = response.form.submit()
|
response = response.form.submit()
|
||||||
assert urlparse(response['Location']).path == reverse('account_management')
|
assert urlparse(response['Location']).path == reverse('account_management')
|
||||||
|
|
||||||
|
|
|
@ -733,6 +733,19 @@ def test_manager_edit_user_email_verified(app, simple_user, superuser_or_admin):
|
||||||
assert not user.email_verified
|
assert not user.email_verified
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_edit_user_address_autocomplete(app, simple_user, superuser_or_admin):
|
||||||
|
url = u'/manage/users/%s/edit/' % simple_user.pk
|
||||||
|
login(app, superuser_or_admin, '/manage/')
|
||||||
|
|
||||||
|
Attribute.objects.create(
|
||||||
|
name='address_autocomplete', label='Address (autocomplete)',
|
||||||
|
kind='address_auto', user_visible=True, user_editable=True)
|
||||||
|
|
||||||
|
resp = app.get(url)
|
||||||
|
assert resp.html.find('select', {'name': 'address_autocomplete'})
|
||||||
|
assert resp.html.find('input', {'id': 'manual-address'})
|
||||||
|
|
||||||
|
|
||||||
def test_manager_email_verified_column_user(app, simple_user, superuser_or_admin):
|
def test_manager_email_verified_column_user(app, simple_user, superuser_or_admin):
|
||||||
login(app, superuser_or_admin, '/manage/')
|
login(app, superuser_or_admin, '/manage/')
|
||||||
|
|
||||||
|
@ -793,6 +806,16 @@ def test_manager_user_username_field(app, superuser, simple_user):
|
||||||
assert resp.html.find('input', {'name': 'username'})
|
assert resp.html.find('input', {'name': 'username'})
|
||||||
|
|
||||||
|
|
||||||
|
def test_manager_user_address_autocomplete_field(app, superuser, simple_user):
|
||||||
|
login(app, superuser, '/manage/')
|
||||||
|
Attribute.objects.create(
|
||||||
|
name='address_autocomplete', label='Address (autocomplete)',
|
||||||
|
kind='address_auto', user_visible=True, user_editable=True)
|
||||||
|
resp = app.get(reverse('a2-manager-user-detail', kwargs={'pk': simple_user.id}))
|
||||||
|
assert not resp.html.find('select', {'name': 'address_autocomplete'})
|
||||||
|
assert not resp.html.find('input', {'id': 'manual-address'})
|
||||||
|
|
||||||
|
|
||||||
def test_manager_user_roles_visibility(app, simple_user, admin, ou1, ou2):
|
def test_manager_user_roles_visibility(app, simple_user, admin, ou1, ou2):
|
||||||
Role = get_role_model()
|
Role = get_role_model()
|
||||||
role1 = Role.objects.create(name='Role 1', slug='role1', ou=ou1)
|
role1 = Role.objects.create(name='Role 1', slug='role1', ou=ou1)
|
||||||
|
|
Loading…
Reference in New Issue