Added initial tests
This commit is contained in:
parent
91dad724fb
commit
18fa453ac0
|
@ -14,3 +14,6 @@ docs/_build
|
|||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
env/
|
||||
venv/
|
||||
.cache/
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
language: python
|
||||
sudo: false
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.2"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "pypy"
|
||||
- "pypy3"
|
||||
env:
|
||||
global:
|
||||
- DISPLAY=:99.0
|
||||
matrix:
|
||||
- DJANGO="<1.5,>=1.4"
|
||||
- DJANGO="<1.7,>=1.6"
|
||||
- DJANGO="<1.8,>=1.7"
|
||||
- DJANGO="==1.8rc1"
|
||||
matrix:
|
||||
exclude:
|
||||
- python: "3.2"
|
||||
env: DJANGO="<1.5,>=1.4"
|
||||
- python: "3.3"
|
||||
env: DJANGO="<1.5,>=1.4"
|
||||
- python: "3.4"
|
||||
env: DJANGO="<1.5,>=1.4"
|
||||
- python: "pypy3"
|
||||
env: DJANGO="<1.5,>=1.4"
|
||||
- python: "2.6"
|
||||
env: DJANGO="<1.8,>=1.7"
|
||||
allow_failures:
|
||||
- env: DJANGO="==1.8rc1"
|
||||
- python: "3.2"
|
||||
- python: "3.3"
|
||||
- python: "3.4"
|
||||
- python: "pypy"
|
||||
- python: "pypy3"
|
||||
install:
|
||||
- pip install --upgrade pip
|
||||
- pip install .
|
||||
- pip install -r requirements_dev.txt
|
||||
- pip install Django$DJANGO
|
||||
- pip install coveralls
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
script:
|
||||
coverage run --source=django_select2 runtests.py
|
||||
after_success:
|
||||
coveralls
|
|
@ -0,0 +1,5 @@
|
|||
[pytest]
|
||||
norecursedirs=env testapp django_select2 docs
|
||||
addopts = --tb=short --pep8 --flakes -rxs
|
||||
pep8ignore=
|
||||
flakes-ignore=
|
|
@ -0,0 +1,6 @@
|
|||
pytest
|
||||
pytest-pep8
|
||||
pytest-flakes
|
||||
pytest-django
|
||||
selenium
|
||||
model_mommy
|
File diff suppressed because it is too large
Load Diff
|
@ -1,107 +1,19 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import sys
|
||||
|
||||
from distutils.util import convert_path
|
||||
from fnmatch import fnmatchcase
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools import setup, find_packages, Command
|
||||
|
||||
|
||||
def read(fname):
|
||||
return codecs.open(os.path.join(os.path.dirname(__file__), fname)).read()
|
||||
f = codecs.open(os.path.join(os.path.dirname(__file__), fname), 'rb')
|
||||
return f.read()
|
||||
|
||||
|
||||
# Provided as an attribute, so you can append to these instead
|
||||
# of replicating them:
|
||||
standard_exclude = ["*.py", "*.pyc", "*$py.class", "*~", ".*", "*.bak"]
|
||||
standard_exclude_directories = [
|
||||
".*", "CVS", "_darcs", "./build", "./dist", "EGG-INFO", "*.egg-info"
|
||||
]
|
||||
|
||||
|
||||
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
|
||||
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
# Note: you may want to copy this into your setup.py file verbatim, as
|
||||
# you can't import this from another package, when you don't know if
|
||||
# that package is installed yet.
|
||||
def find_package_data(
|
||||
where=".",
|
||||
package="",
|
||||
exclude=standard_exclude,
|
||||
exclude_directories=standard_exclude_directories,
|
||||
only_in_packages=True,
|
||||
show_ignored=False):
|
||||
"""
|
||||
Return a dictionary suitable for use in ``package_data``
|
||||
in a distutils ``setup.py`` file.
|
||||
|
||||
The dictionary looks like::
|
||||
|
||||
{"package": [files]}
|
||||
|
||||
Where ``files`` is a list of all the files in that package that
|
||||
don"t match anything in ``exclude``.
|
||||
|
||||
If ``only_in_packages`` is true, then top-level directories that
|
||||
are not packages won"t be included (but directories under packages
|
||||
will).
|
||||
|
||||
Directories matching any pattern in ``exclude_directories`` will
|
||||
be ignored; by default directories with leading ``.``, ``CVS``,
|
||||
and ``_darcs`` will be ignored.
|
||||
|
||||
If ``show_ignored`` is true, then all the files that aren"t
|
||||
included in package data are shown on stderr (for debugging
|
||||
purposes).
|
||||
|
||||
Note patterns use wildcards, or can be exact paths (including
|
||||
leading ``./``), and all searching is case-insensitive.
|
||||
"""
|
||||
out = {}
|
||||
stack = [(convert_path(where), "", package, only_in_packages)]
|
||||
while stack:
|
||||
where, prefix, package, only_in_packages = stack.pop(0)
|
||||
for name in os.listdir(where):
|
||||
fn = os.path.join(where, name)
|
||||
if os.path.isdir(fn):
|
||||
bad_name = False
|
||||
for pattern in exclude_directories:
|
||||
if (fnmatchcase(name, pattern)
|
||||
or fn.lower() == pattern.lower()):
|
||||
bad_name = True
|
||||
if show_ignored:
|
||||
print >> sys.stderr, (
|
||||
"Directory %s ignored by pattern %s"
|
||||
% (fn, pattern))
|
||||
break
|
||||
if bad_name:
|
||||
continue
|
||||
if (os.path.isfile(os.path.join(fn, "__init__.py"))
|
||||
and not prefix):
|
||||
if not package:
|
||||
new_package = name
|
||||
else:
|
||||
new_package = package + "." + name
|
||||
stack.append((fn, "", new_package, False))
|
||||
else:
|
||||
stack.append((fn, prefix + name + "/", package, only_in_packages))
|
||||
elif package or not only_in_packages:
|
||||
# is a file
|
||||
bad_name = False
|
||||
for pattern in exclude:
|
||||
if (fnmatchcase(name, pattern)
|
||||
or fn.lower() == pattern.lower()):
|
||||
bad_name = True
|
||||
if show_ignored:
|
||||
print >> sys.stderr, (
|
||||
"File %s ignored by pattern %s"
|
||||
% (fn, pattern))
|
||||
break
|
||||
if bad_name:
|
||||
continue
|
||||
out.setdefault(package, []).append(prefix+name)
|
||||
return out
|
||||
|
||||
PACKAGE = "django_select2"
|
||||
NAME = "Django-Select2"
|
||||
DESCRIPTION = "Select2 option fields for Django"
|
||||
|
@ -110,11 +22,14 @@ AUTHOR_EMAIL = "admin@applegrew.com"
|
|||
URL = "https://github.com/applegrew/django-select2"
|
||||
VERSION = __import__(PACKAGE).__version__
|
||||
|
||||
|
||||
def getPkgPath():
|
||||
return __import__(PACKAGE).__path__[0] + '/'
|
||||
|
||||
|
||||
def minify(files, outfile, ftype):
|
||||
import urllib, json
|
||||
import urllib
|
||||
import json
|
||||
|
||||
content = u''
|
||||
for filename in files:
|
||||
|
@ -127,7 +42,7 @@ def minify(files, outfile, ftype):
|
|||
data = urllib.urlencode([
|
||||
('code', content.encode('utf-8')),
|
||||
('type', ftype),
|
||||
])
|
||||
])
|
||||
|
||||
f = urllib.urlopen('http://api.applegrew.com/minify', data)
|
||||
data = u''
|
||||
|
@ -142,11 +57,6 @@ def minify(files, outfile, ftype):
|
|||
f.close()
|
||||
|
||||
data = json.loads(data)
|
||||
for key in data:
|
||||
value = data[key]
|
||||
if isinstance(value, str):
|
||||
value = value.decode('utf-8')
|
||||
|
||||
if data['success']:
|
||||
with open(getPkgPath() + outfile, 'w') as f:
|
||||
f.write(data['compiled_code'].encode('utf8'))
|
||||
|
@ -155,13 +65,39 @@ def minify(files, outfile, ftype):
|
|||
print data['error']
|
||||
raise Exception('Could not minify.')
|
||||
|
||||
|
||||
if len(sys.argv) > 1 and 'sdist' == sys.argv[1]:
|
||||
minify(['static/js/select2.js'], 'static/js/select2.min.js', 'js')
|
||||
minify(['static/js/heavy_data.js'], 'static/js/heavy_data.min.js', 'js')
|
||||
minify(['static/css/select2.css'], 'static/css/select2.min.css', 'css')
|
||||
minify(['static/css/select2.css', 'static/css/extra.css'], 'static/css/all.min.css', 'css')
|
||||
minify(['static/css/select2.css', 'static/css/select2-bootstrap.css'], 'static/css/select2-bootstrapped.min.css', 'css')
|
||||
minify(['static/css/select2.css', 'static/css/extra.css', 'static/css/select2-bootstrap.css'], 'static/css/all-bootstrapped.min.css', 'css')
|
||||
minify(['static/css/select2.css', 'static/css/extra.css'],
|
||||
'static/css/all.min.css', 'css')
|
||||
minify(['static/css/select2.css', 'static/css/select2-bootstrap.css'],
|
||||
'static/css/select2-bootstrapped.min.css', 'css')
|
||||
minify(
|
||||
[
|
||||
'static/css/select2.css',
|
||||
'static/css/extra.css',
|
||||
'static/css/select2-bootstrap.css'
|
||||
], 'static/css/all-bootstrapped.min.css', 'css')
|
||||
|
||||
|
||||
class PyTest(Command):
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
errno = subprocess.call([sys.executable, 'runtests.py'])
|
||||
raise SystemExit(errno)
|
||||
|
||||
|
||||
setup(
|
||||
name=NAME,
|
||||
|
@ -172,9 +108,7 @@ setup(
|
|||
author_email=AUTHOR_EMAIL,
|
||||
license="LICENSE.txt",
|
||||
url=URL,
|
||||
packages=[PACKAGE, PACKAGE + '.templatetags'],
|
||||
package_data=find_package_data(),
|
||||
exclude_package_data={ '': standard_exclude },
|
||||
packages=find_packages(exclude=['tests']),
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
|
@ -186,7 +120,8 @@ setup(
|
|||
"Framework :: Django",
|
||||
],
|
||||
install_requires=[
|
||||
"Django>=1.3",
|
||||
"Django>=1.4",
|
||||
],
|
||||
zip_safe=False,
|
||||
cmdclass={'test': PyTest},
|
||||
)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
__author__ = 'johannes'
|
|
@ -0,0 +1,50 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from django import conf
|
||||
from selenium import webdriver
|
||||
from selenium.common.exceptions import WebDriverException
|
||||
|
||||
|
||||
def pytest_configure():
|
||||
os.environ[conf.ENVIRONMENT_VARIABLE] = "tests.testapp.settings"
|
||||
|
||||
try:
|
||||
import django
|
||||
|
||||
django.setup()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
from django.test.utils import setup_test_environment
|
||||
|
||||
setup_test_environment()
|
||||
|
||||
from django.db import connection
|
||||
|
||||
connection.creation.create_test_db()
|
||||
|
||||
|
||||
browsers = {
|
||||
'firefox': webdriver.Firefox,
|
||||
'chrome': webdriver.Chrome,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope='session',
|
||||
params=browsers.keys())
|
||||
def driver(request):
|
||||
if 'DISPLAY' not in os.environ:
|
||||
pytest.skip('Test requires display server (export DISPLAY)')
|
||||
|
||||
try:
|
||||
b = browsers[request.param]()
|
||||
except WebDriverException as e:
|
||||
pytest.skip(e)
|
||||
else:
|
||||
b.set_window_size(1200, 800)
|
||||
request.addfinalizer(lambda *args: b.quit())
|
||||
return b
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import pytest
|
||||
from django.core.urlresolvers import reverse
|
||||
from model_mommy import mommy
|
||||
from selenium.common.exceptions import NoSuchElementException
|
||||
|
||||
|
||||
class ViewTestMixin(object):
|
||||
url = ''
|
||||
|
||||
def test_get(self, client):
|
||||
response = client.get(self.url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def genres(db):
|
||||
mommy.make('testapp.Genre', _quantity=100)
|
||||
|
||||
|
||||
class TestAutoModelSelect2TagField(object):
|
||||
url = reverse('single_value_model_field')
|
||||
|
||||
def test_no_js_error(self, db, client, live_server, driver, genres):
|
||||
driver.get(live_server + self.url)
|
||||
with pytest.raises(NoSuchElementException):
|
||||
error = driver.find_element_by_xpath('//body[@JSError]')
|
||||
pytest.fail(error.get_attribute('JSError'))
|
|
@ -0,0 +1,53 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django import forms
|
||||
|
||||
from django_select2.fields import Select2MultipleWidget
|
||||
|
||||
from tests.testapp import models
|
||||
from . import fields
|
||||
|
||||
|
||||
class GenreModelForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = models.Genre
|
||||
fields = (
|
||||
'title',
|
||||
)
|
||||
|
||||
|
||||
class GenreForm(forms.Form):
|
||||
title = forms.CharField(max_length=50)
|
||||
|
||||
|
||||
class ArtistModelForm(forms.ModelForm):
|
||||
test = forms.BooleanField('asdf')
|
||||
class Meta:
|
||||
model = models.Artist
|
||||
fields = (
|
||||
'title',
|
||||
'genres',
|
||||
)
|
||||
widgets = {
|
||||
'genres': Select2MultipleWidget
|
||||
}
|
||||
|
||||
|
||||
class ArtistForm(forms.Form):
|
||||
title = forms.CharField(max_length=50)
|
||||
genres = fields.GenreTagField()
|
||||
|
||||
|
||||
class AlbumModelForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = models.Album
|
||||
fields = (
|
||||
'title',
|
||||
'artist',
|
||||
)
|
||||
|
||||
|
||||
class AlbumForm(forms.Form):
|
||||
title = forms.CharField(max_length=255)
|
||||
artist = fields.ArtistField()
|
|
@ -0,0 +1,15 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django_select2.fields import (AutoModelSelect2Field,
|
||||
AutoModelSelect2TagField)
|
||||
|
||||
from tests.testapp import models
|
||||
|
||||
|
||||
class GenreTagField(AutoModelSelect2TagField):
|
||||
queryset = models.Genre
|
||||
|
||||
|
||||
class ArtistField(AutoModelSelect2Field):
|
||||
queryset = models.Artist
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Genre(models.Model):
|
||||
title = models.CharField(max_length=50)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Artist(models.Model):
|
||||
title = models.CharField(max_length=50)
|
||||
genres = models.ManyToManyField(Genre)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Album(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
artist = models.ForeignKey(Artist)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Song(models.Model):
|
||||
title = models.CharField(max_length=255)
|
||||
album = models.ForeignKey(Album, blank=True, null=True)
|
||||
artist = models.ForeignKey(Artist)
|
||||
genres = models.ManyToManyField(Genre, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
|
@ -0,0 +1,43 @@
|
|||
import os.path
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ':memory:',
|
||||
}
|
||||
}
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
'django_select2',
|
||||
'tests.testapp',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
)
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
|
||||
SITE_ID = 1
|
||||
ROOT_URLCONF = 'tests.testapp.urls'
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
os.path.join(BASE_DIR, "templates"),
|
||||
)
|
||||
|
||||
SECRET_KEY = '123456'
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
AUTO_RENDER_SELECT2_STATICS = False
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,21 @@
|
|||
{% load staticfiles %}
|
||||
{% load django_select2_tags %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="{% static 'jquery-1.7.2.min.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
window.onerror = function (msg) {
|
||||
$("body").attr("JSError", msg);
|
||||
}
|
||||
</script>
|
||||
{% import_django_select2_js %}
|
||||
{% import_django_select2_css %}
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="Submit Form"/>
|
||||
</form>
|
||||
</body>
|
|
@ -0,0 +1,15 @@
|
|||
# -*- conding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.conf.urls import include, patterns, url
|
||||
|
||||
from .forms import ArtistForm
|
||||
from .views import TemplateFormView
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'single_value_model_field',
|
||||
TemplateFormView.as_view(form_class=ArtistForm), name='single_value_model_field'),
|
||||
|
||||
url(r'^select2/', include('django_select2.urls')),
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.views.generic import FormView
|
||||
|
||||
|
||||
class TemplateFormView(FormView):
|
||||
template_name = 'form.html'
|
Loading…
Reference in New Issue