1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import unittest
import os
import re
from io import StringIO
import mock
from context import nikola
from lxml import etree
class RSSFeedTest(unittest.TestCase):
def setUp(self):
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',
'tags': 'tags', 'link':
'link', 'description':
'description'}))):
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',
'cache',
'blog_folder',
True,
{'en': ''},
'en',
self.blog_url,
'unused message.',
'post.tmpl')
opener_mock = mock.mock_open()
with mock.patch('nikola.nikola.utils.codecs.open', opener_mock, create=True):
nikola.nikola.utils.generic_rss_renderer('en',
"blog_title",
self.blog_url,
"blog_description",
[example_post,
],
'testfeed.rss',
True)
opener_mock.assert_called_once_with(
'testfeed.rss', 'wb+', '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.
open_handle = opener_mock()
file_content = [call[1][0]
for call in open_handle.mock_calls[1:-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()
|