Josh Addington
Tobias Zanke
Petr Dlouhy
+Vinod Kurup
Thanks for all of your work!
-Copyright (c) 2010-2018, Mark Lavin
+Copyright (c) 2010-201999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999, Mark Lavin
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
+++ /dev/null
-Metadata-Version: 1.1
-Name: django-selectable
-Version: 0.9.0
-Summary: Auto-complete selection widgets using Django and jQuery UI.
-Home-page: https://github.com/mlavin/django-selectable
-Author: Mark Lavin
-Author-email: markdlavin@gmail.com
-License: BSD
-Description: django-selectable
- ===================
-
- Tools and widgets for using/creating auto-complete selection widgets using Django and jQuery UI.
-
- .. image:: https://travis-ci.org/mlavin/django-selectable.svg?branch=master
- :target: https://travis-ci.org/mlavin/django-selectable
-
-
- Features
- -----------------------------------
-
- - Works with the latest jQuery UI Autocomplete library
- - Auto-discovery/registration pattern for defining lookups
-
-
- Installation Requirements
- -----------------------------------
-
- - Python 2.6-2.7, 3.2+
- - `Django <http://www.djangoproject.com/>`_ >= 1.5
- - `jQuery <http://jquery.com/>`_ >= 1.7
- - `jQuery UI <http://jqueryui.com/>`_ >= 1.8
-
- To install::
-
- pip install django-selectable
-
- Next add `selectable` to your `INSTALLED_APPS` to include the related css/js::
-
- INSTALLED_APPS = (
- 'contrib.staticfiles',
- # Other apps here
- 'selectable',
- )
-
- The jQuery and jQuery UI libraries are not included in the distribution but must be included
- in your templates. See the example project for an example using these libraries from the
- Google CDN.
-
- Once installed you should add the urls to your root url patterns::
-
- urlpatterns = patterns('',
- # Other patterns go here
- (r'^selectable/', include('selectable.urls')),
- )
-
-
- Documentation
- -----------------------------------
-
- Documentation for django-selectable is available on `Read The Docs <http://readthedocs.org/docs/django-selectable>`_.
-
-
- Additional Help/Support
- -----------------------------------
-
- You can find additional help or support on the mailing list: http://groups.google.com/group/django-selectable
-
-
- Contributing
- --------------------------------------
-
- If you think you've found a bug or are interested in contributing to this project
- check out our `contributing guide <http://readthedocs.org/docs/django-selectable/en/latest/contribute.html>`_.
-
- If you are interested in translating django-selectable into your native language
- you can join the `Transifex project <https://www.transifex.com/projects/p/django-selectable/>`_.
-
-
-Platform: UNKNOWN
-Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Framework :: Django
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Operating System :: OS Independent
Installation Requirements
-----------------------------------
-- Python 2.7, 3.3+
-- `Django <http://www.djangoproject.com/>`_ >= 1.7, <= 1.11
+- Python 2.7, 3.4+
+- `Django <http://www.djangoproject.com/>`_ >= 1.11, <= 3.0
- `jQuery <http://jquery.com/>`_ >= 1.9, < 3.0
-- `jQuery UI <http://jqueryui.com/>`_ >= 1.10, < 1.12
+- `jQuery UI <http://jqueryui.com/>`_ >= 1.10
To install::
@python_2_unicode_compatible
class Farm(models.Model):
name = models.CharField(max_length=200)
- owner = models.ForeignKey('auth.User', related_name='farms')
+ owner = models.ForeignKey('auth.User', related_name='farms', on_delete=models.CASCADE)
fruit = models.ManyToManyField(Fruit)
def __str__(self):
admin.site.register(User, NewUserAdmin)
The auto-complete functions will be bound as new forms are added dynamically.
-
:param item: An item from the search results.
:return: A string representation of the item to be returned by the field/widget.
+
+.. py:method:: LookupBase.split_term(term)
+
+ Split searching term into array of subterms that will be searched separately.
+ You can override this function to achieve different splitting of the term.
+
+ :param term: The search term.
+ :return: Array with subterms
+
.. py:method:: LookupBase.get_item_value(item)
This is last of three formatting methods. The value is shown in the
==================
+v1.2.1 (Released 2019-02-02)
+--------------------------------------
+
+Fixed compatibility issue with jQuery UI 1.12. Thanks to Christian Klus (kluchrj) for the fix.
+
+
+v1.2.0 (Released 2018-10-13)
+--------------------------------------
+
+Primarily a Django support related release. This version adds support for Django 2.0 and 2.1 while
+dropping support for Django versions below 1.11. A number of deprecation warnings for future Django
+versions have also been addressed.
+
+Added the ability to search on multiple terms split by whitespace.
+
+
+Backwards Incompatible Changes
+________________________________
+
+- Dropped support for Django versions below 1.11
+
+
v1.1.0 (Released 2018-01-12)
--------------------------------------
+++ /dev/null
-/*global module:false*/
-module.exports = function(grunt) {
-
- // Project configuration.
- grunt.initConfig({
- qunit: {
- urls: [
- 'http://localhost:<%= server.port %>/selectable/tests/qunit/index.html?jquery=1.10.1&ui=1.10.3',
- 'http://localhost:<%= server.port %>/selectable/tests/qunit/index.html?jquery=1.9.1&ui=1.10.3',
- 'http://localhost:<%= server.port %>/selectable/tests/qunit/index.html?jquery=1.8.3&ui=1.9.2',
- 'http://localhost:<%= server.port %>/selectable/tests/qunit/index.html?jquery=1.7.2&ui=1.8.24',
- 'http://localhost:<%= server.port %>/selectable/tests/qunit/index.html?jquery=1.6.4&ui=1.8.24'
- ]
- },
- lint: {
- files: ['selectable/static/selectable/js/*.js']
- },
- watch: {
- files: '<config:lint.files>',
- tasks: 'lint qunit'
- },
- jshint: {
- options: {
- curly: true,
- eqeqeq: true,
- immed: true,
- latedef: true,
- newcap: true,
- noarg: true,
- sub: true,
- undef: true,
- boss: true,
- eqnull: true,
- browser: true,
- undef: true,
- trailing: true,
- indent: 4
- },
- globals: {
- jQuery: true,
- // Django admin globals
- django: true,
- dismissAddAnotherPopup: true,
- windowname_to_id: true,
- html_unescape: true,
- // Optional globals
- djselectableAdminPatch: true,
- djselectableAutoLoad: true,
- // Grappelli namespace
- grp: true
- }
- },
- server: {
- port: 8085
- },
- });
-
- // Default task.
- grunt.registerTask('default', 'server lint qunit');
-
-};
'NAME': ':memory:',
}
},
- MIDDLEWARE_CLASSES=(),
+ MIDDLEWARE=(),
INSTALLED_APPS=(
'selectable',
),
- SITE_ID=1,
SECRET_KEY='super-secret',
ROOT_URLCONF='selectable.tests.urls',
TEMPLATES=[{
"Auto-complete selection widgets using Django and jQuery UI."
-__version__ = '1.1.0'
+__version__ = '1.2.1'
default_app_config = 'selectable.apps.SelectableConfig'
from django.conf import settings
from django.core.paginator import Paginator, InvalidPage, EmptyPage
-from django.core.urlresolvers import reverse
from django.http import JsonResponse
from django.db.models import Q, Model
+from django.urls import reverse
from django.utils.encoding import smart_text
from django.utils.html import conditional_escape
from django.utils.translation import ugettext as _
-from selectable.forms import BaseLookupForm
-
+from .forms import BaseLookupForm
__all__ = (
'LookupBase',
return name
name = classmethod(_name)
+ def split_term(self, term):
+ """
+ Split searching term into array of subterms
+ that will be searched separately.
+ """
+ return term.split()
+
def _url(cls):
return reverse('selectable-lookup', args=[cls.name()])
url = classmethod(_url)
def get_query(self, request, term):
qs = self.get_queryset()
if term:
- search_filters = []
if self.search_fields:
- for field in self.search_fields:
- search_filters.append(Q(**{field: term}))
- qs = qs.filter(reduce(operator.or_, search_filters))
+ for t in self.split_term(term):
+ search_filters = []
+ for field in self.search_fields:
+ search_filters.append(Q(**{field: t}))
+ qs = qs.filter(reduce(operator.or_, search_filters))
return qs
def get_queryset(self):
-"Compatibility utilites for Python/Django versions."
+"Compatibility utilites for Python versions."
try:
from urllib.parse import urlparse
except ImportError:
+ # This can be removed when Python 2.7 support is dropped
from urlparse import urlparse
@results_decorator
-def ajax_required(request):
+def ajax_required(request):
"Lookup decorator to require AJAX calls to the lookup view."
if not request.is_ajax():
return HttpResponseBadRequest()
def login_required(request):
"Lookup decorator to require the user to be authenticated."
user = getattr(request, 'user', None)
- if user is None or not user.is_authenticated():
+ if user is None or not user.is_authenticated:
return HttpResponse(status=401) # Unauthorized
def staff_member_required(request):
"Lookup decorator to require the user is a staff member."
user = getattr(request, 'user', None)
- if user is None or not user.is_authenticated():
+ if user is None or not user.is_authenticated:
return HttpResponse(status=401) # Unauthorized
elif not user.is_staff:
return HttpResponseForbidden()
from __future__ import unicode_literals
-from django import forms, VERSION as DJANGO_VERSION
+from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import EMPTY_VALUES
from django.utils.translation import ugettext_lazy as _
else:
return data != initial
- if DJANGO_VERSION < (1, 8):
- def _has_changed(self, initial, data):
- return self.has_changed(initial, data)
-
class AutoCompleteSelectField(BaseAutoCompleteField):
widget = AutoCompleteSelectWidget
kwargs['widget'] = widget(lookup_class, allow_new=self.allow_new, limit=self.limit)
super(AutoCompleteSelectField, self).__init__(*args, **kwargs)
-
-
def to_python(self, value):
if value in EMPTY_VALUES:
return None
from __future__ import unicode_literals
-import inspect
import json
from django import forms
from django.conf import settings
-from django.forms.utils import flatatt
from django.utils.encoding import force_text
from django.utils.http import urlencode
-from django.utils.safestring import mark_safe
from selectable import __version__
from selectable.forms.base import import_lookup_class
js = ('%sjs/jquery.dj.selectable.js?v=%s' % (STATIC_PREFIX, __version__),)
-new_style_build_attrs = (
- 'base_attrs' in
- inspect.getargs(forms.widgets.Widget.build_attrs.__code__).args)
-
-
-class BuildAttrsCompat(object):
- """
- Mixin to provide compatibility between old and new function
- signatures for Widget.build_attrs, and a hook for adding our
- own attributes.
- """
- # These are build_attrs definitions that make it easier for
- # us to override, without having to worry about the signature,
- # by adding a standard hook, `build_attrs_extra`.
- # It has a different signature when we are running different Django
- # versions.
- if new_style_build_attrs:
- def build_attrs(self, base_attrs, extra_attrs=None):
- attrs = super(BuildAttrsCompat, self).build_attrs(
- base_attrs, extra_attrs=extra_attrs)
- return self.build_attrs_extra(attrs)
- else:
- def build_attrs(self, extra_attrs=None, **kwargs):
- attrs = super(BuildAttrsCompat, self).build_attrs(
- extra_attrs=extra_attrs, **kwargs)
- return self.build_attrs_extra(attrs)
-
- def build_attrs_extra(self, attrs):
- # Default implementation, does nothing
- return attrs
-
- # These provide a standard interface for when we want to call build_attrs
- # in our own `render` methods. In both cases it is the same as the Django
- # 1.11 signature, but has a different implementation for different Django
- # versions.
- if new_style_build_attrs:
- def build_attrs_compat(self, base_attrs, extra_attrs=None):
- return self.build_attrs(base_attrs, extra_attrs=extra_attrs)
-
- else:
- def build_attrs_compat(self, base_attrs, extra_attrs=None):
- # Implementation copied from Django 1.11, plus include our
- # hook `build_attrs_extra`
- attrs = base_attrs.copy()
- if extra_attrs is not None:
- attrs.update(extra_attrs)
- return self.build_attrs_extra(attrs)
-
-
-CompatMixin = BuildAttrsCompat
-
-
-class AutoCompleteWidget(CompatMixin, forms.TextInput, SelectableMediaMixin):
+class AutoCompleteWidget(forms.TextInput, SelectableMediaMixin):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = import_lookup_class(lookup_class)
def update_query_parameters(self, qs_dict):
self.qs.update(qs_dict)
- def build_attrs_extra(self, attrs):
- attrs = super(AutoCompleteWidget, self).build_attrs_extra(attrs)
+ def build_attrs(self, base_attrs, extra_attrs=None):
+ attrs = super(AutoCompleteWidget, self).build_attrs(base_attrs, extra_attrs)
url = self.lookup_class.url()
if self.limit and 'limit' not in self.qs:
self.qs['limit'] = self.limit
return attrs
-class SelectableMultiWidget(CompatMixin, forms.MultiWidget):
+class SelectableMultiWidget(forms.MultiWidget):
def update_query_parameters(self, qs_dict):
self.widgets[0].update_query_parameters(qs_dict)
class AutoComboboxWidget(AutoCompleteWidget, SelectableMediaMixin):
- def build_attrs_extra(self, attrs):
- attrs = super(AutoComboboxWidget, self).build_attrs_extra(attrs)
+ def build_attrs(self, base_attrs, extra_attrs=None):
+ attrs = super(AutoComboboxWidget, self).build_attrs(base_attrs, extra_attrs)
attrs['data-selectable-type'] = 'combobox'
return attrs
primary_widget = AutoComboboxWidget
-class LookupMultipleHiddenInput(CompatMixin, forms.MultipleHiddenInput):
+class LookupMultipleHiddenInput(forms.MultipleHiddenInput):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = import_lookup_class(lookup_class)
super(LookupMultipleHiddenInput, self).__init__(*args, **kwargs)
- # This supports Django 1.11 and later
def get_context(self, name, value, attrs):
lookup = self.lookup_class()
values = self._normalize_value(value)
widget_ctx['attrs']['title'] = title
return context
- # This supports Django 1.10 and earlier
- def render(self, name, value, attrs=None, choices=()):
- lookup = self.lookup_class()
- value = self._normalize_value(value)
-
- base_attrs = dict(self.attrs, type=self.input_type, name=name)
- combined_attrs = self.build_attrs_compat(base_attrs, attrs)
- id_ = combined_attrs.get('id', None)
- inputs = []
- for i, v in enumerate(value):
- input_attrs = combined_attrs.copy()
- v_, title = self._lookup_value_and_title(lookup, v)
- input_attrs.update(
- value=v_,
- title=title,
- )
- if id_:
- # An ID attribute was given. Add a numeric index as a suffix
- # so that the inputs don't all have the same ID attribute.
- input_attrs['id'] = '%s_%s' % (id_, i)
- inputs.append('<input%s />' % flatatt(input_attrs))
- return mark_safe('\n'.join(inputs))
-
- # These are used by both paths
- def build_attrs_extra(self, attrs):
- attrs = super(LookupMultipleHiddenInput, self).build_attrs_extra(attrs)
+ def build_attrs(self, base_attrs, extra_attrs=None):
+ attrs = super(LookupMultipleHiddenInput, self).build_attrs(base_attrs, extra_attrs)
attrs['data-selectable-type'] = 'hidden-multiple'
return attrs
value = self.get_compatible_postdata(data, name)
return value
- def build_attrs_extra(self, attrs):
- attrs = super(_BaseMultipleSelectWidget, self).build_attrs_extra(attrs)
+ def build_attrs(self, base_attrs, extra_attrs=None):
+ attrs = super(_BaseMultipleSelectWidget, self).build_attrs(base_attrs, extra_attrs)
if 'required' in attrs:
attrs.pop('required')
return attrs
- def render(self, name, value, attrs=None):
+ def render(self, name, value, attrs=None, renderer=None):
if value and not hasattr(value, '__iter__'):
value = [value]
value = ['', value]
- return super(_BaseMultipleSelectWidget, self).render(name, value, attrs)
+ return super(_BaseMultipleSelectWidget, self).render(name, value, attrs, renderer)
class AutoCompleteSelectMultipleWidget(_BaseMultipleSelectWidget):
ul.empty();
}
$input.data('page', null);
- ul.zIndex($input.zIndex() + 1);
+ ul.css("zIndex", $input.css("zIndex") + 1);
this._renderMenu(ul, items);
// jQuery UI menu does not define deactivate
if (this.menu.deactivate) {
@python_2_unicode_compatible
class OtherThing(models.Model):
name = models.CharField(max_length=100)
- thing = models.ForeignKey(Thing)
+ thing = models.ForeignKey(Thing, on_delete=models.CASCADE)
def __str__(self):
return self.name
import random
import string
from collections import defaultdict
-from xml.dom.minidom import parseString
from django.test import TestCase, override_settings
+from django.test.html import parse_html
from . import Thing
from ..base import ModelLookup
-def as_xml(html):
- "Convert HTML portion to minidom node."
- return parseString('<root>%s</root>' % html)
-
-
def parsed_inputs(html):
"Returns a dictionary mapping name --> node of inputs found in the HTML."
- node = as_xml(html)
+ node = parse_html(html)
inputs = {}
- for field in node.getElementsByTagName('input'):
- name = dict(field.attributes.items())['name']
+ for field in [c for c in node.children if c.name == 'input']:
+ name = dict(field.attributes)['name']
current = inputs.get(name, [])
current.append(field)
inputs[name] = current
class AttrMap(object):
def __init__(self, html):
- dom = as_xml(html)
+ dom = parse_html(html)
self._attrs = defaultdict(set)
self._build_attr_map(dom)
def _build_attr_map(self, dom):
for node in _walk_nodes(dom):
if node.attributes is not None:
- for k, v in node.attributes.items():
+ for (k, v) in node.attributes:
self._attrs[k].add(v)
def __contains__(self, key):
def _walk_nodes(dom):
yield dom
- for child in dom.childNodes:
+ for child in dom.children:
for item in _walk_nodes(child):
yield item
+++ /dev/null
-from mock import Mock
-
-from selectable.decorators import ajax_required, login_required, staff_member_required
-from selectable.tests.base import BaseSelectableTestCase, SimpleModelLookup
-
-
-__all__ = (
- 'AjaxRequiredLookupTestCase',
- 'LoginRequiredLookupTestCase',
- 'StaffRequiredLookupTestCase',
-)
-
-
-class AjaxRequiredLookupTestCase(BaseSelectableTestCase):
-
- def setUp(self):
- self.lookup = ajax_required(SimpleModelLookup)()
-
- def test_ajax_call(self):
- "Ajax call should yield a successful response."
- request = Mock()
- request.is_ajax = lambda: True
- response = self.lookup.results(request)
- self.assertTrue(response.status_code, 200)
-
- def test_non_ajax_call(self):
- "Non-Ajax call should yield a bad request response."
- request = Mock()
- request.is_ajax = lambda: False
- response = self.lookup.results(request)
- self.assertEqual(response.status_code, 400)
-
-
-class LoginRequiredLookupTestCase(BaseSelectableTestCase):
-
- def setUp(self):
- self.lookup = login_required(SimpleModelLookup)()
-
- def test_authenicated_call(self):
- "Authenicated call should yield a successful response."
- request = Mock()
- user = Mock()
- user.is_authenticated = lambda: True
- request.user = user
- response = self.lookup.results(request)
- self.assertTrue(response.status_code, 200)
-
- def test_non_authenicated_call(self):
- "Non-Authenicated call should yield an unauthorized response."
- request = Mock()
- user = Mock()
- user.is_authenticated = lambda: False
- request.user = user
- response = self.lookup.results(request)
- self.assertEqual(response.status_code, 401)
-
-
-class StaffRequiredLookupTestCase(BaseSelectableTestCase):
-
- def setUp(self):
- self.lookup = staff_member_required(SimpleModelLookup)()
-
- def test_staff_member_call(self):
- "Staff member call should yield a successful response."
- request = Mock()
- user = Mock()
- user.is_authenticated = lambda: True
- user.is_staff = True
- request.user = user
- response = self.lookup.results(request)
- self.assertTrue(response.status_code, 200)
-
- def test_authenicated_but_not_staff(self):
- "Authenicated but non staff call should yield a forbidden response."
- request = Mock()
- user = Mock()
- user.is_authenticated = lambda: True
- user.is_staff = False
- request.user = user
- response = self.lookup.results(request)
- self.assertTrue(response.status_code, 403)
-
- def test_non_authenicated_call(self):
- "Non-Authenicated call should yield an unauthorized response."
- request = Mock()
- user = Mock()
- user.is_authenticated = lambda: False
- user.is_staff = False
- request.user = user
- response = self.lookup.results(request)
- self.assertEqual(response.status_code, 401)
+++ /dev/null
-from django import forms
-
-from selectable.forms import fields, widgets
-from selectable.tests import ThingLookup
-from selectable.tests.base import BaseSelectableTestCase
-
-
-__all__ = (
- 'AutoCompleteSelectFieldTestCase',
- 'AutoCompleteSelectMultipleFieldTestCase',
-)
-
-class BaseFieldTestCase(BaseSelectableTestCase):
- field_cls = None
- lookup_cls = None
-
- def get_field_instance(self, allow_new=False, limit=None, widget=None):
- return self.field_cls(self.lookup_cls, allow_new=allow_new, limit=limit, widget=widget)
-
- def test_init(self):
- field = self.get_field_instance()
- self.assertEqual(field.lookup_class, self.lookup_cls)
-
- def test_init_with_limit(self):
- field = self.get_field_instance(limit=10)
- self.assertEqual(field.limit, 10)
- self.assertEqual(field.widget.limit, 10)
-
- def test_clean(self):
- self.fail('This test has not yet been written')
-
- def test_dotted_path(self):
- """
- Ensure lookup_class can be imported from a dotted path.
- """
- dotted_path = '.'.join([self.lookup_cls.__module__, self.lookup_cls.__name__])
- field = self.field_cls(dotted_path)
- self.assertEqual(field.lookup_class, self.lookup_cls)
-
- def test_invalid_dotted_path(self):
- """
- An invalid lookup_class dotted path should raise an ImportError.
- """
- with self.assertRaises(ImportError):
- self.field_cls('this.is.an.invalid.path')
-
- def test_dotted_path_wrong_type(self):
- """
- lookup_class must be a subclass of LookupBase.
- """
- dotted_path = 'selectable.forms.fields.AutoCompleteSelectField'
- with self.assertRaises(TypeError):
- self.field_cls(dotted_path)
-
-class AutoCompleteSelectFieldTestCase(BaseFieldTestCase):
- field_cls = fields.AutoCompleteSelectField
- lookup_cls = ThingLookup
-
- def test_clean(self):
- thing = self.create_thing()
- field = self.get_field_instance()
- value = field.clean([thing.name, thing.id])
- self.assertEqual(thing, value)
-
- def test_new_not_allowed(self):
- field = self.get_field_instance()
- value = self.get_random_string()
- self.assertRaises(forms.ValidationError, field.clean, [value, ''])
-
- def test_new_allowed(self):
- field = self.get_field_instance(allow_new=True)
- value = self.get_random_string()
- value = field.clean([value, ''])
- self.assertTrue(isinstance(value, ThingLookup.model))
-
- def test_default_widget(self):
- field = self.get_field_instance()
- self.assertTrue(isinstance(field.widget, widgets.AutoCompleteSelectWidget))
-
- def test_alternate_widget(self):
- widget_cls = widgets.AutoComboboxWidget
- field = self.get_field_instance(widget=widget_cls)
- self.assertTrue(isinstance(field.widget, widget_cls))
-
- def test_alternate_widget_instance(self):
- widget = widgets.AutoComboboxWidget(self.lookup_cls)
- field = self.get_field_instance(widget=widget)
- self.assertTrue(isinstance(field.widget, widgets.AutoComboboxWidget))
-
- def test_invalid_pk(self):
- field = self.get_field_instance()
- value = self.get_random_string()
- self.assertRaises(forms.ValidationError, field.clean, [value, 'XXX'])
-
-
-class AutoCompleteSelectMultipleFieldTestCase(BaseFieldTestCase):
- field_cls = fields.AutoCompleteSelectMultipleField
- lookup_cls = ThingLookup
-
- def get_field_instance(self, limit=None, widget=None):
- return self.field_cls(self.lookup_cls, limit=limit, widget=widget)
-
- def test_clean(self):
- thing = self.create_thing()
- field = self.get_field_instance()
- value = field.clean([thing.id])
- self.assertEqual([thing], value)
-
- def test_clean_multiple(self):
- thing = self.create_thing()
- other_thing = self.create_thing()
- field = self.get_field_instance()
- ids = [thing.id, other_thing.id]
- value = field.clean(ids)
- self.assertEqual([thing, other_thing], value)
-
- def test_default_widget(self):
- field = self.get_field_instance()
- self.assertTrue(isinstance(field.widget, widgets.AutoCompleteSelectMultipleWidget))
-
- def test_alternate_widget(self):
- widget_cls = widgets.AutoComboboxSelectMultipleWidget
- field = self.get_field_instance(widget=widget_cls)
- self.assertTrue(isinstance(field.widget, widget_cls))
-
- def test_alternate_widget_instance(self):
- widget = widgets.AutoComboboxSelectMultipleWidget(self.lookup_cls)
- field = self.get_field_instance(widget=widget)
- self.assertTrue(isinstance(field.widget, widgets.AutoComboboxSelectMultipleWidget))
-
- def test_invalid_pk(self):
- field = self.get_field_instance()
- value = self.get_random_string()
- self.assertRaises(forms.ValidationError, field.clean, ['XXX', ])
+++ /dev/null
-from django.conf import settings
-
-from selectable.forms import BaseLookupForm
-from selectable.tests.base import BaseSelectableTestCase, PatchSettingsMixin
-
-
-__all__ = (
- 'BaseLookupFormTestCase',
-)
-
-
-class BaseLookupFormTestCase(PatchSettingsMixin, BaseSelectableTestCase):
-
- def get_valid_data(self):
- data = {
- 'term': 'foo',
- 'limit': 10,
- }
- return data
-
- def test_valid_data(self):
- data = self.get_valid_data()
- form = BaseLookupForm(data)
- self.assertTrue(form.is_valid(), "%s" % form.errors)
-
- def test_invalid_limit(self):
- """
- Test giving the form an invalid limit.
- """
-
- data = self.get_valid_data()
- data['limit'] = 'bar'
- form = BaseLookupForm(data)
- self.assertFalse(form.is_valid())
-
- def test_no_limit(self):
- """
- If SELECTABLE_MAX_LIMIT is set and limit is not given then
- the form will return SELECTABLE_MAX_LIMIT.
- """
-
- data = self.get_valid_data()
- if 'limit' in data:
- del data['limit']
- form = BaseLookupForm(data)
- self.assertTrue(form.is_valid(), "%s" % form.errors)
- self.assertEqual(form.cleaned_data['limit'], settings.SELECTABLE_MAX_LIMIT)
-
- def test_no_max_set(self):
- """
- If SELECTABLE_MAX_LIMIT is not set but given then the form
- will return the given limit.
- """
-
- settings.SELECTABLE_MAX_LIMIT = None
- data = self.get_valid_data()
- form = BaseLookupForm(data)
- self.assertTrue(form.is_valid(), "%s" % form.errors)
- if 'limit' in data:
- self.assertTrue(form.cleaned_data['limit'], data['limit'])
-
- def test_no_max_set_not_given(self):
- """
- If SELECTABLE_MAX_LIMIT is not set and not given then the form
- will return no limit.
- """
-
- settings.SELECTABLE_MAX_LIMIT = None
- data = self.get_valid_data()
- if 'limit' in data:
- del data['limit']
- form = BaseLookupForm(data)
- self.assertTrue(form.is_valid(), "%s" % form.errors)
- self.assertFalse(form.cleaned_data.get('limit'))
-
- def test_over_limit(self):
- """
- If SELECTABLE_MAX_LIMIT is set and limit given is greater then
- the form will return SELECTABLE_MAX_LIMIT.
- """
-
- data = self.get_valid_data()
- data['limit'] = settings.SELECTABLE_MAX_LIMIT + 100
- form = BaseLookupForm(data)
- self.assertTrue(form.is_valid(), "%s" % form.errors)
- self.assertEqual(form.cleaned_data['limit'], settings.SELECTABLE_MAX_LIMIT)
+++ /dev/null
-"""
-Larger functional tests for fields and widgets.
-"""
-from __future__ import unicode_literals
-
-from django import forms
-
-from selectable.forms import AutoCompleteSelectField, AutoCompleteSelectMultipleField
-from selectable.forms import AutoCompleteSelectWidget, AutoComboboxSelectWidget
-from selectable.tests import ManyThing, OtherThing, ThingLookup
-from selectable.tests.base import BaseSelectableTestCase, parsed_inputs
-
-
-__all__ = (
- 'FuncAutoCompleteSelectTestCase',
- 'FuncSelectModelChoiceTestCase',
- 'FuncComboboxModelChoiceTestCase',
- 'FuncManytoManyMultipleSelectTestCase',
- 'FuncFormTestCase',
-)
-
-
-class OtherThingForm(forms.ModelForm):
-
- thing = AutoCompleteSelectField(lookup_class=ThingLookup)
-
- class Meta(object):
- model = OtherThing
-
-
-class FuncAutoCompleteSelectTestCase(BaseSelectableTestCase):
-
- def setUp(self):
- self.test_thing = self.create_thing()
-
- def test_valid_form(self):
- "Valid form using an AutoCompleteSelectField."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
- }
- form = OtherThingForm(data=data)
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_invalid_form_missing_selected_pk(self):
- "Invalid form using an AutoCompleteSelectField."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': '', # Hidden input
- }
- form = OtherThingForm(data=data)
- self.assertFalse(form.is_valid(), 'Form should not be valid')
- self.assertFalse('name' in form.errors)
- self.assertTrue('thing' in form.errors)
-
- def test_invalid_form_missing_name(self):
- "Invalid form using an AutoCompleteSelectField."
- data = {
- 'name': '',
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
- }
- form = OtherThingForm(data=data)
- self.assertFalse(form.is_valid(), 'Form should not be valid')
- self.assertTrue('name' in form.errors)
- self.assertFalse('thing' in form.errors)
-
- def test_invalid_but_still_selected(self):
- "Invalid form should keep selected item."
- data = {
- 'name': '',
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
- }
- form = OtherThingForm(data=data)
- self.assertFalse(form.is_valid(), 'Form should not be valid')
- rendered_form = form.as_p()
- inputs = parsed_inputs(rendered_form)
- # Selected text should be populated
- thing_0 = inputs['thing_0'][0]
- self.assertEqual(thing_0.attributes['value'].value, self.test_thing.name)
- # Selected pk should be populated
- thing_1 = inputs['thing_1'][0]
- self.assertEqual(int(thing_1.attributes['value'].value), self.test_thing.pk)
-
- def test_populate_from_model(self):
- "Populate from existing model."
- other_thing = OtherThing.objects.create(thing=self.test_thing, name='a')
- form = OtherThingForm(instance=other_thing)
- rendered_form = form.as_p()
- inputs = parsed_inputs(rendered_form)
- # Selected text should be populated
- thing_0 = inputs['thing_0'][0]
- self.assertEqual(thing_0.attributes['value'].value, self.test_thing.name)
- # Selected pk should be populated
- thing_1 = inputs['thing_1'][0]
- self.assertEqual(int(thing_1.attributes['value'].value), self.test_thing.pk)
-
-
-class SelectWidgetForm(forms.ModelForm):
-
- class Meta(object):
- model = OtherThing
- widgets = {
- 'thing': AutoCompleteSelectWidget(lookup_class=ThingLookup)
- }
-
-
-class FuncSelectModelChoiceTestCase(BaseSelectableTestCase):
- """
- Functional tests for AutoCompleteSelectWidget compatibility
- with a ModelChoiceField.
- """
-
- def setUp(self):
- self.test_thing = self.create_thing()
-
- def test_valid_form(self):
- "Valid form using an AutoCompleteSelectWidget."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
- }
- form = SelectWidgetForm(data=data)
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_missing_pk(self):
- "Invalid form (missing required pk) using an AutoCompleteSelectWidget."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': '', # Hidden input missing
- }
- form = SelectWidgetForm(data=data)
- self.assertFalse(form.is_valid())
- self.assertTrue('thing' in form.errors)
-
- def test_invalid_pk(self):
- "Invalid form (invalid pk value) using an AutoCompleteSelectWidget."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': 'XXX', # Hidden input doesn't match a PK
- }
- form = SelectWidgetForm(data=data)
- self.assertFalse(form.is_valid())
- self.assertTrue('thing' in form.errors)
-
-
-class ComboboxSelectWidgetForm(forms.ModelForm):
-
- class Meta(object):
- model = OtherThing
- widgets = {
- 'thing': AutoComboboxSelectWidget(lookup_class=ThingLookup)
- }
-
-
-class FuncComboboxModelChoiceTestCase(BaseSelectableTestCase):
- """
- Functional tests for AutoComboboxSelectWidget compatibility
- with a ModelChoiceField.
- """
-
- def setUp(self):
- self.test_thing = self.create_thing()
-
- def test_valid_form(self):
- "Valid form using an AutoComboboxSelectWidget."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
- }
- form = ComboboxSelectWidgetForm(data=data)
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_missing_pk(self):
- "Invalid form (missing required pk) using an AutoComboboxSelectWidget."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': '', # Hidden input missing
- }
- form = SelectWidgetForm(data=data)
- self.assertFalse(form.is_valid())
- self.assertTrue('thing' in form.errors)
-
- def test_invalid_pk(self):
- "Invalid form (invalid pk value) using an AutoComboboxSelectWidget."
- data = {
- 'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': 'XXX', # Hidden input doesn't match a PK
- }
- form = SelectWidgetForm(data=data)
- self.assertFalse(form.is_valid())
- self.assertTrue('thing' in form.errors)
-
-
-class ManyThingForm(forms.ModelForm):
-
- things = AutoCompleteSelectMultipleField(lookup_class=ThingLookup)
-
- class Meta(object):
- model = ManyThing
-
-
-class FuncManytoManyMultipleSelectTestCase(BaseSelectableTestCase):
- """
- Functional tests for AutoCompleteSelectMultipleField compatibility
- with a ManyToManyField.
- """
-
- def setUp(self):
- self.test_thing = self.create_thing()
-
- def test_valid_form(self):
- "Valid form using an AutoCompleteSelectMultipleField."
- data = {
- 'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [self.test_thing.pk, ], # Hidden inputs
- }
- form = ManyThingForm(data=data)
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_valid_save(self):
- "Saving data from a valid form."
- data = {
- 'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [self.test_thing.pk, ], # Hidden inputs
- }
- form = ManyThingForm(data=data)
- manything = form.save()
- self.assertEqual(manything.name, data['name'])
- things = manything.things.all()
- self.assertEqual(things.count(), 1)
- self.assertTrue(self.test_thing in things)
-
- def test_not_required(self):
- "Valid form where many to many is not required."
- data = {
- 'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [], # Hidden inputs
- }
- form = ManyThingForm(data=data)
- form.fields['things'].required = False
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_not_required_save(self):
- "Saving data when many to many is not required."
- data = {
- 'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [], # Hidden inputs
- }
- form = ManyThingForm(data=data)
- form.fields['things'].required = False
- manything = form.save()
- self.assertEqual(manything.name, data['name'])
- things = manything.things.all()
- self.assertEqual(things.count(), 0)
-
- def test_has_changed(self):
- "Populate intial data from a model."
- manything = ManyThing.objects.create(name='Foo')
- thing_1 = self.create_thing()
- manything.things.add(thing_1)
- data = {
- 'name': manything.name,
- 'things_0': '', # Text input
- 'things_1': [thing_1.pk], # Hidden inputs
- }
- form = ManyThingForm(data=data, instance=manything)
- self.assertFalse(form.has_changed(), str(form.changed_data))
-
-
-class SimpleForm(forms.Form):
- "Non-model form usage."
- thing = AutoCompleteSelectField(lookup_class=ThingLookup)
- new_thing = AutoCompleteSelectField(lookup_class=ThingLookup, allow_new=True)
- things = AutoCompleteSelectMultipleField(lookup_class=ThingLookup)
-
-
-class FuncFormTestCase(BaseSelectableTestCase):
- """
- Functional tests for using AutoCompleteSelectField
- and AutoCompleteSelectMultipleField outside the context
- of a ModelForm.
- """
-
- def setUp(self):
- self.test_thing = self.create_thing()
-
- def test_blank_new_item(self):
- "Regression test for #91. new_thing is required but both are blank."
- data = {
- 'thing_0': self.test_thing.name,
- 'thing_1': self.test_thing.pk,
- 'new_thing_0': '',
- 'new_thing_1': '',
- 'things_0': '',
- 'things_1': [self.test_thing.pk, ]
- }
- form = SimpleForm(data=data)
- self.assertFalse(form.is_valid())
- self.assertTrue('new_thing' in form.errors)
-
- def test_has_changed_with_empty_permitted(self):
- """
- Regression test for #92. has_changed fails when there is no initial and
- allow_new=False.
- """
- data = {
- 'thing_0': '',
- 'thing_1': self.test_thing.pk,
- 'new_thing_0': self.test_thing.name,
- 'new_thing_1': self.test_thing.pk,
- 'things_0': '',
- 'things_1': [self.test_thing.pk, ]
- }
- form = SimpleForm(data=data, empty_permitted=True)
- self.assertTrue(form.has_changed())
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_not_changed(self):
- """
- Regression test for #92. has_changed fails when there is no initial and
- allow_new=False.
- """
- data = {
- 'thing_0': self.test_thing.name,
- 'thing_1': self.test_thing.pk,
- 'new_thing_0': self.test_thing.name,
- 'new_thing_1': self.test_thing.pk,
- 'things_0': '',
- 'things_1': [self.test_thing.pk, ]
- }
- initial = {
- 'thing': self.test_thing.pk,
- 'new_thing': self.test_thing.pk,
- 'things': [self.test_thing.pk, ]
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertFalse(form.has_changed())
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_not_changed_with_empty_permitted(self):
- """
- Regression test for #92. has_changed fails when there is no initial and
- allow_new=False.
- """
- data = {
- 'thing_0': '',
- 'thing_1': '',
- 'new_thing_0': '',
- 'new_thing_1': '',
- 'things_0': '',
- 'things_1': '',
- }
- initial = {
- 'thing': '',
- 'new_thing': '',
- 'things': '',
- }
- form = SimpleForm(data=data, initial=initial, empty_permitted=True)
- self.assertFalse(form.has_changed(), str(form.changed_data))
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_no_initial_with_empty_permitted(self):
- """
- If empty data is submitted and allowed with no initial then
- the form should not be seen as changed.
- """
- data = {
- 'thing_0': '',
- 'thing_1': '',
- 'new_thing_0': '',
- 'new_thing_1': '',
- 'things_0': '',
- 'things_1': '',
- }
- form = SimpleForm(data=data, empty_permitted=True)
- self.assertFalse(form.has_changed(), str(form.changed_data))
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_no_data_with_empty_permitted(self):
- """
- If no data is submitted and allowed with no initial then
- the form should not be seen as changed.
- """
- form = SimpleForm(data={}, empty_permitted=True)
- self.assertFalse(form.has_changed(), str(form.changed_data))
- self.assertTrue(form.is_valid(), str(form.errors))
-
- def test_select_multiple_changed(self):
- """
- Detect changes for a multiple select input with and without
- initial data.
- """
- data = {
- 'thing_0': '',
- 'thing_1': '',
- 'new_thing_0': '',
- 'new_thing_1': '',
- 'things_0': '',
- 'things_1': [self.test_thing.pk, ]
- }
- form = SimpleForm(data=data)
- self.assertTrue(form.has_changed())
- self.assertTrue('things' in form.changed_data)
-
- initial = {
- 'thing': '',
- 'new_thing': '',
- 'things': [self.test_thing.pk, ],
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertFalse(form.has_changed(), str(form.changed_data))
-
- initial = {
- 'thing': '',
- 'new_thing': '',
- 'things': [],
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertTrue(form.has_changed())
- self.assertTrue('things' in form.changed_data)
-
- def test_single_select_changed(self):
- """
- Detect changes for a single select input with and without
- initial data.
- """
- data = {
- 'thing_0': '',
- 'thing_1': self.test_thing.pk,
- 'new_thing_0': '',
- 'new_thing_1': '',
- 'things_0': '',
- 'things_1': ''
- }
- form = SimpleForm(data=data)
- self.assertTrue(form.has_changed())
- self.assertTrue('thing' in form.changed_data)
-
- initial = {
- 'thing': self.test_thing.pk,
- 'new_thing': '',
- 'things': '',
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertFalse(form.has_changed(), str(form.changed_data))
-
- initial = {
- 'thing': '',
- 'new_thing': '',
- 'things': '',
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertTrue(form.has_changed())
- self.assertTrue('thing' in form.changed_data)
-
- def test_new_select_changed(self):
- """
- Detect changes for a single select input which allows new items
- with and without initial data.
- """
- data = {
- 'thing_0': '',
- 'thing_1': '',
- 'new_thing_0': 'Foo',
- 'new_thing_1': '',
- 'things_0': '',
- 'things_1': ''
- }
- form = SimpleForm(data=data)
- self.assertTrue(form.has_changed())
- self.assertTrue('new_thing' in form.changed_data)
-
- initial = {
- 'thing': '',
- 'new_thing': ['Foo', None],
- 'things': '',
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertFalse(form.has_changed(), str(form.changed_data))
-
- initial = {
- 'thing': '',
- 'new_thing': '',
- 'things': '',
- }
- form = SimpleForm(data=data, initial=initial)
- self.assertTrue(form.has_changed())
- self.assertTrue('new_thing' in form.changed_data)
\ No newline at end of file
+++ /dev/null
-from django.template import Template, Context
-
-from selectable.tests.base import BaseSelectableTestCase
-
-__all__ = (
- 'JqueryTagTestCase',
- 'ThemeTagTestCase',
-)
-
-
-class JqueryTagTestCase(BaseSelectableTestCase):
-
- def assertJQueryVersion(self, result, version):
- expected = "//ajax.googleapis.com/ajax/libs/jquery/%s/jquery.min.js" % version
- self.assertTrue(expected in result)
-
- def assertUIVersion(self, result, version):
- expected = "//ajax.googleapis.com/ajax/libs/jqueryui/%s/jquery-ui.js" % version
- self.assertTrue(expected in result)
-
- def test_render(self):
- "Render template tag with default versions."
- template = Template("{% load selectable_tags %}{% include_jquery_libs %}")
- context = Context({})
- result = template.render(context)
- self.assertJQueryVersion(result, '1.7.2')
- self.assertUIVersion(result, '1.8.23')
-
- def test_render_jquery_version(self):
- "Render template tag with specified jQuery version."
- template = Template("{% load selectable_tags %}{% include_jquery_libs '1.4.3' %}")
- context = Context({})
- result = template.render(context)
- self.assertJQueryVersion(result, '1.4.3')
-
- def test_render_variable_jquery_version(self):
- "Render using jQuery version from the template context."
- version = '1.4.3'
- template = Template("{% load selectable_tags %}{% include_jquery_libs version %}")
- context = Context({'version': version})
- result = template.render(context)
- self.assertJQueryVersion(result, '1.4.3')
-
- def test_render_jquery_ui_version(self):
- "Render template tag with specified jQuery UI version."
- template = Template("{% load selectable_tags %}{% include_jquery_libs '1.4.3' '1.8.13' %}")
- context = Context({})
- result = template.render(context)
- self.assertUIVersion(result, '1.8.13')
-
- def test_render_variable_jquery_ui_version(self):
- "Render using jQuery UI version from the template context."
- version = '1.8.13'
- template = Template("{% load selectable_tags %}{% include_jquery_libs '1.4.3' version %}")
- context = Context({'version': version})
- result = template.render(context)
- self.assertUIVersion(result, '1.8.13')
-
- def test_render_no_jquery(self):
- "Render template tag without jQuery."
- template = Template("{% load selectable_tags %}{% include_jquery_libs '' %}")
- context = Context({})
- result = template.render(context)
- self.assertTrue('jquery.min.js' not in result)
-
- def test_render_no_jquery_ui(self):
- "Render template tag without jQuery UI."
- template = Template("{% load selectable_tags %}{% include_jquery_libs '1.7.2' '' %}")
- context = Context({})
- result = template.render(context)
- self.assertTrue('jquery-ui.js' not in result)
-
-
-class ThemeTagTestCase(BaseSelectableTestCase):
-
- def assertUICSS(self, result, theme, version):
- expected = "//ajax.googleapis.com/ajax/libs/jqueryui/%s/themes/%s/jquery-ui.css" % (version, theme)
- self.assertTrue(expected in result)
-
- def test_render(self):
- "Render template tag with default settings."
- template = Template("{% load selectable_tags %}{% include_ui_theme %}")
- context = Context({})
- result = template.render(context)
- self.assertUICSS(result, 'base', '1.8.23')
-
- def test_render_version(self):
- "Render template tag with alternate version."
- template = Template("{% load selectable_tags %}{% include_ui_theme 'base' '1.8.13' %}")
- context = Context({})
- result = template.render(context)
- self.assertUICSS(result, 'base', '1.8.13')
-
- def test_variable_version(self):
- "Render using version from content variable."
- version = '1.8.13'
- template = Template("{% load selectable_tags %}{% include_ui_theme 'base' version %}")
- context = Context({'version': version})
- result = template.render(context)
- self.assertUICSS(result, 'base', version)
-
- def test_render_theme(self):
- "Render template tag with alternate theme."
- template = Template("{% load selectable_tags %}{% include_ui_theme 'ui-lightness' %}")
- context = Context({})
- result = template.render(context)
- self.assertUICSS(result, 'ui-lightness', '1.8.23')
-
- def test_variable_theme(self):
- "Render using theme from content variable."
- theme = 'ui-lightness'
- template = Template("{% load selectable_tags %}{% include_ui_theme theme %}")
- context = Context({'theme': theme})
- result = template.render(context)
- self.assertUICSS(result, theme, '1.8.23')
from __future__ import unicode_literals
-from django.core.urlresolvers import reverse
+from django.urls import reverse
from django.utils.html import escape
from django.utils.safestring import SafeData, mark_safe
def setUp(self):
self.lookup = login_required(SimpleModelLookup)()
-
+
def test_authenicated_call(self):
"Authenicated call should yield a successful response."
request = Mock()
user = Mock()
- user.is_authenticated = lambda: True
+ user.is_authenticated = True
request.user = user
response = self.lookup.results(request)
self.assertTrue(response.status_code, 200)
"Non-Authenicated call should yield an unauthorized response."
request = Mock()
user = Mock()
- user.is_authenticated = lambda: False
+ user.is_authenticated = False
request.user = user
response = self.lookup.results(request)
self.assertEqual(response.status_code, 401)
"Staff member call should yield a successful response."
request = Mock()
user = Mock()
- user.is_authenticated = lambda: True
+ user.is_authenticated = True
user.is_staff = True
request.user = user
response = self.lookup.results(request)
"Authenicated but non staff call should yield a forbidden response."
request = Mock()
user = Mock()
- user.is_authenticated = lambda: True
+ user.is_authenticated = True
user.is_staff = False
request.user = user
response = self.lookup.results(request)
"Non-Authenicated call should yield an unauthorized response."
request = Mock()
user = Mock()
- user.is_authenticated = lambda: False
+ user.is_authenticated = False
user.is_staff = False
request.user = user
response = self.lookup.results(request)
"Valid form using an AutoCompleteSelectField."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': self.test_thing.pk, # Hidden input
}
form = OtherThingForm(data=data)
self.assertTrue(form.is_valid(), str(form.errors))
"Invalid form using an AutoCompleteSelectField."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': '', # Hidden input
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': '', # Hidden input
}
form = OtherThingForm(data=data)
self.assertFalse(form.is_valid(), 'Form should not be valid')
"Invalid form using an AutoCompleteSelectField."
data = {
'name': '',
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': self.test_thing.pk, # Hidden input
}
form = OtherThingForm(data=data)
self.assertFalse(form.is_valid(), 'Form should not be valid')
"Invalid form should keep selected item."
data = {
'name': '',
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': self.test_thing.pk, # Hidden input
}
form = OtherThingForm(data=data)
self.assertFalse(form.is_valid(), 'Form should not be valid')
"Valid form using an AutoCompleteSelectWidget."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': self.test_thing.pk, # Hidden input
}
form = SelectWidgetForm(data=data)
self.assertTrue(form.is_valid(), str(form.errors))
"Invalid form (missing required pk) using an AutoCompleteSelectWidget."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': '', # Hidden input missing
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': '', # Hidden input missing
}
form = SelectWidgetForm(data=data)
self.assertFalse(form.is_valid())
"Invalid form (invalid pk value) using an AutoCompleteSelectWidget."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': 'XXX', # Hidden input doesn't match a PK
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': 'XXX', # Hidden input doesn't match a PK
}
form = SelectWidgetForm(data=data)
self.assertFalse(form.is_valid())
"Valid form using an AutoComboboxSelectWidget."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': self.test_thing.pk, # Hidden input
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': self.test_thing.pk, # Hidden input
}
form = ComboboxSelectWidgetForm(data=data)
self.assertTrue(form.is_valid(), str(form.errors))
"Invalid form (missing required pk) using an AutoComboboxSelectWidget."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': '', # Hidden input missing
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': '', # Hidden input missing
}
form = ComboboxSelectWidgetForm(data=data)
self.assertFalse(form.is_valid())
"Invalid form (invalid pk value) using an AutoComboboxSelectWidget."
data = {
'name': self.get_random_string(),
- 'thing_0': self.test_thing.name, # Text input
- 'thing_1': 'XXX', # Hidden input doesn't match a PK
+ 'thing_0': self.test_thing.name, # Text input
+ 'thing_1': 'XXX', # Hidden input doesn't match a PK
}
form = ComboboxSelectWidgetForm(data=data)
self.assertFalse(form.is_valid())
"Valid form using an AutoCompleteSelectMultipleField."
data = {
'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [self.test_thing.pk, ], # Hidden inputs
+ 'things_0': '', # Text input
+ 'things_1': [self.test_thing.pk, ], # Hidden inputs
}
form = ManyThingForm(data=data)
self.assertTrue(form.is_valid(), str(form.errors))
"Saving data from a valid form."
data = {
'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [self.test_thing.pk, ], # Hidden inputs
+ 'things_0': '', # Text input
+ 'things_1': [self.test_thing.pk, ], # Hidden inputs
}
form = ManyThingForm(data=data)
manything = form.save()
"Valid form where many to many is not required."
data = {
'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [], # Hidden inputs
+ 'things_0': '', # Text input
+ 'things_1': [], # Hidden inputs
}
form = ManyThingForm(data=data)
form.fields['things'].required = False
"Saving data when many to many is not required."
data = {
'name': self.get_random_string(),
- 'things_0': '', # Text input
- 'things_1': [], # Hidden inputs
+ 'things_0': '', # Text input
+ 'things_1': [], # Hidden inputs
}
form = ManyThingForm(data=data)
form.fields['things'].required = False
manything.things.add(thing_1)
data = {
'name': manything.name,
- 'things_0': '', # Text input
- 'things_1': [thing_1.pk], # Hidden inputs
+ 'things_0': '', # Text input
+ 'things_1': [thing_1.pk], # Hidden inputs
}
form = ManyThingForm(data=data, instance=manything)
self.assertFalse(form.has_changed(), str(form.changed_data))
'things_0': '',
'things_1': [self.test_thing.pk, ]
}
- form = SimpleForm(data=data, empty_permitted=True)
+ form = SimpleForm(data=data, empty_permitted=True, use_required_attribute=False)
self.assertTrue(form.has_changed())
self.assertTrue(form.is_valid(), str(form.errors))
'new_thing': '',
'things': '',
}
- form = SimpleForm(data=data, initial=initial, empty_permitted=True)
+ form = SimpleForm(data=data, initial=initial, empty_permitted=True, use_required_attribute=False)
self.assertFalse(form.has_changed(), str(form.changed_data))
self.assertTrue(form.is_valid(), str(form.errors))
'things_0': '',
'things_1': '',
}
- form = SimpleForm(data=data, empty_permitted=True)
+ form = SimpleForm(data=data, empty_permitted=True, use_required_attribute=False)
self.assertFalse(form.has_changed(), str(form.changed_data))
self.assertTrue(form.is_valid(), str(form.errors))
If no data is submitted and allowed with no initial then
the form should not be seen as changed.
"""
- form = SimpleForm(data={}, empty_permitted=True)
+ form = SimpleForm(data={}, empty_permitted=True, use_required_attribute=False)
self.assertFalse(form.has_changed(), str(form.changed_data))
self.assertTrue(form.is_valid(), str(form.errors))
import json
from django.conf import settings
-from django.core.urlresolvers import reverse
+from django.urls import reverse
from django.test import override_settings
from . import ThingLookup
rendered_value = widget.render('field_name', val)
inputs = parsed_inputs(rendered_value)
field = inputs['field_name_1'][0]
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- self.assertEqual(int(field.attributes['value'].value), val)
+ attributes = dict(field.attributes)
+ self.assertEqual(attributes['data-selectable-type'], 'hidden-multiple')
+ self.assertEqual(attributes['type'], 'hidden')
+ self.assertEqual(int(attributes['value']), val)
def test_render_list(self):
widget = self.get_widget_instance()
inputs = parsed_inputs(rendered_value)
found_values = []
for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
+ attributes = dict(field.attributes)
+ self.assertEqual(attributes['data-selectable-type'], 'hidden-multiple')
+ self.assertEqual(attributes['type'], 'hidden')
+ found_values.append(int(attributes['value']))
self.assertListEqual(found_values, list_val)
def test_render_qs(self):
found_values = []
found_titles = []
for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_titles.append(field.attributes['title'].value)
- found_values.append(field.attributes['value'].value)
+ attributes = dict(field.attributes)
+ self.assertEqual(attributes['data-selectable-type'], 'hidden-multiple')
+ self.assertEqual(attributes['type'], 'hidden')
+ found_titles.append(attributes['title'])
+ found_values.append(attributes['value'])
self.assertListEqual(found_values, [str(t1.pk), str(t2.pk)])
self.assertListEqual(found_titles, [t1.name, t2.name])
rendered_value = widget.render('field_name', val)
inputs = parsed_inputs(rendered_value)
field = inputs['field_name_1'][0]
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- self.assertEqual(field.attributes['value'].value, str(val))
+ attributes = dict(field.attributes)
+ self.assertEqual(attributes['data-selectable-type'], 'hidden-multiple')
+ self.assertEqual(attributes['type'], 'hidden')
+ self.assertEqual(attributes['value'], str(val))
def test_render_list(self):
widget = self.get_widget_instance()
inputs = parsed_inputs(rendered_value)
found_values = []
for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
+ attributes = dict(field.attributes)
+ self.assertEqual(attributes['data-selectable-type'], 'hidden-multiple')
+ self.assertEqual(attributes['type'], 'hidden')
+ found_values.append(int(attributes['value']))
self.assertListEqual(found_values, list_val)
def test_render_qs(self):
inputs = parsed_inputs(rendered_value)
found_values = []
for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
+ attributes = dict(field.attributes)
+ self.assertEqual(attributes['data-selectable-type'], 'hidden-multiple')
+ self.assertEqual(attributes['type'], 'hidden')
+ found_values.append(int(attributes['value']))
self.assertListEqual(found_values, [t1.pk, t2.pk])
def test_update_query_parameters(self):
from django.http import HttpResponseNotFound, HttpResponseServerError
-def test_404(request):
+def test_404(request, *args, **kwargs):
return HttpResponseNotFound()
-def test_500(request):
+def test_500(request, *args, **kwargs):
return HttpResponseServerError()
+++ /dev/null
-import json
-
-from django import forms
-from django.utils.http import urlencode
-
-from selectable.compat import urlparse
-from selectable.forms import widgets
-from selectable.tests import Thing, ThingLookup
-from selectable.tests.base import BaseSelectableTestCase, parsed_inputs
-
-
-__all__ = (
- 'AutoCompleteWidgetTestCase',
- 'AutoCompleteSelectWidgetTestCase',
- 'AutoComboboxWidgetTestCase',
- 'AutoComboboxSelectWidgetTestCase',
- 'AutoCompleteSelectMultipleWidgetTestCase',
- 'AutoComboboxSelectMultipleWidgetTestCase',
-)
-
-
-class BaseWidgetTestCase(BaseSelectableTestCase):
- widget_cls = None
- lookup_cls = None
-
- def get_widget_instance(self, **kwargs):
- return self.__class__.widget_cls(self.__class__.lookup_cls, **kwargs)
-
- def test_init(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.lookup_class, self.__class__.lookup_cls)
-
- def test_dotted_path(self):
- """
- Ensure lookup_class can be imported from a dotted path.
- """
- dotted_path = '.'.join([self.__class__.lookup_cls.__module__, self.__class__.lookup_cls.__name__])
- widget = self.__class__.widget_cls(dotted_path)
- self.assertEqual(widget.lookup_class, self.__class__.lookup_cls)
-
- def test_invalid_dotted_path(self):
- """
- An invalid lookup_class dotted path should raise an ImportError.
- """
- with self.assertRaises(ImportError):
- self.__class__.widget_cls('this.is.an.invalid.path')
-
- def test_dotted_path_wrong_type(self):
- """
- lookup_class must be a subclass of LookupBase.
- """
- dotted_path = 'selectable.forms.widgets.AutoCompleteWidget'
- with self.assertRaises(TypeError):
- self.__class__.widget_cls(dotted_path)
-
-
-class AutoCompleteWidgetTestCase(BaseWidgetTestCase):
- widget_cls = widgets.AutoCompleteWidget
- lookup_cls = ThingLookup
-
- def test_build_attrs(self):
- widget = self.get_widget_instance()
- attrs = widget.build_attrs()
- self.assertTrue('data-selectable-url' in attrs)
- self.assertTrue('data-selectable-type' in attrs)
- self.assertTrue('data-selectable-allow-new' in attrs)
-
- def test_update_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance()
- widget.update_query_parameters(params)
- attrs = widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_limit_paramter(self):
- widget = self.get_widget_instance(limit=10)
- attrs = widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertTrue('limit=10' in query)
-
- def test_initial_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance(query_params=params)
- attrs = widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_build_selectable_options(self):
- "Serialize selectable options as json in data attribute."
- options = {'autoFocus': True}
- widget = self.get_widget_instance(attrs={'data-selectable-options': options})
- attrs = widget.build_attrs()
- self.assertTrue('data-selectable-options' in attrs)
- self.assertEqual(attrs['data-selectable-options'], json.dumps(options))
-
-
-class AutoCompleteSelectWidgetTestCase(BaseWidgetTestCase):
- widget_cls = widgets.AutoCompleteSelectWidget
- lookup_cls = ThingLookup
-
- def test_has_complete_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[0].__class__, widgets.AutoCompleteWidget)
-
- def test_has_hidden_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[1].__class__, forms.HiddenInput)
-
- def test_hidden_type(self):
- widget = self.get_widget_instance()
- sub_widget = widget.widgets[1]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-type' in attrs)
- self.assertEqual(attrs['data-selectable-type'], 'hidden')
-
- def test_update_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance()
- widget.update_query_parameters(params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_limit_paramter(self):
- widget = self.get_widget_instance(limit=10)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertTrue('limit=10' in query)
-
- def test_initial_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance(query_params=params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_build_selectable_options(self):
- "Serialize selectable options as json in data attribute."
- options = {'autoFocus': True}
- widget = self.get_widget_instance(attrs={'data-selectable-options': options})
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-options' in attrs)
- self.assertEqual(attrs['data-selectable-options'], json.dumps(options))
-
-
-class AutoComboboxWidgetTestCase(BaseWidgetTestCase):
- widget_cls = widgets.AutoComboboxWidget
- lookup_cls = ThingLookup
-
- def test_build_attrs(self):
- widget = self.get_widget_instance()
- attrs = widget.build_attrs()
- self.assertTrue('data-selectable-url' in attrs)
- self.assertTrue('data-selectable-type' in attrs)
- self.assertTrue('data-selectable-allow-new' in attrs)
-
- def test_update_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance()
- widget.update_query_parameters(params)
- attrs = widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_limit_paramter(self):
- widget = self.get_widget_instance(limit=10)
- attrs = widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertTrue('limit=10' in query)
-
- def test_initial_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance(query_params=params)
- attrs = widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_build_selectable_options(self):
- "Serialize selectable options as json in data attribute."
- options = {'autoFocus': True}
- widget = self.get_widget_instance(attrs={'data-selectable-options': options})
- attrs = widget.build_attrs()
- self.assertTrue('data-selectable-options' in attrs)
- self.assertEqual(attrs['data-selectable-options'], json.dumps(options))
-
-
-class AutoComboboxSelectWidgetTestCase(BaseWidgetTestCase):
- widget_cls = widgets.AutoComboboxSelectWidget
- lookup_cls = ThingLookup
-
- def test_has_complete_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[0].__class__, widgets.AutoComboboxWidget)
-
- def test_has_hidden_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[1].__class__, forms.HiddenInput)
-
- def test_hidden_type(self):
- widget = self.get_widget_instance()
- sub_widget = widget.widgets[1]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-type' in attrs)
- self.assertEqual(attrs['data-selectable-type'], 'hidden')
-
- def test_update_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance()
- widget.update_query_parameters(params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_limit_paramter(self):
- widget = self.get_widget_instance(limit=10)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertTrue('limit=10' in query)
-
- def test_initial_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance(query_params=params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_build_selectable_options(self):
- "Serialize selectable options as json in data attribute."
- options = {'autoFocus': True}
- widget = self.get_widget_instance(attrs={'data-selectable-options': options})
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-options' in attrs)
- self.assertEqual(attrs['data-selectable-options'], json.dumps(options))
-
-
-class AutoCompleteSelectMultipleWidgetTestCase(BaseWidgetTestCase):
- widget_cls = widgets.AutoCompleteSelectMultipleWidget
- lookup_cls = ThingLookup
-
- def test_has_complete_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[0].__class__, widgets.AutoCompleteWidget)
-
- def test_multiple_attr(self):
- widget = self.get_widget_instance()
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-multiple' in attrs)
- self.assertEqual(attrs['data-selectable-multiple'], 'true')
-
- def test_has_hidden_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[1].__class__, widgets.LookupMultipleHiddenInput)
-
- def test_hidden_type(self):
- widget = self.get_widget_instance()
- sub_widget = widget.widgets[1]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-type' in attrs)
- self.assertEqual(attrs['data-selectable-type'], 'hidden-multiple')
-
- def test_render_single(self):
- widget = self.get_widget_instance()
- val = 4
- rendered_value = widget.render('field_name', val)
- inputs = parsed_inputs(rendered_value)
- field = inputs['field_name_1'][0]
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- self.assertEqual(int(field.attributes['value'].value), val)
-
- def test_render_list(self):
- widget = self.get_widget_instance()
- list_val = [8, 5]
- rendered_value = widget.render('field_name', list_val)
- inputs = parsed_inputs(rendered_value)
- found_values = []
- for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
- self.assertListEqual(found_values, list_val)
-
- def test_render_qs(self):
- widget = self.get_widget_instance()
- t1 = self.create_thing()
- t2 = self.create_thing()
- qs_val = Thing.objects.filter(pk__in=[t1.pk, t2.pk]).values_list('pk', flat=True)
- rendered_value = widget.render('field_name', qs_val)
- inputs = parsed_inputs(rendered_value)
- found_values = []
- for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
- self.assertListEqual(found_values, [t1.pk, t2.pk])
-
- def test_update_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance()
- widget.update_query_parameters(params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_limit_paramter(self):
- widget = self.get_widget_instance(limit=10)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertTrue('limit=10' in query)
-
- def test_initial_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance(query_params=params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_build_selectable_options(self):
- "Serialize selectable options as json in data attribute."
- options = {'autoFocus': True}
- widget = self.get_widget_instance(attrs={'data-selectable-options': options})
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-options' in attrs)
- self.assertEqual(attrs['data-selectable-options'], json.dumps(options))
-
-
-class AutoComboboxSelectMultipleWidgetTestCase(BaseWidgetTestCase):
- widget_cls = widgets.AutoComboboxSelectMultipleWidget
- lookup_cls = ThingLookup
-
- def test_has_complete_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[0].__class__, widgets.AutoComboboxWidget)
-
- def test_multiple_attr(self):
- widget = self.get_widget_instance()
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-multiple' in attrs)
- self.assertEqual(attrs['data-selectable-multiple'], 'true')
-
- def test_has_hidden_widget(self):
- widget = self.get_widget_instance()
- self.assertEqual(widget.widgets[1].__class__, widgets.LookupMultipleHiddenInput)
-
- def test_hidden_type(self):
- widget = self.get_widget_instance()
- sub_widget = widget.widgets[1]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-type' in attrs)
- self.assertEqual(attrs['data-selectable-type'], 'hidden-multiple')
-
- def test_render_single(self):
- widget = self.get_widget_instance()
- val = 4
- rendered_value = widget.render('field_name', val)
- inputs = parsed_inputs(rendered_value)
- field = inputs['field_name_1'][0]
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- self.assertEqual(field.attributes['value'].value, str(val))
-
- def test_render_list(self):
- widget = self.get_widget_instance()
- list_val = [8, 5]
- rendered_value = widget.render('field_name', list_val)
- inputs = parsed_inputs(rendered_value)
- found_values = []
- for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
- self.assertListEqual(found_values, list_val)
-
- def test_render_qs(self):
- widget = self.get_widget_instance()
- t1 = self.create_thing()
- t2 = self.create_thing()
- qs_val = Thing.objects.filter(pk__in=[t1.pk, t2.pk]).values_list('pk', flat=True)
- rendered_value = widget.render('field_name', qs_val)
- inputs = parsed_inputs(rendered_value)
- found_values = []
- for field in inputs['field_name_1']:
- self.assertEqual(field.attributes['data-selectable-type'].value, 'hidden-multiple')
- self.assertEqual(field.attributes['type'].value, 'hidden')
- found_values.append(int(field.attributes['value'].value))
- self.assertListEqual(found_values, [t1.pk, t2.pk])
-
- def test_update_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance()
- widget.update_query_parameters(params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_limit_paramter(self):
- widget = self.get_widget_instance(limit=10)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertTrue('limit=10' in query)
-
- def test_initial_query_parameters(self):
- params = {'active': 1}
- widget = self.get_widget_instance(query_params=params)
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- url = attrs['data-selectable-url']
- parse = urlparse(url)
- query = parse.query
- self.assertEqual(query, urlencode(params))
-
- def test_build_selectable_options(self):
- "Serialize selectable options as json in data attribute."
- options = {'autoFocus': True}
- widget = self.get_widget_instance(attrs={'data-selectable-options': options})
- sub_widget = widget.widgets[0]
- attrs = sub_widget.build_attrs()
- self.assertTrue('data-selectable-options' in attrs)
- self.assertEqual(attrs['data-selectable-options'], json.dumps(options))
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Framework :: Django',
+ 'Framework :: Django :: 1.11',
+ 'Framework :: Django :: 2.0',
+ 'Framework :: Django :: 2.1',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
long_description=read_file('README.rst'),
[tox]
-envlist = py{27,33}-django{17,18},py{27,34,35}-django{19,110,111},py35-django_master,docs
+envlist = py{27,34,35,36}-django{111},py{34,35,36}-django{20,21},py35-django_master,docs
[testenv]
basepython =
py27: python2.7
- py33: python3.3
py34: python3.4
py35: python3.5
+ py36: python3.6
deps =
coverage>=4.0,<4.1
- django17: Django>=1.7,<1.8
- django18: Django>=1.8,<1.9
- django19: Django>=1.9,<1.10
- django110: Django>=1.10,<1.11
django111: Django>=1.11,<2.0
+ django20: Django>=2.0,<2.1
+ django21: Django>=2.1,<2.2
django_master: https://github.com/django/django/archive/master.tar.gz
py27: mock
commands = coverage run runtests.py