commit
07593e5d3d
21 changed files with 802 additions and 44 deletions
27
.coveragerc
Normal file
27
.coveragerc
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
[run]
|
||||||
|
branch = True
|
||||||
|
source = djangocms_blog
|
||||||
|
|
||||||
|
[report]
|
||||||
|
omit = ../*migrations*,../*tests*,../*compat.*
|
||||||
|
# Regexes for lines to exclude from consideration
|
||||||
|
exclude_lines =
|
||||||
|
# Have to re-enable the standard pragma
|
||||||
|
pragma: no cover
|
||||||
|
|
||||||
|
# Don't complain about missing debug-only code:
|
||||||
|
def __repr__
|
||||||
|
if self\.debug
|
||||||
|
|
||||||
|
# Don't complain if tests don't hit defensive assertion code:
|
||||||
|
raise AssertionError
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Don't complain if non-runnable code isn't run:
|
||||||
|
if 0:
|
||||||
|
if __name__ == .__main__.:
|
||||||
|
|
||||||
|
ignore_errors = True
|
||||||
|
|
||||||
|
[html]
|
||||||
|
directory = coverage_html
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -43,4 +43,3 @@ lokalize*
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
docs
|
docs
|
||||||
tests
|
|
||||||
|
|
32
.travis.yml
32
.travis.yml
|
@ -3,12 +3,34 @@
|
||||||
language: python
|
language: python
|
||||||
|
|
||||||
python:
|
python:
|
||||||
- "3.3"
|
- 3.3
|
||||||
- "2.7"
|
- 3.4
|
||||||
- "2.6"
|
- 2.7
|
||||||
|
- 2.6
|
||||||
|
|
||||||
|
env:
|
||||||
|
matrix:
|
||||||
|
- DJANGO='django>=1.5,<1.6'
|
||||||
|
- DJANGO='django>=1.6,<1.7'
|
||||||
|
|
||||||
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
|
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
|
||||||
install: pip install -r requirements-test.txt
|
install:
|
||||||
|
- pip install $DJANGO
|
||||||
|
- pip install -r requirements-test.txt
|
||||||
|
|
||||||
# command to run tests, e.g. python setup.py test
|
# command to run tests, e.g. python setup.py test
|
||||||
script: python runtests.py
|
script: coverage run runtests.py
|
||||||
|
|
||||||
|
after_success: coveralls
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
|
||||||
|
allow_failures:
|
||||||
|
- python: 3.3
|
||||||
|
env: DJANGO='django>=1.5,<1.6'
|
||||||
|
- python: 3.3
|
||||||
|
env: DJANGO='django>=1.6,<1.7'
|
||||||
|
- python: 3.4
|
||||||
|
env: DJANGO='django>=1.5,<1.6'
|
||||||
|
- python: 3.4
|
||||||
|
env: DJANGO='django>=1.6,<1.7'
|
|
@ -14,6 +14,15 @@ A djangoCMS 3 blog application.
|
||||||
Still experimental and untested. You are welcome if you want to try it; if
|
Still experimental and untested. You are welcome if you want to try it; if
|
||||||
you encounter any issue, please open an issue.
|
you encounter any issue, please open an issue.
|
||||||
|
|
||||||
|
Supported Django versions:
|
||||||
|
|
||||||
|
* Django 1.5
|
||||||
|
* Django 1.6
|
||||||
|
|
||||||
|
Supported django CMS versions:
|
||||||
|
|
||||||
|
* django CMS 3.0
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class BlogToolbar(CMSToolbar):
|
||||||
|
|
||||||
def populate(self):
|
def populate(self):
|
||||||
if not (self.is_current_app and self.request.user.has_perm('djangocms_blog.add_post')):
|
if not (self.is_current_app and self.request.user.has_perm('djangocms_blog.add_post')):
|
||||||
return
|
return # pragma: no cover
|
||||||
admin_menu = self.toolbar.get_or_create_menu("djangocms_blog", _('Blog'))
|
admin_menu = self.toolbar.get_or_create_menu("djangocms_blog", _('Blog'))
|
||||||
url = reverse('admin:djangocms_blog_post_changelist')
|
url = reverse('admin:djangocms_blog_post_changelist')
|
||||||
admin_menu.add_modal_item(_('Post list'), url=url)
|
admin_menu.add_modal_item(_('Post list'), url=url)
|
||||||
|
@ -21,7 +21,7 @@ class BlogToolbar(CMSToolbar):
|
||||||
admin_menu.add_modal_item(_('Add post'), url=url)
|
admin_menu.add_modal_item(_('Add post'), url=url)
|
||||||
|
|
||||||
current_post = getattr(self.request, BLOG_CURRENT_POST_IDENTIFIER, None)
|
current_post = getattr(self.request, BLOG_CURRENT_POST_IDENTIFIER, None)
|
||||||
if current_post and self.request.user.has_perm('djangocms_blog.change_post'):
|
if current_post and self.request.user.has_perm('djangocms_blog.change_post'): # pragma: no cover
|
||||||
admin_menu.add_modal_item(_('Edit Post'),reverse(
|
admin_menu.add_modal_item(_('Edit Post'),reverse(
|
||||||
'admin:djangocms_blog_post_change', args=(current_post.pk,)),
|
'admin:djangocms_blog_post_change', args=(current_post.pk,)),
|
||||||
active=True)
|
active=True)
|
|
@ -17,7 +17,7 @@ class TaggedFilterItem(object):
|
||||||
o con gli stessi tag di un model o un queryset
|
o con gli stessi tag di un model o un queryset
|
||||||
"""
|
"""
|
||||||
tags = self._taglist(other_model, queryset)
|
tags = self._taglist(other_model, queryset)
|
||||||
return self.get_query_set().filter(taglist__in=tags)
|
return self.get_queryset().filter(taglist__in=tags)
|
||||||
|
|
||||||
def _taglist(self, other_model=None, queryset=None):
|
def _taglist(self, other_model=None, queryset=None):
|
||||||
"""
|
"""
|
||||||
|
@ -74,6 +74,12 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
|
||||||
end_date_field = "date_published_end"
|
end_date_field = "date_published_end"
|
||||||
publish_field = "publish"
|
publish_field = "publish"
|
||||||
|
|
||||||
|
def get_queryset(self, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs)
|
||||||
|
except AttributeError:
|
||||||
|
return super(GenericDateTaggedManager, self).get_query_set(*args, **kwargs)
|
||||||
|
|
||||||
def published(self, queryset=None):
|
def published(self, queryset=None):
|
||||||
queryset = self.published_future(queryset)
|
queryset = self.published_future(queryset)
|
||||||
if self.start_date_field:
|
if self.start_date_field:
|
||||||
|
@ -84,7 +90,7 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
|
||||||
|
|
||||||
def published_future(self, queryset=None):
|
def published_future(self, queryset=None):
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = self.get_query_set().all()
|
queryset = self.get_queryset().all()
|
||||||
if self.end_date_field:
|
if self.end_date_field:
|
||||||
qfilter = (
|
qfilter = (
|
||||||
models.Q(**{"%s__gte" % self.end_date_field: datetime.datetime.now()})
|
models.Q(**{"%s__gte" % self.end_date_field: datetime.datetime.now()})
|
||||||
|
@ -95,7 +101,7 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
|
||||||
|
|
||||||
def archived(self, queryset=None):
|
def archived(self, queryset=None):
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = self.get_query_set().all()
|
queryset = self.get_queryset().all()
|
||||||
if self.end_date_field:
|
if self.end_date_field:
|
||||||
qfilter = (
|
qfilter = (
|
||||||
models.Q(**{"%s__lte" % self.end_date_field: datetime.datetime.now()})
|
models.Q(**{"%s__lte" % self.end_date_field: datetime.datetime.now()})
|
||||||
|
@ -106,17 +112,16 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
|
||||||
|
|
||||||
def available(self, queryset=None):
|
def available(self, queryset=None):
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = self.get_query_set().all()
|
queryset = self.get_queryset().all()
|
||||||
return queryset.filter(**{self.publish_field: True})
|
return queryset.filter(**{self.publish_field: True})
|
||||||
|
|
||||||
def filter_by_language(self, language):
|
def filter_by_language(self, language):
|
||||||
queryset = self.get_query_set()
|
return self.get_queryset().active_translations(language_code=language)
|
||||||
return queryset.filter(models.Q(language__isnull=True) | models.Q(language=language))
|
|
||||||
|
|
||||||
def get_months(self, queryset=None):
|
def get_months(self, queryset=None):
|
||||||
"""Get months with aggregatet count (how much posts is in the month). Results are ordered by date."""
|
"""Get months with aggregate count (how much posts is in the month). Results are ordered by date."""
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = self.get_query_set()
|
queryset = self.get_queryset()
|
||||||
dates = queryset.values_list(self.start_date_field, flat=True)
|
dates = queryset.values_list(self.start_date_field, flat=True)
|
||||||
dates = [(x.year, x.month) for x in dates]
|
dates = [(x.year, x.month) for x in dates]
|
||||||
date_counter = Counter(dates)
|
date_counter = Counter(dates)
|
||||||
|
|
|
@ -6,8 +6,9 @@ from django.contrib.sites.models import Site
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import ugettext_lazy as _, get_language
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from djangocms_text_ckeditor.fields import HTMLField
|
from djangocms_text_ckeditor.fields import HTMLField
|
||||||
from filer.fields.image import FilerImageField
|
from filer.fields.image import FilerImageField
|
||||||
from parler.models import TranslatableModel, TranslatedFields
|
from parler.models import TranslatableModel, TranslatedFields
|
||||||
|
@ -54,7 +55,7 @@ class BlogCategory(TranslatableModel):
|
||||||
for lang in self.get_available_languages():
|
for lang in self.get_available_languages():
|
||||||
self.set_current_language(lang)
|
self.set_current_language(lang)
|
||||||
if not self.slug and self.name:
|
if not self.slug and self.name:
|
||||||
self.slug = slugify(self.name)
|
self.slug = slugify(force_text(self.name))
|
||||||
self.save_translations()
|
self.save_translations()
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
related_name='djangocms_blog_post_full',
|
related_name='djangocms_blog_post_full',
|
||||||
blank=True, null=True)
|
blank=True, null=True)
|
||||||
enable_comments = models.BooleanField(
|
enable_comments = models.BooleanField(
|
||||||
verbose_name = _(u'Enable comments on post'),
|
verbose_name=_(u'Enable comments on post'),
|
||||||
default=settings.BLOG_ENABLE_COMMENTS
|
default=settings.BLOG_ENABLE_COMMENTS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -133,12 +134,12 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_keywords(self):
|
def get_keywords(self):
|
||||||
return self.safe_translation_getter('meta_keywords', language_code=get_language()).strip().split(",")
|
return self.safe_translation_getter('meta_keywords').strip().split(",")
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
description = self.safe_translation_getter('meta_description', language_code=get_language())
|
description = self.safe_translation_getter('meta_description', any_language=True)
|
||||||
if not description:
|
if not description:
|
||||||
description = self.safe_translation_getter('abstract', language_code=get_language())
|
description = self.safe_translation_getter('abstract', any_language=True)
|
||||||
return description.strip()
|
return description.strip()
|
||||||
|
|
||||||
def get_image_url(self):
|
def get_image_url(self):
|
||||||
|
@ -172,7 +173,7 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
kwargs = {'year': self.date_published.year,
|
kwargs = {'year': self.date_published.year,
|
||||||
'month': self.date_published.month,
|
'month': self.date_published.month,
|
||||||
'day': self.date_published.day,
|
'day': self.date_published.day,
|
||||||
'slug': self.safe_translation_getter('slug', language_code=get_language())}
|
'slug': self.safe_translation_getter('slug', any_language=True)}
|
||||||
return reverse('djangocms_blog:post-detail', kwargs=kwargs)
|
return reverse('djangocms_blog:post-detail', kwargs=kwargs)
|
||||||
|
|
||||||
def thumbnail_options(self):
|
def thumbnail_options(self):
|
||||||
|
@ -182,7 +183,7 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
return settings.BLOG_IMAGE_THUMBNAIL_SIZE
|
return settings.BLOG_IMAGE_THUMBNAIL_SIZE
|
||||||
|
|
||||||
def full_image_options(self):
|
def full_image_options(self):
|
||||||
if self.main_image_fulll_id:
|
if self.main_image_full_id:
|
||||||
return self.main_image_full.as_dict
|
return self.main_image_full.as_dict
|
||||||
else:
|
else:
|
||||||
return settings.BLOG_IMAGE_FULL_SIZE
|
return settings.BLOG_IMAGE_FULL_SIZE
|
||||||
|
@ -238,6 +239,7 @@ class AuthorEntriesPlugin(CMSPlugin):
|
||||||
def get_authors(self):
|
def get_authors(self):
|
||||||
authors = self.authors.all()
|
authors = self.authors.all()
|
||||||
for author in authors:
|
for author in authors:
|
||||||
|
author.count = 0
|
||||||
if author.djangocms_blog_post_author.filter(publish=True).exists():
|
if author.djangocms_blog_post_author.filter(publish=True).exists():
|
||||||
author.count = author.djangocms_blog_post_author.filter(publish=True).count()
|
author.count = author.djangocms_blog_post_author.filter(publish=True).count()
|
||||||
return authors
|
return authors
|
||||||
|
|
|
@ -17,7 +17,7 @@ class BaseBlogView(ViewUrlMixin):
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
language = get_language()
|
language = get_language()
|
||||||
manager = self.model._default_manager.language(language)
|
manager = self.model._default_manager.active_translations(language_code=language)
|
||||||
if not self.request.user.is_staff:
|
if not self.request.user.is_staff:
|
||||||
manager = manager.filter(publish=True)
|
manager = manager.filter(publish=True)
|
||||||
return manager
|
return manager
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
django>=1.5.1
|
-r requirements.txt
|
||||||
https://github.com/divio/django-cms/archive/develop.zip
|
|
||||||
coverage
|
coverage
|
||||||
|
coveralls
|
||||||
mock>=1.0.1
|
mock>=1.0.1
|
||||||
nose>=1.3.0
|
nose>=1.3.0
|
||||||
django-nose>=1.2
|
django-nose>=1.2
|
||||||
|
|
||||||
# Additional test requirements go here
|
|
106
runtests.py
106
runtests.py
|
@ -1,31 +1,119 @@
|
||||||
import sys
|
import sys
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
gettext = lambda s: s
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
settings.configure(
|
settings.configure(
|
||||||
DEBUG=True,
|
DEBUG=True,
|
||||||
|
THUMBNAIL_DEBUG=True,
|
||||||
|
TEMPLATE_DEBUG=True,
|
||||||
USE_TZ=True,
|
USE_TZ=True,
|
||||||
DATABASES={
|
DATABASES={
|
||||||
"default": {
|
'default': {
|
||||||
"ENGINE": "django.db.backends.sqlite3",
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ROOT_URLCONF="djangocms_blog.urls",
|
TEMPLATE_CONTEXT_PROCESSORS=[
|
||||||
INSTALLED_APPS=[
|
'django.contrib.auth.context_processors.auth',
|
||||||
"django.contrib.auth",
|
'django.contrib.messages.context_processors.messages',
|
||||||
"django.contrib.contenttypes",
|
'django.core.context_processors.i18n',
|
||||||
"django.contrib.sites",
|
'django.core.context_processors.debug',
|
||||||
"djangocms_blog",
|
'django.core.context_processors.request',
|
||||||
|
'django.core.context_processors.media',
|
||||||
|
'django.core.context_processors.csrf',
|
||||||
|
'cms.context_processors.cms_settings',
|
||||||
|
'sekizai.context_processors.sekizai',
|
||||||
|
'django.core.context_processors.static',
|
||||||
],
|
],
|
||||||
|
MIDDLEWARE_CLASSES=[
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'django.middleware.doc.XViewMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.cache.FetchFromCacheMiddleware',
|
||||||
|
'cms.middleware.language.LanguageCookieMiddleware',
|
||||||
|
'cms.middleware.user.CurrentUserMiddleware',
|
||||||
|
'cms.middleware.page.CurrentPageMiddleware',
|
||||||
|
'cms.middleware.toolbar.ToolbarMiddleware',
|
||||||
|
],
|
||||||
|
ROOT_URLCONF='tests.test_utils.urls',
|
||||||
|
INSTALLED_APPS=[
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sites',
|
||||||
|
'cms',
|
||||||
|
'django_nose',
|
||||||
|
'menus',
|
||||||
|
'mptt',
|
||||||
|
'sekizai',
|
||||||
|
'filer',
|
||||||
|
'parler',
|
||||||
|
'taggit',
|
||||||
|
'meta',
|
||||||
|
'meta_mixin',
|
||||||
|
'easy_thumbnails',
|
||||||
|
'djangocms_text_ckeditor',
|
||||||
|
'cmsplugin_filer_image',
|
||||||
|
'django_select2',
|
||||||
|
'taggit_autosuggest',
|
||||||
|
'djangocms_blog',
|
||||||
|
'tests.test_utils',
|
||||||
|
],
|
||||||
|
LANGUAGE_CODE='en',
|
||||||
|
LANGUAGES=(
|
||||||
|
('en', gettext('English')),
|
||||||
|
('fr', gettext('French')),
|
||||||
|
('it', gettext('Italiano')),
|
||||||
|
),
|
||||||
|
CMS_LANGUAGES={
|
||||||
|
1: [
|
||||||
|
{
|
||||||
|
'code': 'en',
|
||||||
|
'name': gettext('English'),
|
||||||
|
'public': True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'code': 'it',
|
||||||
|
'name': gettext('Italiano'),
|
||||||
|
'public': True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'code': 'fr',
|
||||||
|
'name': gettext('French'),
|
||||||
|
'public': True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'default': {
|
||||||
|
'hide_untranslated': False,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CMS_TEMPLATES=(
|
||||||
|
('page.html', 'page'),
|
||||||
|
),
|
||||||
SITE_ID=1,
|
SITE_ID=1,
|
||||||
NOSE_ARGS=['-s'],
|
NOSE_ARGS=['-s'],
|
||||||
|
META_SITE_PROTOCOL='http',
|
||||||
|
META_SITE_DOMAIN='example.com',
|
||||||
|
META_USE_OG_PROPERTIES=True,
|
||||||
|
META_USE_TWITTER_PROPERTIES=True,
|
||||||
|
META_USE_GOOGLEPLUS_PROPERTIES=True,
|
||||||
|
THUMBNAIL_PROCESSORS=(
|
||||||
|
'easy_thumbnails.processors.colorspace',
|
||||||
|
'easy_thumbnails.processors.autocrop',
|
||||||
|
'filer.thumbnail_processors.scale_and_crop_with_subject_location',
|
||||||
|
'easy_thumbnails.processors.filters',
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
from django_nose import NoseTestSuiteRunner
|
from django_nose import NoseTestSuiteRunner
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError("To fix this error, run: pip install -r requirements-test.txt")
|
raise ImportError('To fix this error, run: pip install -r requirements-test.txt')
|
||||||
|
|
||||||
|
|
||||||
def run_tests(*test_args):
|
def run_tests(*test_args):
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -45,6 +45,8 @@ setup(
|
||||||
'django-taggit-templatetags',
|
'django-taggit-templatetags',
|
||||||
'django-taggit-autosuggest',
|
'django-taggit-autosuggest',
|
||||||
'django-admin-enhancer',
|
'django-admin-enhancer',
|
||||||
|
'djangocms-text-ckeditor',
|
||||||
|
'cmsplugin-filer',
|
||||||
'django-meta-mixin',
|
'django-meta-mixin',
|
||||||
],
|
],
|
||||||
license="BSD",
|
license="BSD",
|
||||||
|
|
125
tests/__init__.py
Normal file
125
tests/__init__.py
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Tests for `djangocms_blog` module.
|
||||||
|
"""
|
||||||
|
from cms.utils.i18n import get_language_list
|
||||||
|
from cmsplugin_filer_image.models import ThumbnailOption
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.http import SimpleCookie
|
||||||
|
from django.test import TestCase, RequestFactory
|
||||||
|
from django.utils.translation import activate
|
||||||
|
from six import StringIO
|
||||||
|
|
||||||
|
from djangocms_blog.models import BlogCategory, Post
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTest(TestCase):
|
||||||
|
"""
|
||||||
|
Base class with utility function
|
||||||
|
"""
|
||||||
|
request_factory = None
|
||||||
|
user = None
|
||||||
|
languages = get_language_list()
|
||||||
|
category_1 = None
|
||||||
|
thumb_1 = None
|
||||||
|
thumb_2 = None
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'it': [
|
||||||
|
{'title': u'Primo post', 'abstract': u'<p>prima riga</p>',
|
||||||
|
'description': u'Questa è la descrizione', 'keywords': u'keyword1, keyword2',
|
||||||
|
'text': u'Testo del post',},
|
||||||
|
{'title': u'Secondo post', 'abstract': u'<p>prima riga del secondo post</p>',
|
||||||
|
'description': u'Descrizione del secondo post', 'keywords': u'keyword3, keyword4',
|
||||||
|
'text': u'Testo del secondo post'},
|
||||||
|
],
|
||||||
|
'en': [
|
||||||
|
{'title': u'First post', 'abstract': u'<p>first line</p>',
|
||||||
|
'description': u'This is the description', 'keywords': u'keyword1, keyword2',
|
||||||
|
'text': u'Post text'},
|
||||||
|
{'title': u'Second post', 'abstract': u'<p>second post first line</p>',
|
||||||
|
'description': u'Second post description', 'keywords': u'keyword3, keyword4',
|
||||||
|
'text': u'Second post text'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.request_factory = RequestFactory()
|
||||||
|
cls.user = User.objects.create(username='admin', is_staff=True, is_superuser=True)
|
||||||
|
cls.user_staff = User.objects.create(username='staff', is_staff=True)
|
||||||
|
cls.user_normal = User.objects.create(username='normal')
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
activate('en')
|
||||||
|
super(BaseTest, self).setUp()
|
||||||
|
self.category_1 = BlogCategory.objects.create()
|
||||||
|
self.category_1.name = u'category 1'
|
||||||
|
self.category_1.save()
|
||||||
|
self.category_1.set_current_language('it')
|
||||||
|
self.category_1.name = u'categoria 1'
|
||||||
|
self.category_1.save()
|
||||||
|
self.category_1.set_current_language('en')
|
||||||
|
self.thumb_1 = ThumbnailOption.objects.create(
|
||||||
|
name='base', width=100, height=100, crop=True, upscale=False
|
||||||
|
)
|
||||||
|
self.thumb_2 = ThumbnailOption.objects.create(
|
||||||
|
name='main', width=200, height=200, crop=False, upscale=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_post(self, data, post=None, lang='en'):
|
||||||
|
if not post:
|
||||||
|
post = Post()
|
||||||
|
post.set_current_language(lang)
|
||||||
|
post.author = self.user
|
||||||
|
post.title = data['title']
|
||||||
|
post.abstract = data['abstract']
|
||||||
|
post.meta_description = data['description']
|
||||||
|
post.meta_keywords = data['keywords']
|
||||||
|
post.save()
|
||||||
|
post.categories.add(self.category_1)
|
||||||
|
post.save()
|
||||||
|
return post
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
User.objects.all().delete()
|
||||||
|
|
||||||
|
def get_pages(self):
|
||||||
|
from cms.api import create_page, create_title
|
||||||
|
page = create_page(u'page one', 'page.html', language='en')
|
||||||
|
page_2 = create_page(u'page two', 'page.html', language='en')
|
||||||
|
create_title(language='fr', title=u'page un', page=page)
|
||||||
|
create_title(language='it', title=u'pagina uno', page=page)
|
||||||
|
for lang in self.languages:
|
||||||
|
page.publish(lang)
|
||||||
|
page_2.publish('en')
|
||||||
|
return page.get_draft_object(), page_2.get_draft_object()
|
||||||
|
|
||||||
|
def get_request(self, page, lang):
|
||||||
|
request = self.request_factory.get(page.get_path(lang))
|
||||||
|
request.current_page = page
|
||||||
|
request.user = self.user
|
||||||
|
request.session = {}
|
||||||
|
request.cookies = SimpleCookie()
|
||||||
|
request.errors = StringIO()
|
||||||
|
return request
|
||||||
|
|
||||||
|
def get_page_request(self, page, user, path=None, edit=False, lang_code='en'):
|
||||||
|
from cms.middleware.toolbar import ToolbarMiddleware
|
||||||
|
path = path or page and page.get_absolute_url()
|
||||||
|
if edit:
|
||||||
|
path += '?edit'
|
||||||
|
request = RequestFactory().get(path)
|
||||||
|
request.session = {}
|
||||||
|
request.user = user
|
||||||
|
request.LANGUAGE_CODE = lang_code
|
||||||
|
if edit:
|
||||||
|
request.GET = {'edit': None}
|
||||||
|
else:
|
||||||
|
request.GET = {'edit_off': None}
|
||||||
|
request.current_page = page
|
||||||
|
mid = ToolbarMiddleware()
|
||||||
|
mid.process_request(request)
|
||||||
|
return request
|
203
tests/test_models.py
Normal file
203
tests/test_models.py
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from cms.api import add_plugin
|
||||||
|
from cms.utils.copy_plugins import copy_plugins_to
|
||||||
|
from cms.utils.plugins import downcast_plugins
|
||||||
|
from datetime import date
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
import parler
|
||||||
|
from taggit.models import Tag
|
||||||
|
|
||||||
|
from djangocms_blog.models import Post
|
||||||
|
from djangocms_blog import settings
|
||||||
|
|
||||||
|
|
||||||
|
from . import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class ModelsTest(BaseTest):
|
||||||
|
|
||||||
|
def test_model_attributes(self):
|
||||||
|
post = self._get_post(self.data['en'][0])
|
||||||
|
post = self._get_post(self.data['it'][0], post, 'it')
|
||||||
|
post.set_current_language('en')
|
||||||
|
meta_en = post.as_meta()
|
||||||
|
self.assertEqual(meta_en.og_type, settings.BLOG_FB_TYPE)
|
||||||
|
self.assertEqual(meta_en.title, post.title)
|
||||||
|
self.assertTrue(meta_en.url.endswith(post.get_absolute_url()))
|
||||||
|
self.assertEqual(meta_en.description, post.meta_description)
|
||||||
|
self.assertEqual(meta_en.keywords, post.meta_keywords.split(','))
|
||||||
|
self.assertEqual(meta_en.published_time, post.date_published)
|
||||||
|
post.set_current_language('it')
|
||||||
|
meta_it = post.as_meta()
|
||||||
|
self.assertEqual(meta_it.title, post.title)
|
||||||
|
self.assertTrue(meta_it.url.endswith(post.get_absolute_url()))
|
||||||
|
self.assertNotEqual(meta_it.title, meta_en.title)
|
||||||
|
self.assertEqual(meta_it.description, post.meta_description)
|
||||||
|
|
||||||
|
post.set_current_language('en')
|
||||||
|
kwargs = {'year': post.date_published.year,
|
||||||
|
'month': post.date_published.month,
|
||||||
|
'day': post.date_published.day,
|
||||||
|
'slug': post.safe_translation_getter('slug', any_language=True)}
|
||||||
|
url_en = reverse('djangocms_blog:post-detail', kwargs=kwargs)
|
||||||
|
self.assertEqual(url_en, post.get_absolute_url())
|
||||||
|
post.set_current_language('it')
|
||||||
|
kwargs = {'year': post.date_published.year,
|
||||||
|
'month': post.date_published.month,
|
||||||
|
'day': post.date_published.day,
|
||||||
|
'slug': post.safe_translation_getter('slug', any_language=True)}
|
||||||
|
url_it = reverse('djangocms_blog:post-detail', kwargs=kwargs)
|
||||||
|
self.assertEqual(url_it, post.get_absolute_url())
|
||||||
|
self.assertNotEqual(url_it, url_en)
|
||||||
|
|
||||||
|
self.assertEqual(post.get_full_url(), 'http://example.com%s' % url_it)
|
||||||
|
|
||||||
|
self.assertEqual(post.thumbnail_options(), settings.BLOG_IMAGE_THUMBNAIL_SIZE)
|
||||||
|
self.assertEqual(post.full_image_options(), settings.BLOG_IMAGE_FULL_SIZE)
|
||||||
|
|
||||||
|
post.main_image_thumbnail = self.thumb_1
|
||||||
|
post.main_image_full = self.thumb_2
|
||||||
|
self.assertEqual(post.thumbnail_options(), {
|
||||||
|
'size': (100, 100),
|
||||||
|
'width': 100, 'height': 100,
|
||||||
|
'crop': True,
|
||||||
|
'upscale': False
|
||||||
|
})
|
||||||
|
self.assertEqual(post.full_image_options(), {
|
||||||
|
'size': (200, 200),
|
||||||
|
'width': 200, 'height': 200,
|
||||||
|
'crop': False,
|
||||||
|
'upscale': False
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_manager(self):
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
|
||||||
|
# default queryset, published and unpublished posts
|
||||||
|
months = Post.objects.get_months()
|
||||||
|
for data in months:
|
||||||
|
self.assertEqual(data['date'], date(year=date.today().year, month=date.today().month, day=1))
|
||||||
|
self.assertEqual(data['count'], 2)
|
||||||
|
|
||||||
|
# custom queryset, only published
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
months = Post.objects.get_months(Post.objects.published())
|
||||||
|
for data in months:
|
||||||
|
self.assertEqual(data['date'], date(year=date.today().year, month=date.today().month, day=1))
|
||||||
|
self.assertEqual(data['count'], 1)
|
||||||
|
|
||||||
|
self.assertEqual(len(Post.objects.available()), 1)
|
||||||
|
|
||||||
|
# If post is published but publishing date is in the future
|
||||||
|
post_2.date_published = date(year=date.today().year+1, month=date.today().month, day=1)
|
||||||
|
post_2.publish = True
|
||||||
|
post_2.save()
|
||||||
|
self.assertEqual(len(Post.objects.available()), 2)
|
||||||
|
self.assertEqual(len(Post.objects.published()), 1)
|
||||||
|
self.assertEqual(len(Post.objects.archived()), 0)
|
||||||
|
|
||||||
|
# If post is published but end publishing date is in the past
|
||||||
|
post_2.date_published = date(year=date.today().year-2, month=date.today().month, day=1)
|
||||||
|
post_2.date_published_end = date(year=date.today().year-1, month=date.today().month, day=1)
|
||||||
|
post_2.save()
|
||||||
|
self.assertEqual(len(Post.objects.available()), 2)
|
||||||
|
self.assertEqual(len(Post.objects.published()), 1)
|
||||||
|
self.assertEqual(len(Post.objects.archived()), 1)
|
||||||
|
|
||||||
|
# counting with language fallback enabled
|
||||||
|
post = self._get_post(self.data['it'][0], post_1, 'it')
|
||||||
|
self.assertEqual(len(Post.objects.filter_by_language('it')), 2)
|
||||||
|
|
||||||
|
# No fallback
|
||||||
|
parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = True
|
||||||
|
self.assertEqual(len(Post.objects.filter_by_language('it')), 1)
|
||||||
|
parler.appsettings.PARLER_LANGUAGES['default']['hide_untranslated'] = False
|
||||||
|
|
||||||
|
def test_tag_cloud(self):
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_1.tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4')
|
||||||
|
post_1.save()
|
||||||
|
post_2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
|
||||||
|
post_2.save()
|
||||||
|
|
||||||
|
self.assertEqual(len(Post.objects.tag_cloud()), 0)
|
||||||
|
|
||||||
|
tags = []
|
||||||
|
for tag in Tag.objects.all():
|
||||||
|
if tag.slug == 'tag-2':
|
||||||
|
tag.count = 2
|
||||||
|
else:
|
||||||
|
tag.count = 1
|
||||||
|
tags.append(tag)
|
||||||
|
|
||||||
|
self.assertEqual(Post.objects.tag_cloud(published=True), [])
|
||||||
|
self.assertEqual(set(Post.objects.tag_cloud(published=False)), set(tags))
|
||||||
|
|
||||||
|
tags_1 = []
|
||||||
|
for tag in Tag.objects.all():
|
||||||
|
if tag.slug == 'tag-2':
|
||||||
|
tag.count = 2
|
||||||
|
tags_1.append(tag)
|
||||||
|
elif tag.slug in ('tag-1', 'tag-3', 'tag-4'):
|
||||||
|
tag.count = 1
|
||||||
|
tags_1.append(tag)
|
||||||
|
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
self.assertEqual(set(Post.objects.tag_cloud()), set(tags_1))
|
||||||
|
self.assertEqual(set(Post.objects.tag_cloud(published=False)), set(tags))
|
||||||
|
|
||||||
|
def test_plugin_latest(self):
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_1.tags.add('tag 1')
|
||||||
|
post_1.save()
|
||||||
|
plugin = add_plugin(post_1.content, 'BlogLatestEntriesPlugin', language='en')
|
||||||
|
tag = Tag.objects.get(slug='tag-1')
|
||||||
|
plugin.tags.add(tag)
|
||||||
|
self.assertEqual(len(plugin.get_posts()), 0)
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
self.assertEqual(len(plugin.get_posts()), 1)
|
||||||
|
|
||||||
|
def test_copy_plugin_latest(self):
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
tag = Tag.objects.create(name='tag 1')
|
||||||
|
plugin = add_plugin(post_1.content, 'BlogLatestEntriesPlugin', language='en')
|
||||||
|
plugin.tags.add(tag)
|
||||||
|
plugins = list(post_1.content.cmsplugin_set.filter(language='en').order_by('tree_id', 'level', 'position'))
|
||||||
|
copy_plugins_to(plugins, post_2.content)
|
||||||
|
new = downcast_plugins(post_2.content.cmsplugin_set.all())
|
||||||
|
self.assertEqual(set(new[0].tags.all()), set([tag]))
|
||||||
|
|
||||||
|
def test_plugin_author(self):
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
plugin = add_plugin(post_1.content, 'BlogAuthorPostsPlugin', language='en')
|
||||||
|
plugin.authors.add(self.user)
|
||||||
|
self.assertEqual(len(plugin.get_posts()), 0)
|
||||||
|
self.assertEqual(plugin.get_authors()[0].count, 0)
|
||||||
|
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
self.assertEqual(len(plugin.get_posts()), 1)
|
||||||
|
self.assertEqual(plugin.get_authors()[0].count, 1)
|
||||||
|
|
||||||
|
post_2.publish = True
|
||||||
|
post_2.save()
|
||||||
|
self.assertEqual(len(plugin.get_posts()), 2)
|
||||||
|
self.assertEqual(plugin.get_authors()[0].count, 2)
|
||||||
|
|
||||||
|
def test_copy_plugin_author(self):
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
plugin = add_plugin(post_1.content, 'BlogAuthorPostsPlugin', language='en')
|
||||||
|
plugin.authors.add(self.user)
|
||||||
|
plugins = list(post_1.content.cmsplugin_set.filter(language='en').order_by('tree_id', 'level', 'position'))
|
||||||
|
copy_plugins_to(plugins, post_2.content)
|
||||||
|
new = downcast_plugins(post_2.content.cmsplugin_set.all())
|
||||||
|
self.assertEqual(set(new[0].authors.all()), set([self.user]))
|
72
tests/test_plugins.py
Normal file
72
tests/test_plugins.py
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
from cms.api import add_plugin
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.template import RequestContext
|
||||||
|
from taggit.models import Tag
|
||||||
|
|
||||||
|
from . import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class PluginTest(BaseTest):
|
||||||
|
|
||||||
|
def test_plugin_latest(self):
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_1.tags.add('tag 1')
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
ph = page1.placeholders.get(slot='placeholder')
|
||||||
|
plugin = add_plugin(ph, 'BlogLatestEntriesPlugin', language='en')
|
||||||
|
tag = Tag.objects.get(slug='tag-1')
|
||||||
|
plugin.tags.add(tag)
|
||||||
|
request = self.get_page_request(page1, self.user, r'/en/blog/', lang_code='en', edit=True)
|
||||||
|
context = RequestContext(request, {})
|
||||||
|
rendered = plugin.render_plugin(context, ph)
|
||||||
|
self.assertTrue(rendered.find('cms_plugin-djangocms_blog-post-abstract-1') > -1)
|
||||||
|
self.assertTrue(rendered.find(reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug})) > -1)
|
||||||
|
self.assertTrue(rendered.find('<p>first line</p>') > -1)
|
||||||
|
self.assertTrue(rendered.find('<article id="post-first-post"') > -1)
|
||||||
|
self.assertTrue(rendered.find(post_1.get_absolute_url()) > -1)
|
||||||
|
|
||||||
|
def test_plugin_authors(self):
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
post_2.publish = True
|
||||||
|
post_2.save()
|
||||||
|
ph = page1.placeholders.get(slot='placeholder')
|
||||||
|
plugin = add_plugin(ph, 'BlogAuthorPostsPlugin', language='en')
|
||||||
|
plugin.authors.add(self.user)
|
||||||
|
request = self.get_page_request(page1, self.user, r'/en/blog/', lang_code='en', edit=True)
|
||||||
|
context = RequestContext(request, {})
|
||||||
|
rendered = plugin.render_plugin(context, ph)
|
||||||
|
self.assertTrue(rendered.find(reverse('djangocms_blog:posts-author', kwargs={'username': self.user.username})) > -1)
|
||||||
|
self.assertTrue(rendered.find('2 articles') > -1)
|
||||||
|
|
||||||
|
def test_plugin_tags(self):
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_1.tags.add('tag 1', 'tag 2', 'test tag')
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
post_2.tags.add('test tag', 'another tag')
|
||||||
|
post_2.publish = True
|
||||||
|
post_2.save()
|
||||||
|
ph = page1.placeholders.get(slot='placeholder')
|
||||||
|
plugin = add_plugin(ph, 'BlogTagsPlugin', language='en')
|
||||||
|
request = self.get_page_request(page1, self.user, r'/en/blog/', lang_code='en', edit=True)
|
||||||
|
context = RequestContext(request, {})
|
||||||
|
rendered = plugin.render_plugin(context, ph).replace("\n", "")
|
||||||
|
for tag in Tag.objects.all():
|
||||||
|
self.assertTrue(rendered.find(reverse('djangocms_blog:posts-tagged', kwargs={'tag': tag.slug})) > -1)
|
||||||
|
if tag.slug == 'test-tag':
|
||||||
|
rf = '\s+%s\s+<span>\(\s+%s articles' % (tag.name, 2)
|
||||||
|
else:
|
||||||
|
rf = '\s+%s\s+<span>\(\s+%s article' % (tag.name, 1)
|
||||||
|
rx = re.compile(rf)
|
||||||
|
self.assertEqual(len(rx.findall(rendered)), 1)
|
27
tests/test_toolbar.py
Normal file
27
tests/test_toolbar.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from cms.toolbar.items import ModalItem
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from djangocms_blog.models import BLOG_CURRENT_POST_IDENTIFIER
|
||||||
|
|
||||||
|
|
||||||
|
from . import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class ToolbarTest(BaseTest):
|
||||||
|
|
||||||
|
def test_toolbar_with_items(self):
|
||||||
|
"""
|
||||||
|
Test that Blog toolbar is present and contains all items
|
||||||
|
"""
|
||||||
|
from cms.toolbar.toolbar import CMSToolbar
|
||||||
|
post = self._get_post(self.data['en'][0])
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True)
|
||||||
|
setattr(request, BLOG_CURRENT_POST_IDENTIFIER, post)
|
||||||
|
toolbar = CMSToolbar(request)
|
||||||
|
toolbar.get_left_items()
|
||||||
|
blog_menu = toolbar.menus['djangocms_blog']
|
||||||
|
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1)
|
||||||
|
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1)
|
||||||
|
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_change', args=(post.pk,)))), 1)
|
||||||
|
|
2
tests/test_utils/__init__.py
Normal file
2
tests/test_utils/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
6
tests/test_utils/templates/base.html
Normal file
6
tests/test_utils/templates/base.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% include "page.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="app app-blog span8">
|
||||||
|
{% block content_blog %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
9
tests/test_utils/templates/page.html
Normal file
9
tests/test_utils/templates/page.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% load cms_tags sekizai_tags %}
|
||||||
|
{% render_block "css" %}
|
||||||
|
{% cms_toolbar %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% placeholder "placeholder" %}
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% render_block "js" %}
|
27
tests/test_utils/urls.py
Normal file
27
tests/test_utils/urls.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from cms.utils.conf import get_cms_setting
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls import patterns, include, url
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.conf.urls.i18n import i18n_patterns
|
||||||
|
|
||||||
|
|
||||||
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||||
|
|
||||||
|
admin.autodiscover()
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
#(r'', include('django.contrib.staticfiles.urls')),
|
||||||
|
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
|
||||||
|
{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
|
||||||
|
url(r'^media/cms/(?P<path>.*)$', 'django.views.static.serve',
|
||||||
|
{'document_root': get_cms_setting('MEDIA_ROOT'), 'show_indexes': True}),
|
||||||
|
url(r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
|
||||||
|
)
|
||||||
|
|
||||||
|
urlpatterns += staticfiles_urlpatterns()
|
||||||
|
|
||||||
|
urlpatterns += i18n_patterns('',
|
||||||
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
|
url(r'^blog/', include('djangocms_blog.urls', namespace='djangocms_blog')),
|
||||||
|
url(r'^', include('cms.urls')),
|
||||||
|
)
|
117
tests/test_views.py
Normal file
117
tests/test_views.py
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from datetime import date
|
||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
|
from django.http import Http404
|
||||||
|
from django.utils.translation import activate
|
||||||
|
from djangocms_blog.views import PostListView, PostDetailView, PostArchiveView
|
||||||
|
|
||||||
|
from . import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class ViewTest(BaseTest):
|
||||||
|
|
||||||
|
def test_post_list_view(self):
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_1 = self._get_post(self.data['it'][0], post_1, 'it')
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
post_1.set_current_language('en')
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_2 = self._get_post(self.data['it'][1], post_2, 'it')
|
||||||
|
post_2.set_current_language('en')
|
||||||
|
|
||||||
|
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False)
|
||||||
|
activate('en')
|
||||||
|
view_obj = PostListView()
|
||||||
|
view_obj.request = request
|
||||||
|
|
||||||
|
self.assertEqual(list(view_obj.get_queryset()), [post_1])
|
||||||
|
|
||||||
|
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False)
|
||||||
|
view_obj.request = request
|
||||||
|
self.assertEqual(set(view_obj.get_queryset()), set([post_1, post_2]))
|
||||||
|
|
||||||
|
view_obj.kwargs = {}
|
||||||
|
view_obj.object_list = view_obj.get_queryset()
|
||||||
|
view_obj.paginate_by = 1
|
||||||
|
context = view_obj.get_context_data(object_list=view_obj.object_list)
|
||||||
|
self.assertTrue(context['is_paginated'])
|
||||||
|
self.assertEqual(list(context['post_list']), [post_2])
|
||||||
|
self.assertEqual(context['paginator'].count, 2)
|
||||||
|
self.assertEqual(context['post_list'][0].title, 'Second post')
|
||||||
|
response = view_obj.render_to_response(context)
|
||||||
|
self.assertContains(response, context['post_list'][0].get_absolute_url())
|
||||||
|
|
||||||
|
request = self.get_page_request(page1, self.user, r'/it/blog/', lang_code='it', edit=False)
|
||||||
|
activate('it')
|
||||||
|
view_obj.request = request
|
||||||
|
view_obj.object_list = view_obj.get_queryset()
|
||||||
|
context = view_obj.get_context_data(object_list=view_obj.object_list)
|
||||||
|
self.assertEqual(context['post_list'][0].title, 'Secondo post')
|
||||||
|
response = view_obj.render_to_response(context)
|
||||||
|
self.assertContains(response, context['post_list'][0].get_absolute_url())
|
||||||
|
|
||||||
|
def test_post_detail_view(self):
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_1 = self._get_post(self.data['it'][0], post_1, 'it')
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
post_1.set_current_language('en')
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_2 = self._get_post(self.data['it'][1], post_2, 'it')
|
||||||
|
post_2.set_current_language('en')
|
||||||
|
|
||||||
|
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False)
|
||||||
|
activate('en')
|
||||||
|
view_obj = PostDetailView()
|
||||||
|
view_obj.request = request
|
||||||
|
|
||||||
|
with self.assertRaises(Http404):
|
||||||
|
view_obj.kwargs = {'slug': 'not-existing'}
|
||||||
|
post_obj = view_obj.get_object()
|
||||||
|
|
||||||
|
view_obj.kwargs = {'slug': post_1.slug}
|
||||||
|
post_obj = view_obj.get_object()
|
||||||
|
self.assertEqual(post_obj, post_1)
|
||||||
|
self.assertEqual(post_obj.language_code, 'en')
|
||||||
|
|
||||||
|
request = self.get_page_request(page1, AnonymousUser(), r'/it/blog/', lang_code='it', edit=False)
|
||||||
|
activate('it')
|
||||||
|
view_obj.request = request
|
||||||
|
post_obj = view_obj.get_object()
|
||||||
|
self.assertEqual(post_obj, post_1)
|
||||||
|
self.assertEqual(post_obj.language_code, 'it')
|
||||||
|
|
||||||
|
view_obj.object = post_obj
|
||||||
|
context = view_obj.get_context_data()
|
||||||
|
self.assertEqual(context['post'], post_1)
|
||||||
|
self.assertEqual(context['post'].language_code, 'it')
|
||||||
|
self.assertTrue(context['meta'])
|
||||||
|
|
||||||
|
def test_post_archive_view(self):
|
||||||
|
page1, page2 = self.get_pages()
|
||||||
|
post_1 = self._get_post(self.data['en'][0])
|
||||||
|
post_1 = self._get_post(self.data['it'][0], post_1, 'it')
|
||||||
|
post_1.publish = True
|
||||||
|
post_1.save()
|
||||||
|
post_1.set_current_language('en')
|
||||||
|
post_2 = self._get_post(self.data['en'][1])
|
||||||
|
post_2 = self._get_post(self.data['it'][1], post_2, 'it')
|
||||||
|
post_2.set_current_language('en')
|
||||||
|
|
||||||
|
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False)
|
||||||
|
activate('en')
|
||||||
|
view_obj = PostArchiveView()
|
||||||
|
view_obj.request = request
|
||||||
|
view_obj.kwargs = {'year': date.today().year, 'month': date.today().month}
|
||||||
|
|
||||||
|
# One post only, anonymous request
|
||||||
|
qs = view_obj.get_queryset()
|
||||||
|
self.assertEqual(qs.count(), 1)
|
||||||
|
self.assertEqual(list(qs), [post_1])
|
||||||
|
|
||||||
|
view_obj.object_list = qs
|
||||||
|
context = view_obj.get_context_data(object_list=view_obj.object_list)
|
||||||
|
self.assertEqual(context['archive_date'], date(year=date.today().year, month=date.today().month, day=1))
|
30
tox.ini
30
tox.ini
|
@ -1,10 +1,28 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py26, py27, py33
|
envlist = py26dj15, py26dj16, py27dj15, py27dj16
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
setenv =
|
commands = python runtests.py
|
||||||
PYTHONPATH = {toxinidir}:{toxinidir}/djangocms_blog
|
|
||||||
commands = python setup.py test
|
|
||||||
deps =
|
deps =
|
||||||
-r{toxinidir}/requirements-dev.txt
|
-r{toxinidir}/requirements-test.txt
|
||||||
-r{toxinidir}/requirements.txt
|
|
||||||
|
[testenv:py26dj15]
|
||||||
|
deps =
|
||||||
|
django<1.6
|
||||||
|
{[testenv]deps}
|
||||||
|
|
||||||
|
[testenv:py26dj16]
|
||||||
|
deps =
|
||||||
|
django<1.7
|
||||||
|
{[testenv]deps}
|
||||||
|
|
||||||
|
[testenv:py27dj15]
|
||||||
|
deps =
|
||||||
|
django<1.6
|
||||||
|
{[testenv]deps}
|
||||||
|
|
||||||
|
[testenv:py27dj16]
|
||||||
|
deps =
|
||||||
|
django<1.7
|
||||||
|
{[testenv]deps}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue