Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

Add minimal test suite #35

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pip-log.txt
.tox
nosetests.xml

# Test cache
/.pytest_cache

# Translations
*.mo

Expand All @@ -45,4 +48,4 @@ docs/_build
output/

#PyCharm
.idea/
.idea/
7 changes: 2 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@ language: python

python:
- "3.5"
- "3.4"
- "2.7"
env:
- DJANGO="Django==1.8.4"
- DJANGO="Django==1.9.9"
- DJANGO="Django==1.10"
- DJANGO="Django==2.0.7"

# command to install dependencies, e.g. pip install -r requirements.txt
install:
- pip install $DJANGO
- pip install -r requirements-test.txt

# command to run tests using coverage, e.g. python setup.py test
script: coverage run --source admin_reorder runtests.py
script: python -m pytest --cov=admin_reorder

# report coverage to coveralls.io
after_success: coveralls
2 changes: 1 addition & 1 deletion admin_reorder/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.3.1'
__version__ = '0.3.2'
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
DJANGO_SETTINGS_MODULE=tests.settings
3 changes: 3 additions & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ django-nose>=1.2
flake8>=2.1.0
tox>=1.7.0

pytest==3.6.3
pytest-django==3.3.2
pytest-cov==2.5.1
52 changes: 0 additions & 52 deletions runtests.py

This file was deleted.

Empty file added tests/app1/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions tests/app1/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.contrib import admin

from tests.app1.models import App1Model1, App1Model2


@admin.register(App1Model1)
class App1Model1Admin(admin.ModelAdmin):
pass


@admin.register(App1Model2)
class App1Model2Admin(admin.ModelAdmin):
pass
9 changes: 9 additions & 0 deletions tests/app1/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.db import models


class App1Model1(models.Model):
field = models.BigIntegerField()


class App1Model2(models.Model):
field = models.BigIntegerField()
Empty file added tests/app2/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions tests/app2/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.contrib import admin

from tests.app2.models import App2Model1, App2Model2


@admin.register(App2Model1)
class App2Model1Admin(admin.ModelAdmin):
pass


@admin.register(App2Model2)
class App2Model2Admin(admin.ModelAdmin):
pass
9 changes: 9 additions & 0 deletions tests/app2/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.db import models


class App2Model1(models.Model):
field = models.BigIntegerField()


class App2Model2(models.Model):
field = models.BigIntegerField()
33 changes: 33 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
DEBUG = True
USE_TZ = True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
}
}
ROOT_URLCONF = 'admin_reorder.urls'
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.admin',
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions',
'django.contrib.sites',
'tests.app1',
'tests.app2',
'admin_reorder',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
]
}
}
]
SITE_ID = 1
SECRET_KEY = 'yolo'
ROOT_URLCONF = 'tests.urls'
120 changes: 120 additions & 0 deletions tests/test_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
import re
import unittest

from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured
from django.test import RequestFactory, override_settings
try:
from django.urls import resolve
except ImportError:
# Backwards compatibility with Django<1.10
from django.core.urlresolvers import resolve
from pytest import raises, mark

from admin_reorder.middleware import ModelAdminReorder
from tests.app1.models import App1Model1, App1Model2
from tests.app2.models import App2Model1, App2Model2


@mark.django_db()
class ModelAdminReorderTest(unittest.TestCase):
"""Tests for the ModelAdminReorder middleware class."""
def setUp(self):
self.superuser = User.objects.create(is_staff=True, is_superuser=True)

def _make_request(self, path):
"""Generates a mocked request by a staff user for a given path."""
request = RequestFactory().get(path)
request.user = self.superuser
return request

@staticmethod
def _get_response_for_path(request, path):
"""Executes the view at path and returns the response."""
return resolve(path).func(request)

def _render_admin_index(self):
path = '/admin/'
request = self._make_request(path)
response = self._get_response_for_path(request, path)

return request, response

def test_require_configuration(self):
"""
Throw an ImproperlyConfigured error if the ADMIN_REORDER config is missing when rendering the admin.
"""
request, response = self._render_admin_index()

with raises(ImproperlyConfigured) as exc_info:
ModelAdminReorder().process_template_response(request, response)

assert str(exc_info.value) == 'ADMIN_REORDER config is not defined.'

def _assert_model_prescence_in_response(self, models_to_expect, response):
"""
Given an unrendered admin index response, check that every model in the given list is mentioned there.
"""
decoded_content = response.content.decode('utf8')

for model_to_expect in models_to_expect:
lower_case_model_name = model_to_expect.__name__.lower()
assert re.search(
'<a href="/admin/\w+/{}/" class="changelink">'.format(lower_case_model_name),
decoded_content,
), lower_case_model_name + ' not present'

def _assert_model_absence_in_response(self, models_to_be_absent, response):
"""
Given an admin index response, check that every model in the given list is missing there.
"""
decoded_content = response.content.decode('utf8')

for model_to_be_absent in models_to_be_absent:
lower_case_model_name = model_to_be_absent.__name__.lower()
assert not re.search(
'<a href="/admin/\w+/{}/" class="changelink">'.format(lower_case_model_name),
decoded_content,
), lower_case_model_name + ' not absent'

def _render_with_configuration_and_check_model_presence(self, config, models_to_expect, models_to_be_absent=None):
"""
Renders the admin index with `config` as the ADMIN_REORDER setting, checks that certain models are
mentioned on the page, and checks that certain models are absent from the page.
"""
with override_settings(ADMIN_REORDER=config):
request, response = self._render_admin_index()
ModelAdminReorder().process_template_response(request, response)
response.render()

# Check that the right models are present/absent
self._assert_model_prescence_in_response(models_to_expect, response)
if models_to_be_absent:
self._assert_model_absence_in_response(models_to_be_absent, response)

def test_only_valid_apps(self):
"""When the config only contains valid app names, the models should be present."""
self._render_with_configuration_and_check_model_presence(
config=(
'app1',
'app2',
),
models_to_expect=[App1Model1, App1Model2, App2Model1, App2Model2],
)

def test_custom_grouping(self):
"""When the config only uses custom grouping, the index should render."""
self._render_with_configuration_and_check_model_presence(
config=(
{
'app': 'app1',
'models': (
'app1.App1Model1',
'app2.App2Model2',
)
},
),
models_to_expect=[App1Model1, App2Model2],
models_to_be_absent=[App1Model2, App2Model1],
)
27 changes: 0 additions & 27 deletions tests/test_models.py

This file was deleted.

14 changes: 14 additions & 0 deletions tests/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.conf.urls import url
from django.contrib import admin
from django.http import HttpResponse


def placeholder_view(request):
return HttpResponse('')


urlpatterns = [
# Don't use path() yet for backwards compatibility in the test suite
url('^$', placeholder_view),
url('^admin/', admin.site.urls),
]
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ envlist = py26, py27, py33
[testenv]
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/admin_reorder
commands = python runtests.py
commands = pytest
deps =
-r{toxinidir}/requirements-test.txt
-r{toxinidir}/requirements-test.txt