summaryrefslogtreecommitdiffstats
path: root/tests/test_rss_feeds.py
blob: 2b48f3624111eb07894e1470636a2f7d6f949ef7 (plain) (blame)
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
# -*- coding: utf-8 -*-

import unittest
import os
import re
from StringIO 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.nikola.utils.get_meta',
                        mock.Mock(return_value=('post title',
                                                'awesome_article',
                                                '2012-10-01 22:41', 'tags',
                                                'link', '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.')

                    opener_mock = mock.mock_open()

                    with mock.patch('nikola.nikola.utils.open', opener_mock, create=True):
                        nikola.nikola.utils.generic_rss_renderer('en',
                                                                 "blog_title",
                                                                 self.blog_url,
                                                                 "blog_description",
                                                                 [example_post,
                                                                  ],
                                                                 'testfeed.rss')

                    self.file_content = ''.join(
                        [call[1][0] for call in opener_mock.mock_calls[2:-1]])

    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()