summaryrefslogtreecommitdiffstats
path: root/tests/test_rss_feeds.py
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2021-02-03 19:17:00 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2021-02-03 19:17:00 -0500
commit3a0d66f07b112b6d2bdc2b57bbf717a89a351ce6 (patch)
treea7cf56282e54f05785243bc1e903d6594f2c06ba /tests/test_rss_feeds.py
parent787b97a4cb24330b36f11297c6d3a7a473a907d0 (diff)
New upstream version 8.1.2.upstream/8.1.2
Diffstat (limited to 'tests/test_rss_feeds.py')
-rw-r--r--tests/test_rss_feeds.py308
1 files changed, 166 insertions, 142 deletions
diff --git a/tests/test_rss_feeds.py b/tests/test_rss_feeds.py
index f67ed40..d976579 100644
--- a/tests/test_rss_feeds.py
+++ b/tests/test_rss_feeds.py
@@ -1,156 +1,180 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import unicode_literals, absolute_import
-
import os
-import sys
-
-
+import re
from collections import defaultdict
from io import StringIO
-import os
-import re
-import unittest
+from unittest import mock
import dateutil.tz
+import pytest
from lxml import etree
-import mock
-
-from .base import LocaleSupportInTesting
-import nikola
-fake_conf = defaultdict(str)
-fake_conf['TIMEZONE'] = 'UTC'
-fake_conf['__tzinfo__'] = dateutil.tz.tzutc()
-fake_conf['DEFAULT_LANG'] = 'en'
-fake_conf['TRANSLATIONS'] = {'en': ''}
-fake_conf['BASE_URL'] = 'http://some.blog/'
-fake_conf['BLOG_AUTHOR'] = nikola.nikola.utils.TranslatableSetting('BLOG_AUTHOR', 'Nikola Tesla', ['en'])
-fake_conf['TRANSLATIONS_PATTERN'] = '{path}.{lang}.{ext}'
-
-
-class FakeCompiler(object):
+from nikola.nikola import Nikola, Post
+from nikola.utils import LocaleBorg, TranslatableSetting
+
+
+def test_feed_is_valid(rss_feed_content, rss_schema):
+ """
+ A testcase to check if the generated feed is valid.
+
+ Validation can be tested with W3 FEED Validator that can be found
+ at http://feedvalidator.org
+ """
+ document = etree.parse(StringIO(rss_feed_content))
+
+ assert rss_schema.validate(document)
+
+
+@pytest.fixture
+def rss_schema(rss_schema_filename):
+ with open(rss_schema_filename, "r") as rss_schema_file:
+ xmlschema_doc = etree.parse(rss_schema_file)
+
+ return etree.XMLSchema(xmlschema_doc)
+
+
+@pytest.fixture
+def rss_schema_filename(test_dir):
+ return os.path.join(test_dir, "data", "rss-2_0.xsd")
+
+
+@pytest.mark.parametrize("element", ["guid", "link"])
+def test_feed_items_have_valid_URLs(rss_feed_content, blog_url, element):
+ """
+ The items in the feed need to have valid urls in link and guid.
+
+ As stated by W3 FEED Validator:
+ * "link must be a full and valid URL"
+ * "guid must be a full URL, unless isPermaLink attribute is false: /weblog/posts/the-minimal-server.html"
+ """
+ # This validation regex is taken from django.core.validators
+ url_validation_regex = re.compile(
+ r"^(?:http|ftp)s?://" # http:// or https://
+ # domain...
+ r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|"
+ r"localhost|" # localhost...
+ # ...or ipv4
+ r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|"
+ # ...or ipv6
+ r"\[?[A-F0-9]*:[A-F0-9:]+\]?)" r"(?::\d+)?" r"(?:/?|[/?]\S+)$", # optional port
+ re.IGNORECASE,
+ )
+
+ def is_valid_URL(url):
+ return url_validation_regex.match(url) is not None
+
+ et = etree.parse(StringIO(rss_feed_content))
+ channel = et.find("channel")
+ item = channel.find("item")
+ element = item.find(element)
+
+ assert is_valid_URL(element.text)
+ assert blog_url in element.text
+
+
+@pytest.fixture(autouse=True)
+def localeborg(default_locale):
+ """
+ LocaleBorg with default settings
+ """
+ LocaleBorg.reset()
+ LocaleBorg.initialize({}, default_locale)
+ try:
+ yield
+ finally:
+ LocaleBorg.reset()
+
+
+@pytest.fixture
+def rss_feed_content(blog_url, config, default_locale):
+ default_post = {
+ "title": "post title",
+ "slug": "awesome_article",
+ "date": "2012-10-01 22:41",
+ "author": None,
+ "tags": "tags",
+ "link": "link",
+ "description": "description",
+ "enclosure": "http://www.example.org/foo.mp3",
+ "enclosure_length": "5",
+ }
+ meta_mock = mock.Mock(return_value=(defaultdict(str, default_post), None))
+ with mock.patch("nikola.post.get_meta", meta_mock):
+ with \
+ mock.patch(
+ "nikola.nikola.utils.os.path.isdir", mock.Mock(return_value=True)), \
+ mock.patch(
+ "nikola.nikola.Post.text", mock.Mock(return_value="some long text")
+ ):
+ with mock.patch(
+ "nikola.post.os.path.isfile", mock.Mock(return_value=True)):
+ example_post = Post(
+ "source.file",
+ config,
+ "blog_folder",
+ True,
+ {"en": ""},
+ "post.tmpl",
+ FakeCompiler(),
+ )
+
+ filename = "testfeed.rss"
+ opener_mock = mock.mock_open()
+
+ with mock.patch("nikola.nikola.io.open", opener_mock, create=True):
+ Nikola().generic_rss_renderer(
+ default_locale,
+ "blog_title",
+ blog_url,
+ "blog_description",
+ [example_post, ],
+ filename,
+ True,
+ False,
+ )
+
+ opener_mock.assert_called_once_with(filename, "w+", encoding="utf-8")
+
+ # Python 3 / unicode strings workaround
+ # lxml will complain if the encoding is specified in the
+ # xml when running with unicode strings.
+ # We do not include this in our content.
+ file_content = [call[1][0] for call in opener_mock.mock_calls[2:-1]][0]
+ splitted_content = file_content.split("\n")
+ # encoding_declaration = splitted_content[0]
+ content_without_encoding_declaration = splitted_content[1:]
+ yield "\n".join(content_without_encoding_declaration)
+
+
+@pytest.fixture
+def config(blog_url, default_locale):
+ fake_conf = defaultdict(str)
+ fake_conf["TIMEZONE"] = "UTC"
+ fake_conf["__tzinfo__"] = dateutil.tz.tzutc()
+ fake_conf["DEFAULT_LANG"] = default_locale
+ fake_conf["TRANSLATIONS"] = {default_locale: ""}
+ fake_conf["BASE_URL"] = blog_url
+ fake_conf["BLOG_AUTHOR"] = TranslatableSetting(
+ "BLOG_AUTHOR", "Nikola Tesla", [default_locale]
+ )
+ fake_conf["TRANSLATIONS_PATTERN"] = "{path}.{lang}.{ext}"
+
+ return fake_conf
+
+
+@pytest.fixture
+def blog_url():
+ return "http://some.blog"
+
+
+class FakeCompiler:
demote_headers = False
- compile_html = None
- extension = lambda self: '.html'
- name = "fake"
+ compile = None
+
+ def extension(self):
+ return ".html"
def read_metadata(*args, **kwargs):
return {}
def register_extra_dependencies(self, post):
pass
-
-
-class RSSFeedTest(unittest.TestCase):
- def setUp(self):
- LocaleSupportInTesting.initialize_locales_for_testing('unilingual')
- self.blog_url = "http://some.blog"
-
- with mock.patch('nikola.post.get_meta',
- mock.Mock(return_value=(
- ({'title': 'post title',
- 'slug': 'awesome_article',
- 'date': '2012-10-01 22:41',
- 'author': None,
- 'tags': 'tags',
- 'link': 'link',
- 'description': 'description',
- 'enclosure': 'http://www.example.org/foo.mp3'}, True)
- ))):
- with mock.patch('nikola.nikola.utils.os.path.isdir',
- mock.Mock(return_value=True)):
- with mock.patch('nikola.nikola.Post.text',
- mock.Mock(return_value='some long text')):
-
- example_post = nikola.nikola.Post('source.file',
- fake_conf,
- 'blog_folder',
- True,
- {'en': ''},
- 'post.tmpl',
- FakeCompiler())
-
- opener_mock = mock.mock_open()
-
- with mock.patch('nikola.nikola.io.open', opener_mock, create=True):
- nikola.nikola.Nikola().generic_rss_renderer('en',
- "blog_title",
- self.blog_url,
- "blog_description",
- [example_post,
- ],
- 'testfeed.rss',
- True,
- False)
-
- opener_mock.assert_called_once_with(
- 'testfeed.rss', 'w+', encoding='utf-8')
-
- # Python 3 / unicode strings workaround
- # lxml will complain if the encoding is specified in the
- # xml when running with unicode strings.
- # We do not include this in our content.
- file_content = [
- call[1][0]
- for call in opener_mock.mock_calls[2:-1]][0]
- splitted_content = file_content.split('\n')
- self.encoding_declaration = splitted_content[0]
- content_without_encoding_declaration = splitted_content[1:]
- self.file_content = '\n'.join(
- content_without_encoding_declaration)
-
- def tearDown(self):
- pass
-
- def test_feed_items_have_valid_URLs(self):
- '''The items in the feed need to have valid urls in link and guid.'''
- # This validation regex is taken from django.core.validators
- url_validation_regex = re.compile(r'^(?:http|ftp)s?://' # http:// or https://
- r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain...
- r'localhost|' # localhost...
- r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|' # ...or ipv4
- r'\[?[A-F0-9]*:[A-F0-9:]+\]?)' # ...or ipv6
- r'(?::\d+)?' # optional port
- r'(?:/?|[/?]\S+)$', re.IGNORECASE)
-
- def is_valid_URL(url):
- return url_validation_regex.match(url) is not None
-
- et = etree.parse(StringIO(self.file_content))
- channel = et.find('channel')
- item = channel.find('item')
- guid = item.find('guid')
- link = item.find('link')
-
- # As stated by W3 FEED Validator: "link must be a full and valid URL"
- self.assertTrue(is_valid_URL(link.text),
- 'The following URL is not valid: %s' % link.text)
- self.assertTrue(self.blog_url in link.text)
-
- # "guid must be a full URL, unless isPermaLink attribute
- # is false: /weblog/posts/the-minimal-server.html "
- self.assertTrue(is_valid_URL(guid.text),
- 'The following URL is not valid: %s' %
- guid.text)
- self.assertTrue(self.blog_url in guid.text)
-
- def test_feed_is_valid(self):
- '''
- A testcase to check if the generated feed is valid.
-
- Validation can be tested with W3 FEED Validator that can be found
- at http://feedvalidator.org
- '''
- rss_schema_filename = os.path.join(os.path.dirname(__file__),
- 'rss-2_0.xsd')
- with open(rss_schema_filename, 'r') as rss_schema_file:
- xmlschema_doc = etree.parse(rss_schema_file)
-
- xmlschema = etree.XMLSchema(xmlschema_doc)
- document = etree.parse(StringIO(self.file_content))
-
- self.assertTrue(xmlschema.validate(document))
-
-if __name__ == '__main__':
- unittest.main()